1 // Copyright (c) 2011 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 "net/base/auth.h"
11 #include "net/base/net_log_unittest.h"
12 #include "net/http/http_network_session_peer.h"
13 #include "net/http/http_transaction_unittest.h"
14 #include "net/socket/client_socket_pool_base.h"
15 #include "net/spdy/spdy_http_stream.h"
16 #include "net/spdy/spdy_http_utils.h"
17 #include "net/spdy/spdy_session.h"
18 #include "net/spdy/spdy_session_pool.h"
19 #include "net/spdy/spdy_test_util.h"
20 #include "net/url_request/url_request_test_util.h"
21 #include "testing/platform_test.h"
23 //-----------------------------------------------------------------------------
27 // This is the expected list of advertised protocols from the browser's NPN
29 static const char kExpectedNPNString
[] = "\x08http/1.1\x06spdy/2";
31 enum SpdyNetworkTransactionTestTypes
{
36 class SpdyNetworkTransactionTest
37 : public ::testing::TestWithParam
<SpdyNetworkTransactionTestTypes
> {
40 virtual void SetUp() {
41 // By default, all tests turn off compression.
42 EnableCompression(false);
43 google_get_request_initialized_
= false;
44 google_post_request_initialized_
= false;
45 google_chunked_post_request_initialized_
= false;
48 virtual void TearDown() {
49 // Empty the current queue.
50 MessageLoop::current()->RunAllPending();
53 struct TransactionHelperResult
{
55 std::string status_line
;
56 std::string response_data
;
57 HttpResponseInfo response_info
;
60 void EnableCompression(bool enabled
) {
61 spdy::SpdyFramer::set_enable_compression_default(enabled
);
64 class StartTransactionCallback
;
65 class DeleteSessionCallback
;
67 // A helper class that handles all the initial npn/ssl setup.
68 class NormalSpdyTransactionHelper
{
70 NormalSpdyTransactionHelper(const HttpRequestInfo
& request
,
71 const BoundNetLog
& log
,
72 SpdyNetworkTransactionTestTypes test_type
)
74 session_deps_(new SpdySessionDependencies()),
75 session_(SpdySessionDependencies::SpdyCreateSession(
76 session_deps_
.get())),
78 test_type_(test_type
),
79 deterministic_(false),
94 ~NormalSpdyTransactionHelper() {
95 // Any test which doesn't close the socket by sending it an EOF will
96 // have a valid session left open, which leaks the entire session pool.
97 // This is just fine - in fact, some of our tests intentionally do this
98 // so that we can check consistency of the SpdySessionPool as the test
99 // finishes. If we had put an EOF on the socket, the SpdySession would
100 // have closed and we wouldn't be able to check the consistency.
102 // Forcefully close existing sessions here.
103 session()->spdy_session_pool()->CloseAllSessions();
106 void SetDeterministic() {
107 session_
= SpdySessionDependencies::SpdyCreateSessionDeterministic(
108 session_deps_
.get());
109 deterministic_
= true;
112 void SetSpdyDisabled() {
113 spdy_enabled_
= false;
116 void RunPreTestSetup() {
117 if (!session_deps_
.get())
118 session_deps_
.reset(new SpdySessionDependencies());
120 session_
= SpdySessionDependencies::SpdyCreateSession(
121 session_deps_
.get());
122 HttpStreamFactory::set_use_alternate_protocols(false);
123 HttpStreamFactory::set_force_spdy_over_ssl(false);
124 HttpStreamFactory::set_force_spdy_always(false);
125 switch (test_type_
) {
127 session_
->mutable_alternate_protocols()->SetAlternateProtocolFor(
128 HostPortPair("www.google.com", 80), 443,
129 HttpAlternateProtocols::NPN_SPDY_2
);
130 HttpStreamFactory::set_use_alternate_protocols(true);
131 HttpStreamFactory::set_next_protos(kExpectedNPNString
);
134 HttpStreamFactory::set_force_spdy_over_ssl(false);
135 HttpStreamFactory::set_force_spdy_always(true);
138 HttpStreamFactory::set_force_spdy_over_ssl(true);
139 HttpStreamFactory::set_force_spdy_always(true);
145 // We're now ready to use SSL-npn SPDY.
146 trans_
.reset(new HttpNetworkTransaction(session_
));
149 // Start the transaction, read some data, finish.
150 void RunDefaultTest() {
151 output_
.rv
= trans_
->Start(&request_
, &callback
, log_
);
153 // We expect an IO Pending or some sort of error.
154 EXPECT_LT(output_
.rv
, 0);
155 if (output_
.rv
!= ERR_IO_PENDING
)
158 output_
.rv
= callback
.WaitForResult();
159 if (output_
.rv
!= OK
) {
160 session_
->spdy_session_pool()->CloseCurrentSessions();
165 const HttpResponseInfo
* response
= trans_
->GetResponseInfo();
166 ASSERT_TRUE(response
!= NULL
);
167 ASSERT_TRUE(response
->headers
!= NULL
);
168 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
169 EXPECT_EQ(spdy_enabled_
, response
->was_fetched_via_spdy
);
170 if (test_type_
== SPDYNPN
&& spdy_enabled_
) {
171 EXPECT_TRUE(response
->was_npn_negotiated
);
173 EXPECT_TRUE(!response
->was_npn_negotiated
);
175 // If SPDY is not enabled, a HTTP request should not be diverted
176 // over a SSL session.
177 if (!spdy_enabled_
) {
178 EXPECT_EQ(request_
.url
.SchemeIs("https"),
179 response
->was_npn_negotiated
);
181 EXPECT_EQ("192.0.2.33", response
->socket_address
.host());
182 EXPECT_EQ(0, response
->socket_address
.port());
183 output_
.status_line
= response
->headers
->GetStatusLine();
184 output_
.response_info
= *response
; // Make a copy so we can verify.
185 output_
.rv
= ReadTransaction(trans_
.get(), &output_
.response_data
);
188 // Most tests will want to call this function. In particular, the MockReads
189 // should end with an empty read, and that read needs to be processed to
190 // ensure proper deletion of the spdy_session_pool.
191 void VerifyDataConsumed() {
192 for (DataVector::iterator it
= data_vector_
.begin();
193 it
!= data_vector_
.end(); ++it
) {
194 EXPECT_TRUE((*it
)->at_read_eof()) << "Read count: "
195 << (*it
)->read_count()
197 << (*it
)->read_index();
198 EXPECT_TRUE((*it
)->at_write_eof()) << "Write count: "
199 << (*it
)->write_count()
201 << (*it
)->write_index();
205 // Occasionally a test will expect to error out before certain reads are
206 // processed. In that case we want to explicitly ensure that the reads were
208 void VerifyDataNotConsumed() {
209 for (DataVector::iterator it
= data_vector_
.begin();
210 it
!= data_vector_
.end(); ++it
) {
211 EXPECT_TRUE(!(*it
)->at_read_eof()) << "Read count: "
212 << (*it
)->read_count()
214 << (*it
)->read_index();
215 EXPECT_TRUE(!(*it
)->at_write_eof()) << "Write count: "
216 << (*it
)->write_count()
218 << (*it
)->write_index();
222 void RunToCompletion(StaticSocketDataProvider
* data
) {
226 VerifyDataConsumed();
229 void AddData(StaticSocketDataProvider
* data
) {
230 DCHECK(!deterministic_
);
231 data_vector_
.push_back(data
);
232 linked_ptr
<SSLSocketDataProvider
> ssl_(
233 new SSLSocketDataProvider(true, OK
));
234 if (test_type_
== SPDYNPN
) {
235 ssl_
->next_proto_status
= SSLClientSocket::kNextProtoNegotiated
;
236 ssl_
->next_proto
= "spdy/2";
237 ssl_
->was_npn_negotiated
= true;
239 ssl_vector_
.push_back(ssl_
);
240 if (test_type_
== SPDYNPN
|| test_type_
== SPDYSSL
)
241 session_deps_
->socket_factory
->AddSSLSocketDataProvider(ssl_
.get());
242 session_deps_
->socket_factory
->AddSocketDataProvider(data
);
243 if (test_type_
== SPDYNPN
) {
244 MockConnect
never_finishing_connect(false, ERR_IO_PENDING
);
245 linked_ptr
<StaticSocketDataProvider
>
246 hanging_non_alternate_protocol_socket(
247 new StaticSocketDataProvider(NULL
, 0, NULL
, 0));
248 hanging_non_alternate_protocol_socket
->set_connect_data(
249 never_finishing_connect
);
250 session_deps_
->socket_factory
->AddSocketDataProvider(
251 hanging_non_alternate_protocol_socket
.get());
252 alternate_vector_
.push_back(hanging_non_alternate_protocol_socket
);
256 void AddDeterministicData(DeterministicSocketData
* data
) {
257 DCHECK(deterministic_
);
258 data_vector_
.push_back(data
);
259 linked_ptr
<SSLSocketDataProvider
> ssl_(
260 new SSLSocketDataProvider(true, OK
));
261 if (test_type_
== SPDYNPN
) {
262 ssl_
->next_proto_status
= SSLClientSocket::kNextProtoNegotiated
;
263 ssl_
->next_proto
= "spdy/2";
264 ssl_
->was_npn_negotiated
= true;
266 ssl_vector_
.push_back(ssl_
);
267 if (test_type_
== SPDYNPN
|| test_type_
== SPDYSSL
) {
268 session_deps_
->deterministic_socket_factory
->
269 AddSSLSocketDataProvider(ssl_
.get());
271 session_deps_
->deterministic_socket_factory
->AddSocketDataProvider(data
);
272 if (test_type_
== SPDYNPN
) {
273 MockConnect
never_finishing_connect(false, ERR_IO_PENDING
);
274 scoped_refptr
<DeterministicSocketData
>
275 hanging_non_alternate_protocol_socket(
276 new DeterministicSocketData(NULL
, 0, NULL
, 0));
277 hanging_non_alternate_protocol_socket
->set_connect_data(
278 never_finishing_connect
);
279 session_deps_
->deterministic_socket_factory
->AddSocketDataProvider(
280 hanging_non_alternate_protocol_socket
);
281 alternate_deterministic_vector_
.push_back(
282 hanging_non_alternate_protocol_socket
);
286 // This can only be called after RunPreTestSetup. It adds a Data Provider,
287 // but not a corresponding SSL data provider
288 void AddDataNoSSL(StaticSocketDataProvider
* data
) {
289 DCHECK(!deterministic_
);
290 session_deps_
->socket_factory
->AddSocketDataProvider(data
);
292 void AddDataNoSSL(DeterministicSocketData
* data
) {
293 DCHECK(deterministic_
);
294 session_deps_
->deterministic_socket_factory
->AddSocketDataProvider(data
);
297 void SetSession(const scoped_refptr
<HttpNetworkSession
>& session
) {
300 HttpNetworkTransaction
* trans() { return trans_
.get(); }
301 void ResetTrans() { trans_
.reset(); }
302 TransactionHelperResult
& output() { return output_
; }
303 const HttpRequestInfo
& request() const { return request_
; }
304 const scoped_refptr
<HttpNetworkSession
>& session() const {
307 scoped_ptr
<SpdySessionDependencies
>& session_deps() {
308 return session_deps_
;
310 int port() const { return port_
; }
311 SpdyNetworkTransactionTestTypes
test_type() const { return test_type_
; }
314 typedef std::vector
<StaticSocketDataProvider
*> DataVector
;
315 typedef std::vector
<linked_ptr
<SSLSocketDataProvider
> > SSLVector
;
316 typedef std::vector
<linked_ptr
<StaticSocketDataProvider
> > AlternateVector
;
317 typedef std::vector
<scoped_refptr
<DeterministicSocketData
> >
318 AlternateDeterministicVector
;
319 HttpRequestInfo request_
;
320 scoped_ptr
<SpdySessionDependencies
> session_deps_
;
321 scoped_refptr
<HttpNetworkSession
> session_
;
322 TransactionHelperResult output_
;
323 scoped_ptr
<StaticSocketDataProvider
> first_transaction_
;
324 SSLVector ssl_vector_
;
325 TestCompletionCallback callback
;
326 scoped_ptr
<HttpNetworkTransaction
> trans_
;
327 scoped_ptr
<HttpNetworkTransaction
> trans_http_
;
328 DataVector data_vector_
;
329 AlternateVector alternate_vector_
;
330 AlternateDeterministicVector alternate_deterministic_vector_
;
331 const BoundNetLog
& log_
;
332 SpdyNetworkTransactionTestTypes test_type_
;
338 void ConnectStatusHelperWithExpectedStatus(const MockRead
& status
,
339 int expected_status
);
341 void ConnectStatusHelper(const MockRead
& status
);
343 const HttpRequestInfo
& CreateGetPushRequest() {
344 google_get_push_request_
.method
= "GET";
345 google_get_push_request_
.url
= GURL("http://www.google.com/foo.dat");
346 google_get_push_request_
.load_flags
= 0;
347 return google_get_push_request_
;
350 const HttpRequestInfo
& CreateGetRequest() {
351 if (!google_get_request_initialized_
) {
352 google_get_request_
.method
= "GET";
353 google_get_request_
.url
= GURL(kDefaultURL
);
354 google_get_request_
.load_flags
= 0;
355 google_get_request_initialized_
= true;
357 return google_get_request_
;
360 const HttpRequestInfo
& CreateGetRequestWithUserAgent() {
361 if (!google_get_request_initialized_
) {
362 google_get_request_
.method
= "GET";
363 google_get_request_
.url
= GURL(kDefaultURL
);
364 google_get_request_
.load_flags
= 0;
365 google_get_request_
.extra_headers
.SetHeader("User-Agent", "Chrome");
366 google_get_request_initialized_
= true;
368 return google_get_request_
;
371 const HttpRequestInfo
& CreatePostRequest() {
372 if (!google_post_request_initialized_
) {
373 google_post_request_
.method
= "POST";
374 google_post_request_
.url
= GURL(kDefaultURL
);
375 google_post_request_
.upload_data
= new UploadData();
376 google_post_request_
.upload_data
->AppendBytes(kUploadData
,
378 google_post_request_initialized_
= true;
380 return google_post_request_
;
383 const HttpRequestInfo
& CreateChunkedPostRequest() {
384 if (!google_chunked_post_request_initialized_
) {
385 google_chunked_post_request_
.method
= "POST";
386 google_chunked_post_request_
.url
= GURL(kDefaultURL
);
387 google_chunked_post_request_
.upload_data
= new UploadData();
388 google_chunked_post_request_
.upload_data
->set_is_chunked(true);
389 google_chunked_post_request_
.upload_data
->AppendChunk(
390 kUploadData
, kUploadDataSize
, false);
391 google_chunked_post_request_
.upload_data
->AppendChunk(
392 kUploadData
, kUploadDataSize
, true);
393 google_chunked_post_request_initialized_
= true;
395 return google_chunked_post_request_
;
398 // Read the result of a particular transaction, knowing that we've got
399 // multiple transactions in the read pipeline; so as we read, we may have
400 // to skip over data destined for other transactions while we consume
401 // the data for |trans|.
402 int ReadResult(HttpNetworkTransaction
* trans
,
403 StaticSocketDataProvider
* data
,
404 std::string
* result
) {
405 const int kSize
= 3000;
408 scoped_refptr
<net::IOBufferWithSize
> buf(new net::IOBufferWithSize(kSize
));
409 TestCompletionCallback callback
;
411 int rv
= trans
->Read(buf
, kSize
, &callback
);
412 if (rv
== ERR_IO_PENDING
) {
413 // Multiple transactions may be in the data set. Keep pulling off
414 // reads until we complete our callback.
415 while (!callback
.have_result()) {
416 data
->CompleteRead();
417 MessageLoop::current()->RunAllPending();
419 rv
= callback
.WaitForResult();
420 } else if (rv
<= 0) {
423 result
->append(buf
->data(), rv
);
429 void VerifyStreamsClosed(const NormalSpdyTransactionHelper
& helper
) {
430 // This lengthy block is reaching into the pool to dig out the active
431 // session. Once we have the session, we verify that the streams are
432 // all closed and not leaked at this point.
433 const GURL
& url
= helper
.request().url
;
434 int port
= helper
.test_type() == SPDYNPN
? 443 : 80;
435 HostPortPair
host_port_pair(url
.host(), port
);
436 HostPortProxyPair
pair(host_port_pair
, ProxyServer::Direct());
438 const scoped_refptr
<HttpNetworkSession
>& session
= helper
.session();
439 SpdySessionPool
* pool(session
->spdy_session_pool());
440 EXPECT_TRUE(pool
->HasSession(pair
));
441 scoped_refptr
<SpdySession
> spdy_session(pool
->Get(pair
, log
));
442 ASSERT_TRUE(spdy_session
.get() != NULL
);
443 EXPECT_EQ(0u, spdy_session
->num_active_streams());
444 EXPECT_EQ(0u, spdy_session
->num_unclaimed_pushed_streams());
447 void RunServerPushTest(OrderedSocketData
* data
,
448 HttpResponseInfo
* response
,
449 HttpResponseInfo
* push_response
,
450 std::string
& expected
) {
451 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
452 BoundNetLog(), GetParam());
453 helper
.RunPreTestSetup();
454 helper
.AddData(data
);
456 HttpNetworkTransaction
* trans
= helper
.trans();
458 // Start the transaction with basic parameters.
459 TestCompletionCallback callback
;
460 int rv
= trans
->Start(&CreateGetRequest(), &callback
, BoundNetLog());
461 EXPECT_EQ(ERR_IO_PENDING
, rv
);
462 rv
= callback
.WaitForResult();
464 // Request the pushed path.
465 scoped_ptr
<HttpNetworkTransaction
> trans2(
466 new HttpNetworkTransaction(helper
.session()));
467 rv
= trans2
->Start(&CreateGetPushRequest(), &callback
, BoundNetLog());
468 EXPECT_EQ(ERR_IO_PENDING
, rv
);
469 MessageLoop::current()->RunAllPending();
471 // The data for the pushed path may be coming in more than 1 packet. Compile
472 // the results into a single string.
474 // Read the server push body.
476 ReadResult(trans2
.get(), data
, &result2
);
477 // Read the response body.
479 ReadResult(trans
, data
, &result
);
481 // Verify that we consumed all test data.
482 EXPECT_TRUE(data
->at_read_eof());
483 EXPECT_TRUE(data
->at_write_eof());
485 // Verify that the received push data is same as the expected push data.
486 EXPECT_EQ(result2
.compare(expected
), 0) << "Received data: "
488 << "||||| Expected data: "
491 // Verify the SYN_REPLY.
492 // Copy the response info, because trans goes away.
493 *response
= *trans
->GetResponseInfo();
494 *push_response
= *trans2
->GetResponseInfo();
496 VerifyStreamsClosed(helper
);
500 bool google_get_request_initialized_
;
501 bool google_post_request_initialized_
;
502 bool google_chunked_post_request_initialized_
;
503 HttpRequestInfo google_get_request_
;
504 HttpRequestInfo google_post_request_
;
505 HttpRequestInfo google_chunked_post_request_
;
506 HttpRequestInfo google_get_push_request_
;
509 //-----------------------------------------------------------------------------
510 // All tests are run with three different connection types: SPDY after NPN
511 // negotiation, SPDY without SSL, and SPDY with SSL.
512 INSTANTIATE_TEST_CASE_P(Spdy
,
513 SpdyNetworkTransactionTest
,
514 ::testing::Values(SPDYNOSSL
, SPDYSSL
, SPDYNPN
));
517 // Verify HttpNetworkTransaction constructor.
518 TEST_P(SpdyNetworkTransactionTest
, Constructor
) {
519 SpdySessionDependencies session_deps
;
520 scoped_refptr
<HttpNetworkSession
> session(
521 SpdySessionDependencies::SpdyCreateSession(&session_deps
));
522 scoped_ptr
<HttpTransaction
> trans(new HttpNetworkTransaction(session
));
525 TEST_P(SpdyNetworkTransactionTest
, Get
) {
526 // Construct the request.
527 scoped_ptr
<spdy::SpdyFrame
> req(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
528 MockWrite writes
[] = { CreateMockWrite(*req
) };
530 scoped_ptr
<spdy::SpdyFrame
> resp(ConstructSpdyGetSynReply(NULL
, 0, 1));
531 scoped_ptr
<spdy::SpdyFrame
> body(ConstructSpdyBodyFrame(1, true));
533 CreateMockRead(*resp
),
534 CreateMockRead(*body
),
535 MockRead(true, 0, 0) // EOF
538 scoped_refptr
<DelayedSocketData
> data(
539 new DelayedSocketData(1, reads
, arraysize(reads
),
540 writes
, arraysize(writes
)));
541 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
542 BoundNetLog(), GetParam());
543 helper
.RunToCompletion(data
.get());
544 TransactionHelperResult out
= helper
.output();
545 EXPECT_EQ(OK
, out
.rv
);
546 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
547 EXPECT_EQ("hello!", out
.response_data
);
550 TEST_P(SpdyNetworkTransactionTest
, GetAtEachPriority
) {
551 for (RequestPriority p
= HIGHEST
; p
< NUM_PRIORITIES
;
552 p
= RequestPriority(p
+1)) {
553 // Construct the request.
554 scoped_ptr
<spdy::SpdyFrame
> req(ConstructSpdyGet(NULL
, 0, false, 1, p
));
555 MockWrite writes
[] = { CreateMockWrite(*req
) };
557 const int spdy_prio
= reinterpret_cast<spdy::SpdySynStreamControlFrame
*>(
558 req
.get())->priority();
559 // this repeats the RequestPriority-->SpdyPriority mapping from
560 // SpdyFramer::ConvertRequestPriorityToSpdyPriority to make
561 // sure it's being done right.
564 EXPECT_EQ(0, spdy_prio
);
567 EXPECT_EQ(1, spdy_prio
);
571 EXPECT_EQ(2, spdy_prio
);
574 EXPECT_EQ(3, spdy_prio
);
580 scoped_ptr
<spdy::SpdyFrame
> resp(ConstructSpdyGetSynReply(NULL
, 0, 1));
581 scoped_ptr
<spdy::SpdyFrame
> body(ConstructSpdyBodyFrame(1, true));
583 CreateMockRead(*resp
),
584 CreateMockRead(*body
),
585 MockRead(true, 0, 0) // EOF
588 scoped_refptr
<DelayedSocketData
> data(
589 new DelayedSocketData(1, reads
, arraysize(reads
),
590 writes
, arraysize(writes
)));
591 HttpRequestInfo http_req
= CreateGetRequest();
592 http_req
.priority
= p
;
594 NormalSpdyTransactionHelper
helper(http_req
, BoundNetLog(), GetParam());
595 helper
.RunToCompletion(data
.get());
596 TransactionHelperResult out
= helper
.output();
597 EXPECT_EQ(OK
, out
.rv
);
598 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
599 EXPECT_EQ("hello!", out
.response_data
);
603 // Start three gets simultaniously; making sure that multiplexed
604 // streams work properly.
606 // This can't use the TransactionHelper method, since it only
607 // handles a single transaction, and finishes them as soon
608 // as it launches them.
610 // TODO(gavinp): create a working generalized TransactionHelper that
611 // can allow multiple streams in flight.
613 TEST_P(SpdyNetworkTransactionTest
, ThreeGets
) {
614 scoped_ptr
<spdy::SpdyFrame
> req(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
615 scoped_ptr
<spdy::SpdyFrame
> resp(ConstructSpdyGetSynReply(NULL
, 0, 1));
616 scoped_ptr
<spdy::SpdyFrame
> body(ConstructSpdyBodyFrame(1, false));
617 scoped_ptr
<spdy::SpdyFrame
> fbody(ConstructSpdyBodyFrame(1, true));
619 scoped_ptr
<spdy::SpdyFrame
> req2(ConstructSpdyGet(NULL
, 0, false, 3, LOWEST
));
620 scoped_ptr
<spdy::SpdyFrame
> resp2(ConstructSpdyGetSynReply(NULL
, 0, 3));
621 scoped_ptr
<spdy::SpdyFrame
> body2(ConstructSpdyBodyFrame(3, false));
622 scoped_ptr
<spdy::SpdyFrame
> fbody2(ConstructSpdyBodyFrame(3, true));
624 scoped_ptr
<spdy::SpdyFrame
> req3(ConstructSpdyGet(NULL
, 0, false, 5, LOWEST
));
625 scoped_ptr
<spdy::SpdyFrame
> resp3(ConstructSpdyGetSynReply(NULL
, 0, 5));
626 scoped_ptr
<spdy::SpdyFrame
> body3(ConstructSpdyBodyFrame(5, false));
627 scoped_ptr
<spdy::SpdyFrame
> fbody3(ConstructSpdyBodyFrame(5, true));
629 MockWrite writes
[] = {
630 CreateMockWrite(*req
),
631 CreateMockWrite(*req2
),
632 CreateMockWrite(*req3
),
635 CreateMockRead(*resp
, 1),
636 CreateMockRead(*body
),
637 CreateMockRead(*resp2
, 4),
638 CreateMockRead(*body2
),
639 CreateMockRead(*resp3
, 7),
640 CreateMockRead(*body3
),
642 CreateMockRead(*fbody
),
643 CreateMockRead(*fbody2
),
644 CreateMockRead(*fbody3
),
646 MockRead(true, 0, 0), // EOF
648 scoped_refptr
<OrderedSocketData
> data(
649 new OrderedSocketData(reads
, arraysize(reads
),
650 writes
, arraysize(writes
)));
651 scoped_refptr
<OrderedSocketData
> data_placeholder(
652 new OrderedSocketData(NULL
, 0, NULL
, 0));
655 TransactionHelperResult out
;
656 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
657 BoundNetLog(), GetParam());
658 helper
.RunPreTestSetup();
659 helper
.AddData(data
.get());
660 // We require placeholder data because three get requests are sent out, so
661 // there needs to be three sets of SSL connection data.
662 helper
.AddData(data_placeholder
.get());
663 helper
.AddData(data_placeholder
.get());
664 scoped_ptr
<HttpNetworkTransaction
> trans1(
665 new HttpNetworkTransaction(helper
.session()));
666 scoped_ptr
<HttpNetworkTransaction
> trans2(
667 new HttpNetworkTransaction(helper
.session()));
668 scoped_ptr
<HttpNetworkTransaction
> trans3(
669 new HttpNetworkTransaction(helper
.session()));
671 TestCompletionCallback callback1
;
672 TestCompletionCallback callback2
;
673 TestCompletionCallback callback3
;
675 HttpRequestInfo httpreq1
= CreateGetRequest();
676 HttpRequestInfo httpreq2
= CreateGetRequest();
677 HttpRequestInfo httpreq3
= CreateGetRequest();
679 out
.rv
= trans1
->Start(&httpreq1
, &callback1
, log
);
680 ASSERT_EQ(ERR_IO_PENDING
, out
.rv
);
681 out
.rv
= trans2
->Start(&httpreq2
, &callback2
, log
);
682 ASSERT_EQ(ERR_IO_PENDING
, out
.rv
);
683 out
.rv
= trans3
->Start(&httpreq3
, &callback3
, log
);
684 ASSERT_EQ(ERR_IO_PENDING
, out
.rv
);
686 out
.rv
= callback1
.WaitForResult();
687 ASSERT_EQ(OK
, out
.rv
);
688 out
.rv
= callback3
.WaitForResult();
689 ASSERT_EQ(OK
, out
.rv
);
691 const HttpResponseInfo
* response1
= trans1
->GetResponseInfo();
692 EXPECT_TRUE(response1
->headers
!= NULL
);
693 EXPECT_TRUE(response1
->was_fetched_via_spdy
);
694 out
.status_line
= response1
->headers
->GetStatusLine();
695 out
.response_info
= *response1
;
697 trans2
->GetResponseInfo();
699 out
.rv
= ReadTransaction(trans1
.get(), &out
.response_data
);
700 helper
.VerifyDataConsumed();
701 EXPECT_EQ(OK
, out
.rv
);
703 EXPECT_EQ(OK
, out
.rv
);
704 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
705 EXPECT_EQ("hello!hello!", out
.response_data
);
708 TEST_P(SpdyNetworkTransactionTest
, TwoGetsLateBinding
) {
709 scoped_ptr
<spdy::SpdyFrame
> req(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
710 scoped_ptr
<spdy::SpdyFrame
> resp(ConstructSpdyGetSynReply(NULL
, 0, 1));
711 scoped_ptr
<spdy::SpdyFrame
> body(ConstructSpdyBodyFrame(1, false));
712 scoped_ptr
<spdy::SpdyFrame
> fbody(ConstructSpdyBodyFrame(1, true));
714 scoped_ptr
<spdy::SpdyFrame
> req2(ConstructSpdyGet(NULL
, 0, false, 3, LOWEST
));
715 scoped_ptr
<spdy::SpdyFrame
> resp2(ConstructSpdyGetSynReply(NULL
, 0, 3));
716 scoped_ptr
<spdy::SpdyFrame
> body2(ConstructSpdyBodyFrame(3, false));
717 scoped_ptr
<spdy::SpdyFrame
> fbody2(ConstructSpdyBodyFrame(3, true));
719 MockWrite writes
[] = {
720 CreateMockWrite(*req
),
721 CreateMockWrite(*req2
),
724 CreateMockRead(*resp
, 1),
725 CreateMockRead(*body
),
726 CreateMockRead(*resp2
, 4),
727 CreateMockRead(*body2
),
728 CreateMockRead(*fbody
),
729 CreateMockRead(*fbody2
),
730 MockRead(true, 0, 0), // EOF
732 scoped_refptr
<OrderedSocketData
> data(
733 new OrderedSocketData(reads
, arraysize(reads
),
734 writes
, arraysize(writes
)));
736 MockConnect
never_finishing_connect(false, ERR_IO_PENDING
);
738 scoped_refptr
<OrderedSocketData
> data_placeholder(
739 new OrderedSocketData(NULL
, 0, NULL
, 0));
740 data_placeholder
->set_connect_data(never_finishing_connect
);
743 TransactionHelperResult out
;
744 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
745 BoundNetLog(), GetParam());
746 helper
.RunPreTestSetup();
747 helper
.AddData(data
.get());
748 // We require placeholder data because two get requests are sent out, so
749 // there needs to be two sets of SSL connection data.
750 helper
.AddData(data_placeholder
.get());
751 scoped_ptr
<HttpNetworkTransaction
> trans1(
752 new HttpNetworkTransaction(helper
.session()));
753 scoped_ptr
<HttpNetworkTransaction
> trans2(
754 new HttpNetworkTransaction(helper
.session()));
756 TestCompletionCallback callback1
;
757 TestCompletionCallback callback2
;
759 HttpRequestInfo httpreq1
= CreateGetRequest();
760 HttpRequestInfo httpreq2
= CreateGetRequest();
762 out
.rv
= trans1
->Start(&httpreq1
, &callback1
, log
);
763 ASSERT_EQ(ERR_IO_PENDING
, out
.rv
);
764 out
.rv
= trans2
->Start(&httpreq2
, &callback2
, log
);
765 ASSERT_EQ(ERR_IO_PENDING
, out
.rv
);
767 out
.rv
= callback1
.WaitForResult();
768 ASSERT_EQ(OK
, out
.rv
);
769 out
.rv
= callback2
.WaitForResult();
770 ASSERT_EQ(OK
, out
.rv
);
772 const HttpResponseInfo
* response1
= trans1
->GetResponseInfo();
773 EXPECT_TRUE(response1
->headers
!= NULL
);
774 EXPECT_TRUE(response1
->was_fetched_via_spdy
);
775 out
.status_line
= response1
->headers
->GetStatusLine();
776 out
.response_info
= *response1
;
777 out
.rv
= ReadTransaction(trans1
.get(), &out
.response_data
);
778 EXPECT_EQ(OK
, out
.rv
);
779 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
780 EXPECT_EQ("hello!hello!", out
.response_data
);
782 const HttpResponseInfo
* response2
= trans2
->GetResponseInfo();
783 EXPECT_TRUE(response2
->headers
!= NULL
);
784 EXPECT_TRUE(response2
->was_fetched_via_spdy
);
785 out
.status_line
= response2
->headers
->GetStatusLine();
786 out
.response_info
= *response2
;
787 out
.rv
= ReadTransaction(trans2
.get(), &out
.response_data
);
788 EXPECT_EQ(OK
, out
.rv
);
789 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
790 EXPECT_EQ("hello!hello!", out
.response_data
);
792 helper
.VerifyDataConsumed();
795 TEST_P(SpdyNetworkTransactionTest
, TwoGetsLateBindingFromPreconnect
) {
796 scoped_ptr
<spdy::SpdyFrame
> req(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
797 scoped_ptr
<spdy::SpdyFrame
> resp(ConstructSpdyGetSynReply(NULL
, 0, 1));
798 scoped_ptr
<spdy::SpdyFrame
> body(ConstructSpdyBodyFrame(1, false));
799 scoped_ptr
<spdy::SpdyFrame
> fbody(ConstructSpdyBodyFrame(1, true));
801 scoped_ptr
<spdy::SpdyFrame
> req2(ConstructSpdyGet(NULL
, 0, false, 3, LOWEST
));
802 scoped_ptr
<spdy::SpdyFrame
> resp2(ConstructSpdyGetSynReply(NULL
, 0, 3));
803 scoped_ptr
<spdy::SpdyFrame
> body2(ConstructSpdyBodyFrame(3, false));
804 scoped_ptr
<spdy::SpdyFrame
> fbody2(ConstructSpdyBodyFrame(3, true));
806 MockWrite writes
[] = {
807 CreateMockWrite(*req
),
808 CreateMockWrite(*req2
),
811 CreateMockRead(*resp
, 1),
812 CreateMockRead(*body
),
813 CreateMockRead(*resp2
, 4),
814 CreateMockRead(*body2
),
815 CreateMockRead(*fbody
),
816 CreateMockRead(*fbody2
),
817 MockRead(true, 0, 0), // EOF
819 scoped_refptr
<OrderedSocketData
> preconnect_data(
820 new OrderedSocketData(reads
, arraysize(reads
),
821 writes
, arraysize(writes
)));
823 MockConnect
never_finishing_connect(true, ERR_IO_PENDING
);
825 scoped_refptr
<OrderedSocketData
> data_placeholder(
826 new OrderedSocketData(NULL
, 0, NULL
, 0));
827 data_placeholder
->set_connect_data(never_finishing_connect
);
830 TransactionHelperResult out
;
831 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
832 BoundNetLog(), GetParam());
833 helper
.RunPreTestSetup();
834 helper
.AddData(preconnect_data
.get());
835 // We require placeholder data because 3 connections are attempted (first is
836 // the preconnect, 2nd and 3rd are the never finished connections.
837 helper
.AddData(data_placeholder
.get());
838 helper
.AddData(data_placeholder
.get());
840 scoped_ptr
<HttpNetworkTransaction
> trans1(
841 new HttpNetworkTransaction(helper
.session()));
842 scoped_ptr
<HttpNetworkTransaction
> trans2(
843 new HttpNetworkTransaction(helper
.session()));
845 TestCompletionCallback callback1
;
846 TestCompletionCallback callback2
;
848 HttpRequestInfo httpreq
= CreateGetRequest();
850 // Preconnect the first.
851 SSLConfig preconnect_ssl_config
;
852 helper
.session()->ssl_config_service()->GetSSLConfig(&preconnect_ssl_config
);
853 HttpStreamFactory
* http_stream_factory
=
854 helper
.session()->http_stream_factory();
855 if (http_stream_factory
->next_protos()) {
856 preconnect_ssl_config
.next_protos
= *http_stream_factory
->next_protos();
859 http_stream_factory
->PreconnectStreams(
860 1, httpreq
, preconnect_ssl_config
, log
);
862 out
.rv
= trans1
->Start(&httpreq
, &callback1
, log
);
863 ASSERT_EQ(ERR_IO_PENDING
, out
.rv
);
864 out
.rv
= trans2
->Start(&httpreq
, &callback2
, log
);
865 ASSERT_EQ(ERR_IO_PENDING
, out
.rv
);
867 out
.rv
= callback1
.WaitForResult();
868 ASSERT_EQ(OK
, out
.rv
);
869 out
.rv
= callback2
.WaitForResult();
870 ASSERT_EQ(OK
, out
.rv
);
872 const HttpResponseInfo
* response1
= trans1
->GetResponseInfo();
873 EXPECT_TRUE(response1
->headers
!= NULL
);
874 EXPECT_TRUE(response1
->was_fetched_via_spdy
);
875 out
.status_line
= response1
->headers
->GetStatusLine();
876 out
.response_info
= *response1
;
877 out
.rv
= ReadTransaction(trans1
.get(), &out
.response_data
);
878 EXPECT_EQ(OK
, out
.rv
);
879 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
880 EXPECT_EQ("hello!hello!", out
.response_data
);
882 const HttpResponseInfo
* response2
= trans2
->GetResponseInfo();
883 EXPECT_TRUE(response2
->headers
!= NULL
);
884 EXPECT_TRUE(response2
->was_fetched_via_spdy
);
885 out
.status_line
= response2
->headers
->GetStatusLine();
886 out
.response_info
= *response2
;
887 out
.rv
= ReadTransaction(trans2
.get(), &out
.response_data
);
888 EXPECT_EQ(OK
, out
.rv
);
889 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
890 EXPECT_EQ("hello!hello!", out
.response_data
);
892 helper
.VerifyDataConsumed();
895 // Similar to ThreeGets above, however this test adds a SETTINGS
896 // frame. The SETTINGS frame is read during the IO loop waiting on
897 // the first transaction completion, and sets a maximum concurrent
898 // stream limit of 1. This means that our IO loop exists after the
899 // second transaction completes, so we can assert on read_index().
900 TEST_P(SpdyNetworkTransactionTest
, ThreeGetsWithMaxConcurrent
) {
901 // Construct the request.
902 scoped_ptr
<spdy::SpdyFrame
> req(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
903 scoped_ptr
<spdy::SpdyFrame
> resp(ConstructSpdyGetSynReply(NULL
, 0, 1));
904 scoped_ptr
<spdy::SpdyFrame
> body(ConstructSpdyBodyFrame(1, false));
905 scoped_ptr
<spdy::SpdyFrame
> fbody(ConstructSpdyBodyFrame(1, true));
907 scoped_ptr
<spdy::SpdyFrame
> req2(ConstructSpdyGet(NULL
, 0, false, 3, LOWEST
));
908 scoped_ptr
<spdy::SpdyFrame
> resp2(ConstructSpdyGetSynReply(NULL
, 0, 3));
909 scoped_ptr
<spdy::SpdyFrame
> body2(ConstructSpdyBodyFrame(3, false));
910 scoped_ptr
<spdy::SpdyFrame
> fbody2(ConstructSpdyBodyFrame(3, true));
912 scoped_ptr
<spdy::SpdyFrame
> req3(ConstructSpdyGet(NULL
, 0, false, 5, LOWEST
));
913 scoped_ptr
<spdy::SpdyFrame
> resp3(ConstructSpdyGetSynReply(NULL
, 0, 5));
914 scoped_ptr
<spdy::SpdyFrame
> body3(ConstructSpdyBodyFrame(5, false));
915 scoped_ptr
<spdy::SpdyFrame
> fbody3(ConstructSpdyBodyFrame(5, true));
917 spdy::SpdySettings settings
;
918 spdy::SettingsFlagsAndId
id(0);
919 id
.set_id(spdy::SETTINGS_MAX_CONCURRENT_STREAMS
);
920 const size_t max_concurrent_streams
= 1;
922 settings
.push_back(spdy::SpdySetting(id
, max_concurrent_streams
));
923 scoped_ptr
<spdy::SpdyFrame
> settings_frame(ConstructSpdySettings(settings
));
925 MockWrite writes
[] = {
926 CreateMockWrite(*req
),
927 CreateMockWrite(*req2
),
928 CreateMockWrite(*req3
),
932 CreateMockRead(*settings_frame
, 1),
933 CreateMockRead(*resp
),
934 CreateMockRead(*body
),
935 CreateMockRead(*fbody
),
936 CreateMockRead(*resp2
, 7),
937 CreateMockRead(*body2
),
938 CreateMockRead(*fbody2
),
939 CreateMockRead(*resp3
, 12),
940 CreateMockRead(*body3
),
941 CreateMockRead(*fbody3
),
943 MockRead(true, 0, 0), // EOF
946 scoped_refptr
<OrderedSocketData
> data(
947 new OrderedSocketData(reads
, arraysize(reads
),
948 writes
, arraysize(writes
)));
949 scoped_refptr
<OrderedSocketData
> data_placeholder(
950 new OrderedSocketData(NULL
, 0, NULL
, 0));
953 TransactionHelperResult out
;
955 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
956 BoundNetLog(), GetParam());
957 helper
.RunPreTestSetup();
958 helper
.AddData(data
.get());
959 // We require placeholder data because three get requests are sent out, so
960 // there needs to be three sets of SSL connection data.
961 helper
.AddData(data_placeholder
.get());
962 helper
.AddData(data_placeholder
.get());
963 scoped_ptr
<HttpNetworkTransaction
> trans1(
964 new HttpNetworkTransaction(helper
.session()));
965 scoped_ptr
<HttpNetworkTransaction
> trans2(
966 new HttpNetworkTransaction(helper
.session()));
967 scoped_ptr
<HttpNetworkTransaction
> trans3(
968 new HttpNetworkTransaction(helper
.session()));
970 TestCompletionCallback callback1
;
971 TestCompletionCallback callback2
;
972 TestCompletionCallback callback3
;
974 HttpRequestInfo httpreq1
= CreateGetRequest();
975 HttpRequestInfo httpreq2
= CreateGetRequest();
976 HttpRequestInfo httpreq3
= CreateGetRequest();
978 out
.rv
= trans1
->Start(&httpreq1
, &callback1
, log
);
979 ASSERT_EQ(out
.rv
, ERR_IO_PENDING
);
980 // run transaction 1 through quickly to force a read of our SETTINGS
982 out
.rv
= callback1
.WaitForResult();
983 ASSERT_EQ(OK
, out
.rv
);
985 out
.rv
= trans2
->Start(&httpreq2
, &callback2
, log
);
986 ASSERT_EQ(out
.rv
, ERR_IO_PENDING
);
987 out
.rv
= trans3
->Start(&httpreq3
, &callback3
, log
);
988 ASSERT_EQ(out
.rv
, ERR_IO_PENDING
);
989 out
.rv
= callback2
.WaitForResult();
990 ASSERT_EQ(OK
, out
.rv
);
991 EXPECT_EQ(7U, data
->read_index()); // i.e. the third trans was queued
993 out
.rv
= callback3
.WaitForResult();
994 ASSERT_EQ(OK
, out
.rv
);
996 const HttpResponseInfo
* response1
= trans1
->GetResponseInfo();
997 ASSERT_TRUE(response1
!= NULL
);
998 EXPECT_TRUE(response1
->headers
!= NULL
);
999 EXPECT_TRUE(response1
->was_fetched_via_spdy
);
1000 out
.status_line
= response1
->headers
->GetStatusLine();
1001 out
.response_info
= *response1
;
1002 out
.rv
= ReadTransaction(trans1
.get(), &out
.response_data
);
1003 EXPECT_EQ(OK
, out
.rv
);
1004 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1005 EXPECT_EQ("hello!hello!", out
.response_data
);
1007 const HttpResponseInfo
* response2
= trans2
->GetResponseInfo();
1008 out
.status_line
= response2
->headers
->GetStatusLine();
1009 out
.response_info
= *response2
;
1010 out
.rv
= ReadTransaction(trans2
.get(), &out
.response_data
);
1011 EXPECT_EQ(OK
, out
.rv
);
1012 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1013 EXPECT_EQ("hello!hello!", out
.response_data
);
1015 const HttpResponseInfo
* response3
= trans3
->GetResponseInfo();
1016 out
.status_line
= response3
->headers
->GetStatusLine();
1017 out
.response_info
= *response3
;
1018 out
.rv
= ReadTransaction(trans3
.get(), &out
.response_data
);
1019 EXPECT_EQ(OK
, out
.rv
);
1020 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1021 EXPECT_EQ("hello!hello!", out
.response_data
);
1023 helper
.VerifyDataConsumed();
1025 EXPECT_EQ(OK
, out
.rv
);
1028 // Similar to ThreeGetsWithMaxConcurrent above, however this test adds
1029 // a fourth transaction. The third and fourth transactions have
1030 // different data ("hello!" vs "hello!hello!") and because of the
1031 // user specified priority, we expect to see them inverted in
1032 // the response from the server.
1033 TEST_P(SpdyNetworkTransactionTest
, FourGetsWithMaxConcurrentPriority
) {
1034 // Construct the request.
1035 scoped_ptr
<spdy::SpdyFrame
> req(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
1036 scoped_ptr
<spdy::SpdyFrame
> resp(ConstructSpdyGetSynReply(NULL
, 0, 1));
1037 scoped_ptr
<spdy::SpdyFrame
> body(ConstructSpdyBodyFrame(1, false));
1038 scoped_ptr
<spdy::SpdyFrame
> fbody(ConstructSpdyBodyFrame(1, true));
1040 scoped_ptr
<spdy::SpdyFrame
> req2(ConstructSpdyGet(NULL
, 0, false, 3, LOWEST
));
1041 scoped_ptr
<spdy::SpdyFrame
> resp2(ConstructSpdyGetSynReply(NULL
, 0, 3));
1042 scoped_ptr
<spdy::SpdyFrame
> body2(ConstructSpdyBodyFrame(3, false));
1043 scoped_ptr
<spdy::SpdyFrame
> fbody2(ConstructSpdyBodyFrame(3, true));
1045 scoped_ptr
<spdy::SpdyFrame
> req4(
1046 ConstructSpdyGet(NULL
, 0, false, 5, HIGHEST
));
1047 scoped_ptr
<spdy::SpdyFrame
> resp4(ConstructSpdyGetSynReply(NULL
, 0, 5));
1048 scoped_ptr
<spdy::SpdyFrame
> fbody4(ConstructSpdyBodyFrame(5, true));
1050 scoped_ptr
<spdy::SpdyFrame
> req3(ConstructSpdyGet(NULL
, 0, false, 7, LOWEST
));
1051 scoped_ptr
<spdy::SpdyFrame
> resp3(ConstructSpdyGetSynReply(NULL
, 0, 7));
1052 scoped_ptr
<spdy::SpdyFrame
> body3(ConstructSpdyBodyFrame(7, false));
1053 scoped_ptr
<spdy::SpdyFrame
> fbody3(ConstructSpdyBodyFrame(7, true));
1056 spdy::SpdySettings settings
;
1057 spdy::SettingsFlagsAndId
id(0);
1058 id
.set_id(spdy::SETTINGS_MAX_CONCURRENT_STREAMS
);
1059 const size_t max_concurrent_streams
= 1;
1061 settings
.push_back(spdy::SpdySetting(id
, max_concurrent_streams
));
1062 scoped_ptr
<spdy::SpdyFrame
> settings_frame(ConstructSpdySettings(settings
));
1064 MockWrite writes
[] = { CreateMockWrite(*req
),
1065 CreateMockWrite(*req2
),
1066 CreateMockWrite(*req4
),
1067 CreateMockWrite(*req3
),
1069 MockRead reads
[] = {
1070 CreateMockRead(*settings_frame
, 1),
1071 CreateMockRead(*resp
),
1072 CreateMockRead(*body
),
1073 CreateMockRead(*fbody
),
1074 CreateMockRead(*resp2
, 7),
1075 CreateMockRead(*body2
),
1076 CreateMockRead(*fbody2
),
1077 CreateMockRead(*resp4
, 13),
1078 CreateMockRead(*fbody4
),
1079 CreateMockRead(*resp3
, 16),
1080 CreateMockRead(*body3
),
1081 CreateMockRead(*fbody3
),
1083 MockRead(true, 0, 0), // EOF
1086 scoped_refptr
<OrderedSocketData
> data(
1087 new OrderedSocketData(reads
, arraysize(reads
),
1088 writes
, arraysize(writes
)));
1089 scoped_refptr
<OrderedSocketData
> data_placeholder(
1090 new OrderedSocketData(NULL
, 0, NULL
, 0));
1093 TransactionHelperResult out
;
1094 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
1095 BoundNetLog(), GetParam());
1096 helper
.RunPreTestSetup();
1097 helper
.AddData(data
.get());
1098 // We require placeholder data because four get requests are sent out, so
1099 // there needs to be four sets of SSL connection data.
1100 helper
.AddData(data_placeholder
.get());
1101 helper
.AddData(data_placeholder
.get());
1102 helper
.AddData(data_placeholder
.get());
1103 scoped_ptr
<HttpNetworkTransaction
> trans1(
1104 new HttpNetworkTransaction(helper
.session()));
1105 scoped_ptr
<HttpNetworkTransaction
> trans2(
1106 new HttpNetworkTransaction(helper
.session()));
1107 scoped_ptr
<HttpNetworkTransaction
> trans3(
1108 new HttpNetworkTransaction(helper
.session()));
1109 scoped_ptr
<HttpNetworkTransaction
> trans4(
1110 new HttpNetworkTransaction(helper
.session()));
1112 TestCompletionCallback callback1
;
1113 TestCompletionCallback callback2
;
1114 TestCompletionCallback callback3
;
1115 TestCompletionCallback callback4
;
1117 HttpRequestInfo httpreq1
= CreateGetRequest();
1118 HttpRequestInfo httpreq2
= CreateGetRequest();
1119 HttpRequestInfo httpreq3
= CreateGetRequest();
1120 HttpRequestInfo httpreq4
= CreateGetRequest();
1121 httpreq4
.priority
= HIGHEST
;
1123 out
.rv
= trans1
->Start(&httpreq1
, &callback1
, log
);
1124 ASSERT_EQ(ERR_IO_PENDING
, out
.rv
);
1125 // run transaction 1 through quickly to force a read of our SETTINGS
1127 out
.rv
= callback1
.WaitForResult();
1128 ASSERT_EQ(OK
, out
.rv
);
1130 out
.rv
= trans2
->Start(&httpreq2
, &callback2
, log
);
1131 ASSERT_EQ(ERR_IO_PENDING
, out
.rv
);
1132 out
.rv
= trans3
->Start(&httpreq3
, &callback3
, log
);
1133 ASSERT_EQ(ERR_IO_PENDING
, out
.rv
);
1134 out
.rv
= trans4
->Start(&httpreq4
, &callback4
, log
);
1135 ASSERT_EQ(ERR_IO_PENDING
, out
.rv
);
1137 out
.rv
= callback2
.WaitForResult();
1138 ASSERT_EQ(OK
, out
.rv
);
1139 EXPECT_EQ(data
->read_index(), 7U); // i.e. the third & fourth trans queued
1141 out
.rv
= callback3
.WaitForResult();
1142 ASSERT_EQ(OK
, out
.rv
);
1144 const HttpResponseInfo
* response1
= trans1
->GetResponseInfo();
1145 EXPECT_TRUE(response1
->headers
!= NULL
);
1146 EXPECT_TRUE(response1
->was_fetched_via_spdy
);
1147 out
.status_line
= response1
->headers
->GetStatusLine();
1148 out
.response_info
= *response1
;
1149 out
.rv
= ReadTransaction(trans1
.get(), &out
.response_data
);
1150 EXPECT_EQ(OK
, out
.rv
);
1151 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1152 EXPECT_EQ("hello!hello!", out
.response_data
);
1154 const HttpResponseInfo
* response2
= trans2
->GetResponseInfo();
1155 out
.status_line
= response2
->headers
->GetStatusLine();
1156 out
.response_info
= *response2
;
1157 out
.rv
= ReadTransaction(trans2
.get(), &out
.response_data
);
1158 EXPECT_EQ(OK
, out
.rv
);
1159 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1160 EXPECT_EQ("hello!hello!", out
.response_data
);
1162 // notice: response3 gets two hellos, response4 gets one
1163 // hello, so we know dequeuing priority was respected.
1164 const HttpResponseInfo
* response3
= trans3
->GetResponseInfo();
1165 out
.status_line
= response3
->headers
->GetStatusLine();
1166 out
.response_info
= *response3
;
1167 out
.rv
= ReadTransaction(trans3
.get(), &out
.response_data
);
1168 EXPECT_EQ(OK
, out
.rv
);
1169 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1170 EXPECT_EQ("hello!hello!", out
.response_data
);
1172 out
.rv
= callback4
.WaitForResult();
1173 EXPECT_EQ(OK
, out
.rv
);
1174 const HttpResponseInfo
* response4
= trans4
->GetResponseInfo();
1175 out
.status_line
= response4
->headers
->GetStatusLine();
1176 out
.response_info
= *response4
;
1177 out
.rv
= ReadTransaction(trans4
.get(), &out
.response_data
);
1178 EXPECT_EQ(OK
, out
.rv
);
1179 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1180 EXPECT_EQ("hello!", out
.response_data
);
1181 helper
.VerifyDataConsumed();
1182 EXPECT_EQ(OK
, out
.rv
);
1185 // Similar to ThreeGetsMaxConcurrrent above, however, this test
1186 // deletes a session in the middle of the transaction to insure
1187 // that we properly remove pendingcreatestream objects from
1189 TEST_P(SpdyNetworkTransactionTest
, ThreeGetsWithMaxConcurrentDelete
) {
1190 // Construct the request.
1191 scoped_ptr
<spdy::SpdyFrame
> req(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
1192 scoped_ptr
<spdy::SpdyFrame
> resp(ConstructSpdyGetSynReply(NULL
, 0, 1));
1193 scoped_ptr
<spdy::SpdyFrame
> body(ConstructSpdyBodyFrame(1, false));
1194 scoped_ptr
<spdy::SpdyFrame
> fbody(ConstructSpdyBodyFrame(1, true));
1196 scoped_ptr
<spdy::SpdyFrame
> req2(ConstructSpdyGet(NULL
, 0, false, 3, LOWEST
));
1197 scoped_ptr
<spdy::SpdyFrame
> resp2(ConstructSpdyGetSynReply(NULL
, 0, 3));
1198 scoped_ptr
<spdy::SpdyFrame
> body2(ConstructSpdyBodyFrame(3, false));
1199 scoped_ptr
<spdy::SpdyFrame
> fbody2(ConstructSpdyBodyFrame(3, true));
1201 spdy::SpdySettings settings
;
1202 spdy::SettingsFlagsAndId
id(0);
1203 id
.set_id(spdy::SETTINGS_MAX_CONCURRENT_STREAMS
);
1204 const size_t max_concurrent_streams
= 1;
1206 settings
.push_back(spdy::SpdySetting(id
, max_concurrent_streams
));
1207 scoped_ptr
<spdy::SpdyFrame
> settings_frame(ConstructSpdySettings(settings
));
1209 MockWrite writes
[] = { CreateMockWrite(*req
),
1210 CreateMockWrite(*req2
),
1212 MockRead reads
[] = {
1213 CreateMockRead(*settings_frame
, 1),
1214 CreateMockRead(*resp
),
1215 CreateMockRead(*body
),
1216 CreateMockRead(*fbody
),
1217 CreateMockRead(*resp2
, 7),
1218 CreateMockRead(*body2
),
1219 CreateMockRead(*fbody2
),
1220 MockRead(true, 0, 0), // EOF
1223 scoped_refptr
<OrderedSocketData
> data(
1224 new OrderedSocketData(reads
, arraysize(reads
),
1225 writes
, arraysize(writes
)));
1226 scoped_refptr
<OrderedSocketData
> data_placeholder(
1227 new OrderedSocketData(NULL
, 0, NULL
, 0));
1230 TransactionHelperResult out
;
1231 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
1232 BoundNetLog(), GetParam());
1233 helper
.RunPreTestSetup();
1234 helper
.AddData(data
.get());
1235 // We require placeholder data because three get requests are sent out, so
1236 // there needs to be three sets of SSL connection data.
1237 helper
.AddData(data_placeholder
.get());
1238 helper
.AddData(data_placeholder
.get());
1239 scoped_ptr
<HttpNetworkTransaction
> trans1(
1240 new HttpNetworkTransaction(helper
.session()));
1241 scoped_ptr
<HttpNetworkTransaction
> trans2(
1242 new HttpNetworkTransaction(helper
.session()));
1243 scoped_ptr
<HttpNetworkTransaction
> trans3(
1244 new HttpNetworkTransaction(helper
.session()));
1246 TestCompletionCallback callback1
;
1247 TestCompletionCallback callback2
;
1248 TestCompletionCallback callback3
;
1250 HttpRequestInfo httpreq1
= CreateGetRequest();
1251 HttpRequestInfo httpreq2
= CreateGetRequest();
1252 HttpRequestInfo httpreq3
= CreateGetRequest();
1254 out
.rv
= trans1
->Start(&httpreq1
, &callback1
, log
);
1255 ASSERT_EQ(out
.rv
, ERR_IO_PENDING
);
1256 // run transaction 1 through quickly to force a read of our SETTINGS
1258 out
.rv
= callback1
.WaitForResult();
1259 ASSERT_EQ(OK
, out
.rv
);
1261 out
.rv
= trans2
->Start(&httpreq2
, &callback2
, log
);
1262 ASSERT_EQ(out
.rv
, ERR_IO_PENDING
);
1263 out
.rv
= trans3
->Start(&httpreq3
, &callback3
, log
);
1264 delete trans3
.release();
1265 ASSERT_EQ(out
.rv
, ERR_IO_PENDING
);
1266 out
.rv
= callback2
.WaitForResult();
1267 ASSERT_EQ(OK
, out
.rv
);
1269 EXPECT_EQ(8U, data
->read_index());
1271 const HttpResponseInfo
* response1
= trans1
->GetResponseInfo();
1272 ASSERT_TRUE(response1
!= NULL
);
1273 EXPECT_TRUE(response1
->headers
!= NULL
);
1274 EXPECT_TRUE(response1
->was_fetched_via_spdy
);
1275 out
.status_line
= response1
->headers
->GetStatusLine();
1276 out
.response_info
= *response1
;
1277 out
.rv
= ReadTransaction(trans1
.get(), &out
.response_data
);
1278 EXPECT_EQ(OK
, out
.rv
);
1279 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1280 EXPECT_EQ("hello!hello!", out
.response_data
);
1282 const HttpResponseInfo
* response2
= trans2
->GetResponseInfo();
1283 ASSERT_TRUE(response2
!= NULL
);
1284 out
.status_line
= response2
->headers
->GetStatusLine();
1285 out
.response_info
= *response2
;
1286 out
.rv
= ReadTransaction(trans2
.get(), &out
.response_data
);
1287 EXPECT_EQ(OK
, out
.rv
);
1288 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1289 EXPECT_EQ("hello!hello!", out
.response_data
);
1290 helper
.VerifyDataConsumed();
1291 EXPECT_EQ(OK
, out
.rv
);
1294 // The KillerCallback will delete the transaction on error as part of the
1296 class KillerCallback
: public TestCompletionCallback
{
1298 explicit KillerCallback(HttpNetworkTransaction
* transaction
)
1299 : transaction_(transaction
) {}
1301 virtual void RunWithParams(const Tuple1
<int>& params
) {
1303 delete transaction_
;
1304 TestCompletionCallback::RunWithParams(params
);
1308 HttpNetworkTransaction
* transaction_
;
1311 // Similar to ThreeGetsMaxConcurrrentDelete above, however, this test
1312 // closes the socket while we have a pending transaction waiting for
1313 // a pending stream creation. http://crbug.com/52901
1314 TEST_P(SpdyNetworkTransactionTest
, ThreeGetsWithMaxConcurrentSocketClose
) {
1315 // Construct the request.
1316 scoped_ptr
<spdy::SpdyFrame
> req(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
1317 scoped_ptr
<spdy::SpdyFrame
> resp(ConstructSpdyGetSynReply(NULL
, 0, 1));
1318 scoped_ptr
<spdy::SpdyFrame
> body(ConstructSpdyBodyFrame(1, false));
1319 scoped_ptr
<spdy::SpdyFrame
> fin_body(ConstructSpdyBodyFrame(1, true));
1321 scoped_ptr
<spdy::SpdyFrame
> req2(ConstructSpdyGet(NULL
, 0, false, 3, LOWEST
));
1322 scoped_ptr
<spdy::SpdyFrame
> resp2(ConstructSpdyGetSynReply(NULL
, 0, 3));
1324 spdy::SpdySettings settings
;
1325 spdy::SettingsFlagsAndId
id(0);
1326 id
.set_id(spdy::SETTINGS_MAX_CONCURRENT_STREAMS
);
1327 const size_t max_concurrent_streams
= 1;
1329 settings
.push_back(spdy::SpdySetting(id
, max_concurrent_streams
));
1330 scoped_ptr
<spdy::SpdyFrame
> settings_frame(ConstructSpdySettings(settings
));
1332 MockWrite writes
[] = { CreateMockWrite(*req
),
1333 CreateMockWrite(*req2
),
1335 MockRead reads
[] = {
1336 CreateMockRead(*settings_frame
, 1),
1337 CreateMockRead(*resp
),
1338 CreateMockRead(*body
),
1339 CreateMockRead(*fin_body
),
1340 CreateMockRead(*resp2
, 7),
1341 MockRead(true, ERR_CONNECTION_RESET
, 0), // Abort!
1344 scoped_refptr
<OrderedSocketData
> data(
1345 new OrderedSocketData(reads
, arraysize(reads
),
1346 writes
, arraysize(writes
)));
1347 scoped_refptr
<OrderedSocketData
> data_placeholder(
1348 new OrderedSocketData(NULL
, 0, NULL
, 0));
1351 TransactionHelperResult out
;
1352 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
1353 BoundNetLog(), GetParam());
1354 helper
.RunPreTestSetup();
1355 helper
.AddData(data
.get());
1356 // We require placeholder data because three get requests are sent out, so
1357 // there needs to be three sets of SSL connection data.
1358 helper
.AddData(data_placeholder
.get());
1359 helper
.AddData(data_placeholder
.get());
1360 HttpNetworkTransaction
trans1(helper
.session());
1361 HttpNetworkTransaction
trans2(helper
.session());
1362 HttpNetworkTransaction
* trans3(new HttpNetworkTransaction(helper
.session()));
1364 TestCompletionCallback callback1
;
1365 TestCompletionCallback callback2
;
1366 KillerCallback
callback3(trans3
);
1368 HttpRequestInfo httpreq1
= CreateGetRequest();
1369 HttpRequestInfo httpreq2
= CreateGetRequest();
1370 HttpRequestInfo httpreq3
= CreateGetRequest();
1372 out
.rv
= trans1
.Start(&httpreq1
, &callback1
, log
);
1373 ASSERT_EQ(out
.rv
, ERR_IO_PENDING
);
1374 // run transaction 1 through quickly to force a read of our SETTINGS
1376 out
.rv
= callback1
.WaitForResult();
1377 ASSERT_EQ(OK
, out
.rv
);
1379 out
.rv
= trans2
.Start(&httpreq2
, &callback2
, log
);
1380 ASSERT_EQ(out
.rv
, ERR_IO_PENDING
);
1381 out
.rv
= trans3
->Start(&httpreq3
, &callback3
, log
);
1382 ASSERT_EQ(out
.rv
, ERR_IO_PENDING
);
1383 out
.rv
= callback3
.WaitForResult();
1384 ASSERT_EQ(ERR_ABORTED
, out
.rv
);
1386 EXPECT_EQ(6U, data
->read_index());
1388 const HttpResponseInfo
* response1
= trans1
.GetResponseInfo();
1389 ASSERT_TRUE(response1
!= NULL
);
1390 EXPECT_TRUE(response1
->headers
!= NULL
);
1391 EXPECT_TRUE(response1
->was_fetched_via_spdy
);
1392 out
.status_line
= response1
->headers
->GetStatusLine();
1393 out
.response_info
= *response1
;
1394 out
.rv
= ReadTransaction(&trans1
, &out
.response_data
);
1395 EXPECT_EQ(OK
, out
.rv
);
1397 const HttpResponseInfo
* response2
= trans2
.GetResponseInfo();
1398 ASSERT_TRUE(response2
!= NULL
);
1399 out
.status_line
= response2
->headers
->GetStatusLine();
1400 out
.response_info
= *response2
;
1401 out
.rv
= ReadTransaction(&trans2
, &out
.response_data
);
1402 EXPECT_EQ(ERR_CONNECTION_RESET
, out
.rv
);
1404 helper
.VerifyDataConsumed();
1407 // Test that a simple PUT request works.
1408 TEST_P(SpdyNetworkTransactionTest
, Put
) {
1409 // Setup the request
1410 HttpRequestInfo request
;
1411 request
.method
= "PUT";
1412 request
.url
= GURL("http://www.google.com/");
1414 const SpdyHeaderInfo kSynStartHeader
= {
1415 spdy::SYN_STREAM
, // Kind = Syn
1417 0, // Associated stream ID
1418 net::ConvertRequestPriorityToSpdyPriority(LOWEST
), // Priority
1419 spdy::CONTROL_FLAG_FIN
, // Control Flags
1420 false, // Compressed
1421 spdy::INVALID
, // Status
1424 spdy::DATA_FLAG_NONE
// Data Flags
1426 const char* const kPutHeaders
[] = {
1429 "host", "www.google.com",
1431 "version", "HTTP/1.1",
1432 "content-length", "0"
1434 scoped_ptr
<spdy::SpdyFrame
> req(ConstructSpdyPacket(kSynStartHeader
, NULL
, 0,
1435 kPutHeaders
, arraysize(kPutHeaders
) / 2));
1436 MockWrite writes
[] = {
1437 CreateMockWrite(*req
)
1440 scoped_ptr
<spdy::SpdyFrame
> body(ConstructSpdyBodyFrame(1, true));
1441 const SpdyHeaderInfo kSynReplyHeader
= {
1442 spdy::SYN_REPLY
, // Kind = SynReply
1444 0, // Associated stream ID
1445 net::ConvertRequestPriorityToSpdyPriority(LOWEST
), // Priority
1446 spdy::CONTROL_FLAG_NONE
, // Control Flags
1447 false, // Compressed
1448 spdy::INVALID
, // Status
1451 spdy::DATA_FLAG_NONE
// Data Flags
1453 static const char* const kStandardGetHeaders
[] = {
1455 "version", "HTTP/1.1"
1456 "content-length", "1234"
1458 scoped_ptr
<spdy::SpdyFrame
> resp(ConstructSpdyPacket(kSynReplyHeader
,
1459 NULL
, 0, kStandardGetHeaders
, arraysize(kStandardGetHeaders
) / 2));
1460 MockRead reads
[] = {
1461 CreateMockRead(*resp
),
1462 CreateMockRead(*body
),
1463 MockRead(true, 0, 0) // EOF
1466 scoped_refptr
<DelayedSocketData
> data(
1467 new DelayedSocketData(1, reads
, arraysize(reads
),
1468 writes
, arraysize(writes
)));
1469 NormalSpdyTransactionHelper
helper(request
,
1470 BoundNetLog(), GetParam());
1471 helper
.RunToCompletion(data
.get());
1472 TransactionHelperResult out
= helper
.output();
1474 EXPECT_EQ(OK
, out
.rv
);
1475 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1478 // Test that a simple HEAD request works.
1479 TEST_P(SpdyNetworkTransactionTest
, Head
) {
1480 // Setup the request
1481 HttpRequestInfo request
;
1482 request
.method
= "HEAD";
1483 request
.url
= GURL("http://www.google.com/");
1485 const SpdyHeaderInfo kSynStartHeader
= {
1486 spdy::SYN_STREAM
, // Kind = Syn
1488 0, // Associated stream ID
1489 net::ConvertRequestPriorityToSpdyPriority(LOWEST
), // Priority
1490 spdy::CONTROL_FLAG_FIN
, // Control Flags
1491 false, // Compressed
1492 spdy::INVALID
, // Status
1495 spdy::DATA_FLAG_NONE
// Data Flags
1497 const char* const kHeadHeaders
[] = {
1500 "host", "www.google.com",
1502 "version", "HTTP/1.1",
1503 "content-length", "0"
1505 scoped_ptr
<spdy::SpdyFrame
> req(ConstructSpdyPacket(kSynStartHeader
, NULL
, 0,
1506 kHeadHeaders
, arraysize(kHeadHeaders
) / 2));
1507 MockWrite writes
[] = {
1508 CreateMockWrite(*req
)
1511 scoped_ptr
<spdy::SpdyFrame
> body(ConstructSpdyBodyFrame(1, true));
1512 const SpdyHeaderInfo kSynReplyHeader
= {
1513 spdy::SYN_REPLY
, // Kind = SynReply
1515 0, // Associated stream ID
1516 net::ConvertRequestPriorityToSpdyPriority(LOWEST
), // Priority
1517 spdy::CONTROL_FLAG_NONE
, // Control Flags
1518 false, // Compressed
1519 spdy::INVALID
, // Status
1522 spdy::DATA_FLAG_NONE
// Data Flags
1524 static const char* const kStandardGetHeaders
[] = {
1526 "version", "HTTP/1.1"
1527 "content-length", "1234"
1529 scoped_ptr
<spdy::SpdyFrame
> resp(ConstructSpdyPacket(kSynReplyHeader
,
1530 NULL
, 0, kStandardGetHeaders
, arraysize(kStandardGetHeaders
) / 2));
1531 MockRead reads
[] = {
1532 CreateMockRead(*resp
),
1533 CreateMockRead(*body
),
1534 MockRead(true, 0, 0) // EOF
1537 scoped_refptr
<DelayedSocketData
> data(
1538 new DelayedSocketData(1, reads
, arraysize(reads
),
1539 writes
, arraysize(writes
)));
1540 NormalSpdyTransactionHelper
helper(request
,
1541 BoundNetLog(), GetParam());
1542 helper
.RunToCompletion(data
.get());
1543 TransactionHelperResult out
= helper
.output();
1545 EXPECT_EQ(OK
, out
.rv
);
1546 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1549 // Test that a simple POST works.
1550 TEST_P(SpdyNetworkTransactionTest
, Post
) {
1551 scoped_ptr
<spdy::SpdyFrame
> req(ConstructSpdyPost(kUploadDataSize
, NULL
, 0));
1552 scoped_ptr
<spdy::SpdyFrame
> body(ConstructSpdyBodyFrame(1, true));
1553 MockWrite writes
[] = {
1554 CreateMockWrite(*req
),
1555 CreateMockWrite(*body
), // POST upload frame
1558 scoped_ptr
<spdy::SpdyFrame
> resp(ConstructSpdyPostSynReply(NULL
, 0));
1559 MockRead reads
[] = {
1560 CreateMockRead(*resp
),
1561 CreateMockRead(*body
),
1562 MockRead(true, 0, 0) // EOF
1565 scoped_refptr
<DelayedSocketData
> data(
1566 new DelayedSocketData(2, reads
, arraysize(reads
),
1567 writes
, arraysize(writes
)));
1568 NormalSpdyTransactionHelper
helper(CreatePostRequest(),
1569 BoundNetLog(), GetParam());
1570 helper
.RunToCompletion(data
.get());
1571 TransactionHelperResult out
= helper
.output();
1572 EXPECT_EQ(OK
, out
.rv
);
1573 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1574 EXPECT_EQ("hello!", out
.response_data
);
1577 // Test that a chunked POST works.
1578 TEST_P(SpdyNetworkTransactionTest
, ChunkedPost
) {
1579 UploadDataStream::set_merge_chunks(false);
1580 scoped_ptr
<spdy::SpdyFrame
> req(ConstructChunkedSpdyPost(NULL
, 0));
1581 scoped_ptr
<spdy::SpdyFrame
> chunk1(ConstructSpdyBodyFrame(1, false));
1582 scoped_ptr
<spdy::SpdyFrame
> chunk2(ConstructSpdyBodyFrame(1, true));
1583 MockWrite writes
[] = {
1584 CreateMockWrite(*req
),
1585 CreateMockWrite(*chunk1
),
1586 CreateMockWrite(*chunk2
),
1589 scoped_ptr
<spdy::SpdyFrame
> resp(ConstructSpdyPostSynReply(NULL
, 0));
1590 MockRead reads
[] = {
1591 CreateMockRead(*resp
),
1592 CreateMockRead(*chunk1
),
1593 CreateMockRead(*chunk2
),
1594 MockRead(true, 0, 0) // EOF
1597 scoped_refptr
<DelayedSocketData
> data(
1598 new DelayedSocketData(2, reads
, arraysize(reads
),
1599 writes
, arraysize(writes
)));
1600 NormalSpdyTransactionHelper
helper(CreateChunkedPostRequest(),
1601 BoundNetLog(), GetParam());
1602 helper
.RunToCompletion(data
.get());
1603 TransactionHelperResult out
= helper
.output();
1604 EXPECT_EQ(OK
, out
.rv
);
1605 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1606 EXPECT_EQ("hello!hello!", out
.response_data
);
1609 // Test that a POST without any post data works.
1610 TEST_P(SpdyNetworkTransactionTest
, NullPost
) {
1611 // Setup the request
1612 HttpRequestInfo request
;
1613 request
.method
= "POST";
1614 request
.url
= GURL("http://www.google.com/");
1615 // Create an empty UploadData.
1616 request
.upload_data
= NULL
;
1618 // When request.upload_data is NULL for post, content-length is
1619 // expected to be 0.
1620 scoped_ptr
<spdy::SpdyFrame
> req(ConstructSpdyPost(0, NULL
, 0));
1621 // Set the FIN bit since there will be no body.
1622 req
->set_flags(spdy::CONTROL_FLAG_FIN
);
1623 MockWrite writes
[] = {
1624 CreateMockWrite(*req
),
1627 scoped_ptr
<spdy::SpdyFrame
> resp(ConstructSpdyPostSynReply(NULL
, 0));
1628 scoped_ptr
<spdy::SpdyFrame
> body(ConstructSpdyBodyFrame(1, true));
1629 MockRead reads
[] = {
1630 CreateMockRead(*resp
),
1631 CreateMockRead(*body
),
1632 MockRead(true, 0, 0) // EOF
1635 scoped_refptr
<DelayedSocketData
> data(
1636 new DelayedSocketData(1, reads
, arraysize(reads
),
1637 writes
, arraysize(writes
)));
1639 NormalSpdyTransactionHelper
helper(request
,
1640 BoundNetLog(), GetParam());
1641 helper
.RunToCompletion(data
.get());
1642 TransactionHelperResult out
= helper
.output();
1643 EXPECT_EQ(OK
, out
.rv
);
1644 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1645 EXPECT_EQ("hello!", out
.response_data
);
1648 // Test that a simple POST works.
1649 TEST_P(SpdyNetworkTransactionTest
, EmptyPost
) {
1650 // Setup the request
1651 HttpRequestInfo request
;
1652 request
.method
= "POST";
1653 request
.url
= GURL("http://www.google.com/");
1654 // Create an empty UploadData.
1655 request
.upload_data
= new UploadData();
1657 // Http POST Content-Length is using UploadDataStream::size().
1658 // It is the same as request.upload_data->GetContentLength().
1659 scoped_ptr
<UploadDataStream
> stream(UploadDataStream::Create(
1660 request
.upload_data
, NULL
));
1661 ASSERT_EQ(request
.upload_data
->GetContentLength(), stream
->size());
1663 scoped_ptr
<spdy::SpdyFrame
>
1664 req(ConstructSpdyPost(request
.upload_data
->GetContentLength(), NULL
, 0));
1665 // Set the FIN bit since there will be no body.
1666 req
->set_flags(spdy::CONTROL_FLAG_FIN
);
1667 MockWrite writes
[] = {
1668 CreateMockWrite(*req
),
1671 scoped_ptr
<spdy::SpdyFrame
> resp(ConstructSpdyPostSynReply(NULL
, 0));
1672 scoped_ptr
<spdy::SpdyFrame
> body(ConstructSpdyBodyFrame(1, true));
1673 MockRead reads
[] = {
1674 CreateMockRead(*resp
),
1675 CreateMockRead(*body
),
1676 MockRead(true, 0, 0) // EOF
1679 scoped_refptr
<DelayedSocketData
> data(
1680 new DelayedSocketData(1, reads
, arraysize(reads
),
1681 writes
, arraysize(writes
)));
1683 NormalSpdyTransactionHelper
helper(request
,
1684 BoundNetLog(), GetParam());
1685 helper
.RunToCompletion(data
.get());
1686 TransactionHelperResult out
= helper
.output();
1687 EXPECT_EQ(OK
, out
.rv
);
1688 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1689 EXPECT_EQ("hello!", out
.response_data
);
1692 // While we're doing a post, the server sends back a SYN_REPLY.
1693 TEST_P(SpdyNetworkTransactionTest
, PostWithEarlySynReply
) {
1694 static const char upload
[] = { "hello!" };
1696 // Setup the request
1697 HttpRequestInfo request
;
1698 request
.method
= "POST";
1699 request
.url
= GURL("http://www.google.com/");
1700 request
.upload_data
= new UploadData();
1701 request
.upload_data
->AppendBytes(upload
, sizeof(upload
));
1703 // Http POST Content-Length is using UploadDataStream::size().
1704 // It is the same as request.upload_data->GetContentLength().
1705 scoped_ptr
<UploadDataStream
> stream(UploadDataStream::Create(
1706 request
.upload_data
, NULL
));
1707 ASSERT_EQ(request
.upload_data
->GetContentLength(), stream
->size());
1708 scoped_ptr
<spdy::SpdyFrame
> stream_reply(ConstructSpdyPostSynReply(NULL
, 0));
1709 scoped_ptr
<spdy::SpdyFrame
> stream_body(ConstructSpdyBodyFrame(1, true));
1710 MockRead reads
[] = {
1711 CreateMockRead(*stream_reply
, 2),
1712 CreateMockRead(*stream_body
, 3),
1713 MockRead(false, 0, 0) // EOF
1716 scoped_refptr
<DelayedSocketData
> data(
1717 new DelayedSocketData(0, reads
, arraysize(reads
), NULL
, 0));
1718 NormalSpdyTransactionHelper
helper(request
,
1719 BoundNetLog(), GetParam());
1720 helper
.RunPreTestSetup();
1721 helper
.AddData(data
.get());
1722 helper
.RunDefaultTest();
1723 helper
.VerifyDataConsumed();
1725 TransactionHelperResult out
= helper
.output();
1726 EXPECT_EQ(ERR_SYN_REPLY_NOT_RECEIVED
, out
.rv
);
1729 // The client upon cancellation tries to send a RST_STREAM frame. The mock
1730 // socket causes the TCP write to return zero. This test checks that the client
1731 // tries to queue up the RST_STREAM frame again.
1732 TEST_P(SpdyNetworkTransactionTest
, SocketWriteReturnsZero
) {
1733 scoped_ptr
<spdy::SpdyFrame
> req(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
1734 scoped_ptr
<spdy::SpdyFrame
> rst(
1735 ConstructSpdyRstStream(1, spdy::CANCEL
));
1736 MockWrite writes
[] = {
1737 CreateMockWrite(*req
.get(), 0, false),
1738 MockWrite(false, 0, 0, 2),
1739 CreateMockWrite(*rst
.get(), 3, false),
1742 scoped_ptr
<spdy::SpdyFrame
> resp(ConstructSpdyGetSynReply(NULL
, 0, 1));
1743 MockRead reads
[] = {
1744 CreateMockRead(*resp
.get(), 1, true),
1745 MockRead(true, 0, 0, 4) // EOF
1748 scoped_refptr
<DeterministicSocketData
> data(
1749 new DeterministicSocketData(reads
, arraysize(reads
),
1750 writes
, arraysize(writes
)));
1751 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
1752 BoundNetLog(), GetParam());
1753 helper
.SetDeterministic();
1754 helper
.RunPreTestSetup();
1755 helper
.AddDeterministicData(data
.get());
1756 HttpNetworkTransaction
* trans
= helper
.trans();
1758 TestCompletionCallback callback
;
1759 int rv
= trans
->Start(&CreateGetRequest(), &callback
, BoundNetLog());
1760 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1764 helper
.ResetTrans();
1768 helper
.VerifyDataConsumed();
1771 // Test that the transaction doesn't crash when we don't have a reply.
1772 TEST_P(SpdyNetworkTransactionTest
, ResponseWithoutSynReply
) {
1773 scoped_ptr
<spdy::SpdyFrame
> body(ConstructSpdyBodyFrame(1, true));
1774 MockRead reads
[] = {
1775 CreateMockRead(*body
),
1776 MockRead(true, 0, 0) // EOF
1779 scoped_refptr
<DelayedSocketData
> data(
1780 new DelayedSocketData(1, reads
, arraysize(reads
), NULL
, 0));
1781 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
1782 BoundNetLog(), GetParam());
1783 helper
.RunToCompletion(data
.get());
1784 TransactionHelperResult out
= helper
.output();
1785 EXPECT_EQ(ERR_SYN_REPLY_NOT_RECEIVED
, out
.rv
);
1788 // Test that the transaction doesn't crash when we get two replies on the same
1789 // stream ID. See http://crbug.com/45639.
1790 TEST_P(SpdyNetworkTransactionTest
, ResponseWithTwoSynReplies
) {
1791 scoped_ptr
<spdy::SpdyFrame
> req(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
1792 MockWrite writes
[] = { CreateMockWrite(*req
) };
1794 scoped_ptr
<spdy::SpdyFrame
> resp(ConstructSpdyGetSynReply(NULL
, 0, 1));
1795 scoped_ptr
<spdy::SpdyFrame
> body(ConstructSpdyBodyFrame(1, true));
1796 MockRead reads
[] = {
1797 CreateMockRead(*resp
),
1798 CreateMockRead(*resp
),
1799 CreateMockRead(*body
),
1800 MockRead(true, 0, 0) // EOF
1803 scoped_refptr
<DelayedSocketData
> data(
1804 new DelayedSocketData(1, reads
, arraysize(reads
),
1805 writes
, arraysize(writes
)));
1807 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
1808 BoundNetLog(), GetParam());
1809 helper
.RunPreTestSetup();
1810 helper
.AddData(data
.get());
1812 HttpNetworkTransaction
* trans
= helper
.trans();
1814 TestCompletionCallback callback
;
1815 int rv
= trans
->Start(&helper
.request(), &callback
, BoundNetLog());
1816 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1817 rv
= callback
.WaitForResult();
1820 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1821 ASSERT_TRUE(response
!= NULL
);
1822 EXPECT_TRUE(response
->headers
!= NULL
);
1823 EXPECT_TRUE(response
->was_fetched_via_spdy
);
1824 std::string response_data
;
1825 rv
= ReadTransaction(trans
, &response_data
);
1826 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR
, rv
);
1828 helper
.VerifyDataConsumed();
1831 // Test that sent data frames and received WINDOW_UPDATE frames change
1832 // the send_window_size_ correctly.
1834 // WINDOW_UPDATE is different than most other frames in that it can arrive
1835 // while the client is still sending the request body. In order to enforce
1836 // this scenario, we feed a couple of dummy frames and give a delay of 0 to
1837 // socket data provider, so that initial read that is done as soon as the
1838 // stream is created, succeeds and schedules another read. This way reads
1839 // and writes are interleaved; after doing a full frame write, SpdyStream
1840 // will break out of DoLoop and will read and process a WINDOW_UPDATE.
1841 // Once our WINDOW_UPDATE is read, we cannot send SYN_REPLY right away
1842 // since request has not been completely written, therefore we feed
1843 // enough number of WINDOW_UPDATEs to finish the first read and cause a
1844 // write, leading to a complete write of request body; after that we send
1845 // a reply with a body, to cause a graceful shutdown.
1847 // TODO(agayev): develop a socket data provider where both, reads and
1848 // writes are ordered so that writing tests like these are easy and rewrite
1849 // all these tests using it. Right now we are working around the
1850 // limitations as described above and it's not deterministic, tests may
1851 // fail under specific circumstances.
1852 TEST_P(SpdyNetworkTransactionTest
, WindowUpdateReceived
) {
1853 SpdySession::set_flow_control(true);
1855 static int kFrameCount
= 2;
1856 scoped_ptr
<std::string
> content(
1857 new std::string(kMaxSpdyFrameChunkSize
, 'a'));
1858 scoped_ptr
<spdy::SpdyFrame
> req(ConstructSpdyPost(
1859 kMaxSpdyFrameChunkSize
* kFrameCount
, NULL
, 0));
1860 scoped_ptr
<spdy::SpdyFrame
> body(
1861 ConstructSpdyBodyFrame(1, content
->c_str(), content
->size(), false));
1862 scoped_ptr
<spdy::SpdyFrame
> body_end(
1863 ConstructSpdyBodyFrame(1, content
->c_str(), content
->size(), true));
1865 MockWrite writes
[] = {
1866 CreateMockWrite(*req
),
1867 CreateMockWrite(*body
),
1868 CreateMockWrite(*body_end
),
1871 static const int kDeltaWindowSize
= 0xff;
1872 static const int kDeltaCount
= 4;
1873 scoped_ptr
<spdy::SpdyFrame
> window_update(
1874 ConstructSpdyWindowUpdate(1, kDeltaWindowSize
));
1875 scoped_ptr
<spdy::SpdyFrame
> window_update_dummy(
1876 ConstructSpdyWindowUpdate(2, kDeltaWindowSize
));
1877 scoped_ptr
<spdy::SpdyFrame
> resp(ConstructSpdyPostSynReply(NULL
, 0));
1878 MockRead reads
[] = {
1879 CreateMockRead(*window_update_dummy
),
1880 CreateMockRead(*window_update_dummy
),
1881 CreateMockRead(*window_update_dummy
),
1882 CreateMockRead(*window_update
), // Four updates, therefore window
1883 CreateMockRead(*window_update
), // size should increase by
1884 CreateMockRead(*window_update
), // kDeltaWindowSize * 4
1885 CreateMockRead(*window_update
),
1886 CreateMockRead(*resp
),
1887 CreateMockRead(*body_end
),
1888 MockRead(true, 0, 0) // EOF
1891 scoped_refptr
<DelayedSocketData
> data(
1892 new DelayedSocketData(0, reads
, arraysize(reads
),
1893 writes
, arraysize(writes
)));
1895 // Setup the request
1896 HttpRequestInfo request
;
1897 request
.method
= "POST";
1898 request
.url
= GURL(kDefaultURL
);
1899 request
.upload_data
= new UploadData();
1900 for (int i
= 0; i
< kFrameCount
; ++i
)
1901 request
.upload_data
->AppendBytes(content
->c_str(), content
->size());
1903 NormalSpdyTransactionHelper
helper(request
, BoundNetLog(), GetParam());
1904 helper
.AddData(data
.get());
1905 helper
.RunPreTestSetup();
1907 HttpNetworkTransaction
* trans
= helper
.trans();
1909 TestCompletionCallback callback
;
1910 int rv
= trans
->Start(&helper
.request(), &callback
, BoundNetLog());
1912 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1913 rv
= callback
.WaitForResult();
1916 SpdyHttpStream
* stream
= static_cast<SpdyHttpStream
*>(trans
->stream_
.get());
1917 ASSERT_TRUE(stream
!= NULL
);
1918 ASSERT_TRUE(stream
->stream() != NULL
);
1919 EXPECT_EQ(static_cast<int>(spdy::kSpdyStreamInitialWindowSize
) +
1920 kDeltaWindowSize
* kDeltaCount
-
1921 kMaxSpdyFrameChunkSize
* kFrameCount
,
1922 stream
->stream()->send_window_size());
1923 helper
.VerifyDataConsumed();
1924 SpdySession::set_flow_control(false);
1927 // Test that received data frames and sent WINDOW_UPDATE frames change
1928 // the recv_window_size_ correctly.
1929 TEST_P(SpdyNetworkTransactionTest
, WindowUpdateSent
) {
1930 SpdySession::set_flow_control(true);
1932 scoped_ptr
<spdy::SpdyFrame
> req(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
1933 scoped_ptr
<spdy::SpdyFrame
> window_update(
1934 ConstructSpdyWindowUpdate(1, kUploadDataSize
));
1936 MockWrite writes
[] = {
1937 CreateMockWrite(*req
),
1938 CreateMockWrite(*window_update
),
1941 scoped_ptr
<spdy::SpdyFrame
> resp(
1942 ConstructSpdyGetSynReply(NULL
, 0, 1));
1943 scoped_ptr
<spdy::SpdyFrame
> body_no_fin(
1944 ConstructSpdyBodyFrame(1, false));
1945 scoped_ptr
<spdy::SpdyFrame
> body_fin(
1946 ConstructSpdyBodyFrame(1, NULL
, 0, true));
1947 MockRead reads
[] = {
1948 CreateMockRead(*resp
),
1949 CreateMockRead(*body_no_fin
),
1950 MockRead(true, ERR_IO_PENDING
, 0), // Force a pause
1951 CreateMockRead(*body_fin
),
1952 MockRead(true, ERR_IO_PENDING
, 0), // Force a pause
1953 MockRead(true, 0, 0) // EOF
1956 scoped_refptr
<DelayedSocketData
> data(
1957 new DelayedSocketData(1, reads
, arraysize(reads
),
1958 writes
, arraysize(writes
)));
1960 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
1961 BoundNetLog(), GetParam());
1962 helper
.AddData(data
.get());
1963 helper
.RunPreTestSetup();
1964 HttpNetworkTransaction
* trans
= helper
.trans();
1966 TestCompletionCallback callback
;
1967 int rv
= trans
->Start(&helper
.request(), &callback
, BoundNetLog());
1969 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1970 rv
= callback
.WaitForResult();
1973 SpdyHttpStream
* stream
=
1974 static_cast<SpdyHttpStream
*>(trans
->stream_
.get());
1975 ASSERT_TRUE(stream
!= NULL
);
1976 ASSERT_TRUE(stream
->stream() != NULL
);
1979 static_cast<int>(spdy::kSpdyStreamInitialWindowSize
) - kUploadDataSize
,
1980 stream
->stream()->recv_window_size());
1982 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1983 ASSERT_TRUE(response
!= NULL
);
1984 ASSERT_TRUE(response
->headers
!= NULL
);
1985 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
1986 EXPECT_TRUE(response
->was_fetched_via_spdy
);
1988 // Issue a read which will cause a WINDOW_UPDATE to be sent and window
1989 // size increased to default.
1990 scoped_refptr
<net::IOBuffer
> buf(new net::IOBuffer(kUploadDataSize
));
1991 rv
= trans
->Read(buf
, kUploadDataSize
, NULL
);
1992 EXPECT_EQ(kUploadDataSize
, rv
);
1993 std::string
content(buf
->data(), buf
->data()+kUploadDataSize
);
1994 EXPECT_STREQ(kUploadData
, content
.c_str());
1996 // Schedule the reading of empty data frame with FIN
1997 data
->CompleteRead();
1999 // Force write of WINDOW_UPDATE which was scheduled during the above
2001 MessageLoop::current()->RunAllPending();
2004 data
->CompleteRead();
2006 helper
.VerifyDataConsumed();
2007 SpdySession::set_flow_control(false);
2010 // Test that WINDOW_UPDATE frame causing overflow is handled correctly. We
2011 // use the same trick as in the above test to enforce our scenario.
2012 TEST_P(SpdyNetworkTransactionTest
, WindowUpdateOverflow
) {
2013 SpdySession::set_flow_control(true);
2015 // number of full frames we hope to write (but will not, used to
2016 // set content-length header correctly)
2017 static int kFrameCount
= 3;
2019 scoped_ptr
<std::string
> content(
2020 new std::string(kMaxSpdyFrameChunkSize
, 'a'));
2021 scoped_ptr
<spdy::SpdyFrame
> req(ConstructSpdyPost(
2022 kMaxSpdyFrameChunkSize
* kFrameCount
, NULL
, 0));
2023 scoped_ptr
<spdy::SpdyFrame
> body(
2024 ConstructSpdyBodyFrame(1, content
->c_str(), content
->size(), false));
2025 scoped_ptr
<spdy::SpdyFrame
> rst(
2026 ConstructSpdyRstStream(1, spdy::FLOW_CONTROL_ERROR
));
2028 // We're not going to write a data frame with FIN, we'll receive a bad
2029 // WINDOW_UPDATE while sending a request and will send a RST_STREAM frame.
2030 MockWrite writes
[] = {
2031 CreateMockWrite(*req
),
2032 CreateMockWrite(*body
),
2033 CreateMockWrite(*rst
),
2036 static const int kDeltaWindowSize
= 0x7fffffff; // cause an overflow
2037 scoped_ptr
<spdy::SpdyFrame
> window_update(
2038 ConstructSpdyWindowUpdate(1, kDeltaWindowSize
));
2039 scoped_ptr
<spdy::SpdyFrame
> window_update2(
2040 ConstructSpdyWindowUpdate(2, kDeltaWindowSize
));
2041 scoped_ptr
<spdy::SpdyFrame
> reply(ConstructSpdyPostSynReply(NULL
, 0));
2043 MockRead reads
[] = {
2044 CreateMockRead(*window_update2
),
2045 CreateMockRead(*window_update2
),
2046 CreateMockRead(*window_update
),
2047 CreateMockRead(*window_update
),
2048 CreateMockRead(*window_update
),
2049 MockRead(true, ERR_IO_PENDING
, 0), // Wait for the RST to be written.
2050 MockRead(true, 0, 0) // EOF
2053 scoped_refptr
<DelayedSocketData
> data(
2054 new DelayedSocketData(0, reads
, arraysize(reads
),
2055 writes
, arraysize(writes
)));
2057 // Setup the request
2058 HttpRequestInfo request
;
2059 request
.method
= "POST";
2060 request
.url
= GURL("http://www.google.com/");
2061 request
.upload_data
= new UploadData();
2062 for (int i
= 0; i
< kFrameCount
; ++i
)
2063 request
.upload_data
->AppendBytes(content
->c_str(), content
->size());
2065 NormalSpdyTransactionHelper
helper(request
,
2066 BoundNetLog(), GetParam());
2067 helper
.AddData(data
.get());
2068 helper
.RunPreTestSetup();
2070 HttpNetworkTransaction
* trans
= helper
.trans();
2072 TestCompletionCallback callback
;
2073 int rv
= trans
->Start(&helper
.request(), &callback
, BoundNetLog());
2075 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2076 rv
= callback
.WaitForResult();
2077 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR
, rv
);
2079 data
->CompleteRead();
2081 ASSERT_TRUE(helper
.session() != NULL
);
2082 ASSERT_TRUE(helper
.session()->spdy_session_pool() != NULL
);
2083 helper
.session()->spdy_session_pool()->CloseAllSessions();
2084 helper
.VerifyDataConsumed();
2086 SpdySession::set_flow_control(false);
2089 // Test that after hitting a send window size of 0, the write process
2090 // stalls and upon receiving WINDOW_UPDATE frame write resumes.
2092 // This test constructs a POST request followed by enough data frames
2093 // containing 'a' that would make the window size 0, followed by another
2094 // data frame containing default content (which is "hello!") and this frame
2095 // also contains a FIN flag. DelayedSocketData is used to enforce all
2096 // writes go through before a read could happen. However, the last frame
2097 // ("hello!") is not supposed to go through since by the time its turn
2098 // arrives, window size is 0. At this point MessageLoop::Run() called via
2099 // callback would block. Therefore we call MessageLoop::RunAllPending()
2100 // which returns after performing all possible writes. We use DCHECKS to
2101 // ensure that last data frame is still there and stream has stalled.
2102 // After that, next read is artifically enforced, which causes a
2103 // WINDOW_UPDATE to be read and I/O process resumes.
2104 TEST_P(SpdyNetworkTransactionTest
, FlowControlStallResume
) {
2105 SpdySession::set_flow_control(true);
2107 // Number of frames we need to send to zero out the window size: data
2108 // frames plus SYN_STREAM plus the last data frame; also we need another
2109 // data frame that we will send once the WINDOW_UPDATE is received,
2112 spdy::kSpdyStreamInitialWindowSize
/ kMaxSpdyFrameChunkSize
+ 3;
2114 // Calculate last frame's size; 0 size data frame is legal.
2115 size_t last_frame_size
=
2116 spdy::kSpdyStreamInitialWindowSize
% kMaxSpdyFrameChunkSize
;
2118 // Construct content for a data frame of maximum size.
2119 scoped_ptr
<std::string
> content(
2120 new std::string(kMaxSpdyFrameChunkSize
, 'a'));
2122 scoped_ptr
<spdy::SpdyFrame
> req(ConstructSpdyPost(
2123 spdy::kSpdyStreamInitialWindowSize
+ kUploadDataSize
, NULL
, 0));
2126 scoped_ptr
<spdy::SpdyFrame
> body1(
2127 ConstructSpdyBodyFrame(1, content
->c_str(), content
->size(), false));
2129 // Last frame to zero out the window size.
2130 scoped_ptr
<spdy::SpdyFrame
> body2(
2131 ConstructSpdyBodyFrame(1, content
->c_str(), last_frame_size
, false));
2133 // Data frame to be sent once WINDOW_UPDATE frame is received.
2134 scoped_ptr
<spdy::SpdyFrame
> body3(ConstructSpdyBodyFrame(1, true));
2136 // Fill in mock writes.
2137 scoped_array
<MockWrite
> writes(new MockWrite
[nwrites
]);
2139 writes
[i
] = CreateMockWrite(*req
);
2140 for (i
= 1; i
< nwrites
-2; i
++)
2141 writes
[i
] = CreateMockWrite(*body1
);
2142 writes
[i
++] = CreateMockWrite(*body2
);
2143 writes
[i
] = CreateMockWrite(*body3
);
2145 // Construct read frame, give enough space to upload the rest of the
2147 scoped_ptr
<spdy::SpdyFrame
> window_update(
2148 ConstructSpdyWindowUpdate(1, kUploadDataSize
));
2149 scoped_ptr
<spdy::SpdyFrame
> reply(ConstructSpdyPostSynReply(NULL
, 0));
2150 MockRead reads
[] = {
2151 CreateMockRead(*window_update
),
2152 CreateMockRead(*window_update
),
2153 CreateMockRead(*reply
),
2154 CreateMockRead(*body2
),
2155 CreateMockRead(*body3
),
2156 MockRead(true, 0, 0) // EOF
2159 // Force all writes to happen before any read, last write will not
2160 // actually queue a frame, due to window size being 0.
2161 scoped_refptr
<DelayedSocketData
> data(
2162 new DelayedSocketData(nwrites
, reads
, arraysize(reads
),
2163 writes
.get(), nwrites
));
2165 HttpRequestInfo request
;
2166 request
.method
= "POST";
2167 request
.url
= GURL("http://www.google.com/");
2168 request
.upload_data
= new UploadData();
2169 scoped_ptr
<std::string
> upload_data(
2170 new std::string(spdy::kSpdyStreamInitialWindowSize
, 'a'));
2171 upload_data
->append(kUploadData
, kUploadDataSize
);
2172 request
.upload_data
->AppendBytes(upload_data
->c_str(), upload_data
->size());
2173 NormalSpdyTransactionHelper
helper(request
,
2174 BoundNetLog(), GetParam());
2175 helper
.AddData(data
.get());
2176 helper
.RunPreTestSetup();
2178 HttpNetworkTransaction
* trans
= helper
.trans();
2180 TestCompletionCallback callback
;
2181 int rv
= trans
->Start(&helper
.request(), &callback
, BoundNetLog());
2182 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2184 MessageLoop::current()->RunAllPending(); // Write as much as we can.
2186 SpdyHttpStream
* stream
= static_cast<SpdyHttpStream
*>(trans
->stream_
.get());
2187 ASSERT_TRUE(stream
!= NULL
);
2188 ASSERT_TRUE(stream
->stream() != NULL
);
2189 EXPECT_EQ(0, stream
->stream()->send_window_size());
2190 EXPECT_FALSE(stream
->request_body_stream_
->eof());
2192 data
->ForceNextRead(); // Read in WINDOW_UPDATE frame.
2193 rv
= callback
.WaitForResult();
2194 helper
.VerifyDataConsumed();
2196 SpdySession::set_flow_control(false);
2199 TEST_P(SpdyNetworkTransactionTest
, CancelledTransaction
) {
2200 // Construct the request.
2201 scoped_ptr
<spdy::SpdyFrame
> req(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
2202 MockWrite writes
[] = {
2203 CreateMockWrite(*req
),
2206 scoped_ptr
<spdy::SpdyFrame
> resp(ConstructSpdyGetSynReply(NULL
, 0, 1));
2207 MockRead reads
[] = {
2208 CreateMockRead(*resp
),
2209 // This following read isn't used by the test, except during the
2210 // RunAllPending() call at the end since the SpdySession survives the
2211 // HttpNetworkTransaction and still tries to continue Read()'ing. Any
2212 // MockRead will do here.
2213 MockRead(true, 0, 0) // EOF
2216 StaticSocketDataProvider
data(reads
, arraysize(reads
),
2217 writes
, arraysize(writes
));
2219 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
2220 BoundNetLog(), GetParam());
2221 helper
.RunPreTestSetup();
2222 helper
.AddData(&data
);
2223 HttpNetworkTransaction
* trans
= helper
.trans();
2225 TestCompletionCallback callback
;
2226 int rv
= trans
->Start(&CreateGetRequest(), &callback
, BoundNetLog());
2227 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2228 helper
.ResetTrans(); // Cancel the transaction.
2230 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
2231 // MockClientSocketFactory) are still alive.
2232 MessageLoop::current()->RunAllPending();
2233 helper
.VerifyDataNotConsumed();
2236 // Verify that the client sends a Rst Frame upon cancelling the stream.
2237 TEST_P(SpdyNetworkTransactionTest
, CancelledTransactionSendRst
) {
2238 scoped_ptr
<spdy::SpdyFrame
> req(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
2239 scoped_ptr
<spdy::SpdyFrame
> rst(
2240 ConstructSpdyRstStream(1, spdy::CANCEL
));
2241 MockWrite writes
[] = {
2242 CreateMockWrite(*req
, 0, false),
2243 CreateMockWrite(*rst
, 2, false),
2246 scoped_ptr
<spdy::SpdyFrame
> resp(ConstructSpdyGetSynReply(NULL
, 0, 1));
2247 MockRead reads
[] = {
2248 CreateMockRead(*resp
, 1, true),
2249 MockRead(true, 0, 0, 3) // EOF
2252 scoped_refptr
<DeterministicSocketData
> data(
2253 new DeterministicSocketData(reads
, arraysize(reads
),
2254 writes
, arraysize(writes
)));
2256 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
2259 helper
.SetDeterministic();
2260 helper
.RunPreTestSetup();
2261 helper
.AddDeterministicData(data
.get());
2262 HttpNetworkTransaction
* trans
= helper
.trans();
2264 TestCompletionCallback callback
;
2266 int rv
= trans
->Start(&CreateGetRequest(), &callback
, BoundNetLog());
2267 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2271 helper
.ResetTrans();
2275 helper
.VerifyDataConsumed();
2278 class SpdyNetworkTransactionTest::StartTransactionCallback
2279 : public CallbackRunner
< Tuple1
<int> > {
2281 explicit StartTransactionCallback(
2282 const scoped_refptr
<HttpNetworkSession
>& session
,
2283 NormalSpdyTransactionHelper
& helper
)
2284 : session_(session
), helper_(helper
) {}
2286 // We try to start another transaction, which should succeed.
2287 virtual void RunWithParams(const Tuple1
<int>& params
) {
2288 scoped_ptr
<HttpNetworkTransaction
> trans(
2289 new HttpNetworkTransaction(session_
));
2290 TestCompletionCallback callback
;
2291 HttpRequestInfo request
;
2292 request
.method
= "GET";
2293 request
.url
= GURL("http://www.google.com/");
2294 request
.load_flags
= 0;
2295 int rv
= trans
->Start(&request
, &callback
, BoundNetLog());
2296 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2297 rv
= callback
.WaitForResult();
2301 const scoped_refptr
<HttpNetworkSession
>& session_
;
2302 NormalSpdyTransactionHelper
& helper_
;
2305 // Verify that the client can correctly deal with the user callback attempting
2306 // to start another transaction on a session that is closing down. See
2307 // http://crbug.com/47455
2308 TEST_P(SpdyNetworkTransactionTest
, StartTransactionOnReadCallback
) {
2309 scoped_ptr
<spdy::SpdyFrame
> req(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
2310 MockWrite writes
[] = { CreateMockWrite(*req
) };
2311 MockWrite writes2
[] = { CreateMockWrite(*req
) };
2313 // The indicated length of this packet is longer than its actual length. When
2314 // the session receives an empty packet after this one, it shuts down the
2315 // session, and calls the read callback with the incomplete data.
2316 const uint8 kGetBodyFrame2
[] = {
2317 0x00, 0x00, 0x00, 0x01,
2318 0x01, 0x00, 0x00, 0x07,
2319 'h', 'e', 'l', 'l', 'o', '!',
2322 scoped_ptr
<spdy::SpdyFrame
> resp(ConstructSpdyGetSynReply(NULL
, 0, 1));
2323 MockRead reads
[] = {
2324 CreateMockRead(*resp
, 2),
2325 MockRead(true, ERR_IO_PENDING
, 3), // Force a pause
2326 MockRead(true, reinterpret_cast<const char*>(kGetBodyFrame2
),
2327 arraysize(kGetBodyFrame2
), 4),
2328 MockRead(true, ERR_IO_PENDING
, 5), // Force a pause
2329 MockRead(true, 0, 0, 6), // EOF
2331 MockRead reads2
[] = {
2332 CreateMockRead(*resp
, 2),
2333 MockRead(true, 0, 0, 3), // EOF
2336 scoped_refptr
<OrderedSocketData
> data(
2337 new OrderedSocketData(reads
, arraysize(reads
),
2338 writes
, arraysize(writes
)));
2339 scoped_refptr
<DelayedSocketData
> data2(
2340 new DelayedSocketData(1, reads2
, arraysize(reads2
),
2341 writes2
, arraysize(writes2
)));
2343 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
2344 BoundNetLog(), GetParam());
2345 helper
.RunPreTestSetup();
2346 helper
.AddData(data
.get());
2347 helper
.AddData(data2
.get());
2348 HttpNetworkTransaction
* trans
= helper
.trans();
2350 // Start the transaction with basic parameters.
2351 TestCompletionCallback callback
;
2352 int rv
= trans
->Start(&helper
.request(), &callback
, BoundNetLog());
2353 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2354 rv
= callback
.WaitForResult();
2356 StartTransactionCallback
callback2(helper
.session(), helper
);
2357 const int kSize
= 3000;
2358 scoped_refptr
<net::IOBuffer
> buf(new net::IOBuffer(kSize
));
2359 rv
= trans
->Read(buf
, kSize
, &callback2
);
2360 // This forces an err_IO_pending, which sets the callback.
2361 data
->CompleteRead();
2362 // This finishes the read.
2363 data
->CompleteRead();
2364 helper
.VerifyDataConsumed();
2367 class SpdyNetworkTransactionTest::DeleteSessionCallback
2368 : public CallbackRunner
< Tuple1
<int> > {
2370 explicit DeleteSessionCallback(NormalSpdyTransactionHelper
& helper
) :
2373 // We kill the transaction, which deletes the session and stream.
2374 virtual void RunWithParams(const Tuple1
<int>& params
) {
2375 helper_
.ResetTrans();
2379 NormalSpdyTransactionHelper
& helper_
;
2382 // Verify that the client can correctly deal with the user callback deleting the
2383 // transaction. Failures will usually be valgrind errors. See
2384 // http://crbug.com/46925
2385 TEST_P(SpdyNetworkTransactionTest
, DeleteSessionOnReadCallback
) {
2386 scoped_ptr
<spdy::SpdyFrame
> req(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
2387 MockWrite writes
[] = { CreateMockWrite(*req
) };
2389 scoped_ptr
<spdy::SpdyFrame
> resp(ConstructSpdyGetSynReply(NULL
, 0, 1));
2390 scoped_ptr
<spdy::SpdyFrame
> body(ConstructSpdyBodyFrame(1, true));
2391 MockRead reads
[] = {
2392 CreateMockRead(*resp
.get(), 2),
2393 MockRead(true, ERR_IO_PENDING
, 3), // Force a pause
2394 CreateMockRead(*body
.get(), 4),
2395 MockRead(true, 0, 0, 5), // EOF
2398 scoped_refptr
<OrderedSocketData
> data(
2399 new OrderedSocketData(reads
, arraysize(reads
),
2400 writes
, arraysize(writes
)));
2402 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
2403 BoundNetLog(), GetParam());
2404 helper
.RunPreTestSetup();
2405 helper
.AddData(data
.get());
2406 HttpNetworkTransaction
* trans
= helper
.trans();
2408 // Start the transaction with basic parameters.
2409 TestCompletionCallback callback
;
2410 int rv
= trans
->Start(&helper
.request(), &callback
, BoundNetLog());
2411 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2412 rv
= callback
.WaitForResult();
2414 // Setup a user callback which will delete the session, and clear out the
2415 // memory holding the stream object. Note that the callback deletes trans.
2416 DeleteSessionCallback
callback2(helper
);
2417 const int kSize
= 3000;
2418 scoped_refptr
<net::IOBuffer
> buf(new net::IOBuffer(kSize
));
2419 rv
= trans
->Read(buf
, kSize
, &callback2
);
2420 ASSERT_EQ(ERR_IO_PENDING
, rv
);
2421 data
->CompleteRead();
2423 // Finish running rest of tasks.
2424 MessageLoop::current()->RunAllPending();
2425 helper
.VerifyDataConsumed();
2428 // Send a spdy request to www.google.com that gets redirected to www.foo.com.
2429 TEST_P(SpdyNetworkTransactionTest
, RedirectGetRequest
) {
2430 // These are headers which the net::URLRequest tacks on.
2431 const char* const kExtraHeaders
[] = {
2435 const SpdyHeaderInfo kSynStartHeader
= MakeSpdyHeader(spdy::SYN_STREAM
);
2436 const char* const kStandardGetHeaders
[] = {
2450 const char* const kStandardGetHeaders2
[] = {
2465 // Setup writes/reads to www.google.com
2466 scoped_ptr
<spdy::SpdyFrame
> req(ConstructSpdyPacket(
2467 kSynStartHeader
, kExtraHeaders
, arraysize(kExtraHeaders
) / 2,
2468 kStandardGetHeaders
, arraysize(kStandardGetHeaders
) / 2));
2469 scoped_ptr
<spdy::SpdyFrame
> req2(ConstructSpdyPacket(
2470 kSynStartHeader
, kExtraHeaders
, arraysize(kExtraHeaders
) / 2,
2471 kStandardGetHeaders2
, arraysize(kStandardGetHeaders2
) / 2));
2472 scoped_ptr
<spdy::SpdyFrame
> resp(ConstructSpdyGetSynReplyRedirect(1));
2473 MockWrite writes
[] = {
2474 CreateMockWrite(*req
, 1),
2476 MockRead reads
[] = {
2477 CreateMockRead(*resp
, 2),
2478 MockRead(true, 0, 0, 3) // EOF
2481 // Setup writes/reads to www.foo.com
2482 scoped_ptr
<spdy::SpdyFrame
> resp2(ConstructSpdyGetSynReply(NULL
, 0, 1));
2483 scoped_ptr
<spdy::SpdyFrame
> body2(ConstructSpdyBodyFrame(1, true));
2484 MockWrite writes2
[] = {
2485 CreateMockWrite(*req2
, 1),
2487 MockRead reads2
[] = {
2488 CreateMockRead(*resp2
, 2),
2489 CreateMockRead(*body2
, 3),
2490 MockRead(true, 0, 0, 4) // EOF
2492 scoped_refptr
<OrderedSocketData
> data(
2493 new OrderedSocketData(reads
, arraysize(reads
),
2494 writes
, arraysize(writes
)));
2495 scoped_refptr
<OrderedSocketData
> data2(
2496 new OrderedSocketData(reads2
, arraysize(reads2
),
2497 writes2
, arraysize(writes2
)));
2499 // TODO(erikchen): Make test support SPDYSSL, SPDYNPN
2500 HttpStreamFactory::set_force_spdy_over_ssl(false);
2501 HttpStreamFactory::set_force_spdy_always(true);
2504 net::URLRequest
r(GURL("http://www.google.com/"), &d
);
2505 SpdyURLRequestContext
* spdy_url_request_context
=
2506 new SpdyURLRequestContext();
2507 r
.set_context(spdy_url_request_context
);
2508 spdy_url_request_context
->socket_factory().
2509 AddSocketDataProvider(data
.get());
2510 spdy_url_request_context
->socket_factory().
2511 AddSocketDataProvider(data2
.get());
2513 d
.set_quit_on_redirect(true);
2515 MessageLoop::current()->Run();
2517 EXPECT_EQ(1, d
.received_redirect_count());
2519 r
.FollowDeferredRedirect();
2520 MessageLoop::current()->Run();
2521 EXPECT_EQ(1, d
.response_started_count());
2522 EXPECT_FALSE(d
.received_data_before_response());
2523 EXPECT_EQ(net::URLRequestStatus::SUCCESS
, r
.status().status());
2524 std::string
contents("hello!");
2525 EXPECT_EQ(contents
, d
.data_received());
2527 EXPECT_TRUE(data
->at_read_eof());
2528 EXPECT_TRUE(data
->at_write_eof());
2529 EXPECT_TRUE(data2
->at_read_eof());
2530 EXPECT_TRUE(data2
->at_write_eof());
2533 // Send a spdy request to www.google.com. Get a pushed stream that redirects to
2535 TEST_P(SpdyNetworkTransactionTest
, RedirectServerPush
) {
2536 // These are headers which the net::URLRequest tacks on.
2537 const char* const kExtraHeaders
[] = {
2541 const SpdyHeaderInfo kSynStartHeader
= MakeSpdyHeader(spdy::SYN_STREAM
);
2542 const char* const kStandardGetHeaders
[] = {
2557 // Setup writes/reads to www.google.com
2558 scoped_ptr
<spdy::SpdyFrame
> req(
2559 ConstructSpdyPacket(kSynStartHeader
,
2561 arraysize(kExtraHeaders
) / 2,
2562 kStandardGetHeaders
,
2563 arraysize(kStandardGetHeaders
) / 2));
2564 scoped_ptr
<spdy::SpdyFrame
> resp(ConstructSpdyGetSynReply(NULL
, 0, 1));
2565 scoped_ptr
<spdy::SpdyFrame
> rep(
2566 ConstructSpdyPush(NULL
,
2570 "http://www.google.com/foo.dat",
2571 "301 Moved Permanently",
2572 "http://www.foo.com/index.php"));
2573 scoped_ptr
<spdy::SpdyFrame
> body(ConstructSpdyBodyFrame(1, true));
2574 scoped_ptr
<spdy::SpdyFrame
> rst(ConstructSpdyRstStream(2, spdy::CANCEL
));
2575 MockWrite writes
[] = {
2576 CreateMockWrite(*req
, 1),
2577 CreateMockWrite(*rst
, 6),
2579 MockRead reads
[] = {
2580 CreateMockRead(*resp
, 2),
2581 CreateMockRead(*rep
, 3),
2582 CreateMockRead(*body
, 4),
2583 MockRead(true, ERR_IO_PENDING
, 5), // Force a pause
2584 MockRead(true, 0, 0, 7) // EOF
2587 // Setup writes/reads to www.foo.com
2588 const char* const kStandardGetHeaders2
[] = {
2602 scoped_ptr
<spdy::SpdyFrame
> req2(
2603 ConstructSpdyPacket(kSynStartHeader
,
2605 arraysize(kExtraHeaders
) / 2,
2606 kStandardGetHeaders2
,
2607 arraysize(kStandardGetHeaders2
) / 2));
2608 scoped_ptr
<spdy::SpdyFrame
> resp2(ConstructSpdyGetSynReply(NULL
, 0, 1));
2609 scoped_ptr
<spdy::SpdyFrame
> body2(ConstructSpdyBodyFrame(1, true));
2610 MockWrite writes2
[] = {
2611 CreateMockWrite(*req2
, 1),
2613 MockRead reads2
[] = {
2614 CreateMockRead(*resp2
, 2),
2615 CreateMockRead(*body2
, 3),
2616 MockRead(true, 0, 0, 5) // EOF
2618 scoped_refptr
<OrderedSocketData
> data(
2619 new OrderedSocketData(reads
, arraysize(reads
),
2620 writes
, arraysize(writes
)));
2621 scoped_refptr
<OrderedSocketData
> data2(
2622 new OrderedSocketData(reads2
, arraysize(reads2
),
2623 writes2
, arraysize(writes2
)));
2625 // TODO(erikchen): Make test support SPDYSSL, SPDYNPN
2626 HttpStreamFactory::set_force_spdy_over_ssl(false);
2627 HttpStreamFactory::set_force_spdy_always(true);
2630 scoped_refptr
<SpdyURLRequestContext
> spdy_url_request_context(
2631 new SpdyURLRequestContext());
2633 net::URLRequest
r(GURL("http://www.google.com/"), &d
);
2634 r
.set_context(spdy_url_request_context
);
2635 spdy_url_request_context
->socket_factory().
2636 AddSocketDataProvider(data
.get());
2639 MessageLoop::current()->Run();
2641 EXPECT_EQ(0, d
.received_redirect_count());
2642 std::string
contents("hello!");
2643 EXPECT_EQ(contents
, d
.data_received());
2645 net::URLRequest
r2(GURL("http://www.google.com/foo.dat"), &d2
);
2646 r2
.set_context(spdy_url_request_context
);
2647 spdy_url_request_context
->socket_factory().
2648 AddSocketDataProvider(data2
.get());
2650 d2
.set_quit_on_redirect(true);
2652 MessageLoop::current()->Run();
2653 EXPECT_EQ(1, d2
.received_redirect_count());
2655 r2
.FollowDeferredRedirect();
2656 MessageLoop::current()->Run();
2657 EXPECT_EQ(1, d2
.response_started_count());
2658 EXPECT_FALSE(d2
.received_data_before_response());
2659 EXPECT_EQ(net::URLRequestStatus::SUCCESS
, r2
.status().status());
2660 std::string
contents2("hello!");
2661 EXPECT_EQ(contents2
, d2
.data_received());
2663 data
->CompleteRead();
2664 data2
->CompleteRead();
2665 EXPECT_TRUE(data
->at_read_eof());
2666 EXPECT_TRUE(data
->at_write_eof());
2667 EXPECT_TRUE(data2
->at_read_eof());
2668 EXPECT_TRUE(data2
->at_write_eof());
2671 TEST_P(SpdyNetworkTransactionTest
, ServerPushSingleDataFrame
) {
2672 static const unsigned char kPushBodyFrame
[] = {
2673 0x00, 0x00, 0x00, 0x02, // header, ID
2674 0x01, 0x00, 0x00, 0x06, // FIN, length
2675 'p', 'u', 's', 'h', 'e', 'd' // "pushed"
2677 scoped_ptr
<spdy::SpdyFrame
>
2678 stream1_syn(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
2679 scoped_ptr
<spdy::SpdyFrame
>
2680 stream1_body(ConstructSpdyBodyFrame(1, true));
2681 MockWrite writes
[] = {
2682 CreateMockWrite(*stream1_syn
, 1),
2685 scoped_ptr
<spdy::SpdyFrame
>
2686 stream1_reply(ConstructSpdyGetSynReply(NULL
, 0, 1));
2687 scoped_ptr
<spdy::SpdyFrame
>
2688 stream2_syn(ConstructSpdyPush(NULL
,
2692 "http://www.google.com/foo.dat"));
2693 MockRead reads
[] = {
2694 CreateMockRead(*stream1_reply
, 2),
2695 CreateMockRead(*stream2_syn
, 3),
2696 CreateMockRead(*stream1_body
, 4, false),
2697 MockRead(true, reinterpret_cast<const char*>(kPushBodyFrame
),
2698 arraysize(kPushBodyFrame
), 5),
2699 MockRead(true, ERR_IO_PENDING
, 6), // Force a pause
2702 HttpResponseInfo response
;
2703 HttpResponseInfo response2
;
2704 std::string
expected_push_result("pushed");
2705 scoped_refptr
<OrderedSocketData
> data(new OrderedSocketData(
2709 arraysize(writes
)));
2710 RunServerPushTest(data
.get(),
2713 expected_push_result
);
2715 // Verify the SYN_REPLY.
2716 EXPECT_TRUE(response
.headers
!= NULL
);
2717 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
2719 // Verify the pushed stream.
2720 EXPECT_TRUE(response2
.headers
!= NULL
);
2721 EXPECT_EQ("HTTP/1.1 200 OK", response2
.headers
->GetStatusLine());
2724 TEST_P(SpdyNetworkTransactionTest
, ServerPushSingleDataFrame2
) {
2725 static const unsigned char kPushBodyFrame
[] = {
2726 0x00, 0x00, 0x00, 0x02, // header, ID
2727 0x01, 0x00, 0x00, 0x06, // FIN, length
2728 'p', 'u', 's', 'h', 'e', 'd' // "pushed"
2730 scoped_ptr
<spdy::SpdyFrame
>
2731 stream1_syn(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
2732 MockWrite writes
[] = {
2733 CreateMockWrite(*stream1_syn
, 1),
2736 scoped_ptr
<spdy::SpdyFrame
>
2737 stream1_reply(ConstructSpdyGetSynReply(NULL
, 0, 1));
2738 scoped_ptr
<spdy::SpdyFrame
>
2739 stream2_syn(ConstructSpdyPush(NULL
,
2743 "http://www.google.com/foo.dat"));
2744 scoped_ptr
<spdy::SpdyFrame
>
2745 stream1_body(ConstructSpdyBodyFrame(1, true));
2746 MockRead reads
[] = {
2747 CreateMockRead(*stream1_reply
, 2),
2748 CreateMockRead(*stream2_syn
, 3),
2749 MockRead(true, reinterpret_cast<const char*>(kPushBodyFrame
),
2750 arraysize(kPushBodyFrame
), 5),
2751 CreateMockRead(*stream1_body
, 4, false),
2752 MockRead(true, ERR_IO_PENDING
, 6), // Force a pause
2755 HttpResponseInfo response
;
2756 HttpResponseInfo response2
;
2757 std::string
expected_push_result("pushed");
2758 scoped_refptr
<OrderedSocketData
> data(new OrderedSocketData(
2762 arraysize(writes
)));
2763 RunServerPushTest(data
.get(),
2766 expected_push_result
);
2768 // Verify the SYN_REPLY.
2769 EXPECT_TRUE(response
.headers
!= NULL
);
2770 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
2772 // Verify the pushed stream.
2773 EXPECT_TRUE(response2
.headers
!= NULL
);
2774 EXPECT_EQ("HTTP/1.1 200 OK", response2
.headers
->GetStatusLine());
2777 TEST_P(SpdyNetworkTransactionTest
, ServerPushServerAborted
) {
2778 scoped_ptr
<spdy::SpdyFrame
>
2779 stream1_syn(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
2780 scoped_ptr
<spdy::SpdyFrame
>
2781 stream1_body(ConstructSpdyBodyFrame(1, true));
2782 MockWrite writes
[] = {
2783 CreateMockWrite(*stream1_syn
, 1),
2786 scoped_ptr
<spdy::SpdyFrame
>
2787 stream1_reply(ConstructSpdyGetSynReply(NULL
, 0, 1));
2788 scoped_ptr
<spdy::SpdyFrame
>
2789 stream2_syn(ConstructSpdyPush(NULL
,
2793 "http://www.google.com/foo.dat"));
2794 scoped_ptr
<spdy::SpdyFrame
>
2795 stream2_rst(ConstructSpdyRstStream(2, spdy::PROTOCOL_ERROR
));
2796 MockRead reads
[] = {
2797 CreateMockRead(*stream1_reply
, 2),
2798 CreateMockRead(*stream2_syn
, 3),
2799 CreateMockRead(*stream2_rst
, 4),
2800 CreateMockRead(*stream1_body
, 5, false),
2801 MockRead(true, ERR_IO_PENDING
, 6), // Force a pause
2804 scoped_refptr
<OrderedSocketData
> data(
2805 new OrderedSocketData(reads
, arraysize(reads
),
2806 writes
, arraysize(writes
)));
2807 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
2808 BoundNetLog(), GetParam());
2810 helper
.RunPreTestSetup();
2811 helper
.AddData(data
.get());
2813 HttpNetworkTransaction
* trans
= helper
.trans();
2815 // Start the transaction with basic parameters.
2816 TestCompletionCallback callback
;
2817 int rv
= trans
->Start(&CreateGetRequest(), &callback
, BoundNetLog());
2818 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2819 rv
= callback
.WaitForResult();
2822 // Verify that we consumed all test data.
2823 EXPECT_TRUE(data
->at_read_eof()) << "Read count: "
2824 << data
->read_count()
2826 << data
->read_index();
2827 EXPECT_TRUE(data
->at_write_eof()) << "Write count: "
2828 << data
->write_count()
2830 << data
->write_index();
2832 // Verify the SYN_REPLY.
2833 HttpResponseInfo response
= *trans
->GetResponseInfo();
2834 EXPECT_TRUE(response
.headers
!= NULL
);
2835 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
2838 TEST_P(SpdyNetworkTransactionTest
, ServerPushDuplicate
) {
2839 // Verify that we don't leak streams and that we properly send a reset
2840 // if the server pushes the same stream twice.
2841 static const unsigned char kPushBodyFrame
[] = {
2842 0x00, 0x00, 0x00, 0x02, // header, ID
2843 0x01, 0x00, 0x00, 0x06, // FIN, length
2844 'p', 'u', 's', 'h', 'e', 'd' // "pushed"
2847 scoped_ptr
<spdy::SpdyFrame
>
2848 stream1_syn(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
2849 scoped_ptr
<spdy::SpdyFrame
>
2850 stream1_body(ConstructSpdyBodyFrame(1, true));
2851 scoped_ptr
<spdy::SpdyFrame
>
2852 stream3_rst(ConstructSpdyRstStream(4, spdy::PROTOCOL_ERROR
));
2853 MockWrite writes
[] = {
2854 CreateMockWrite(*stream1_syn
, 1),
2855 CreateMockWrite(*stream3_rst
, 5),
2858 scoped_ptr
<spdy::SpdyFrame
>
2859 stream1_reply(ConstructSpdyGetSynReply(NULL
, 0, 1));
2860 scoped_ptr
<spdy::SpdyFrame
>
2861 stream2_syn(ConstructSpdyPush(NULL
,
2865 "http://www.google.com/foo.dat"));
2866 scoped_ptr
<spdy::SpdyFrame
>
2867 stream3_syn(ConstructSpdyPush(NULL
,
2871 "http://www.google.com/foo.dat"));
2872 MockRead reads
[] = {
2873 CreateMockRead(*stream1_reply
, 2),
2874 CreateMockRead(*stream2_syn
, 3),
2875 CreateMockRead(*stream3_syn
, 4),
2876 CreateMockRead(*stream1_body
, 6, false),
2877 MockRead(true, reinterpret_cast<const char*>(kPushBodyFrame
),
2878 arraysize(kPushBodyFrame
), 7),
2879 MockRead(true, ERR_IO_PENDING
, 8), // Force a pause
2882 HttpResponseInfo response
;
2883 HttpResponseInfo response2
;
2884 std::string
expected_push_result("pushed");
2885 scoped_refptr
<OrderedSocketData
> data(new OrderedSocketData(
2889 arraysize(writes
)));
2890 RunServerPushTest(data
.get(),
2893 expected_push_result
);
2895 // Verify the SYN_REPLY.
2896 EXPECT_TRUE(response
.headers
!= NULL
);
2897 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
2899 // Verify the pushed stream.
2900 EXPECT_TRUE(response2
.headers
!= NULL
);
2901 EXPECT_EQ("HTTP/1.1 200 OK", response2
.headers
->GetStatusLine());
2904 TEST_P(SpdyNetworkTransactionTest
, ServerPushMultipleDataFrame
) {
2905 static const unsigned char kPushBodyFrame1
[] = {
2906 0x00, 0x00, 0x00, 0x02, // header, ID
2907 0x01, 0x00, 0x00, 0x1F, // FIN, length
2908 'p', 'u', 's', 'h', 'e', 'd' // "pushed"
2910 static const char kPushBodyFrame2
[] = " my darling";
2911 static const char kPushBodyFrame3
[] = " hello";
2912 static const char kPushBodyFrame4
[] = " my baby";
2914 scoped_ptr
<spdy::SpdyFrame
>
2915 stream1_syn(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
2916 scoped_ptr
<spdy::SpdyFrame
>
2917 stream1_body(ConstructSpdyBodyFrame(1, true));
2918 MockWrite writes
[] = {
2919 CreateMockWrite(*stream1_syn
, 1),
2922 scoped_ptr
<spdy::SpdyFrame
>
2923 stream1_reply(ConstructSpdyGetSynReply(NULL
, 0, 1));
2924 scoped_ptr
<spdy::SpdyFrame
>
2925 stream2_syn(ConstructSpdyPush(NULL
,
2929 "http://www.google.com/foo.dat"));
2930 MockRead reads
[] = {
2931 CreateMockRead(*stream1_reply
, 2),
2932 CreateMockRead(*stream2_syn
, 3),
2933 MockRead(true, reinterpret_cast<const char*>(kPushBodyFrame1
),
2934 arraysize(kPushBodyFrame1
), 4),
2935 MockRead(true, reinterpret_cast<const char*>(kPushBodyFrame2
),
2936 arraysize(kPushBodyFrame2
) - 1, 5),
2937 MockRead(true, reinterpret_cast<const char*>(kPushBodyFrame3
),
2938 arraysize(kPushBodyFrame3
) - 1, 6),
2939 MockRead(true, reinterpret_cast<const char*>(kPushBodyFrame4
),
2940 arraysize(kPushBodyFrame4
) - 1, 7),
2941 CreateMockRead(*stream1_body
, 8, false),
2942 MockRead(true, ERR_IO_PENDING
, 9), // Force a pause
2945 HttpResponseInfo response
;
2946 HttpResponseInfo response2
;
2947 std::string
expected_push_result("pushed my darling hello my baby");
2948 scoped_refptr
<OrderedSocketData
> data(new OrderedSocketData(
2952 arraysize(writes
)));
2953 RunServerPushTest(data
.get(),
2956 expected_push_result
);
2958 // Verify the SYN_REPLY.
2959 EXPECT_TRUE(response
.headers
!= NULL
);
2960 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
2962 // Verify the pushed stream.
2963 EXPECT_TRUE(response2
.headers
!= NULL
);
2964 EXPECT_EQ("HTTP/1.1 200 OK", response2
.headers
->GetStatusLine());
2967 TEST_P(SpdyNetworkTransactionTest
, ServerPushMultipleDataFrameInterrupted
) {
2968 static const unsigned char kPushBodyFrame1
[] = {
2969 0x00, 0x00, 0x00, 0x02, // header, ID
2970 0x01, 0x00, 0x00, 0x1F, // FIN, length
2971 'p', 'u', 's', 'h', 'e', 'd' // "pushed"
2973 static const char kPushBodyFrame2
[] = " my darling";
2974 static const char kPushBodyFrame3
[] = " hello";
2975 static const char kPushBodyFrame4
[] = " my baby";
2977 scoped_ptr
<spdy::SpdyFrame
>
2978 stream1_syn(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
2979 scoped_ptr
<spdy::SpdyFrame
>
2980 stream1_body(ConstructSpdyBodyFrame(1, true));
2981 MockWrite writes
[] = {
2982 CreateMockWrite(*stream1_syn
, 1),
2985 scoped_ptr
<spdy::SpdyFrame
>
2986 stream1_reply(ConstructSpdyGetSynReply(NULL
, 0, 1));
2987 scoped_ptr
<spdy::SpdyFrame
>
2988 stream2_syn(ConstructSpdyPush(NULL
,
2992 "http://www.google.com/foo.dat"));
2993 MockRead reads
[] = {
2994 CreateMockRead(*stream1_reply
, 2),
2995 CreateMockRead(*stream2_syn
, 3),
2996 MockRead(true, reinterpret_cast<const char*>(kPushBodyFrame1
),
2997 arraysize(kPushBodyFrame1
), 4),
2998 MockRead(true, reinterpret_cast<const char*>(kPushBodyFrame2
),
2999 arraysize(kPushBodyFrame2
) - 1, 5),
3000 MockRead(true, ERR_IO_PENDING
, 6), // Force a pause
3001 MockRead(true, reinterpret_cast<const char*>(kPushBodyFrame3
),
3002 arraysize(kPushBodyFrame3
) - 1, 7),
3003 MockRead(true, reinterpret_cast<const char*>(kPushBodyFrame4
),
3004 arraysize(kPushBodyFrame4
) - 1, 8),
3005 CreateMockRead(*stream1_body
.get(), 9, false),
3006 MockRead(true, ERR_IO_PENDING
, 10) // Force a pause.
3009 HttpResponseInfo response
;
3010 HttpResponseInfo response2
;
3011 std::string
expected_push_result("pushed my darling hello my baby");
3012 scoped_refptr
<OrderedSocketData
> data(new OrderedSocketData(
3016 arraysize(writes
)));
3017 RunServerPushTest(data
.get(),
3020 expected_push_result
);
3022 // Verify the SYN_REPLY.
3023 EXPECT_TRUE(response
.headers
!= NULL
);
3024 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
3026 // Verify the pushed stream.
3027 EXPECT_TRUE(response2
.headers
!= NULL
);
3028 EXPECT_EQ("HTTP/1.1 200 OK", response2
.headers
->GetStatusLine());
3031 TEST_P(SpdyNetworkTransactionTest
, ServerPushInvalidAssociatedStreamID0
) {
3032 scoped_ptr
<spdy::SpdyFrame
>
3033 stream1_syn(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
3034 scoped_ptr
<spdy::SpdyFrame
>
3035 stream1_body(ConstructSpdyBodyFrame(1, true));
3036 scoped_ptr
<spdy::SpdyFrame
>
3037 stream2_rst(ConstructSpdyRstStream(2, spdy::INVALID_STREAM
));
3038 MockWrite writes
[] = {
3039 CreateMockWrite(*stream1_syn
, 1),
3040 CreateMockWrite(*stream2_rst
, 4),
3043 scoped_ptr
<spdy::SpdyFrame
>
3044 stream1_reply(ConstructSpdyGetSynReply(NULL
, 0, 1));
3045 scoped_ptr
<spdy::SpdyFrame
>
3046 stream2_syn(ConstructSpdyPush(NULL
,
3050 "http://www.google.com/foo.dat"));
3051 MockRead reads
[] = {
3052 CreateMockRead(*stream1_reply
, 2),
3053 CreateMockRead(*stream2_syn
, 3),
3054 CreateMockRead(*stream1_body
, 4),
3055 MockRead(true, ERR_IO_PENDING
, 5) // Force a pause
3058 scoped_refptr
<OrderedSocketData
> data(
3059 new OrderedSocketData(reads
, arraysize(reads
),
3060 writes
, arraysize(writes
)));
3061 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
3062 BoundNetLog(), GetParam());
3064 helper
.RunPreTestSetup();
3065 helper
.AddData(data
.get());
3067 HttpNetworkTransaction
* trans
= helper
.trans();
3069 // Start the transaction with basic parameters.
3070 TestCompletionCallback callback
;
3071 int rv
= trans
->Start(&CreateGetRequest(), &callback
, BoundNetLog());
3072 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3073 rv
= callback
.WaitForResult();
3076 // Verify that we consumed all test data.
3077 EXPECT_TRUE(data
->at_read_eof()) << "Read count: "
3078 << data
->read_count()
3080 << data
->read_index();
3081 EXPECT_TRUE(data
->at_write_eof()) << "Write count: "
3082 << data
->write_count()
3084 << data
->write_index();
3086 // Verify the SYN_REPLY.
3087 HttpResponseInfo response
= *trans
->GetResponseInfo();
3088 EXPECT_TRUE(response
.headers
!= NULL
);
3089 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
3092 TEST_P(SpdyNetworkTransactionTest
, ServerPushInvalidAssociatedStreamID9
) {
3093 scoped_ptr
<spdy::SpdyFrame
>
3094 stream1_syn(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
3095 scoped_ptr
<spdy::SpdyFrame
>
3096 stream1_body(ConstructSpdyBodyFrame(1, true));
3097 scoped_ptr
<spdy::SpdyFrame
>
3098 stream2_rst(ConstructSpdyRstStream(2, spdy::INVALID_ASSOCIATED_STREAM
));
3099 MockWrite writes
[] = {
3100 CreateMockWrite(*stream1_syn
, 1),
3101 CreateMockWrite(*stream2_rst
, 4),
3104 scoped_ptr
<spdy::SpdyFrame
>
3105 stream1_reply(ConstructSpdyGetSynReply(NULL
, 0, 1));
3106 scoped_ptr
<spdy::SpdyFrame
>
3107 stream2_syn(ConstructSpdyPush(NULL
,
3111 "http://www.google.com/foo.dat"));
3112 MockRead reads
[] = {
3113 CreateMockRead(*stream1_reply
, 2),
3114 CreateMockRead(*stream2_syn
, 3),
3115 CreateMockRead(*stream1_body
, 4),
3116 MockRead(true, ERR_IO_PENDING
, 5), // Force a pause
3119 scoped_refptr
<OrderedSocketData
> data(
3120 new OrderedSocketData(reads
, arraysize(reads
),
3121 writes
, arraysize(writes
)));
3122 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
3123 BoundNetLog(), GetParam());
3125 helper
.RunPreTestSetup();
3126 helper
.AddData(data
.get());
3128 HttpNetworkTransaction
* trans
= helper
.trans();
3130 // Start the transaction with basic parameters.
3131 TestCompletionCallback callback
;
3132 int rv
= trans
->Start(&CreateGetRequest(), &callback
, BoundNetLog());
3133 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3134 rv
= callback
.WaitForResult();
3137 // Verify that we consumed all test data.
3138 EXPECT_TRUE(data
->at_read_eof()) << "Read count: "
3139 << data
->read_count()
3141 << data
->read_index();
3142 EXPECT_TRUE(data
->at_write_eof()) << "Write count: "
3143 << data
->write_count()
3145 << data
->write_index();
3147 // Verify the SYN_REPLY.
3148 HttpResponseInfo response
= *trans
->GetResponseInfo();
3149 EXPECT_TRUE(response
.headers
!= NULL
);
3150 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
3153 TEST_P(SpdyNetworkTransactionTest
, ServerPushNoURL
) {
3154 scoped_ptr
<spdy::SpdyFrame
>
3155 stream1_syn(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
3156 scoped_ptr
<spdy::SpdyFrame
>
3157 stream1_body(ConstructSpdyBodyFrame(1, true));
3158 scoped_ptr
<spdy::SpdyFrame
>
3159 stream2_rst(ConstructSpdyRstStream(2, spdy::PROTOCOL_ERROR
));
3160 MockWrite writes
[] = {
3161 CreateMockWrite(*stream1_syn
, 1),
3162 CreateMockWrite(*stream2_rst
, 4),
3165 scoped_ptr
<spdy::SpdyFrame
>
3166 stream1_reply(ConstructSpdyGetSynReply(NULL
, 0, 1));
3167 scoped_ptr
<spdy::SpdyFrame
>
3168 stream2_syn(ConstructSpdyPush(NULL
, 0, 2, 1));
3169 MockRead reads
[] = {
3170 CreateMockRead(*stream1_reply
, 2),
3171 CreateMockRead(*stream2_syn
, 3),
3172 CreateMockRead(*stream1_body
, 4),
3173 MockRead(true, ERR_IO_PENDING
, 5) // Force a pause
3176 scoped_refptr
<OrderedSocketData
> data(
3177 new OrderedSocketData(reads
, arraysize(reads
),
3178 writes
, arraysize(writes
)));
3179 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
3180 BoundNetLog(), GetParam());
3182 helper
.RunPreTestSetup();
3183 helper
.AddData(data
.get());
3185 HttpNetworkTransaction
* trans
= helper
.trans();
3187 // Start the transaction with basic parameters.
3188 TestCompletionCallback callback
;
3189 int rv
= trans
->Start(&CreateGetRequest(), &callback
, BoundNetLog());
3190 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3191 rv
= callback
.WaitForResult();
3193 // Verify that we consumed all test data.
3194 EXPECT_TRUE(data
->at_read_eof()) << "Read count: "
3195 << data
->read_count()
3197 << data
->read_index();
3198 EXPECT_TRUE(data
->at_write_eof()) << "Write count: "
3199 << data
->write_count()
3201 << data
->write_index();
3203 // Verify the SYN_REPLY.
3204 HttpResponseInfo response
= *trans
->GetResponseInfo();
3205 EXPECT_TRUE(response
.headers
!= NULL
);
3206 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
3209 // Verify that various SynReply headers parse correctly through the
3211 TEST_P(SpdyNetworkTransactionTest
, SynReplyHeaders
) {
3212 struct SynReplyHeadersTests
{
3214 const char* extra_headers
[5];
3215 const char* expected_headers
;
3217 // This uses a multi-valued cookie header.
3220 "cookie", "val2", // will get appended separated by NULL
3227 "version: HTTP/1.1\n"
3229 // This is the minimalist set of headers.
3234 "version: HTTP/1.1\n"
3236 // Headers with a comma separated list.
3238 { "cookie", "val1,val2",
3241 "cookie: val1,val2\n"
3244 "version: HTTP/1.1\n"
3248 for (size_t i
= 0; i
< ARRAYSIZE_UNSAFE(test_cases
); ++i
) {
3249 scoped_ptr
<spdy::SpdyFrame
> req(
3250 ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
3251 MockWrite writes
[] = { CreateMockWrite(*req
) };
3253 scoped_ptr
<spdy::SpdyFrame
> resp(
3254 ConstructSpdyGetSynReply(test_cases
[i
].extra_headers
,
3255 test_cases
[i
].num_headers
,
3257 scoped_ptr
<spdy::SpdyFrame
> body(ConstructSpdyBodyFrame(1, true));
3258 MockRead reads
[] = {
3259 CreateMockRead(*resp
),
3260 CreateMockRead(*body
),
3261 MockRead(true, 0, 0) // EOF
3264 scoped_refptr
<DelayedSocketData
> data(
3265 new DelayedSocketData(1, reads
, arraysize(reads
),
3266 writes
, arraysize(writes
)));
3267 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
3268 BoundNetLog(), GetParam());
3269 helper
.RunToCompletion(data
.get());
3270 TransactionHelperResult out
= helper
.output();
3272 EXPECT_EQ(OK
, out
.rv
);
3273 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
3274 EXPECT_EQ("hello!", out
.response_data
);
3276 scoped_refptr
<HttpResponseHeaders
> headers
= out
.response_info
.headers
;
3277 EXPECT_TRUE(headers
.get() != NULL
);
3279 std::string name
, value
, lines
;
3280 while (headers
->EnumerateHeaderLines(&iter
, &name
, &value
)) {
3283 lines
.append(value
);
3286 EXPECT_EQ(std::string(test_cases
[i
].expected_headers
), lines
);
3290 // Verify that various SynReply headers parse vary fields correctly
3291 // through the HTTP layer, and the response matches the request.
3292 TEST_P(SpdyNetworkTransactionTest
, SynReplyHeadersVary
) {
3293 static const SpdyHeaderInfo syn_reply_info
= {
3294 spdy::SYN_REPLY
, // Syn Reply
3296 0, // Associated Stream ID
3297 net::ConvertRequestPriorityToSpdyPriority(LOWEST
),
3299 spdy::CONTROL_FLAG_NONE
, // Control Flags
3300 false, // Compressed
3301 spdy::INVALID
, // Status
3304 spdy::DATA_FLAG_NONE
// Data Flags
3306 // Modify the following data to change/add test cases:
3307 struct SynReplyTests
{
3308 const SpdyHeaderInfo
* syn_reply
;
3311 const char* extra_headers
[2][16];
3313 // Test the case of a multi-valued cookie. When the value is delimited
3314 // with NUL characters, it needs to be unfolded into multiple headers.
3319 { { "cookie", "val1,val2",
3324 "url", "/index.php",
3325 "version", "HTTP/1.1",
3329 }, { // Multiple vary fields.
3333 { { "friend", "barney",
3334 "enemy", "snaggletooth",
3340 "url", "/index.php",
3341 "version", "HTTP/1.1",
3345 }, { // Test a '*' vary field.
3349 { { "cookie", "val1,val2",
3354 "url", "/index.php",
3355 "version", "HTTP/1.1",
3359 }, { // Multiple comma-separated vary fields.
3363 { { "friend", "barney",
3364 "enemy", "snaggletooth",
3367 { "vary", "friend,enemy",
3369 "url", "/index.php",
3370 "version", "HTTP/1.1",
3377 for (size_t i
= 0; i
< ARRAYSIZE_UNSAFE(test_cases
); ++i
) {
3378 // Construct the request.
3379 scoped_ptr
<spdy::SpdyFrame
> frame_req(
3380 ConstructSpdyGet(test_cases
[i
].extra_headers
[0],
3381 test_cases
[i
].num_headers
[0],
3384 MockWrite writes
[] = {
3385 CreateMockWrite(*frame_req
),
3388 // Construct the reply.
3389 scoped_ptr
<spdy::SpdyFrame
> frame_reply(
3390 ConstructSpdyPacket(*test_cases
[i
].syn_reply
,
3391 test_cases
[i
].extra_headers
[1],
3392 test_cases
[i
].num_headers
[1],
3396 scoped_ptr
<spdy::SpdyFrame
> body(ConstructSpdyBodyFrame(1, true));
3397 MockRead reads
[] = {
3398 CreateMockRead(*frame_reply
),
3399 CreateMockRead(*body
),
3400 MockRead(true, 0, 0) // EOF
3403 // Attach the headers to the request.
3404 int header_count
= test_cases
[i
].num_headers
[0];
3406 HttpRequestInfo request
= CreateGetRequest();
3407 for (int ct
= 0; ct
< header_count
; ct
++) {
3408 const char* header_key
= test_cases
[i
].extra_headers
[0][ct
* 2];
3409 const char* header_value
= test_cases
[i
].extra_headers
[0][ct
* 2 + 1];
3410 request
.extra_headers
.SetHeader(header_key
, header_value
);
3413 scoped_refptr
<DelayedSocketData
> data(
3414 new DelayedSocketData(1, reads
, arraysize(reads
),
3415 writes
, arraysize(writes
)));
3416 NormalSpdyTransactionHelper
helper(request
,
3417 BoundNetLog(), GetParam());
3418 helper
.RunToCompletion(data
.get());
3419 TransactionHelperResult out
= helper
.output();
3421 EXPECT_EQ(OK
, out
.rv
) << i
;
3422 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
) << i
;
3423 EXPECT_EQ("hello!", out
.response_data
) << i
;
3425 // Test the response information.
3426 EXPECT_TRUE(out
.response_info
.response_time
>
3427 out
.response_info
.request_time
) << i
;
3428 base::TimeDelta test_delay
= out
.response_info
.response_time
-
3429 out
.response_info
.request_time
;
3430 base::TimeDelta min_expected_delay
;
3431 min_expected_delay
.FromMilliseconds(10);
3432 EXPECT_GT(test_delay
.InMillisecondsF(),
3433 min_expected_delay
.InMillisecondsF()) << i
;
3434 EXPECT_EQ(out
.response_info
.vary_data
.is_valid(),
3435 test_cases
[i
].vary_matches
) << i
;
3437 // Check the headers.
3438 scoped_refptr
<HttpResponseHeaders
> headers
= out
.response_info
.headers
;
3439 ASSERT_TRUE(headers
.get() != NULL
) << i
;
3441 std::string name
, value
, lines
;
3442 while (headers
->EnumerateHeaderLines(&iter
, &name
, &value
)) {
3445 lines
.append(value
);
3449 // Construct the expected header reply string.
3450 char reply_buffer
[256] = "";
3451 ConstructSpdyReplyString(test_cases
[i
].extra_headers
[1],
3452 test_cases
[i
].num_headers
[1],
3456 EXPECT_EQ(std::string(reply_buffer
), lines
) << i
;
3460 // Verify that we don't crash on invalid SynReply responses.
3461 TEST_P(SpdyNetworkTransactionTest
, InvalidSynReply
) {
3462 const SpdyHeaderInfo kSynStartHeader
= {
3463 spdy::SYN_REPLY
, // Kind = SynReply
3465 0, // Associated stream ID
3466 net::ConvertRequestPriorityToSpdyPriority(LOWEST
),
3468 spdy::CONTROL_FLAG_NONE
, // Control Flags
3469 false, // Compressed
3470 spdy::INVALID
, // Status
3473 spdy::DATA_FLAG_NONE
// Data Flags
3476 struct InvalidSynReplyTests
{
3478 const char* headers
[10];
3480 // SYN_REPLY missing status header
3484 "url", "/index.php",
3485 "version", "HTTP/1.1",
3489 // SYN_REPLY missing version header
3492 "url", "/index.php",
3496 // SYN_REPLY with no headers
3500 for (size_t i
= 0; i
< ARRAYSIZE_UNSAFE(test_cases
); ++i
) {
3501 scoped_ptr
<spdy::SpdyFrame
> req(
3502 ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
3503 MockWrite writes
[] = {
3504 CreateMockWrite(*req
),
3507 scoped_ptr
<spdy::SpdyFrame
> resp(
3508 ConstructSpdyPacket(kSynStartHeader
,
3510 test_cases
[i
].headers
,
3511 test_cases
[i
].num_headers
));
3512 scoped_ptr
<spdy::SpdyFrame
> body(ConstructSpdyBodyFrame(1, true));
3513 MockRead reads
[] = {
3514 CreateMockRead(*resp
),
3515 CreateMockRead(*body
),
3516 MockRead(true, 0, 0) // EOF
3519 scoped_refptr
<DelayedSocketData
> data(
3520 new DelayedSocketData(1, reads
, arraysize(reads
),
3521 writes
, arraysize(writes
)));
3522 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
3523 BoundNetLog(), GetParam());
3524 helper
.RunToCompletion(data
.get());
3525 TransactionHelperResult out
= helper
.output();
3526 EXPECT_EQ(ERR_INCOMPLETE_SPDY_HEADERS
, out
.rv
);
3530 // Verify that we don't crash on some corrupt frames.
3531 TEST_P(SpdyNetworkTransactionTest
, CorruptFrameSessionError
) {
3532 // This is the length field that's too short.
3533 scoped_ptr
<spdy::SpdyFrame
> syn_reply_wrong_length(
3534 ConstructSpdyGetSynReply(NULL
, 0, 1));
3535 syn_reply_wrong_length
->set_length(syn_reply_wrong_length
->length() - 4);
3537 struct SynReplyTests
{
3538 const spdy::SpdyFrame
* syn_reply
;
3540 { syn_reply_wrong_length
.get(), },
3543 for (size_t i
= 0; i
< ARRAYSIZE_UNSAFE(test_cases
); ++i
) {
3544 scoped_ptr
<spdy::SpdyFrame
> req(
3545 ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
3546 MockWrite writes
[] = {
3547 CreateMockWrite(*req
),
3548 MockWrite(true, 0, 0) // EOF
3551 scoped_ptr
<spdy::SpdyFrame
> body(ConstructSpdyBodyFrame(1, true));
3552 MockRead reads
[] = {
3553 CreateMockRead(*test_cases
[i
].syn_reply
),
3554 CreateMockRead(*body
),
3555 MockRead(true, 0, 0) // EOF
3558 scoped_refptr
<DelayedSocketData
> data(
3559 new DelayedSocketData(1, reads
, arraysize(reads
),
3560 writes
, arraysize(writes
)));
3561 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
3562 BoundNetLog(), GetParam());
3563 helper
.RunToCompletion(data
.get());
3564 TransactionHelperResult out
= helper
.output();
3565 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR
, out
.rv
);
3569 // Test that we shutdown correctly on write errors.
3570 TEST_P(SpdyNetworkTransactionTest
, WriteError
) {
3571 scoped_ptr
<spdy::SpdyFrame
> req(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
3572 MockWrite writes
[] = {
3573 // We'll write 10 bytes successfully
3574 MockWrite(true, req
->data(), 10),
3575 // Followed by ERROR!
3576 MockWrite(true, ERR_FAILED
),
3579 scoped_refptr
<DelayedSocketData
> data(
3580 new DelayedSocketData(2, NULL
, 0,
3581 writes
, arraysize(writes
)));
3582 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
3583 BoundNetLog(), GetParam());
3584 helper
.RunToCompletion(data
.get());
3585 TransactionHelperResult out
= helper
.output();
3586 EXPECT_EQ(ERR_FAILED
, out
.rv
);
3590 // Test that partial writes work.
3591 TEST_P(SpdyNetworkTransactionTest
, PartialWrite
) {
3592 // Chop the SYN_STREAM frame into 5 chunks.
3593 scoped_ptr
<spdy::SpdyFrame
> req(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
3594 const int kChunks
= 5;
3595 scoped_array
<MockWrite
> writes(ChopWriteFrame(*req
.get(), kChunks
));
3597 scoped_ptr
<spdy::SpdyFrame
> resp(ConstructSpdyGetSynReply(NULL
, 0, 1));
3598 scoped_ptr
<spdy::SpdyFrame
> body(ConstructSpdyBodyFrame(1, true));
3599 MockRead reads
[] = {
3600 CreateMockRead(*resp
),
3601 CreateMockRead(*body
),
3602 MockRead(true, 0, 0) // EOF
3605 scoped_refptr
<DelayedSocketData
> data(
3606 new DelayedSocketData(kChunks
, reads
, arraysize(reads
),
3607 writes
.get(), kChunks
));
3608 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
3609 BoundNetLog(), GetParam());
3610 helper
.RunToCompletion(data
.get());
3611 TransactionHelperResult out
= helper
.output();
3612 EXPECT_EQ(OK
, out
.rv
);
3613 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
3614 EXPECT_EQ("hello!", out
.response_data
);
3617 // In this test, we enable compression, but get a uncompressed SynReply from
3618 // the server. Verify that teardown is all clean.
3619 TEST_P(SpdyNetworkTransactionTest
, DecompressFailureOnSynReply
) {
3620 // For this test, we turn on the normal compression.
3621 EnableCompression(true);
3623 scoped_ptr
<spdy::SpdyFrame
> compressed(
3624 ConstructSpdyGet(NULL
, 0, true, 1, LOWEST
));
3625 scoped_ptr
<spdy::SpdyFrame
> rst(
3626 ConstructSpdyRstStream(1, spdy::PROTOCOL_ERROR
));
3627 MockWrite writes
[] = {
3628 CreateMockWrite(*compressed
),
3629 CreateMockWrite(*rst
),
3632 scoped_ptr
<spdy::SpdyFrame
> resp(ConstructSpdyGetSynReply(NULL
, 0, 1));
3633 scoped_ptr
<spdy::SpdyFrame
> body(ConstructSpdyBodyFrame(1, true));
3634 MockRead reads
[] = {
3635 CreateMockRead(*resp
),
3636 CreateMockRead(*body
),
3637 MockRead(true, 0, 0)
3640 scoped_refptr
<DelayedSocketData
> data(
3641 new DelayedSocketData(1, reads
, arraysize(reads
),
3642 writes
, arraysize(writes
)));
3643 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
3644 BoundNetLog(), GetParam());
3645 helper
.RunToCompletion(data
.get());
3646 TransactionHelperResult out
= helper
.output();
3647 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR
, out
.rv
);
3650 EnableCompression(false);
3653 // Test that the NetLog contains good data for a simple GET request.
3654 TEST_P(SpdyNetworkTransactionTest
, NetLog
) {
3655 static const char* const kExtraHeaders
[] = {
3656 "user-agent", "Chrome",
3658 scoped_ptr
<spdy::SpdyFrame
> req(ConstructSpdyGet(kExtraHeaders
, 1, false, 1,
3660 MockWrite writes
[] = { CreateMockWrite(*req
) };
3662 scoped_ptr
<spdy::SpdyFrame
> resp(ConstructSpdyGetSynReply(NULL
, 0, 1));
3663 scoped_ptr
<spdy::SpdyFrame
> body(ConstructSpdyBodyFrame(1, true));
3664 MockRead reads
[] = {
3665 CreateMockRead(*resp
),
3666 CreateMockRead(*body
),
3667 MockRead(true, 0, 0) // EOF
3670 net::CapturingBoundNetLog
log(net::CapturingNetLog::kUnbounded
);
3672 scoped_refptr
<DelayedSocketData
> data(
3673 new DelayedSocketData(1, reads
, arraysize(reads
),
3674 writes
, arraysize(writes
)));
3675 NormalSpdyTransactionHelper
helper(CreateGetRequestWithUserAgent(),
3676 log
.bound(), GetParam());
3677 helper
.RunToCompletion(data
.get());
3678 TransactionHelperResult out
= helper
.output();
3679 EXPECT_EQ(OK
, out
.rv
);
3680 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
3681 EXPECT_EQ("hello!", out
.response_data
);
3683 // Check that the NetLog was filled reasonably.
3684 // This test is intentionally non-specific about the exact ordering of the
3685 // log; instead we just check to make sure that certain events exist, and that
3686 // they are in the right order.
3687 net::CapturingNetLog::EntryList entries
;
3688 log
.GetEntries(&entries
);
3690 EXPECT_LT(0u, entries
.size());
3692 pos
= net::ExpectLogContainsSomewhere(entries
, 0,
3693 net::NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST
,
3694 net::NetLog::PHASE_BEGIN
);
3695 pos
= net::ExpectLogContainsSomewhere(entries
, pos
+ 1,
3696 net::NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST
,
3697 net::NetLog::PHASE_END
);
3698 pos
= net::ExpectLogContainsSomewhere(entries
, pos
+ 1,
3699 net::NetLog::TYPE_HTTP_TRANSACTION_READ_HEADERS
,
3700 net::NetLog::PHASE_BEGIN
);
3701 pos
= net::ExpectLogContainsSomewhere(entries
, pos
+ 1,
3702 net::NetLog::TYPE_HTTP_TRANSACTION_READ_HEADERS
,
3703 net::NetLog::PHASE_END
);
3704 pos
= net::ExpectLogContainsSomewhere(entries
, pos
+ 1,
3705 net::NetLog::TYPE_HTTP_TRANSACTION_READ_BODY
,
3706 net::NetLog::PHASE_BEGIN
);
3707 pos
= net::ExpectLogContainsSomewhere(entries
, pos
+ 1,
3708 net::NetLog::TYPE_HTTP_TRANSACTION_READ_BODY
,
3709 net::NetLog::PHASE_END
);
3711 // Check that we logged all the headers correctly
3712 pos
= net::ExpectLogContainsSomewhere(
3714 net::NetLog::TYPE_SPDY_SESSION_SYN_STREAM
,
3715 net::NetLog::PHASE_NONE
);
3716 CapturingNetLog::Entry entry
= entries
[pos
];
3717 NetLogSpdySynParameter
* request_params
=
3718 static_cast<NetLogSpdySynParameter
*>(entry
.extra_parameters
.get());
3719 spdy::SpdyHeaderBlock
* headers
=
3720 request_params
->GetHeaders().get();
3722 spdy::SpdyHeaderBlock expected
;
3723 expected
["host"] = "www.google.com";
3724 expected
["url"] = "/";
3725 expected
["scheme"] = "http";
3726 expected
["version"] = "HTTP/1.1";
3727 expected
["method"] = "GET";
3728 expected
["user-agent"] = "Chrome";
3729 EXPECT_EQ(expected
.size(), headers
->size());
3730 spdy::SpdyHeaderBlock::const_iterator end
= expected
.end();
3731 for (spdy::SpdyHeaderBlock::const_iterator it
= expected
.begin();
3734 EXPECT_EQ(it
->second
, (*headers
)[it
->first
]);
3738 // Since we buffer the IO from the stream to the renderer, this test verifies
3739 // that when we read out the maximum amount of data (e.g. we received 50 bytes
3740 // on the network, but issued a Read for only 5 of those bytes) that the data
3741 // flow still works correctly.
3742 TEST_P(SpdyNetworkTransactionTest
, BufferFull
) {
3743 spdy::SpdyFramer framer
;
3745 scoped_ptr
<spdy::SpdyFrame
> req(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
3746 MockWrite writes
[] = { CreateMockWrite(*req
) };
3748 // 2 data frames in a single read.
3749 scoped_ptr
<spdy::SpdyFrame
> data_frame_1(
3750 framer
.CreateDataFrame(1, "goodby", 6, spdy::DATA_FLAG_NONE
));
3751 scoped_ptr
<spdy::SpdyFrame
> data_frame_2(
3752 framer
.CreateDataFrame(1, "e worl", 6, spdy::DATA_FLAG_NONE
));
3753 const spdy::SpdyFrame
* data_frames
[2] = {
3757 char combined_data_frames
[100];
3758 int combined_data_frames_len
=
3759 CombineFrames(data_frames
, arraysize(data_frames
),
3760 combined_data_frames
, arraysize(combined_data_frames
));
3761 scoped_ptr
<spdy::SpdyFrame
> last_frame(
3762 framer
.CreateDataFrame(1, "d", 1, spdy::DATA_FLAG_FIN
));
3764 scoped_ptr
<spdy::SpdyFrame
> resp(ConstructSpdyGetSynReply(NULL
, 0, 1));
3765 MockRead reads
[] = {
3766 CreateMockRead(*resp
),
3767 MockRead(true, ERR_IO_PENDING
), // Force a pause
3768 MockRead(true, combined_data_frames
, combined_data_frames_len
),
3769 MockRead(true, ERR_IO_PENDING
), // Force a pause
3770 CreateMockRead(*last_frame
),
3771 MockRead(true, 0, 0) // EOF
3774 scoped_refptr
<DelayedSocketData
> data(
3775 new DelayedSocketData(1, reads
, arraysize(reads
),
3776 writes
, arraysize(writes
)));
3779 TestCompletionCallback callback
;
3781 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
3782 BoundNetLog(), GetParam());
3783 helper
.RunPreTestSetup();
3784 helper
.AddData(data
.get());
3785 HttpNetworkTransaction
* trans
= helper
.trans();
3786 int rv
= trans
->Start(&CreateGetRequest(), &callback
, BoundNetLog());
3787 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3789 TransactionHelperResult out
= helper
.output();
3790 out
.rv
= callback
.WaitForResult();
3791 EXPECT_EQ(out
.rv
, OK
);
3793 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3794 EXPECT_TRUE(response
->headers
!= NULL
);
3795 EXPECT_TRUE(response
->was_fetched_via_spdy
);
3796 out
.status_line
= response
->headers
->GetStatusLine();
3797 out
.response_info
= *response
; // Make a copy so we can verify.
3800 TestCompletionCallback read_callback
;
3802 std::string content
;
3804 // Read small chunks at a time.
3805 const int kSmallReadSize
= 3;
3806 scoped_refptr
<net::IOBuffer
> buf(new net::IOBuffer(kSmallReadSize
));
3807 rv
= trans
->Read(buf
, kSmallReadSize
, &read_callback
);
3808 if (rv
== net::ERR_IO_PENDING
) {
3809 data
->CompleteRead();
3810 rv
= read_callback
.WaitForResult();
3813 content
.append(buf
->data(), rv
);
3814 } else if (rv
< 0) {
3819 out
.response_data
.swap(content
);
3821 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
3822 // MockClientSocketFactory) are still alive.
3823 MessageLoop::current()->RunAllPending();
3825 // Verify that we consumed all test data.
3826 helper
.VerifyDataConsumed();
3828 EXPECT_EQ(OK
, out
.rv
);
3829 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
3830 EXPECT_EQ("goodbye world", out
.response_data
);
3833 // Verify that basic buffering works; when multiple data frames arrive
3834 // at the same time, ensure that we don't notify a read completion for
3835 // each data frame individually.
3836 TEST_P(SpdyNetworkTransactionTest
, Buffering
) {
3837 spdy::SpdyFramer framer
;
3839 scoped_ptr
<spdy::SpdyFrame
> req(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
3840 MockWrite writes
[] = { CreateMockWrite(*req
) };
3842 // 4 data frames in a single read.
3843 scoped_ptr
<spdy::SpdyFrame
> data_frame(
3844 framer
.CreateDataFrame(1, "message", 7, spdy::DATA_FLAG_NONE
));
3845 scoped_ptr
<spdy::SpdyFrame
> data_frame_fin(
3846 framer
.CreateDataFrame(1, "message", 7, spdy::DATA_FLAG_FIN
));
3847 const spdy::SpdyFrame
* data_frames
[4] = {
3851 data_frame_fin
.get()
3853 char combined_data_frames
[100];
3854 int combined_data_frames_len
=
3855 CombineFrames(data_frames
, arraysize(data_frames
),
3856 combined_data_frames
, arraysize(combined_data_frames
));
3858 scoped_ptr
<spdy::SpdyFrame
> resp(ConstructSpdyGetSynReply(NULL
, 0, 1));
3859 MockRead reads
[] = {
3860 CreateMockRead(*resp
),
3861 MockRead(true, ERR_IO_PENDING
), // Force a pause
3862 MockRead(true, combined_data_frames
, combined_data_frames_len
),
3863 MockRead(true, 0, 0) // EOF
3866 scoped_refptr
<DelayedSocketData
> data(
3867 new DelayedSocketData(1, reads
, arraysize(reads
),
3868 writes
, arraysize(writes
)));
3870 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
3871 BoundNetLog(), GetParam());
3872 helper
.RunPreTestSetup();
3873 helper
.AddData(data
.get());
3874 HttpNetworkTransaction
* trans
= helper
.trans();
3876 TestCompletionCallback callback
;
3877 int rv
= trans
->Start(&CreateGetRequest(), &callback
, BoundNetLog());
3878 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3880 TransactionHelperResult out
= helper
.output();
3881 out
.rv
= callback
.WaitForResult();
3882 EXPECT_EQ(out
.rv
, OK
);
3884 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3885 EXPECT_TRUE(response
->headers
!= NULL
);
3886 EXPECT_TRUE(response
->was_fetched_via_spdy
);
3887 out
.status_line
= response
->headers
->GetStatusLine();
3888 out
.response_info
= *response
; // Make a copy so we can verify.
3891 TestCompletionCallback read_callback
;
3893 std::string content
;
3894 int reads_completed
= 0;
3896 // Read small chunks at a time.
3897 const int kSmallReadSize
= 14;
3898 scoped_refptr
<net::IOBuffer
> buf(new net::IOBuffer(kSmallReadSize
));
3899 rv
= trans
->Read(buf
, kSmallReadSize
, &read_callback
);
3900 if (rv
== net::ERR_IO_PENDING
) {
3901 data
->CompleteRead();
3902 rv
= read_callback
.WaitForResult();
3905 EXPECT_EQ(kSmallReadSize
, rv
);
3906 content
.append(buf
->data(), rv
);
3907 } else if (rv
< 0) {
3908 FAIL() << "Unexpected read error: " << rv
;
3913 EXPECT_EQ(3, reads_completed
); // Reads are: 14 bytes, 14 bytes, 0 bytes.
3915 out
.response_data
.swap(content
);
3917 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
3918 // MockClientSocketFactory) are still alive.
3919 MessageLoop::current()->RunAllPending();
3921 // Verify that we consumed all test data.
3922 helper
.VerifyDataConsumed();
3924 EXPECT_EQ(OK
, out
.rv
);
3925 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
3926 EXPECT_EQ("messagemessagemessagemessage", out
.response_data
);
3929 // Verify the case where we buffer data but read it after it has been buffered.
3930 TEST_P(SpdyNetworkTransactionTest
, BufferedAll
) {
3931 spdy::SpdyFramer framer
;
3933 scoped_ptr
<spdy::SpdyFrame
> req(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
3934 MockWrite writes
[] = { CreateMockWrite(*req
) };
3936 // 5 data frames in a single read.
3937 scoped_ptr
<spdy::SpdyFrame
> syn_reply(
3938 ConstructSpdyGetSynReply(NULL
, 0, 1));
3939 syn_reply
->set_flags(spdy::CONTROL_FLAG_NONE
); // turn off FIN bit
3940 scoped_ptr
<spdy::SpdyFrame
> data_frame(
3941 framer
.CreateDataFrame(1, "message", 7, spdy::DATA_FLAG_NONE
));
3942 scoped_ptr
<spdy::SpdyFrame
> data_frame_fin(
3943 framer
.CreateDataFrame(1, "message", 7, spdy::DATA_FLAG_FIN
));
3944 const spdy::SpdyFrame
* frames
[5] = {
3949 data_frame_fin
.get()
3951 char combined_frames
[200];
3952 int combined_frames_len
=
3953 CombineFrames(frames
, arraysize(frames
),
3954 combined_frames
, arraysize(combined_frames
));
3956 MockRead reads
[] = {
3957 MockRead(true, combined_frames
, combined_frames_len
),
3958 MockRead(true, 0, 0) // EOF
3961 scoped_refptr
<DelayedSocketData
> data(
3962 new DelayedSocketData(1, reads
, arraysize(reads
),
3963 writes
, arraysize(writes
)));
3965 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
3966 BoundNetLog(), GetParam());
3967 helper
.RunPreTestSetup();
3968 helper
.AddData(data
.get());
3969 HttpNetworkTransaction
* trans
= helper
.trans();
3971 TestCompletionCallback callback
;
3972 int rv
= trans
->Start(&CreateGetRequest(), &callback
, BoundNetLog());
3973 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3975 TransactionHelperResult out
= helper
.output();
3976 out
.rv
= callback
.WaitForResult();
3977 EXPECT_EQ(out
.rv
, OK
);
3979 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3980 EXPECT_TRUE(response
->headers
!= NULL
);
3981 EXPECT_TRUE(response
->was_fetched_via_spdy
);
3982 out
.status_line
= response
->headers
->GetStatusLine();
3983 out
.response_info
= *response
; // Make a copy so we can verify.
3986 TestCompletionCallback read_callback
;
3988 std::string content
;
3989 int reads_completed
= 0;
3991 // Read small chunks at a time.
3992 const int kSmallReadSize
= 14;
3993 scoped_refptr
<net::IOBuffer
> buf(new net::IOBuffer(kSmallReadSize
));
3994 rv
= trans
->Read(buf
, kSmallReadSize
, &read_callback
);
3996 EXPECT_EQ(kSmallReadSize
, rv
);
3997 content
.append(buf
->data(), rv
);
3998 } else if (rv
< 0) {
3999 FAIL() << "Unexpected read error: " << rv
;
4004 EXPECT_EQ(3, reads_completed
);
4006 out
.response_data
.swap(content
);
4008 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
4009 // MockClientSocketFactory) are still alive.
4010 MessageLoop::current()->RunAllPending();
4012 // Verify that we consumed all test data.
4013 helper
.VerifyDataConsumed();
4015 EXPECT_EQ(OK
, out
.rv
);
4016 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
4017 EXPECT_EQ("messagemessagemessagemessage", out
.response_data
);
4020 // Verify the case where we buffer data and close the connection.
4021 TEST_P(SpdyNetworkTransactionTest
, BufferedClosed
) {
4022 spdy::SpdyFramer framer
;
4024 scoped_ptr
<spdy::SpdyFrame
> req(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
4025 MockWrite writes
[] = { CreateMockWrite(*req
) };
4027 // All data frames in a single read.
4028 // NOTE: We don't FIN the stream.
4029 scoped_ptr
<spdy::SpdyFrame
> data_frame(
4030 framer
.CreateDataFrame(1, "message", 7, spdy::DATA_FLAG_NONE
));
4031 const spdy::SpdyFrame
* data_frames
[4] = {
4037 char combined_data_frames
[100];
4038 int combined_data_frames_len
=
4039 CombineFrames(data_frames
, arraysize(data_frames
),
4040 combined_data_frames
, arraysize(combined_data_frames
));
4041 scoped_ptr
<spdy::SpdyFrame
> resp(ConstructSpdyGetSynReply(NULL
, 0, 1));
4042 MockRead reads
[] = {
4043 CreateMockRead(*resp
),
4044 MockRead(true, ERR_IO_PENDING
), // Force a wait
4045 MockRead(true, combined_data_frames
, combined_data_frames_len
),
4046 MockRead(true, 0, 0) // EOF
4049 scoped_refptr
<DelayedSocketData
> data(
4050 new DelayedSocketData(1, reads
, arraysize(reads
),
4051 writes
, arraysize(writes
)));
4053 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
4054 BoundNetLog(), GetParam());
4055 helper
.RunPreTestSetup();
4056 helper
.AddData(data
.get());
4057 HttpNetworkTransaction
* trans
= helper
.trans();
4059 TestCompletionCallback callback
;
4061 int rv
= trans
->Start(&CreateGetRequest(), &callback
, BoundNetLog());
4062 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4064 TransactionHelperResult out
= helper
.output();
4065 out
.rv
= callback
.WaitForResult();
4066 EXPECT_EQ(out
.rv
, OK
);
4068 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4069 EXPECT_TRUE(response
->headers
!= NULL
);
4070 EXPECT_TRUE(response
->was_fetched_via_spdy
);
4071 out
.status_line
= response
->headers
->GetStatusLine();
4072 out
.response_info
= *response
; // Make a copy so we can verify.
4075 TestCompletionCallback read_callback
;
4077 std::string content
;
4078 int reads_completed
= 0;
4080 // Read small chunks at a time.
4081 const int kSmallReadSize
= 14;
4082 scoped_refptr
<net::IOBuffer
> buf(new net::IOBuffer(kSmallReadSize
));
4083 rv
= trans
->Read(buf
, kSmallReadSize
, &read_callback
);
4084 if (rv
== net::ERR_IO_PENDING
) {
4085 data
->CompleteRead();
4086 rv
= read_callback
.WaitForResult();
4089 content
.append(buf
->data(), rv
);
4090 } else if (rv
< 0) {
4091 // This test intentionally closes the connection, and will get an error.
4092 EXPECT_EQ(ERR_CONNECTION_CLOSED
, rv
);
4098 EXPECT_EQ(0, reads_completed
);
4100 out
.response_data
.swap(content
);
4102 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
4103 // MockClientSocketFactory) are still alive.
4104 MessageLoop::current()->RunAllPending();
4106 // Verify that we consumed all test data.
4107 helper
.VerifyDataConsumed();
4110 // Verify the case where we buffer data and cancel the transaction.
4111 TEST_P(SpdyNetworkTransactionTest
, BufferedCancelled
) {
4112 spdy::SpdyFramer framer
;
4114 scoped_ptr
<spdy::SpdyFrame
> req(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
4115 MockWrite writes
[] = { CreateMockWrite(*req
) };
4117 // NOTE: We don't FIN the stream.
4118 scoped_ptr
<spdy::SpdyFrame
> data_frame(
4119 framer
.CreateDataFrame(1, "message", 7, spdy::DATA_FLAG_NONE
));
4121 scoped_ptr
<spdy::SpdyFrame
> resp(ConstructSpdyGetSynReply(NULL
, 0, 1));
4122 MockRead reads
[] = {
4123 CreateMockRead(*resp
),
4124 MockRead(true, ERR_IO_PENDING
), // Force a wait
4125 CreateMockRead(*data_frame
),
4126 MockRead(true, 0, 0) // EOF
4129 scoped_refptr
<DelayedSocketData
> data(
4130 new DelayedSocketData(1, reads
, arraysize(reads
),
4131 writes
, arraysize(writes
)));
4133 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
4134 BoundNetLog(), GetParam());
4135 helper
.RunPreTestSetup();
4136 helper
.AddData(data
.get());
4137 HttpNetworkTransaction
* trans
= helper
.trans();
4138 TestCompletionCallback callback
;
4140 int rv
= trans
->Start(&CreateGetRequest(), &callback
, BoundNetLog());
4141 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4143 TransactionHelperResult out
= helper
.output();
4144 out
.rv
= callback
.WaitForResult();
4145 EXPECT_EQ(out
.rv
, OK
);
4147 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4148 EXPECT_TRUE(response
->headers
!= NULL
);
4149 EXPECT_TRUE(response
->was_fetched_via_spdy
);
4150 out
.status_line
= response
->headers
->GetStatusLine();
4151 out
.response_info
= *response
; // Make a copy so we can verify.
4154 TestCompletionCallback read_callback
;
4157 const int kReadSize
= 256;
4158 scoped_refptr
<net::IOBuffer
> buf(new net::IOBuffer(kReadSize
));
4159 rv
= trans
->Read(buf
, kReadSize
, &read_callback
);
4160 if (rv
== net::ERR_IO_PENDING
) {
4161 // Complete the read now, which causes buffering to start.
4162 data
->CompleteRead();
4163 // Destroy the transaction, causing the stream to get cancelled
4164 // and orphaning the buffered IO task.
4165 helper
.ResetTrans();
4168 // We shouldn't get here in this test.
4169 FAIL() << "Unexpected read: " << rv
;
4172 // Flush the MessageLoop; this will cause the buffered IO task
4173 // to run for the final time.
4174 MessageLoop::current()->RunAllPending();
4176 // Verify that we consumed all test data.
4177 helper
.VerifyDataConsumed();
4180 // Test that if the server requests persistence of settings, that we save
4181 // the settings in the SpdySettingsStorage.
4182 TEST_P(SpdyNetworkTransactionTest
, SettingsSaved
) {
4183 static const SpdyHeaderInfo kSynReplyInfo
= {
4184 spdy::SYN_REPLY
, // Syn Reply
4186 0, // Associated Stream ID
4187 net::ConvertRequestPriorityToSpdyPriority(LOWEST
),
4189 spdy::CONTROL_FLAG_NONE
, // Control Flags
4190 false, // Compressed
4191 spdy::INVALID
, // Status
4194 spdy::DATA_FLAG_NONE
// Data Flags
4196 static const char* const kExtraHeaders
[] = {
4198 "version", "HTTP/1.1"
4201 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
4202 BoundNetLog(), GetParam());
4203 helper
.RunPreTestSetup();
4205 // Verify that no settings exist initially.
4206 HostPortPair
host_port_pair("www.google.com", helper
.port());
4207 SpdySessionPool
* spdy_session_pool
= helper
.session()->spdy_session_pool();
4208 EXPECT_TRUE(spdy_session_pool
->spdy_settings().Get(host_port_pair
).empty());
4210 // Construct the request.
4211 scoped_ptr
<spdy::SpdyFrame
> req(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
4212 MockWrite writes
[] = { CreateMockWrite(*req
) };
4214 // Construct the reply.
4215 scoped_ptr
<spdy::SpdyFrame
> reply(
4216 ConstructSpdyPacket(kSynReplyInfo
,
4218 arraysize(kExtraHeaders
) / 2,
4222 unsigned int kSampleId1
= 0x1;
4223 unsigned int kSampleValue1
= 0x0a0a0a0a;
4224 unsigned int kSampleId2
= 0x2;
4225 unsigned int kSampleValue2
= 0x0b0b0b0b;
4226 unsigned int kSampleId3
= 0xababab;
4227 unsigned int kSampleValue3
= 0x0c0c0c0c;
4228 scoped_ptr
<spdy::SpdyFrame
> settings_frame
;
4230 // Construct the SETTINGS frame.
4231 spdy::SpdySettings settings
;
4232 spdy::SettingsFlagsAndId
setting(0);
4233 // First add a persisted setting
4234 setting
.set_flags(spdy::SETTINGS_FLAG_PLEASE_PERSIST
);
4235 setting
.set_id(kSampleId1
);
4236 settings
.push_back(std::make_pair(setting
, kSampleValue1
));
4237 // Next add a non-persisted setting
4238 setting
.set_flags(0);
4239 setting
.set_id(kSampleId2
);
4240 settings
.push_back(std::make_pair(setting
, kSampleValue2
));
4241 // Next add another persisted setting
4242 setting
.set_flags(spdy::SETTINGS_FLAG_PLEASE_PERSIST
);
4243 setting
.set_id(kSampleId3
);
4244 settings
.push_back(std::make_pair(setting
, kSampleValue3
));
4245 settings_frame
.reset(ConstructSpdySettings(settings
));
4248 scoped_ptr
<spdy::SpdyFrame
> body(ConstructSpdyBodyFrame(1, true));
4249 MockRead reads
[] = {
4250 CreateMockRead(*reply
),
4251 CreateMockRead(*body
),
4252 CreateMockRead(*settings_frame
),
4253 MockRead(true, 0, 0) // EOF
4256 scoped_refptr
<DelayedSocketData
> data(
4257 new DelayedSocketData(1, reads
, arraysize(reads
),
4258 writes
, arraysize(writes
)));
4259 helper
.AddData(data
.get());
4260 helper
.RunDefaultTest();
4261 helper
.VerifyDataConsumed();
4262 TransactionHelperResult out
= helper
.output();
4263 EXPECT_EQ(OK
, out
.rv
);
4264 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
4265 EXPECT_EQ("hello!", out
.response_data
);
4268 // Verify we had two persisted settings.
4269 spdy::SpdySettings saved_settings
=
4270 spdy_session_pool
->spdy_settings().Get(host_port_pair
);
4271 ASSERT_EQ(2u, saved_settings
.size());
4273 // Verify the first persisted setting.
4274 spdy::SpdySetting setting
= saved_settings
.front();
4275 saved_settings
.pop_front();
4276 EXPECT_EQ(spdy::SETTINGS_FLAG_PERSISTED
, setting
.first
.flags());
4277 EXPECT_EQ(kSampleId1
, setting
.first
.id());
4278 EXPECT_EQ(kSampleValue1
, setting
.second
);
4280 // Verify the second persisted setting.
4281 setting
= saved_settings
.front();
4282 saved_settings
.pop_front();
4283 EXPECT_EQ(spdy::SETTINGS_FLAG_PERSISTED
, setting
.first
.flags());
4284 EXPECT_EQ(kSampleId3
, setting
.first
.id());
4285 EXPECT_EQ(kSampleValue3
, setting
.second
);
4289 // Test that when there are settings saved that they are sent back to the
4290 // server upon session establishment.
4291 TEST_P(SpdyNetworkTransactionTest
, SettingsPlayback
) {
4292 static const SpdyHeaderInfo kSynReplyInfo
= {
4293 spdy::SYN_REPLY
, // Syn Reply
4295 0, // Associated Stream ID
4296 net::ConvertRequestPriorityToSpdyPriority(LOWEST
),
4298 spdy::CONTROL_FLAG_NONE
, // Control Flags
4299 false, // Compressed
4300 spdy::INVALID
, // Status
4303 spdy::DATA_FLAG_NONE
// Data Flags
4305 static const char* kExtraHeaders
[] = {
4307 "version", "HTTP/1.1"
4310 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
4311 BoundNetLog(), GetParam());
4312 helper
.RunPreTestSetup();
4314 // Verify that no settings exist initially.
4315 HostPortPair
host_port_pair("www.google.com", helper
.port());
4316 SpdySessionPool
* spdy_session_pool
= helper
.session()->spdy_session_pool();
4317 EXPECT_TRUE(spdy_session_pool
->spdy_settings().Get(host_port_pair
).empty());
4319 unsigned int kSampleId1
= 0x1;
4320 unsigned int kSampleValue1
= 0x0a0a0a0a;
4321 unsigned int kSampleId2
= 0xababab;
4322 unsigned int kSampleValue2
= 0x0c0c0c0c;
4323 // Manually insert settings into the SpdySettingsStorage here.
4325 spdy::SpdySettings settings
;
4326 spdy::SettingsFlagsAndId
setting(0);
4327 // First add a persisted setting
4328 setting
.set_flags(spdy::SETTINGS_FLAG_PLEASE_PERSIST
);
4329 setting
.set_id(kSampleId1
);
4330 settings
.push_back(std::make_pair(setting
, kSampleValue1
));
4331 // Next add another persisted setting
4332 setting
.set_flags(spdy::SETTINGS_FLAG_PLEASE_PERSIST
);
4333 setting
.set_id(kSampleId2
);
4334 settings
.push_back(std::make_pair(setting
, kSampleValue2
));
4336 spdy_session_pool
->mutable_spdy_settings()->Set(host_port_pair
, settings
);
4339 EXPECT_EQ(2u, spdy_session_pool
->spdy_settings().Get(host_port_pair
).size());
4341 // Construct the SETTINGS frame.
4342 const spdy::SpdySettings
& settings
=
4343 spdy_session_pool
->spdy_settings().Get(host_port_pair
);
4344 scoped_ptr
<spdy::SpdyFrame
> settings_frame(ConstructSpdySettings(settings
));
4346 // Construct the request.
4347 scoped_ptr
<spdy::SpdyFrame
> req(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
4349 MockWrite writes
[] = {
4350 CreateMockWrite(*settings_frame
),
4351 CreateMockWrite(*req
),
4354 // Construct the reply.
4355 scoped_ptr
<spdy::SpdyFrame
> reply(
4356 ConstructSpdyPacket(kSynReplyInfo
,
4358 arraysize(kExtraHeaders
) / 2,
4362 scoped_ptr
<spdy::SpdyFrame
> body(ConstructSpdyBodyFrame(1, true));
4363 MockRead reads
[] = {
4364 CreateMockRead(*reply
),
4365 CreateMockRead(*body
),
4366 MockRead(true, 0, 0) // EOF
4369 scoped_refptr
<DelayedSocketData
> data(
4370 new DelayedSocketData(2, reads
, arraysize(reads
),
4371 writes
, arraysize(writes
)));
4372 helper
.AddData(data
.get());
4373 helper
.RunDefaultTest();
4374 helper
.VerifyDataConsumed();
4375 TransactionHelperResult out
= helper
.output();
4376 EXPECT_EQ(OK
, out
.rv
);
4377 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
4378 EXPECT_EQ("hello!", out
.response_data
);
4381 // Verify we had two persisted settings.
4382 spdy::SpdySettings saved_settings
=
4383 spdy_session_pool
->spdy_settings().Get(host_port_pair
);
4384 ASSERT_EQ(2u, saved_settings
.size());
4386 // Verify the first persisted setting.
4387 spdy::SpdySetting setting
= saved_settings
.front();
4388 saved_settings
.pop_front();
4389 EXPECT_EQ(spdy::SETTINGS_FLAG_PERSISTED
, setting
.first
.flags());
4390 EXPECT_EQ(kSampleId1
, setting
.first
.id());
4391 EXPECT_EQ(kSampleValue1
, setting
.second
);
4393 // Verify the second persisted setting.
4394 setting
= saved_settings
.front();
4395 saved_settings
.pop_front();
4396 EXPECT_EQ(spdy::SETTINGS_FLAG_PERSISTED
, setting
.first
.flags());
4397 EXPECT_EQ(kSampleId2
, setting
.first
.id());
4398 EXPECT_EQ(kSampleValue2
, setting
.second
);
4402 TEST_P(SpdyNetworkTransactionTest
, GoAwayWithActiveStream
) {
4403 scoped_ptr
<spdy::SpdyFrame
> req(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
4404 MockWrite writes
[] = { CreateMockWrite(*req
) };
4406 scoped_ptr
<spdy::SpdyFrame
> go_away(ConstructSpdyGoAway());
4407 MockRead reads
[] = {
4408 CreateMockRead(*go_away
),
4409 MockRead(true, 0, 0), // EOF
4412 scoped_refptr
<DelayedSocketData
> data(
4413 new DelayedSocketData(1, reads
, arraysize(reads
),
4414 writes
, arraysize(writes
)));
4415 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
4416 BoundNetLog(), GetParam());
4417 helper
.AddData(data
);
4418 helper
.RunToCompletion(data
.get());
4419 TransactionHelperResult out
= helper
.output();
4420 EXPECT_EQ(ERR_ABORTED
, out
.rv
);
4423 TEST_P(SpdyNetworkTransactionTest
, CloseWithActiveStream
) {
4424 scoped_ptr
<spdy::SpdyFrame
> req(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
4425 MockWrite writes
[] = { CreateMockWrite(*req
) };
4427 scoped_ptr
<spdy::SpdyFrame
> resp(ConstructSpdyGetSynReply(NULL
, 0, 1));
4428 MockRead reads
[] = {
4429 CreateMockRead(*resp
),
4430 MockRead(false, 0, 0) // EOF
4433 scoped_refptr
<DelayedSocketData
> data(
4434 new DelayedSocketData(1, reads
, arraysize(reads
),
4435 writes
, arraysize(writes
)));
4437 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
4439 helper
.RunPreTestSetup();
4440 helper
.AddData(data
.get());
4441 HttpNetworkTransaction
* trans
= helper
.trans();
4443 TestCompletionCallback callback
;
4444 TransactionHelperResult out
;
4445 out
.rv
= trans
->Start(&CreateGetRequest(), &callback
, log
);
4447 EXPECT_EQ(out
.rv
, ERR_IO_PENDING
);
4448 out
.rv
= callback
.WaitForResult();
4449 EXPECT_EQ(out
.rv
, OK
);
4451 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4452 EXPECT_TRUE(response
->headers
!= NULL
);
4453 EXPECT_TRUE(response
->was_fetched_via_spdy
);
4454 out
.rv
= ReadTransaction(trans
, &out
.response_data
);
4455 EXPECT_EQ(ERR_CONNECTION_CLOSED
, out
.rv
);
4457 // Verify that we consumed all test data.
4458 helper
.VerifyDataConsumed();
4461 // Test to make sure we can correctly connect through a proxy.
4462 TEST_P(SpdyNetworkTransactionTest
, ProxyConnect
) {
4463 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
4464 BoundNetLog(), GetParam());
4465 helper
.session_deps().reset(new SpdySessionDependencies(
4466 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70")));
4467 helper
.SetSession(make_scoped_refptr(
4468 SpdySessionDependencies::SpdyCreateSession(helper
.session_deps().get())));
4469 helper
.RunPreTestSetup();
4470 HttpNetworkTransaction
* trans
= helper
.trans();
4472 const char kConnect443
[] = {"CONNECT www.google.com:443 HTTP/1.1\r\n"
4473 "Host: www.google.com\r\n"
4474 "Proxy-Connection: keep-alive\r\n\r\n"};
4475 const char kConnect80
[] = {"CONNECT www.google.com:80 HTTP/1.1\r\n"
4476 "Host: www.google.com\r\n"
4477 "Proxy-Connection: keep-alive\r\n\r\n"};
4478 const char kHTTP200
[] = {"HTTP/1.1 200 OK\r\n\r\n"};
4479 scoped_ptr
<spdy::SpdyFrame
> req(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
4480 scoped_ptr
<spdy::SpdyFrame
> resp(ConstructSpdyGetSynReply(NULL
, 0, 1));
4481 scoped_ptr
<spdy::SpdyFrame
> body(ConstructSpdyBodyFrame(1, true));
4483 MockWrite writes_SPDYNPN
[] = {
4484 MockWrite(false, kConnect443
, arraysize(kConnect443
) - 1, 0),
4485 CreateMockWrite(*req
, 2),
4487 MockRead reads_SPDYNPN
[] = {
4488 MockRead(false, kHTTP200
, arraysize(kHTTP200
) - 1, 1),
4489 CreateMockRead(*resp
, 3),
4490 CreateMockRead(*body
.get(), 4),
4491 MockRead(true, 0, 0, 5),
4494 MockWrite writes_SPDYSSL
[] = {
4495 MockWrite(false, kConnect80
, arraysize(kConnect80
) - 1, 0),
4496 CreateMockWrite(*req
, 2),
4498 MockRead reads_SPDYSSL
[] = {
4499 MockRead(false, kHTTP200
, arraysize(kHTTP200
) - 1, 1),
4500 CreateMockRead(*resp
, 3),
4501 CreateMockRead(*body
.get(), 4),
4502 MockRead(true, 0, 0, 5),
4505 MockWrite writes_SPDYNOSSL
[] = {
4506 CreateMockWrite(*req
, 0),
4509 MockRead reads_SPDYNOSSL
[] = {
4510 CreateMockRead(*resp
, 1),
4511 CreateMockRead(*body
.get(), 2),
4512 MockRead(true, 0, 0, 3),
4515 scoped_refptr
<OrderedSocketData
> data
;
4516 switch(GetParam()) {
4518 data
= new OrderedSocketData(reads_SPDYNOSSL
,
4519 arraysize(reads_SPDYNOSSL
),
4521 arraysize(writes_SPDYNOSSL
));
4524 data
= new OrderedSocketData(reads_SPDYSSL
, arraysize(reads_SPDYSSL
),
4525 writes_SPDYSSL
, arraysize(writes_SPDYSSL
));
4528 data
= new OrderedSocketData(reads_SPDYNPN
, arraysize(reads_SPDYNPN
),
4529 writes_SPDYNPN
, arraysize(writes_SPDYNPN
));
4535 helper
.AddData(data
.get());
4536 TestCompletionCallback callback
;
4538 int rv
= trans
->Start(&CreateGetRequest(), &callback
, BoundNetLog());
4539 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4541 rv
= callback
.WaitForResult();
4544 // Verify the SYN_REPLY.
4545 HttpResponseInfo response
= *trans
->GetResponseInfo();
4546 EXPECT_TRUE(response
.headers
!= NULL
);
4547 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
4549 std::string response_data
;
4550 ASSERT_EQ(OK
, ReadTransaction(trans
, &response_data
));
4551 EXPECT_EQ("hello!", response_data
);
4552 helper
.VerifyDataConsumed();
4555 // Test to make sure we can correctly connect through a proxy to www.google.com,
4556 // if there already exists a direct spdy connection to www.google.com. See
4557 // http://crbug.com/49874
4558 TEST_P(SpdyNetworkTransactionTest
, DirectConnectProxyReconnect
) {
4559 // When setting up the first transaction, we store the SpdySessionPool so that
4560 // we can use the same pool in the second transaction.
4561 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
4562 BoundNetLog(), GetParam());
4564 // Use a proxy service which returns a proxy fallback list from DIRECT to
4565 // myproxy:70. For this test there will be no fallback, so it is equivalent
4566 // to simply DIRECT. The reason for appending the second proxy is to verify
4567 // that the session pool key used does is just "DIRECT".
4568 helper
.session_deps().reset(new SpdySessionDependencies(
4569 ProxyService::CreateFixedFromPacResult("DIRECT; PROXY myproxy:70")));
4570 helper
.SetSession(make_scoped_refptr(
4571 SpdySessionDependencies::SpdyCreateSession(helper
.session_deps().get())));
4573 SpdySessionPool
* spdy_session_pool
= helper
.session()->spdy_session_pool();
4574 helper
.RunPreTestSetup();
4576 // Construct and send a simple GET request.
4577 scoped_ptr
<spdy::SpdyFrame
> req(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
4578 MockWrite writes
[] = {
4579 CreateMockWrite(*req
, 1),
4582 scoped_ptr
<spdy::SpdyFrame
> resp(ConstructSpdyGetSynReply(NULL
, 0, 1));
4583 scoped_ptr
<spdy::SpdyFrame
> body(ConstructSpdyBodyFrame(1, true));
4584 MockRead reads
[] = {
4585 CreateMockRead(*resp
, 2),
4586 CreateMockRead(*body
, 3),
4587 MockRead(true, ERR_IO_PENDING
, 4), // Force a pause
4588 MockRead(true, 0, 5) // EOF
4590 scoped_refptr
<OrderedSocketData
> data(
4591 new OrderedSocketData(reads
, arraysize(reads
),
4592 writes
, arraysize(writes
)));
4593 helper
.AddData(data
.get());
4594 HttpNetworkTransaction
* trans
= helper
.trans();
4596 TestCompletionCallback callback
;
4597 TransactionHelperResult out
;
4598 out
.rv
= trans
->Start(&CreateGetRequest(), &callback
, BoundNetLog());
4600 EXPECT_EQ(out
.rv
, ERR_IO_PENDING
);
4601 out
.rv
= callback
.WaitForResult();
4602 EXPECT_EQ(out
.rv
, OK
);
4604 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4605 EXPECT_TRUE(response
->headers
!= NULL
);
4606 EXPECT_TRUE(response
->was_fetched_via_spdy
);
4607 out
.rv
= ReadTransaction(trans
, &out
.response_data
);
4608 EXPECT_EQ(OK
, out
.rv
);
4609 out
.status_line
= response
->headers
->GetStatusLine();
4610 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
4611 EXPECT_EQ("hello!", out
.response_data
);
4613 // Check that the SpdySession is still in the SpdySessionPool.
4614 HostPortPair
host_port_pair("www.google.com", helper
.port());
4615 HostPortProxyPair
session_pool_key_direct(
4616 host_port_pair
, ProxyServer::Direct());
4617 EXPECT_TRUE(spdy_session_pool
->HasSession(session_pool_key_direct
));
4618 HostPortProxyPair
session_pool_key_proxy(
4620 ProxyServer::FromURI("www.foo.com", ProxyServer::SCHEME_HTTP
));
4621 EXPECT_FALSE(spdy_session_pool
->HasSession(session_pool_key_proxy
));
4623 // Set up data for the proxy connection.
4624 const char kConnect443
[] = {"CONNECT www.google.com:443 HTTP/1.1\r\n"
4625 "Host: www.google.com\r\n"
4626 "Proxy-Connection: keep-alive\r\n\r\n"};
4627 const char kConnect80
[] = {"CONNECT www.google.com:80 HTTP/1.1\r\n"
4628 "Host: www.google.com\r\n"
4629 "Proxy-Connection: keep-alive\r\n\r\n"};
4630 const char kHTTP200
[] = {"HTTP/1.1 200 OK\r\n\r\n"};
4631 scoped_ptr
<spdy::SpdyFrame
> req2(ConstructSpdyGet(
4632 "http://www.google.com/foo.dat", false, 1, LOWEST
));
4633 scoped_ptr
<spdy::SpdyFrame
> resp2(ConstructSpdyGetSynReply(NULL
, 0, 1));
4634 scoped_ptr
<spdy::SpdyFrame
> body2(ConstructSpdyBodyFrame(1, true));
4636 MockWrite writes_SPDYNPN
[] = {
4637 MockWrite(false, kConnect443
, arraysize(kConnect443
) - 1, 0),
4638 CreateMockWrite(*req2
, 2),
4640 MockRead reads_SPDYNPN
[] = {
4641 MockRead(false, kHTTP200
, arraysize(kHTTP200
) - 1, 1),
4642 CreateMockRead(*resp2
, 3),
4643 CreateMockRead(*body2
, 4),
4644 MockRead(true, 0, 5) // EOF
4647 MockWrite writes_SPDYNOSSL
[] = {
4648 CreateMockWrite(*req2
, 0),
4650 MockRead reads_SPDYNOSSL
[] = {
4651 CreateMockRead(*resp2
, 1),
4652 CreateMockRead(*body2
, 2),
4653 MockRead(true, 0, 3) // EOF
4656 MockWrite writes_SPDYSSL
[] = {
4657 MockWrite(false, kConnect80
, arraysize(kConnect80
) - 1, 0),
4658 CreateMockWrite(*req2
, 2),
4660 MockRead reads_SPDYSSL
[] = {
4661 MockRead(false, kHTTP200
, arraysize(kHTTP200
) - 1, 1),
4662 CreateMockRead(*resp2
, 3),
4663 CreateMockRead(*body2
, 4),
4664 MockRead(true, 0, 0, 5),
4667 scoped_refptr
<OrderedSocketData
> data_proxy
;
4668 switch(GetParam()) {
4670 data_proxy
= new OrderedSocketData(reads_SPDYNPN
,
4671 arraysize(reads_SPDYNPN
),
4673 arraysize(writes_SPDYNPN
));
4676 data_proxy
= new OrderedSocketData(reads_SPDYNOSSL
,
4677 arraysize(reads_SPDYNOSSL
),
4679 arraysize(writes_SPDYNOSSL
));
4682 data_proxy
= new OrderedSocketData(reads_SPDYSSL
,
4683 arraysize(reads_SPDYSSL
),
4685 arraysize(writes_SPDYSSL
));
4691 // Create another request to www.google.com, but this time through a proxy.
4692 HttpRequestInfo request_proxy
;
4693 request_proxy
.method
= "GET";
4694 request_proxy
.url
= GURL("http://www.google.com/foo.dat");
4695 request_proxy
.load_flags
= 0;
4696 scoped_ptr
<SpdySessionDependencies
> ssd_proxy(new SpdySessionDependencies());
4697 // Ensure that this transaction uses the same SpdySessionPool.
4698 scoped_refptr
<HttpNetworkSession
> session_proxy(
4699 SpdySessionDependencies::SpdyCreateSession(ssd_proxy
.get()));
4700 NormalSpdyTransactionHelper
helper_proxy(request_proxy
,
4701 BoundNetLog(), GetParam());
4702 HttpNetworkSessionPeer
session_peer(session_proxy
);
4703 scoped_ptr
<net::ProxyService
> proxy_service(
4704 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
4705 session_peer
.SetProxyService(proxy_service
.get());
4706 helper_proxy
.session_deps().swap(ssd_proxy
);
4707 helper_proxy
.SetSession(session_proxy
);
4708 helper_proxy
.RunPreTestSetup();
4709 helper_proxy
.AddData(data_proxy
.get());
4711 HttpNetworkTransaction
* trans_proxy
= helper_proxy
.trans();
4712 TestCompletionCallback callback_proxy
;
4713 int rv
= trans_proxy
->Start(&request_proxy
, &callback_proxy
, BoundNetLog());
4714 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4715 rv
= callback_proxy
.WaitForResult();
4718 HttpResponseInfo response_proxy
= *trans_proxy
->GetResponseInfo();
4719 EXPECT_TRUE(response_proxy
.headers
!= NULL
);
4720 EXPECT_EQ("HTTP/1.1 200 OK", response_proxy
.headers
->GetStatusLine());
4722 std::string response_data
;
4723 ASSERT_EQ(OK
, ReadTransaction(trans_proxy
, &response_data
));
4724 EXPECT_EQ("hello!", response_data
);
4726 data
->CompleteRead();
4727 helper_proxy
.VerifyDataConsumed();
4730 // When we get a TCP-level RST, we need to retry a HttpNetworkTransaction
4731 // on a new connection, if the connection was previously known to be good.
4732 // This can happen when a server reboots without saying goodbye, or when
4733 // we're behind a NAT that masked the RST.
4734 TEST_P(SpdyNetworkTransactionTest
, VerifyRetryOnConnectionReset
) {
4735 scoped_ptr
<spdy::SpdyFrame
> resp(ConstructSpdyGetSynReply(NULL
, 0, 1));
4736 scoped_ptr
<spdy::SpdyFrame
> body(ConstructSpdyBodyFrame(1, true));
4737 MockRead reads
[] = {
4738 CreateMockRead(*resp
),
4739 CreateMockRead(*body
),
4740 MockRead(true, ERR_IO_PENDING
),
4741 MockRead(true, ERR_CONNECTION_RESET
),
4744 MockRead reads2
[] = {
4745 CreateMockRead(*resp
),
4746 CreateMockRead(*body
),
4747 MockRead(true, 0, 0) // EOF
4750 // This test has a couple of variants.
4752 // Induce the RST while waiting for our transaction to send.
4753 VARIANT_RST_DURING_SEND_COMPLETION
,
4754 // Induce the RST while waiting for our transaction to read.
4755 // In this case, the send completed - everything copied into the SNDBUF.
4756 VARIANT_RST_DURING_READ_COMPLETION
4759 for (int variant
= VARIANT_RST_DURING_SEND_COMPLETION
;
4760 variant
<= VARIANT_RST_DURING_READ_COMPLETION
;
4762 scoped_refptr
<DelayedSocketData
> data1(
4763 new DelayedSocketData(1, reads
, arraysize(reads
),
4766 scoped_refptr
<DelayedSocketData
> data2(
4767 new DelayedSocketData(1, reads2
, arraysize(reads2
),
4770 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
4771 BoundNetLog(), GetParam());
4772 helper
.AddData(data1
.get());
4773 helper
.AddData(data2
.get());
4774 helper
.RunPreTestSetup();
4776 for (int i
= 0; i
< 2; ++i
) {
4777 scoped_ptr
<HttpNetworkTransaction
> trans(
4778 new HttpNetworkTransaction(helper
.session()));
4780 TestCompletionCallback callback
;
4781 int rv
= trans
->Start(&helper
.request(), &callback
, BoundNetLog());
4782 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4783 // On the second transaction, we trigger the RST.
4785 if (variant
== VARIANT_RST_DURING_READ_COMPLETION
) {
4786 // Writes to the socket complete asynchronously on SPDY by running
4787 // through the message loop. Complete the write here.
4788 MessageLoop::current()->RunAllPending();
4791 // Now schedule the ERR_CONNECTION_RESET.
4792 EXPECT_EQ(3u, data1
->read_index());
4793 data1
->CompleteRead();
4794 EXPECT_EQ(4u, data1
->read_index());
4796 rv
= callback
.WaitForResult();
4799 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4800 ASSERT_TRUE(response
!= NULL
);
4801 EXPECT_TRUE(response
->headers
!= NULL
);
4802 EXPECT_TRUE(response
->was_fetched_via_spdy
);
4803 std::string response_data
;
4804 rv
= ReadTransaction(trans
.get(), &response_data
);
4806 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
4807 EXPECT_EQ("hello!", response_data
);
4810 helper
.VerifyDataConsumed();
4814 // Test that turning SPDY on and off works properly.
4815 TEST_P(SpdyNetworkTransactionTest
, SpdyOnOffToggle
) {
4816 net::HttpStreamFactory::set_spdy_enabled(true);
4817 scoped_ptr
<spdy::SpdyFrame
> req(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
4818 MockWrite spdy_writes
[] = { CreateMockWrite(*req
) };
4820 scoped_ptr
<spdy::SpdyFrame
> resp(ConstructSpdyGetSynReply(NULL
, 0, 1));
4821 scoped_ptr
<spdy::SpdyFrame
> body(ConstructSpdyBodyFrame(1, true));
4822 MockRead spdy_reads
[] = {
4823 CreateMockRead(*resp
),
4824 CreateMockRead(*body
),
4825 MockRead(true, 0, 0) // EOF
4828 scoped_refptr
<DelayedSocketData
> data(
4829 new DelayedSocketData(1,
4830 spdy_reads
, arraysize(spdy_reads
),
4831 spdy_writes
, arraysize(spdy_writes
)));
4832 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
4833 BoundNetLog(), GetParam());
4834 helper
.RunToCompletion(data
.get());
4835 TransactionHelperResult out
= helper
.output();
4836 EXPECT_EQ(OK
, out
.rv
);
4837 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
4838 EXPECT_EQ("hello!", out
.response_data
);
4840 net::HttpStreamFactory::set_spdy_enabled(false);
4841 MockRead http_reads
[] = {
4842 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
4843 MockRead("hello from http"),
4844 MockRead(false, OK
),
4846 scoped_refptr
<DelayedSocketData
> data2(
4847 new DelayedSocketData(1, http_reads
, arraysize(http_reads
),
4849 NormalSpdyTransactionHelper
helper2(CreateGetRequest(),
4850 BoundNetLog(), GetParam());
4851 helper2
.SetSpdyDisabled();
4852 helper2
.RunToCompletion(data2
.get());
4853 TransactionHelperResult out2
= helper2
.output();
4854 EXPECT_EQ(OK
, out2
.rv
);
4855 EXPECT_EQ("HTTP/1.1 200 OK", out2
.status_line
);
4856 EXPECT_EQ("hello from http", out2
.response_data
);
4858 net::HttpStreamFactory::set_spdy_enabled(true);
4861 // Tests that Basic authentication works over SPDY
4862 TEST_P(SpdyNetworkTransactionTest
, SpdyBasicAuth
) {
4863 net::HttpStreamFactory::set_spdy_enabled(true);
4865 // The first request will be a bare GET, the second request will be a
4866 // GET with an Authorization header.
4867 scoped_ptr
<spdy::SpdyFrame
> req_get(
4868 ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
4869 const char* const kExtraAuthorizationHeaders
[] = {
4871 "Basic Zm9vOmJhcg==",
4873 scoped_ptr
<spdy::SpdyFrame
> req_get_authorization(
4875 kExtraAuthorizationHeaders
,
4876 arraysize(kExtraAuthorizationHeaders
) / 2,
4878 MockWrite spdy_writes
[] = {
4879 CreateMockWrite(*req_get
, 1),
4880 CreateMockWrite(*req_get_authorization
, 4),
4883 // The first response is a 401 authentication challenge, and the second
4884 // response will be a 200 response since the second request includes a valid
4885 // Authorization header.
4886 const char* const kExtraAuthenticationHeaders
[] = {
4888 "Basic realm=\"MyRealm\""
4890 scoped_ptr
<spdy::SpdyFrame
> resp_authentication(
4891 ConstructSpdySynReplyError(
4892 "401 Authentication Required",
4893 kExtraAuthenticationHeaders
,
4894 arraysize(kExtraAuthenticationHeaders
) / 2,
4896 scoped_ptr
<spdy::SpdyFrame
> body_authentication(
4897 ConstructSpdyBodyFrame(1, true));
4898 scoped_ptr
<spdy::SpdyFrame
> resp_data(ConstructSpdyGetSynReply(NULL
, 0, 3));
4899 scoped_ptr
<spdy::SpdyFrame
> body_data(ConstructSpdyBodyFrame(3, true));
4900 MockRead spdy_reads
[] = {
4901 CreateMockRead(*resp_authentication
, 2),
4902 CreateMockRead(*body_authentication
, 3),
4903 CreateMockRead(*resp_data
, 5),
4904 CreateMockRead(*body_data
, 6),
4905 MockRead(true, 0, 7),
4908 scoped_refptr
<OrderedSocketData
> data(
4909 new OrderedSocketData(spdy_reads
, arraysize(spdy_reads
),
4910 spdy_writes
, arraysize(spdy_writes
)));
4911 HttpRequestInfo
request(CreateGetRequest());
4912 BoundNetLog net_log
;
4913 NormalSpdyTransactionHelper
helper(request
, net_log
, GetParam());
4915 helper
.RunPreTestSetup();
4916 helper
.AddData(data
.get());
4917 HttpNetworkTransaction
* trans
= helper
.trans();
4918 TestCompletionCallback callback_start
;
4919 const int rv_start
= trans
->Start(&request
, &callback_start
, net_log
);
4920 EXPECT_EQ(ERR_IO_PENDING
, rv_start
);
4921 const int rv_start_complete
= callback_start
.WaitForResult();
4922 EXPECT_EQ(OK
, rv_start_complete
);
4924 // Make sure the response has an auth challenge.
4925 const HttpResponseInfo
* const response_start
= trans
->GetResponseInfo();
4926 ASSERT_TRUE(response_start
!= NULL
);
4927 ASSERT_TRUE(response_start
->headers
!= NULL
);
4928 EXPECT_EQ(401, response_start
->headers
->response_code());
4929 EXPECT_TRUE(response_start
->was_fetched_via_spdy
);
4930 ASSERT_TRUE(response_start
->auth_challenge
.get() != NULL
);
4931 EXPECT_FALSE(response_start
->auth_challenge
->is_proxy
);
4932 EXPECT_EQ(L
"basic", response_start
->auth_challenge
->scheme
);
4933 EXPECT_EQ(L
"MyRealm", response_start
->auth_challenge
->realm
);
4935 // Restart with a username/password.
4936 const string16
kFoo(ASCIIToUTF16("foo"));
4937 const string16
kBar(ASCIIToUTF16("bar"));
4938 TestCompletionCallback callback_restart
;
4939 const int rv_restart
= trans
->RestartWithAuth(kFoo
, kBar
, &callback_restart
);
4940 EXPECT_EQ(ERR_IO_PENDING
, rv_restart
);
4941 const int rv_restart_complete
= callback_restart
.WaitForResult();
4942 EXPECT_EQ(OK
, rv_restart_complete
);
4943 // TODO(cbentzel): This is actually the same response object as before, but
4944 // data has changed.
4945 const HttpResponseInfo
* const response_restart
= trans
->GetResponseInfo();
4946 ASSERT_TRUE(response_restart
!= NULL
);
4947 ASSERT_TRUE(response_restart
->headers
!= NULL
);
4948 EXPECT_EQ(200, response_restart
->headers
->response_code());
4949 EXPECT_TRUE(response_restart
->auth_challenge
.get() == NULL
);
4952 TEST_P(SpdyNetworkTransactionTest
, ServerPushWithHeaders
) {
4953 static const unsigned char kPushBodyFrame
[] = {
4954 0x00, 0x00, 0x00, 0x02, // header, ID
4955 0x01, 0x00, 0x00, 0x06, // FIN, length
4956 'p', 'u', 's', 'h', 'e', 'd' // "pushed"
4958 scoped_ptr
<spdy::SpdyFrame
>
4959 stream1_syn(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
4960 scoped_ptr
<spdy::SpdyFrame
>
4961 stream1_body(ConstructSpdyBodyFrame(1, true));
4962 MockWrite writes
[] = {
4963 CreateMockWrite(*stream1_syn
, 1),
4966 static const char* const kInitialHeaders
[] = {
4968 "http://www.google.com/foo.dat",
4970 static const char* const kLateHeaders
[] = {
4978 scoped_ptr
<spdy::SpdyFrame
>
4979 stream2_syn(ConstructSpdyControlFrame(kInitialHeaders
,
4980 arraysize(kInitialHeaders
) / 2,
4985 spdy::CONTROL_FLAG_NONE
,
4989 scoped_ptr
<spdy::SpdyFrame
>
4990 stream2_headers(ConstructSpdyControlFrame(kLateHeaders
,
4991 arraysize(kLateHeaders
) / 2,
4996 spdy::CONTROL_FLAG_NONE
,
5001 scoped_ptr
<spdy::SpdyFrame
>
5002 stream1_reply(ConstructSpdyGetSynReply(NULL
, 0, 1));
5003 MockRead reads
[] = {
5004 CreateMockRead(*stream1_reply
, 2),
5005 CreateMockRead(*stream2_syn
, 3),
5006 CreateMockRead(*stream2_headers
, 4),
5007 CreateMockRead(*stream1_body
, 5, false),
5008 MockRead(true, reinterpret_cast<const char*>(kPushBodyFrame
),
5009 arraysize(kPushBodyFrame
), 6),
5010 MockRead(true, ERR_IO_PENDING
, 7), // Force a pause
5013 HttpResponseInfo response
;
5014 HttpResponseInfo response2
;
5015 std::string
expected_push_result("pushed");
5016 scoped_refptr
<OrderedSocketData
> data(new OrderedSocketData(
5020 arraysize(writes
)));
5021 RunServerPushTest(data
.get(),
5024 expected_push_result
);
5026 // Verify the SYN_REPLY.
5027 EXPECT_TRUE(response
.headers
!= NULL
);
5028 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
5030 // Verify the pushed stream.
5031 EXPECT_TRUE(response2
.headers
!= NULL
);
5032 EXPECT_EQ("HTTP/1.1 200 OK", response2
.headers
->GetStatusLine());
5035 TEST_P(SpdyNetworkTransactionTest
, ServerPushClaimBeforeHeaders
) {
5036 // We push a stream and attempt to claim it before the headers come down.
5037 static const unsigned char kPushBodyFrame
[] = {
5038 0x00, 0x00, 0x00, 0x02, // header, ID
5039 0x01, 0x00, 0x00, 0x06, // FIN, length
5040 'p', 'u', 's', 'h', 'e', 'd' // "pushed"
5042 scoped_ptr
<spdy::SpdyFrame
>
5043 stream1_syn(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
5044 scoped_ptr
<spdy::SpdyFrame
>
5045 stream1_body(ConstructSpdyBodyFrame(1, true));
5046 MockWrite writes
[] = {
5047 CreateMockWrite(*stream1_syn
, 0, false),
5050 static const char* const kInitialHeaders
[] = {
5052 "http://www.google.com/foo.dat",
5054 static const char* const kLateHeaders
[] = {
5062 scoped_ptr
<spdy::SpdyFrame
>
5063 stream2_syn(ConstructSpdyControlFrame(kInitialHeaders
,
5064 arraysize(kInitialHeaders
) / 2,
5069 spdy::CONTROL_FLAG_NONE
,
5073 scoped_ptr
<spdy::SpdyFrame
>
5074 stream2_headers(ConstructSpdyControlFrame(kLateHeaders
,
5075 arraysize(kLateHeaders
) / 2,
5080 spdy::CONTROL_FLAG_NONE
,
5085 scoped_ptr
<spdy::SpdyFrame
>
5086 stream1_reply(ConstructSpdyGetSynReply(NULL
, 0, 1));
5087 MockRead reads
[] = {
5088 CreateMockRead(*stream1_reply
, 1),
5089 CreateMockRead(*stream2_syn
, 2),
5090 CreateMockRead(*stream1_body
, 3),
5091 CreateMockRead(*stream2_headers
, 4),
5092 MockRead(true, reinterpret_cast<const char*>(kPushBodyFrame
),
5093 arraysize(kPushBodyFrame
), 5),
5094 MockRead(true, 0, 5), // EOF
5097 HttpResponseInfo response
;
5098 HttpResponseInfo response2
;
5099 std::string
expected_push_result("pushed");
5100 scoped_refptr
<DeterministicSocketData
> data(new DeterministicSocketData(
5104 arraysize(writes
)));
5106 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
5107 BoundNetLog(), GetParam());
5108 helper
.SetDeterministic();
5109 helper
.AddDeterministicData(static_cast<DeterministicSocketData
*>(data
));
5110 helper
.RunPreTestSetup();
5112 HttpNetworkTransaction
* trans
= helper
.trans();
5114 // Run until we've received the primary SYN_STREAM, the pushed SYN_STREAM,
5115 // and the body of the primary stream, but before we've received the HEADERS
5116 // for the pushed stream.
5119 // Start the transaction.
5120 TestCompletionCallback callback
;
5121 int rv
= trans
->Start(&CreateGetRequest(), &callback
, BoundNetLog());
5122 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5124 rv
= callback
.WaitForResult();
5127 // Request the pushed path. At this point, we've received the push, but the
5128 // headers are not yet complete.
5129 scoped_ptr
<HttpNetworkTransaction
> trans2(
5130 new HttpNetworkTransaction(helper
.session()));
5131 rv
= trans2
->Start(&CreateGetPushRequest(), &callback
, BoundNetLog());
5132 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5134 MessageLoop::current()->RunAllPending();
5136 // Read the server push body.
5137 std::string result2
;
5138 ReadResult(trans2
.get(), data
.get(), &result2
);
5139 // Read the response body.
5141 ReadResult(trans
, data
, &result
);
5143 // Verify that we consumed all test data.
5144 EXPECT_TRUE(data
->at_read_eof());
5145 EXPECT_TRUE(data
->at_write_eof());
5147 // Verify that the received push data is same as the expected push data.
5148 EXPECT_EQ(result2
.compare(expected_push_result
), 0)
5149 << "Received data: "
5151 << "||||| Expected data: "
5152 << expected_push_result
;
5154 // Verify the SYN_REPLY.
5155 // Copy the response info, because trans goes away.
5156 response
= *trans
->GetResponseInfo();
5157 response2
= *trans2
->GetResponseInfo();
5159 VerifyStreamsClosed(helper
);
5161 // Verify the SYN_REPLY.
5162 EXPECT_TRUE(response
.headers
!= NULL
);
5163 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
5165 // Verify the pushed stream.
5166 EXPECT_TRUE(response2
.headers
!= NULL
);
5167 EXPECT_EQ("HTTP/1.1 200 OK", response2
.headers
->GetStatusLine());
5170 TEST_P(SpdyNetworkTransactionTest
, ServerPushWithTwoHeaderFrames
) {
5171 // We push a stream and attempt to claim it before the headers come down.
5172 static const unsigned char kPushBodyFrame
[] = {
5173 0x00, 0x00, 0x00, 0x02, // header, ID
5174 0x01, 0x00, 0x00, 0x06, // FIN, length
5175 'p', 'u', 's', 'h', 'e', 'd' // "pushed"
5177 scoped_ptr
<spdy::SpdyFrame
>
5178 stream1_syn(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
5179 scoped_ptr
<spdy::SpdyFrame
>
5180 stream1_body(ConstructSpdyBodyFrame(1, true));
5181 MockWrite writes
[] = {
5182 CreateMockWrite(*stream1_syn
, 0, false),
5185 static const char* const kInitialHeaders
[] = {
5187 "http://www.google.com/foo.dat",
5189 static const char* const kMiddleHeaders
[] = {
5193 static const char* const kLateHeaders
[] = {
5199 scoped_ptr
<spdy::SpdyFrame
>
5200 stream2_syn(ConstructSpdyControlFrame(kInitialHeaders
,
5201 arraysize(kInitialHeaders
) / 2,
5206 spdy::CONTROL_FLAG_NONE
,
5210 scoped_ptr
<spdy::SpdyFrame
>
5211 stream2_headers1(ConstructSpdyControlFrame(kMiddleHeaders
,
5212 arraysize(kMiddleHeaders
) / 2,
5217 spdy::CONTROL_FLAG_NONE
,
5221 scoped_ptr
<spdy::SpdyFrame
>
5222 stream2_headers2(ConstructSpdyControlFrame(kLateHeaders
,
5223 arraysize(kLateHeaders
) / 2,
5228 spdy::CONTROL_FLAG_NONE
,
5233 scoped_ptr
<spdy::SpdyFrame
>
5234 stream1_reply(ConstructSpdyGetSynReply(NULL
, 0, 1));
5235 MockRead reads
[] = {
5236 CreateMockRead(*stream1_reply
, 1),
5237 CreateMockRead(*stream2_syn
, 2),
5238 CreateMockRead(*stream1_body
, 3),
5239 CreateMockRead(*stream2_headers1
, 4),
5240 CreateMockRead(*stream2_headers2
, 5),
5241 MockRead(true, reinterpret_cast<const char*>(kPushBodyFrame
),
5242 arraysize(kPushBodyFrame
), 6),
5243 MockRead(true, 0, 6), // EOF
5246 HttpResponseInfo response
;
5247 HttpResponseInfo response2
;
5248 std::string
expected_push_result("pushed");
5249 scoped_refptr
<DeterministicSocketData
> data(new DeterministicSocketData(
5253 arraysize(writes
)));
5255 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
5256 BoundNetLog(), GetParam());
5257 helper
.SetDeterministic();
5258 helper
.AddDeterministicData(static_cast<DeterministicSocketData
*>(data
));
5259 helper
.RunPreTestSetup();
5261 HttpNetworkTransaction
* trans
= helper
.trans();
5263 // Run until we've received the primary SYN_STREAM, the pushed SYN_STREAM,
5264 // the first HEADERS frame, and the body of the primary stream, but before
5265 // we've received the final HEADERS for the pushed stream.
5268 // Start the transaction.
5269 TestCompletionCallback callback
;
5270 int rv
= trans
->Start(&CreateGetRequest(), &callback
, BoundNetLog());
5271 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5273 rv
= callback
.WaitForResult();
5276 // Request the pushed path. At this point, we've received the push, but the
5277 // headers are not yet complete.
5278 scoped_ptr
<HttpNetworkTransaction
> trans2(
5279 new HttpNetworkTransaction(helper
.session()));
5280 rv
= trans2
->Start(&CreateGetPushRequest(), &callback
, BoundNetLog());
5281 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5283 MessageLoop::current()->RunAllPending();
5285 // Read the server push body.
5286 std::string result2
;
5287 ReadResult(trans2
.get(), data
, &result2
);
5288 // Read the response body.
5290 ReadResult(trans
, data
, &result
);
5292 // Verify that we consumed all test data.
5293 EXPECT_TRUE(data
->at_read_eof());
5294 EXPECT_TRUE(data
->at_write_eof());
5296 // Verify that the received push data is same as the expected push data.
5297 EXPECT_EQ(result2
.compare(expected_push_result
), 0)
5298 << "Received data: "
5300 << "||||| Expected data: "
5301 << expected_push_result
;
5303 // Verify the SYN_REPLY.
5304 // Copy the response info, because trans goes away.
5305 response
= *trans
->GetResponseInfo();
5306 response2
= *trans2
->GetResponseInfo();
5308 VerifyStreamsClosed(helper
);
5310 // Verify the SYN_REPLY.
5311 EXPECT_TRUE(response
.headers
!= NULL
);
5312 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
5314 // Verify the pushed stream.
5315 EXPECT_TRUE(response2
.headers
!= NULL
);
5316 EXPECT_EQ("HTTP/1.1 200 OK", response2
.headers
->GetStatusLine());
5318 // Verify we got all the headers
5319 EXPECT_TRUE(response2
.headers
->HasHeaderValue(
5321 "http://www.google.com/foo.dat"));
5322 EXPECT_TRUE(response2
.headers
->HasHeaderValue("hello", "bye"));
5323 EXPECT_TRUE(response2
.headers
->HasHeaderValue("status", "200"));
5324 EXPECT_TRUE(response2
.headers
->HasHeaderValue("version", "HTTP/1.1"));
5327 TEST_P(SpdyNetworkTransactionTest
, SynReplyWithHeaders
) {
5328 scoped_ptr
<spdy::SpdyFrame
> req(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
5329 MockWrite writes
[] = { CreateMockWrite(*req
) };
5331 static const char* const kInitialHeaders
[] = {
5337 static const char* const kLateHeaders
[] = {
5341 scoped_ptr
<spdy::SpdyFrame
>
5342 stream1_reply(ConstructSpdyControlFrame(kInitialHeaders
,
5343 arraysize(kInitialHeaders
) / 2,
5348 spdy::CONTROL_FLAG_NONE
,
5352 scoped_ptr
<spdy::SpdyFrame
>
5353 stream1_headers(ConstructSpdyControlFrame(kLateHeaders
,
5354 arraysize(kLateHeaders
) / 2,
5359 spdy::CONTROL_FLAG_NONE
,
5363 scoped_ptr
<spdy::SpdyFrame
> stream1_body(ConstructSpdyBodyFrame(1, true));
5364 MockRead reads
[] = {
5365 CreateMockRead(*stream1_reply
),
5366 CreateMockRead(*stream1_headers
),
5367 CreateMockRead(*stream1_body
),
5368 MockRead(true, 0, 0) // EOF
5371 scoped_refptr
<DelayedSocketData
> data(
5372 new DelayedSocketData(1, reads
, arraysize(reads
),
5373 writes
, arraysize(writes
)));
5374 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
5375 BoundNetLog(), GetParam());
5376 helper
.RunToCompletion(data
.get());
5377 TransactionHelperResult out
= helper
.output();
5378 EXPECT_EQ(OK
, out
.rv
);
5379 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
5380 EXPECT_EQ("hello!", out
.response_data
);
5383 TEST_P(SpdyNetworkTransactionTest
, SynReplyWithLateHeaders
) {
5384 scoped_ptr
<spdy::SpdyFrame
> req(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
5385 MockWrite writes
[] = { CreateMockWrite(*req
) };
5387 static const char* const kInitialHeaders
[] = {
5393 static const char* const kLateHeaders
[] = {
5397 scoped_ptr
<spdy::SpdyFrame
>
5398 stream1_reply(ConstructSpdyControlFrame(kInitialHeaders
,
5399 arraysize(kInitialHeaders
) / 2,
5404 spdy::CONTROL_FLAG_NONE
,
5408 scoped_ptr
<spdy::SpdyFrame
>
5409 stream1_headers(ConstructSpdyControlFrame(kLateHeaders
,
5410 arraysize(kLateHeaders
) / 2,
5415 spdy::CONTROL_FLAG_NONE
,
5419 scoped_ptr
<spdy::SpdyFrame
> stream1_body(ConstructSpdyBodyFrame(1, false));
5420 scoped_ptr
<spdy::SpdyFrame
> stream1_body2(ConstructSpdyBodyFrame(1, true));
5421 MockRead reads
[] = {
5422 CreateMockRead(*stream1_reply
),
5423 CreateMockRead(*stream1_body
),
5424 CreateMockRead(*stream1_headers
),
5425 CreateMockRead(*stream1_body2
),
5426 MockRead(true, 0, 0) // EOF
5429 scoped_refptr
<DelayedSocketData
> data(
5430 new DelayedSocketData(1, reads
, arraysize(reads
),
5431 writes
, arraysize(writes
)));
5432 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
5433 BoundNetLog(), GetParam());
5434 helper
.RunToCompletion(data
.get());
5435 TransactionHelperResult out
= helper
.output();
5436 EXPECT_EQ(OK
, out
.rv
);
5437 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
5438 EXPECT_EQ("hello!hello!", out
.response_data
);
5441 TEST_P(SpdyNetworkTransactionTest
, SynReplyWithDuplicateLateHeaders
) {
5442 scoped_ptr
<spdy::SpdyFrame
> req(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
5443 MockWrite writes
[] = { CreateMockWrite(*req
) };
5445 static const char* const kInitialHeaders
[] = {
5451 static const char* const kLateHeaders
[] = {
5455 scoped_ptr
<spdy::SpdyFrame
>
5456 stream1_reply(ConstructSpdyControlFrame(kInitialHeaders
,
5457 arraysize(kInitialHeaders
) / 2,
5462 spdy::CONTROL_FLAG_NONE
,
5466 scoped_ptr
<spdy::SpdyFrame
>
5467 stream1_headers(ConstructSpdyControlFrame(kLateHeaders
,
5468 arraysize(kLateHeaders
) / 2,
5473 spdy::CONTROL_FLAG_NONE
,
5477 scoped_ptr
<spdy::SpdyFrame
> stream1_body(ConstructSpdyBodyFrame(1, false));
5478 scoped_ptr
<spdy::SpdyFrame
> stream1_body2(ConstructSpdyBodyFrame(1, true));
5479 MockRead reads
[] = {
5480 CreateMockRead(*stream1_reply
),
5481 CreateMockRead(*stream1_body
),
5482 CreateMockRead(*stream1_headers
),
5483 CreateMockRead(*stream1_body2
),
5484 MockRead(true, 0, 0) // EOF
5487 scoped_refptr
<DelayedSocketData
> data(
5488 new DelayedSocketData(1, reads
, arraysize(reads
),
5489 writes
, arraysize(writes
)));
5490 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
5491 BoundNetLog(), GetParam());
5492 helper
.RunToCompletion(data
.get());
5493 TransactionHelperResult out
= helper
.output();
5494 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR
, out
.rv
);
5497 TEST_P(SpdyNetworkTransactionTest
, ServerPushCrossOriginCorrectness
) {
5498 // In this test we want to verify that we can't accidentally push content
5499 // which can't be pushed by this content server.
5500 // This test assumes that:
5501 // - if we're requesting http://www.foo.com/barbaz
5502 // - the browser has made a connection to "www.foo.com".
5504 // A list of the URL to fetch, followed by the URL being pushed.
5505 static const char* const kTestCases
[] = {
5506 "http://www.google.com/foo.html",
5507 "http://www.google.com:81/foo.js", // Bad port
5509 "http://www.google.com/foo.html",
5510 "https://www.google.com/foo.js", // Bad protocol
5512 "http://www.google.com/foo.html",
5513 "ftp://www.google.com/foo.js", // Invalid Protocol
5515 "http://www.google.com/foo.html",
5516 "http://blat.www.google.com/foo.js", // Cross subdomain
5518 "http://www.google.com/foo.html",
5519 "http://www.foo.com/foo.js", // Cross domain
5523 static const unsigned char kPushBodyFrame
[] = {
5524 0x00, 0x00, 0x00, 0x02, // header, ID
5525 0x01, 0x00, 0x00, 0x06, // FIN, length
5526 'p', 'u', 's', 'h', 'e', 'd' // "pushed"
5529 for (size_t index
= 0; index
< arraysize(kTestCases
); index
+= 2) {
5530 const char* url_to_fetch
= kTestCases
[index
];
5531 const char* url_to_push
= kTestCases
[index
+ 1];
5533 scoped_ptr
<spdy::SpdyFrame
>
5534 stream1_syn(ConstructSpdyGet(url_to_fetch
, false, 1, LOWEST
));
5535 scoped_ptr
<spdy::SpdyFrame
>
5536 stream1_body(ConstructSpdyBodyFrame(1, true));
5537 scoped_ptr
<spdy::SpdyFrame
> push_rst(
5538 ConstructSpdyRstStream(2, spdy::REFUSED_STREAM
));
5539 MockWrite writes
[] = {
5540 CreateMockWrite(*stream1_syn
, 1),
5541 CreateMockWrite(*push_rst
, 4),
5544 scoped_ptr
<spdy::SpdyFrame
>
5545 stream1_reply(ConstructSpdyGetSynReply(NULL
, 0, 1));
5546 scoped_ptr
<spdy::SpdyFrame
>
5547 stream2_syn(ConstructSpdyPush(NULL
,
5552 scoped_ptr
<spdy::SpdyFrame
> rst(
5553 ConstructSpdyRstStream(2, spdy::CANCEL
));
5555 MockRead reads
[] = {
5556 CreateMockRead(*stream1_reply
, 2),
5557 CreateMockRead(*stream2_syn
, 3),
5558 CreateMockRead(*stream1_body
, 5, false),
5559 MockRead(true, reinterpret_cast<const char*>(kPushBodyFrame
),
5560 arraysize(kPushBodyFrame
), 6),
5561 MockRead(true, ERR_IO_PENDING
, 7), // Force a pause
5564 HttpResponseInfo response
;
5565 scoped_refptr
<OrderedSocketData
> data(new OrderedSocketData(
5569 arraysize(writes
)));
5571 HttpRequestInfo request
;
5572 request
.method
= "GET";
5573 request
.url
= GURL(url_to_fetch
);
5574 request
.load_flags
= 0;
5575 NormalSpdyTransactionHelper
helper(request
,
5576 BoundNetLog(), GetParam());
5577 helper
.RunPreTestSetup();
5578 helper
.AddData(data
);
5580 HttpNetworkTransaction
* trans
= helper
.trans();
5582 // Start the transaction with basic parameters.
5583 TestCompletionCallback callback
;
5585 int rv
= trans
->Start(&request
, &callback
, BoundNetLog());
5586 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5587 rv
= callback
.WaitForResult();
5589 // Read the response body.
5591 ReadResult(trans
, data
, &result
);
5593 // Verify that we consumed all test data.
5594 EXPECT_TRUE(data
->at_read_eof());
5595 EXPECT_TRUE(data
->at_write_eof());
5597 // Verify the SYN_REPLY.
5598 // Copy the response info, because trans goes away.
5599 response
= *trans
->GetResponseInfo();
5601 VerifyStreamsClosed(helper
);
5603 // Verify the SYN_REPLY.
5604 EXPECT_TRUE(response
.headers
!= NULL
);
5605 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());