1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "net/http/http_network_transaction.h"
10 #include "base/bind.h"
11 #include "base/bind_helpers.h"
12 #include "net/base/auth.h"
13 #include "net/base/net_log_unittest.h"
14 #include "net/http/http_network_session_peer.h"
15 #include "net/http/http_transaction_unittest.h"
16 #include "net/socket/client_socket_pool_base.h"
17 #include "net/spdy/spdy_http_stream.h"
18 #include "net/spdy/spdy_http_utils.h"
19 #include "net/spdy/spdy_session.h"
20 #include "net/spdy/spdy_session_pool.h"
21 #include "net/spdy/spdy_test_util.h"
22 #include "net/url_request/url_request_test_util.h"
23 #include "testing/platform_test.h"
25 //-----------------------------------------------------------------------------
29 enum SpdyNetworkTransactionTestTypes
{
34 class SpdyNetworkTransactionTest
35 : public ::testing::TestWithParam
<SpdyNetworkTransactionTestTypes
> {
38 virtual void SetUp() {
39 // By default, all tests turn off compression.
40 EnableCompression(false);
41 google_get_request_initialized_
= false;
42 google_post_request_initialized_
= false;
43 google_chunked_post_request_initialized_
= false;
46 virtual void TearDown() {
47 // Empty the current queue.
48 MessageLoop::current()->RunAllPending();
51 struct TransactionHelperResult
{
53 std::string status_line
;
54 std::string response_data
;
55 HttpResponseInfo response_info
;
58 void EnableCompression(bool enabled
) {
59 spdy::SpdyFramer::set_enable_compression_default(enabled
);
62 // A helper class that handles all the initial npn/ssl setup.
63 class NormalSpdyTransactionHelper
{
65 NormalSpdyTransactionHelper(const HttpRequestInfo
& request
,
66 const BoundNetLog
& log
,
67 SpdyNetworkTransactionTestTypes test_type
)
69 session_deps_(new SpdySessionDependencies()),
70 session_(SpdySessionDependencies::SpdyCreateSession(
71 session_deps_
.get())),
73 test_type_(test_type
),
74 deterministic_(false),
89 ~NormalSpdyTransactionHelper() {
90 // Any test which doesn't close the socket by sending it an EOF will
91 // have a valid session left open, which leaks the entire session pool.
92 // This is just fine - in fact, some of our tests intentionally do this
93 // so that we can check consistency of the SpdySessionPool as the test
94 // finishes. If we had put an EOF on the socket, the SpdySession would
95 // have closed and we wouldn't be able to check the consistency.
97 // Forcefully close existing sessions here.
98 session()->spdy_session_pool()->CloseAllSessions();
101 void SetDeterministic() {
102 session_
= SpdySessionDependencies::SpdyCreateSessionDeterministic(
103 session_deps_
.get());
104 deterministic_
= true;
107 void SetSpdyDisabled() {
108 spdy_enabled_
= false;
111 void RunPreTestSetup() {
112 if (!session_deps_
.get())
113 session_deps_
.reset(new SpdySessionDependencies());
115 session_
= SpdySessionDependencies::SpdyCreateSession(
116 session_deps_
.get());
117 HttpStreamFactory::set_use_alternate_protocols(false);
118 HttpStreamFactory::set_force_spdy_over_ssl(false);
119 HttpStreamFactory::set_force_spdy_always(false);
121 std::vector
<std::string
> next_protos
;
122 next_protos
.push_back("http/1.1");
123 next_protos
.push_back("spdy/2");
124 next_protos
.push_back("spdy/2.1");
126 switch (test_type_
) {
128 session_
->http_server_properties()->SetAlternateProtocol(
129 HostPortPair("www.google.com", 80), 443,
131 HttpStreamFactory::set_use_alternate_protocols(true);
132 HttpStreamFactory::set_next_protos(next_protos
);
135 HttpStreamFactory::set_force_spdy_over_ssl(false);
136 HttpStreamFactory::set_force_spdy_always(true);
139 HttpStreamFactory::set_force_spdy_over_ssl(true);
140 HttpStreamFactory::set_force_spdy_always(true);
146 // We're now ready to use SSL-npn SPDY.
147 trans_
.reset(new HttpNetworkTransaction(session_
));
150 // Start the transaction, read some data, finish.
151 void RunDefaultTest() {
152 output_
.rv
= trans_
->Start(&request_
, callback
.callback(), log_
);
154 // We expect an IO Pending or some sort of error.
155 EXPECT_LT(output_
.rv
, 0);
156 if (output_
.rv
!= ERR_IO_PENDING
)
159 output_
.rv
= callback
.WaitForResult();
160 if (output_
.rv
!= OK
) {
161 session_
->spdy_session_pool()->CloseCurrentSessions();
166 const HttpResponseInfo
* response
= trans_
->GetResponseInfo();
167 ASSERT_TRUE(response
!= NULL
);
168 ASSERT_TRUE(response
->headers
!= NULL
);
169 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
170 EXPECT_EQ(spdy_enabled_
, response
->was_fetched_via_spdy
);
171 if (test_type_
== SPDYNPN
&& spdy_enabled_
) {
172 EXPECT_TRUE(response
->was_npn_negotiated
);
174 EXPECT_TRUE(!response
->was_npn_negotiated
);
176 // If SPDY is not enabled, a HTTP request should not be diverted
177 // over a SSL session.
178 if (!spdy_enabled_
) {
179 EXPECT_EQ(request_
.url
.SchemeIs("https"),
180 response
->was_npn_negotiated
);
182 EXPECT_EQ("192.0.2.33", response
->socket_address
.host());
183 EXPECT_EQ(0, response
->socket_address
.port());
184 output_
.status_line
= response
->headers
->GetStatusLine();
185 output_
.response_info
= *response
; // Make a copy so we can verify.
186 output_
.rv
= ReadTransaction(trans_
.get(), &output_
.response_data
);
189 // Most tests will want to call this function. In particular, the MockReads
190 // should end with an empty read, and that read needs to be processed to
191 // ensure proper deletion of the spdy_session_pool.
192 void VerifyDataConsumed() {
193 for (DataVector::iterator it
= data_vector_
.begin();
194 it
!= data_vector_
.end(); ++it
) {
195 EXPECT_TRUE((*it
)->at_read_eof()) << "Read count: "
196 << (*it
)->read_count()
198 << (*it
)->read_index();
199 EXPECT_TRUE((*it
)->at_write_eof()) << "Write count: "
200 << (*it
)->write_count()
202 << (*it
)->write_index();
206 // Occasionally a test will expect to error out before certain reads are
207 // processed. In that case we want to explicitly ensure that the reads were
209 void VerifyDataNotConsumed() {
210 for (DataVector::iterator it
= data_vector_
.begin();
211 it
!= data_vector_
.end(); ++it
) {
212 EXPECT_TRUE(!(*it
)->at_read_eof()) << "Read count: "
213 << (*it
)->read_count()
215 << (*it
)->read_index();
216 EXPECT_TRUE(!(*it
)->at_write_eof()) << "Write count: "
217 << (*it
)->write_count()
219 << (*it
)->write_index();
223 void RunToCompletion(StaticSocketDataProvider
* data
) {
227 VerifyDataConsumed();
230 void AddData(StaticSocketDataProvider
* data
) {
231 DCHECK(!deterministic_
);
232 data_vector_
.push_back(data
);
233 linked_ptr
<SSLSocketDataProvider
> ssl_(
234 new SSLSocketDataProvider(ASYNC
, OK
));
235 if (test_type_
== SPDYNPN
) {
236 ssl_
->SetNextProto(SSLClientSocket::kProtoSPDY21
);
238 ssl_vector_
.push_back(ssl_
);
239 if (test_type_
== SPDYNPN
|| test_type_
== SPDYSSL
)
240 session_deps_
->socket_factory
->AddSSLSocketDataProvider(ssl_
.get());
241 session_deps_
->socket_factory
->AddSocketDataProvider(data
);
242 if (test_type_
== SPDYNPN
) {
243 MockConnect
never_finishing_connect(SYNCHRONOUS
, ERR_IO_PENDING
);
244 linked_ptr
<StaticSocketDataProvider
>
245 hanging_non_alternate_protocol_socket(
246 new StaticSocketDataProvider(NULL
, 0, NULL
, 0));
247 hanging_non_alternate_protocol_socket
->set_connect_data(
248 never_finishing_connect
);
249 session_deps_
->socket_factory
->AddSocketDataProvider(
250 hanging_non_alternate_protocol_socket
.get());
251 alternate_vector_
.push_back(hanging_non_alternate_protocol_socket
);
255 void AddDeterministicData(DeterministicSocketData
* data
) {
256 DCHECK(deterministic_
);
257 data_vector_
.push_back(data
);
258 linked_ptr
<SSLSocketDataProvider
> ssl_(
259 new SSLSocketDataProvider(ASYNC
, OK
));
260 if (test_type_
== SPDYNPN
) {
261 ssl_
->SetNextProto(SSLClientSocket::kProtoSPDY21
);
263 ssl_vector_
.push_back(ssl_
);
264 if (test_type_
== SPDYNPN
|| test_type_
== SPDYSSL
) {
265 session_deps_
->deterministic_socket_factory
->
266 AddSSLSocketDataProvider(ssl_
.get());
268 session_deps_
->deterministic_socket_factory
->AddSocketDataProvider(data
);
269 if (test_type_
== SPDYNPN
) {
270 MockConnect
never_finishing_connect(SYNCHRONOUS
, ERR_IO_PENDING
);
271 scoped_refptr
<DeterministicSocketData
>
272 hanging_non_alternate_protocol_socket(
273 new DeterministicSocketData(NULL
, 0, NULL
, 0));
274 hanging_non_alternate_protocol_socket
->set_connect_data(
275 never_finishing_connect
);
276 session_deps_
->deterministic_socket_factory
->AddSocketDataProvider(
277 hanging_non_alternate_protocol_socket
);
278 alternate_deterministic_vector_
.push_back(
279 hanging_non_alternate_protocol_socket
);
283 // This can only be called after RunPreTestSetup. It adds a Data Provider,
284 // but not a corresponding SSL data provider
285 void AddDataNoSSL(StaticSocketDataProvider
* data
) {
286 DCHECK(!deterministic_
);
287 session_deps_
->socket_factory
->AddSocketDataProvider(data
);
289 void AddDataNoSSL(DeterministicSocketData
* data
) {
290 DCHECK(deterministic_
);
291 session_deps_
->deterministic_socket_factory
->AddSocketDataProvider(data
);
294 void SetSession(const scoped_refptr
<HttpNetworkSession
>& session
) {
297 HttpNetworkTransaction
* trans() { return trans_
.get(); }
298 void ResetTrans() { trans_
.reset(); }
299 TransactionHelperResult
& output() { return output_
; }
300 const HttpRequestInfo
& request() const { return request_
; }
301 const scoped_refptr
<HttpNetworkSession
>& session() const {
304 scoped_ptr
<SpdySessionDependencies
>& session_deps() {
305 return session_deps_
;
307 int port() const { return port_
; }
308 SpdyNetworkTransactionTestTypes
test_type() const { return test_type_
; }
311 typedef std::vector
<StaticSocketDataProvider
*> DataVector
;
312 typedef std::vector
<linked_ptr
<SSLSocketDataProvider
> > SSLVector
;
313 typedef std::vector
<linked_ptr
<StaticSocketDataProvider
> > AlternateVector
;
314 typedef std::vector
<scoped_refptr
<DeterministicSocketData
> >
315 AlternateDeterministicVector
;
316 HttpRequestInfo request_
;
317 scoped_ptr
<SpdySessionDependencies
> session_deps_
;
318 scoped_refptr
<HttpNetworkSession
> session_
;
319 TransactionHelperResult output_
;
320 scoped_ptr
<StaticSocketDataProvider
> first_transaction_
;
321 SSLVector ssl_vector_
;
322 TestCompletionCallback callback
;
323 scoped_ptr
<HttpNetworkTransaction
> trans_
;
324 scoped_ptr
<HttpNetworkTransaction
> trans_http_
;
325 DataVector data_vector_
;
326 AlternateVector alternate_vector_
;
327 AlternateDeterministicVector alternate_deterministic_vector_
;
328 const BoundNetLog
& log_
;
329 SpdyNetworkTransactionTestTypes test_type_
;
335 void ConnectStatusHelperWithExpectedStatus(const MockRead
& status
,
336 int expected_status
);
338 void ConnectStatusHelper(const MockRead
& status
);
340 const HttpRequestInfo
& CreateGetPushRequest() {
341 google_get_push_request_
.method
= "GET";
342 google_get_push_request_
.url
= GURL("http://www.google.com/foo.dat");
343 google_get_push_request_
.load_flags
= 0;
344 return google_get_push_request_
;
347 const HttpRequestInfo
& CreateGetRequest() {
348 if (!google_get_request_initialized_
) {
349 google_get_request_
.method
= "GET";
350 google_get_request_
.url
= GURL(kDefaultURL
);
351 google_get_request_
.load_flags
= 0;
352 google_get_request_initialized_
= true;
354 return google_get_request_
;
357 const HttpRequestInfo
& CreateGetRequestWithUserAgent() {
358 if (!google_get_request_initialized_
) {
359 google_get_request_
.method
= "GET";
360 google_get_request_
.url
= GURL(kDefaultURL
);
361 google_get_request_
.load_flags
= 0;
362 google_get_request_
.extra_headers
.SetHeader("User-Agent", "Chrome");
363 google_get_request_initialized_
= true;
365 return google_get_request_
;
368 const HttpRequestInfo
& CreatePostRequest() {
369 if (!google_post_request_initialized_
) {
370 google_post_request_
.method
= "POST";
371 google_post_request_
.url
= GURL(kDefaultURL
);
372 google_post_request_
.upload_data
= new UploadData();
373 google_post_request_
.upload_data
->AppendBytes(kUploadData
,
375 google_post_request_initialized_
= true;
377 return google_post_request_
;
380 const HttpRequestInfo
& CreateChunkedPostRequest() {
381 if (!google_chunked_post_request_initialized_
) {
382 google_chunked_post_request_
.method
= "POST";
383 google_chunked_post_request_
.url
= GURL(kDefaultURL
);
384 google_chunked_post_request_
.upload_data
= new UploadData();
385 google_chunked_post_request_
.upload_data
->set_is_chunked(true);
386 google_chunked_post_request_
.upload_data
->AppendChunk(
387 kUploadData
, kUploadDataSize
, false);
388 google_chunked_post_request_
.upload_data
->AppendChunk(
389 kUploadData
, kUploadDataSize
, true);
390 google_chunked_post_request_initialized_
= true;
392 return google_chunked_post_request_
;
395 // Read the result of a particular transaction, knowing that we've got
396 // multiple transactions in the read pipeline; so as we read, we may have
397 // to skip over data destined for other transactions while we consume
398 // the data for |trans|.
399 int ReadResult(HttpNetworkTransaction
* trans
,
400 StaticSocketDataProvider
* data
,
401 std::string
* result
) {
402 const int kSize
= 3000;
405 scoped_refptr
<net::IOBufferWithSize
> buf(new net::IOBufferWithSize(kSize
));
406 TestCompletionCallback callback
;
408 int rv
= trans
->Read(buf
, kSize
, callback
.callback());
409 if (rv
== ERR_IO_PENDING
) {
410 // Multiple transactions may be in the data set. Keep pulling off
411 // reads until we complete our callback.
412 while (!callback
.have_result()) {
413 data
->CompleteRead();
414 MessageLoop::current()->RunAllPending();
416 rv
= callback
.WaitForResult();
417 } else if (rv
<= 0) {
420 result
->append(buf
->data(), rv
);
426 void VerifyStreamsClosed(const NormalSpdyTransactionHelper
& helper
) {
427 // This lengthy block is reaching into the pool to dig out the active
428 // session. Once we have the session, we verify that the streams are
429 // all closed and not leaked at this point.
430 const GURL
& url
= helper
.request().url
;
431 int port
= helper
.test_type() == SPDYNPN
? 443 : 80;
432 HostPortPair
host_port_pair(url
.host(), port
);
433 HostPortProxyPair
pair(host_port_pair
, ProxyServer::Direct());
435 const scoped_refptr
<HttpNetworkSession
>& session
= helper
.session();
436 SpdySessionPool
* pool(session
->spdy_session_pool());
437 EXPECT_TRUE(pool
->HasSession(pair
));
438 scoped_refptr
<SpdySession
> spdy_session(pool
->Get(pair
, log
));
439 ASSERT_TRUE(spdy_session
.get() != NULL
);
440 EXPECT_EQ(0u, spdy_session
->num_active_streams());
441 EXPECT_EQ(0u, spdy_session
->num_unclaimed_pushed_streams());
444 void RunServerPushTest(OrderedSocketData
* data
,
445 HttpResponseInfo
* response
,
446 HttpResponseInfo
* push_response
,
447 std::string
& expected
) {
448 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
449 BoundNetLog(), GetParam());
450 helper
.RunPreTestSetup();
451 helper
.AddData(data
);
453 HttpNetworkTransaction
* trans
= helper
.trans();
455 // Start the transaction with basic parameters.
456 TestCompletionCallback callback
;
457 int rv
= trans
->Start(
458 &CreateGetRequest(), callback
.callback(), BoundNetLog());
459 EXPECT_EQ(ERR_IO_PENDING
, rv
);
460 rv
= callback
.WaitForResult();
462 // Request the pushed path.
463 scoped_ptr
<HttpNetworkTransaction
> trans2(
464 new HttpNetworkTransaction(helper
.session()));
466 &CreateGetPushRequest(), callback
.callback(), BoundNetLog());
467 EXPECT_EQ(ERR_IO_PENDING
, rv
);
468 MessageLoop::current()->RunAllPending();
470 // The data for the pushed path may be coming in more than 1 packet. Compile
471 // the results into a single string.
473 // Read the server push body.
475 ReadResult(trans2
.get(), data
, &result2
);
476 // Read the response body.
478 ReadResult(trans
, data
, &result
);
480 // Verify that we consumed all test data.
481 EXPECT_TRUE(data
->at_read_eof());
482 EXPECT_TRUE(data
->at_write_eof());
484 // Verify that the received push data is same as the expected push data.
485 EXPECT_EQ(result2
.compare(expected
), 0) << "Received data: "
487 << "||||| Expected data: "
490 // Verify the SYN_REPLY.
491 // Copy the response info, because trans goes away.
492 *response
= *trans
->GetResponseInfo();
493 *push_response
= *trans2
->GetResponseInfo();
495 VerifyStreamsClosed(helper
);
498 static void DeleteSessionCallback(NormalSpdyTransactionHelper
* helper
,
500 helper
->ResetTrans();
503 static void StartTransactionCallback(
504 const scoped_refptr
<HttpNetworkSession
>& session
,
506 scoped_ptr
<HttpNetworkTransaction
> trans(
507 new HttpNetworkTransaction(session
));
508 TestCompletionCallback callback
;
509 HttpRequestInfo request
;
510 request
.method
= "GET";
511 request
.url
= GURL("http://www.google.com/");
512 request
.load_flags
= 0;
513 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
514 EXPECT_EQ(ERR_IO_PENDING
, rv
);
515 callback
.WaitForResult();
519 bool google_get_request_initialized_
;
520 bool google_post_request_initialized_
;
521 bool google_chunked_post_request_initialized_
;
522 HttpRequestInfo google_get_request_
;
523 HttpRequestInfo google_post_request_
;
524 HttpRequestInfo google_chunked_post_request_
;
525 HttpRequestInfo google_get_push_request_
;
528 //-----------------------------------------------------------------------------
529 // All tests are run with three different connection types: SPDY after NPN
530 // negotiation, SPDY without SSL, and SPDY with SSL.
531 INSTANTIATE_TEST_CASE_P(Spdy
,
532 SpdyNetworkTransactionTest
,
533 ::testing::Values(SPDYNOSSL
, SPDYSSL
, SPDYNPN
));
536 // Verify HttpNetworkTransaction constructor.
537 TEST_P(SpdyNetworkTransactionTest
, Constructor
) {
538 SpdySessionDependencies session_deps
;
539 scoped_refptr
<HttpNetworkSession
> session(
540 SpdySessionDependencies::SpdyCreateSession(&session_deps
));
541 scoped_ptr
<HttpTransaction
> trans(new HttpNetworkTransaction(session
));
544 TEST_P(SpdyNetworkTransactionTest
, Get
) {
545 // Construct the request.
546 scoped_ptr
<spdy::SpdyFrame
> req(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
547 MockWrite writes
[] = { CreateMockWrite(*req
) };
549 scoped_ptr
<spdy::SpdyFrame
> resp(ConstructSpdyGetSynReply(NULL
, 0, 1));
550 scoped_ptr
<spdy::SpdyFrame
> body(ConstructSpdyBodyFrame(1, true));
552 CreateMockRead(*resp
),
553 CreateMockRead(*body
),
554 MockRead(ASYNC
, 0, 0) // EOF
557 scoped_ptr
<DelayedSocketData
> data(
558 new DelayedSocketData(1, reads
, arraysize(reads
),
559 writes
, arraysize(writes
)));
560 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
561 BoundNetLog(), GetParam());
562 helper
.RunToCompletion(data
.get());
563 TransactionHelperResult out
= helper
.output();
564 EXPECT_EQ(OK
, out
.rv
);
565 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
566 EXPECT_EQ("hello!", out
.response_data
);
569 TEST_P(SpdyNetworkTransactionTest
, GetAtEachPriority
) {
570 for (RequestPriority p
= HIGHEST
; p
< NUM_PRIORITIES
;
571 p
= RequestPriority(p
+1)) {
572 // Construct the request.
573 scoped_ptr
<spdy::SpdyFrame
> req(ConstructSpdyGet(NULL
, 0, false, 1, p
));
574 MockWrite writes
[] = { CreateMockWrite(*req
) };
576 const int spdy_prio
= reinterpret_cast<spdy::SpdySynStreamControlFrame
*>(
577 req
.get())->priority();
578 // this repeats the RequestPriority-->SpdyPriority mapping from
579 // SpdyFramer::ConvertRequestPriorityToSpdyPriority to make
580 // sure it's being done right.
583 EXPECT_EQ(0, spdy_prio
);
586 EXPECT_EQ(1, spdy_prio
);
590 EXPECT_EQ(2, spdy_prio
);
593 EXPECT_EQ(3, spdy_prio
);
599 scoped_ptr
<spdy::SpdyFrame
> resp(ConstructSpdyGetSynReply(NULL
, 0, 1));
600 scoped_ptr
<spdy::SpdyFrame
> body(ConstructSpdyBodyFrame(1, true));
602 CreateMockRead(*resp
),
603 CreateMockRead(*body
),
604 MockRead(ASYNC
, 0, 0) // EOF
607 scoped_ptr
<DelayedSocketData
> data(
608 new DelayedSocketData(1, reads
, arraysize(reads
),
609 writes
, arraysize(writes
)));
610 HttpRequestInfo http_req
= CreateGetRequest();
611 http_req
.priority
= p
;
613 NormalSpdyTransactionHelper
helper(http_req
, BoundNetLog(), GetParam());
614 helper
.RunToCompletion(data
.get());
615 TransactionHelperResult out
= helper
.output();
616 EXPECT_EQ(OK
, out
.rv
);
617 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
618 EXPECT_EQ("hello!", out
.response_data
);
622 // Start three gets simultaniously; making sure that multiplexed
623 // streams work properly.
625 // This can't use the TransactionHelper method, since it only
626 // handles a single transaction, and finishes them as soon
627 // as it launches them.
629 // TODO(gavinp): create a working generalized TransactionHelper that
630 // can allow multiple streams in flight.
632 TEST_P(SpdyNetworkTransactionTest
, ThreeGets
) {
633 scoped_ptr
<spdy::SpdyFrame
> req(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
634 scoped_ptr
<spdy::SpdyFrame
> resp(ConstructSpdyGetSynReply(NULL
, 0, 1));
635 scoped_ptr
<spdy::SpdyFrame
> body(ConstructSpdyBodyFrame(1, false));
636 scoped_ptr
<spdy::SpdyFrame
> fbody(ConstructSpdyBodyFrame(1, true));
638 scoped_ptr
<spdy::SpdyFrame
> req2(ConstructSpdyGet(NULL
, 0, false, 3, LOWEST
));
639 scoped_ptr
<spdy::SpdyFrame
> resp2(ConstructSpdyGetSynReply(NULL
, 0, 3));
640 scoped_ptr
<spdy::SpdyFrame
> body2(ConstructSpdyBodyFrame(3, false));
641 scoped_ptr
<spdy::SpdyFrame
> fbody2(ConstructSpdyBodyFrame(3, true));
643 scoped_ptr
<spdy::SpdyFrame
> req3(ConstructSpdyGet(NULL
, 0, false, 5, LOWEST
));
644 scoped_ptr
<spdy::SpdyFrame
> resp3(ConstructSpdyGetSynReply(NULL
, 0, 5));
645 scoped_ptr
<spdy::SpdyFrame
> body3(ConstructSpdyBodyFrame(5, false));
646 scoped_ptr
<spdy::SpdyFrame
> fbody3(ConstructSpdyBodyFrame(5, true));
648 MockWrite writes
[] = {
649 CreateMockWrite(*req
),
650 CreateMockWrite(*req2
),
651 CreateMockWrite(*req3
),
654 CreateMockRead(*resp
, 1),
655 CreateMockRead(*body
),
656 CreateMockRead(*resp2
, 4),
657 CreateMockRead(*body2
),
658 CreateMockRead(*resp3
, 7),
659 CreateMockRead(*body3
),
661 CreateMockRead(*fbody
),
662 CreateMockRead(*fbody2
),
663 CreateMockRead(*fbody3
),
665 MockRead(ASYNC
, 0, 0), // EOF
667 scoped_ptr
<OrderedSocketData
> data(
668 new OrderedSocketData(reads
, arraysize(reads
),
669 writes
, arraysize(writes
)));
670 scoped_ptr
<OrderedSocketData
> data_placeholder(
671 new OrderedSocketData(NULL
, 0, NULL
, 0));
674 TransactionHelperResult out
;
675 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
676 BoundNetLog(), GetParam());
677 helper
.RunPreTestSetup();
678 helper
.AddData(data
.get());
679 // We require placeholder data because three get requests are sent out, so
680 // there needs to be three sets of SSL connection data.
681 helper
.AddData(data_placeholder
.get());
682 helper
.AddData(data_placeholder
.get());
683 scoped_ptr
<HttpNetworkTransaction
> trans1(
684 new HttpNetworkTransaction(helper
.session()));
685 scoped_ptr
<HttpNetworkTransaction
> trans2(
686 new HttpNetworkTransaction(helper
.session()));
687 scoped_ptr
<HttpNetworkTransaction
> trans3(
688 new HttpNetworkTransaction(helper
.session()));
690 TestCompletionCallback callback1
;
691 TestCompletionCallback callback2
;
692 TestCompletionCallback callback3
;
694 HttpRequestInfo httpreq1
= CreateGetRequest();
695 HttpRequestInfo httpreq2
= CreateGetRequest();
696 HttpRequestInfo httpreq3
= CreateGetRequest();
698 out
.rv
= trans1
->Start(&httpreq1
, callback1
.callback(), log
);
699 ASSERT_EQ(ERR_IO_PENDING
, out
.rv
);
700 out
.rv
= trans2
->Start(&httpreq2
, callback2
.callback(), log
);
701 ASSERT_EQ(ERR_IO_PENDING
, out
.rv
);
702 out
.rv
= trans3
->Start(&httpreq3
, callback3
.callback(), log
);
703 ASSERT_EQ(ERR_IO_PENDING
, out
.rv
);
705 out
.rv
= callback1
.WaitForResult();
706 ASSERT_EQ(OK
, out
.rv
);
707 out
.rv
= callback3
.WaitForResult();
708 ASSERT_EQ(OK
, out
.rv
);
710 const HttpResponseInfo
* response1
= trans1
->GetResponseInfo();
711 EXPECT_TRUE(response1
->headers
!= NULL
);
712 EXPECT_TRUE(response1
->was_fetched_via_spdy
);
713 out
.status_line
= response1
->headers
->GetStatusLine();
714 out
.response_info
= *response1
;
716 trans2
->GetResponseInfo();
718 out
.rv
= ReadTransaction(trans1
.get(), &out
.response_data
);
719 helper
.VerifyDataConsumed();
720 EXPECT_EQ(OK
, out
.rv
);
722 EXPECT_EQ(OK
, out
.rv
);
723 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
724 EXPECT_EQ("hello!hello!", out
.response_data
);
727 TEST_P(SpdyNetworkTransactionTest
, TwoGetsLateBinding
) {
728 scoped_ptr
<spdy::SpdyFrame
> req(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
729 scoped_ptr
<spdy::SpdyFrame
> resp(ConstructSpdyGetSynReply(NULL
, 0, 1));
730 scoped_ptr
<spdy::SpdyFrame
> body(ConstructSpdyBodyFrame(1, false));
731 scoped_ptr
<spdy::SpdyFrame
> fbody(ConstructSpdyBodyFrame(1, true));
733 scoped_ptr
<spdy::SpdyFrame
> req2(ConstructSpdyGet(NULL
, 0, false, 3, LOWEST
));
734 scoped_ptr
<spdy::SpdyFrame
> resp2(ConstructSpdyGetSynReply(NULL
, 0, 3));
735 scoped_ptr
<spdy::SpdyFrame
> body2(ConstructSpdyBodyFrame(3, false));
736 scoped_ptr
<spdy::SpdyFrame
> fbody2(ConstructSpdyBodyFrame(3, true));
738 MockWrite writes
[] = {
739 CreateMockWrite(*req
),
740 CreateMockWrite(*req2
),
743 CreateMockRead(*resp
, 1),
744 CreateMockRead(*body
),
745 CreateMockRead(*resp2
, 4),
746 CreateMockRead(*body2
),
747 CreateMockRead(*fbody
),
748 CreateMockRead(*fbody2
),
749 MockRead(ASYNC
, 0, 0), // EOF
751 scoped_ptr
<OrderedSocketData
> data(
752 new OrderedSocketData(reads
, arraysize(reads
),
753 writes
, arraysize(writes
)));
755 MockConnect
never_finishing_connect(SYNCHRONOUS
, ERR_IO_PENDING
);
757 scoped_ptr
<OrderedSocketData
> data_placeholder(
758 new OrderedSocketData(NULL
, 0, NULL
, 0));
759 data_placeholder
->set_connect_data(never_finishing_connect
);
762 TransactionHelperResult out
;
763 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
764 BoundNetLog(), GetParam());
765 helper
.RunPreTestSetup();
766 helper
.AddData(data
.get());
767 // We require placeholder data because two get requests are sent out, so
768 // there needs to be two sets of SSL connection data.
769 helper
.AddData(data_placeholder
.get());
770 scoped_ptr
<HttpNetworkTransaction
> trans1(
771 new HttpNetworkTransaction(helper
.session()));
772 scoped_ptr
<HttpNetworkTransaction
> trans2(
773 new HttpNetworkTransaction(helper
.session()));
775 TestCompletionCallback callback1
;
776 TestCompletionCallback callback2
;
778 HttpRequestInfo httpreq1
= CreateGetRequest();
779 HttpRequestInfo httpreq2
= CreateGetRequest();
781 out
.rv
= trans1
->Start(&httpreq1
, callback1
.callback(), log
);
782 ASSERT_EQ(ERR_IO_PENDING
, out
.rv
);
783 out
.rv
= trans2
->Start(&httpreq2
, callback2
.callback(), log
);
784 ASSERT_EQ(ERR_IO_PENDING
, out
.rv
);
786 out
.rv
= callback1
.WaitForResult();
787 ASSERT_EQ(OK
, out
.rv
);
788 out
.rv
= callback2
.WaitForResult();
789 ASSERT_EQ(OK
, out
.rv
);
791 const HttpResponseInfo
* response1
= trans1
->GetResponseInfo();
792 EXPECT_TRUE(response1
->headers
!= NULL
);
793 EXPECT_TRUE(response1
->was_fetched_via_spdy
);
794 out
.status_line
= response1
->headers
->GetStatusLine();
795 out
.response_info
= *response1
;
796 out
.rv
= ReadTransaction(trans1
.get(), &out
.response_data
);
797 EXPECT_EQ(OK
, out
.rv
);
798 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
799 EXPECT_EQ("hello!hello!", out
.response_data
);
801 const HttpResponseInfo
* response2
= trans2
->GetResponseInfo();
802 EXPECT_TRUE(response2
->headers
!= NULL
);
803 EXPECT_TRUE(response2
->was_fetched_via_spdy
);
804 out
.status_line
= response2
->headers
->GetStatusLine();
805 out
.response_info
= *response2
;
806 out
.rv
= ReadTransaction(trans2
.get(), &out
.response_data
);
807 EXPECT_EQ(OK
, out
.rv
);
808 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
809 EXPECT_EQ("hello!hello!", out
.response_data
);
811 helper
.VerifyDataConsumed();
814 TEST_P(SpdyNetworkTransactionTest
, TwoGetsLateBindingFromPreconnect
) {
815 scoped_ptr
<spdy::SpdyFrame
> req(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
816 scoped_ptr
<spdy::SpdyFrame
> resp(ConstructSpdyGetSynReply(NULL
, 0, 1));
817 scoped_ptr
<spdy::SpdyFrame
> body(ConstructSpdyBodyFrame(1, false));
818 scoped_ptr
<spdy::SpdyFrame
> fbody(ConstructSpdyBodyFrame(1, true));
820 scoped_ptr
<spdy::SpdyFrame
> req2(ConstructSpdyGet(NULL
, 0, false, 3, LOWEST
));
821 scoped_ptr
<spdy::SpdyFrame
> resp2(ConstructSpdyGetSynReply(NULL
, 0, 3));
822 scoped_ptr
<spdy::SpdyFrame
> body2(ConstructSpdyBodyFrame(3, false));
823 scoped_ptr
<spdy::SpdyFrame
> fbody2(ConstructSpdyBodyFrame(3, true));
825 MockWrite writes
[] = {
826 CreateMockWrite(*req
),
827 CreateMockWrite(*req2
),
830 CreateMockRead(*resp
, 1),
831 CreateMockRead(*body
),
832 CreateMockRead(*resp2
, 4),
833 CreateMockRead(*body2
),
834 CreateMockRead(*fbody
),
835 CreateMockRead(*fbody2
),
836 MockRead(ASYNC
, 0, 0), // EOF
838 scoped_ptr
<OrderedSocketData
> preconnect_data(
839 new OrderedSocketData(reads
, arraysize(reads
),
840 writes
, arraysize(writes
)));
842 MockConnect
never_finishing_connect(ASYNC
, ERR_IO_PENDING
);
844 scoped_ptr
<OrderedSocketData
> data_placeholder(
845 new OrderedSocketData(NULL
, 0, NULL
, 0));
846 data_placeholder
->set_connect_data(never_finishing_connect
);
849 TransactionHelperResult out
;
850 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
851 BoundNetLog(), GetParam());
852 helper
.RunPreTestSetup();
853 helper
.AddData(preconnect_data
.get());
854 // We require placeholder data because 3 connections are attempted (first is
855 // the preconnect, 2nd and 3rd are the never finished connections.
856 helper
.AddData(data_placeholder
.get());
857 helper
.AddData(data_placeholder
.get());
859 scoped_ptr
<HttpNetworkTransaction
> trans1(
860 new HttpNetworkTransaction(helper
.session()));
861 scoped_ptr
<HttpNetworkTransaction
> trans2(
862 new HttpNetworkTransaction(helper
.session()));
864 TestCompletionCallback callback1
;
865 TestCompletionCallback callback2
;
867 HttpRequestInfo httpreq
= CreateGetRequest();
869 // Preconnect the first.
870 SSLConfig preconnect_ssl_config
;
871 helper
.session()->ssl_config_service()->GetSSLConfig(&preconnect_ssl_config
);
872 HttpStreamFactory
* http_stream_factory
=
873 helper
.session()->http_stream_factory();
874 if (http_stream_factory
->has_next_protos()) {
875 preconnect_ssl_config
.next_protos
= http_stream_factory
->next_protos();
878 http_stream_factory
->PreconnectStreams(
879 1, httpreq
, preconnect_ssl_config
, preconnect_ssl_config
);
881 out
.rv
= trans1
->Start(&httpreq
, callback1
.callback(), log
);
882 ASSERT_EQ(ERR_IO_PENDING
, out
.rv
);
883 out
.rv
= trans2
->Start(&httpreq
, callback2
.callback(), log
);
884 ASSERT_EQ(ERR_IO_PENDING
, out
.rv
);
886 out
.rv
= callback1
.WaitForResult();
887 ASSERT_EQ(OK
, out
.rv
);
888 out
.rv
= callback2
.WaitForResult();
889 ASSERT_EQ(OK
, out
.rv
);
891 const HttpResponseInfo
* response1
= trans1
->GetResponseInfo();
892 EXPECT_TRUE(response1
->headers
!= NULL
);
893 EXPECT_TRUE(response1
->was_fetched_via_spdy
);
894 out
.status_line
= response1
->headers
->GetStatusLine();
895 out
.response_info
= *response1
;
896 out
.rv
= ReadTransaction(trans1
.get(), &out
.response_data
);
897 EXPECT_EQ(OK
, out
.rv
);
898 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
899 EXPECT_EQ("hello!hello!", out
.response_data
);
901 const HttpResponseInfo
* response2
= trans2
->GetResponseInfo();
902 EXPECT_TRUE(response2
->headers
!= NULL
);
903 EXPECT_TRUE(response2
->was_fetched_via_spdy
);
904 out
.status_line
= response2
->headers
->GetStatusLine();
905 out
.response_info
= *response2
;
906 out
.rv
= ReadTransaction(trans2
.get(), &out
.response_data
);
907 EXPECT_EQ(OK
, out
.rv
);
908 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
909 EXPECT_EQ("hello!hello!", out
.response_data
);
911 helper
.VerifyDataConsumed();
914 // Similar to ThreeGets above, however this test adds a SETTINGS
915 // frame. The SETTINGS frame is read during the IO loop waiting on
916 // the first transaction completion, and sets a maximum concurrent
917 // stream limit of 1. This means that our IO loop exists after the
918 // second transaction completes, so we can assert on read_index().
919 TEST_P(SpdyNetworkTransactionTest
, ThreeGetsWithMaxConcurrent
) {
920 // Construct the request.
921 scoped_ptr
<spdy::SpdyFrame
> req(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
922 scoped_ptr
<spdy::SpdyFrame
> resp(ConstructSpdyGetSynReply(NULL
, 0, 1));
923 scoped_ptr
<spdy::SpdyFrame
> body(ConstructSpdyBodyFrame(1, false));
924 scoped_ptr
<spdy::SpdyFrame
> fbody(ConstructSpdyBodyFrame(1, true));
926 scoped_ptr
<spdy::SpdyFrame
> req2(ConstructSpdyGet(NULL
, 0, false, 3, LOWEST
));
927 scoped_ptr
<spdy::SpdyFrame
> resp2(ConstructSpdyGetSynReply(NULL
, 0, 3));
928 scoped_ptr
<spdy::SpdyFrame
> body2(ConstructSpdyBodyFrame(3, false));
929 scoped_ptr
<spdy::SpdyFrame
> fbody2(ConstructSpdyBodyFrame(3, true));
931 scoped_ptr
<spdy::SpdyFrame
> req3(ConstructSpdyGet(NULL
, 0, false, 5, LOWEST
));
932 scoped_ptr
<spdy::SpdyFrame
> resp3(ConstructSpdyGetSynReply(NULL
, 0, 5));
933 scoped_ptr
<spdy::SpdyFrame
> body3(ConstructSpdyBodyFrame(5, false));
934 scoped_ptr
<spdy::SpdyFrame
> fbody3(ConstructSpdyBodyFrame(5, true));
936 spdy::SpdySettings settings
;
937 spdy::SettingsFlagsAndId
id(0);
938 id
.set_id(spdy::SETTINGS_MAX_CONCURRENT_STREAMS
);
939 const size_t max_concurrent_streams
= 1;
941 settings
.push_back(spdy::SpdySetting(id
, max_concurrent_streams
));
942 scoped_ptr
<spdy::SpdyFrame
> settings_frame(ConstructSpdySettings(settings
));
944 MockWrite writes
[] = {
945 CreateMockWrite(*req
),
946 CreateMockWrite(*req2
),
947 CreateMockWrite(*req3
),
951 CreateMockRead(*settings_frame
, 1),
952 CreateMockRead(*resp
),
953 CreateMockRead(*body
),
954 CreateMockRead(*fbody
),
955 CreateMockRead(*resp2
, 7),
956 CreateMockRead(*body2
),
957 CreateMockRead(*fbody2
),
958 CreateMockRead(*resp3
, 12),
959 CreateMockRead(*body3
),
960 CreateMockRead(*fbody3
),
962 MockRead(ASYNC
, 0, 0), // EOF
965 scoped_ptr
<OrderedSocketData
> data(
966 new OrderedSocketData(reads
, arraysize(reads
),
967 writes
, arraysize(writes
)));
968 scoped_ptr
<OrderedSocketData
> data_placeholder(
969 new OrderedSocketData(NULL
, 0, NULL
, 0));
972 TransactionHelperResult out
;
974 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
975 BoundNetLog(), GetParam());
976 helper
.RunPreTestSetup();
977 helper
.AddData(data
.get());
978 // We require placeholder data because three get requests are sent out, so
979 // there needs to be three sets of SSL connection data.
980 helper
.AddData(data_placeholder
.get());
981 helper
.AddData(data_placeholder
.get());
982 scoped_ptr
<HttpNetworkTransaction
> trans1(
983 new HttpNetworkTransaction(helper
.session()));
984 scoped_ptr
<HttpNetworkTransaction
> trans2(
985 new HttpNetworkTransaction(helper
.session()));
986 scoped_ptr
<HttpNetworkTransaction
> trans3(
987 new HttpNetworkTransaction(helper
.session()));
989 TestCompletionCallback callback1
;
990 TestCompletionCallback callback2
;
991 TestCompletionCallback callback3
;
993 HttpRequestInfo httpreq1
= CreateGetRequest();
994 HttpRequestInfo httpreq2
= CreateGetRequest();
995 HttpRequestInfo httpreq3
= CreateGetRequest();
997 out
.rv
= trans1
->Start(&httpreq1
, callback1
.callback(), log
);
998 ASSERT_EQ(out
.rv
, ERR_IO_PENDING
);
999 // run transaction 1 through quickly to force a read of our SETTINGS
1001 out
.rv
= callback1
.WaitForResult();
1002 ASSERT_EQ(OK
, out
.rv
);
1004 out
.rv
= trans2
->Start(&httpreq2
, callback2
.callback(), log
);
1005 ASSERT_EQ(out
.rv
, ERR_IO_PENDING
);
1006 out
.rv
= trans3
->Start(&httpreq3
, callback3
.callback(), log
);
1007 ASSERT_EQ(out
.rv
, ERR_IO_PENDING
);
1008 out
.rv
= callback2
.WaitForResult();
1009 ASSERT_EQ(OK
, out
.rv
);
1010 EXPECT_EQ(7U, data
->read_index()); // i.e. the third trans was queued
1012 out
.rv
= callback3
.WaitForResult();
1013 ASSERT_EQ(OK
, out
.rv
);
1015 const HttpResponseInfo
* response1
= trans1
->GetResponseInfo();
1016 ASSERT_TRUE(response1
!= NULL
);
1017 EXPECT_TRUE(response1
->headers
!= NULL
);
1018 EXPECT_TRUE(response1
->was_fetched_via_spdy
);
1019 out
.status_line
= response1
->headers
->GetStatusLine();
1020 out
.response_info
= *response1
;
1021 out
.rv
= ReadTransaction(trans1
.get(), &out
.response_data
);
1022 EXPECT_EQ(OK
, out
.rv
);
1023 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1024 EXPECT_EQ("hello!hello!", out
.response_data
);
1026 const HttpResponseInfo
* response2
= trans2
->GetResponseInfo();
1027 out
.status_line
= response2
->headers
->GetStatusLine();
1028 out
.response_info
= *response2
;
1029 out
.rv
= ReadTransaction(trans2
.get(), &out
.response_data
);
1030 EXPECT_EQ(OK
, out
.rv
);
1031 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1032 EXPECT_EQ("hello!hello!", out
.response_data
);
1034 const HttpResponseInfo
* response3
= trans3
->GetResponseInfo();
1035 out
.status_line
= response3
->headers
->GetStatusLine();
1036 out
.response_info
= *response3
;
1037 out
.rv
= ReadTransaction(trans3
.get(), &out
.response_data
);
1038 EXPECT_EQ(OK
, out
.rv
);
1039 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1040 EXPECT_EQ("hello!hello!", out
.response_data
);
1042 helper
.VerifyDataConsumed();
1044 EXPECT_EQ(OK
, out
.rv
);
1047 // Similar to ThreeGetsWithMaxConcurrent above, however this test adds
1048 // a fourth transaction. The third and fourth transactions have
1049 // different data ("hello!" vs "hello!hello!") and because of the
1050 // user specified priority, we expect to see them inverted in
1051 // the response from the server.
1052 TEST_P(SpdyNetworkTransactionTest
, FourGetsWithMaxConcurrentPriority
) {
1053 // Construct the request.
1054 scoped_ptr
<spdy::SpdyFrame
> req(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
1055 scoped_ptr
<spdy::SpdyFrame
> resp(ConstructSpdyGetSynReply(NULL
, 0, 1));
1056 scoped_ptr
<spdy::SpdyFrame
> body(ConstructSpdyBodyFrame(1, false));
1057 scoped_ptr
<spdy::SpdyFrame
> fbody(ConstructSpdyBodyFrame(1, true));
1059 scoped_ptr
<spdy::SpdyFrame
> req2(ConstructSpdyGet(NULL
, 0, false, 3, LOWEST
));
1060 scoped_ptr
<spdy::SpdyFrame
> resp2(ConstructSpdyGetSynReply(NULL
, 0, 3));
1061 scoped_ptr
<spdy::SpdyFrame
> body2(ConstructSpdyBodyFrame(3, false));
1062 scoped_ptr
<spdy::SpdyFrame
> fbody2(ConstructSpdyBodyFrame(3, true));
1064 scoped_ptr
<spdy::SpdyFrame
> req4(
1065 ConstructSpdyGet(NULL
, 0, false, 5, HIGHEST
));
1066 scoped_ptr
<spdy::SpdyFrame
> resp4(ConstructSpdyGetSynReply(NULL
, 0, 5));
1067 scoped_ptr
<spdy::SpdyFrame
> fbody4(ConstructSpdyBodyFrame(5, true));
1069 scoped_ptr
<spdy::SpdyFrame
> req3(ConstructSpdyGet(NULL
, 0, false, 7, LOWEST
));
1070 scoped_ptr
<spdy::SpdyFrame
> resp3(ConstructSpdyGetSynReply(NULL
, 0, 7));
1071 scoped_ptr
<spdy::SpdyFrame
> body3(ConstructSpdyBodyFrame(7, false));
1072 scoped_ptr
<spdy::SpdyFrame
> fbody3(ConstructSpdyBodyFrame(7, true));
1075 spdy::SpdySettings settings
;
1076 spdy::SettingsFlagsAndId
id(0);
1077 id
.set_id(spdy::SETTINGS_MAX_CONCURRENT_STREAMS
);
1078 const size_t max_concurrent_streams
= 1;
1080 settings
.push_back(spdy::SpdySetting(id
, max_concurrent_streams
));
1081 scoped_ptr
<spdy::SpdyFrame
> settings_frame(ConstructSpdySettings(settings
));
1083 MockWrite writes
[] = { CreateMockWrite(*req
),
1084 CreateMockWrite(*req2
),
1085 CreateMockWrite(*req4
),
1086 CreateMockWrite(*req3
),
1088 MockRead reads
[] = {
1089 CreateMockRead(*settings_frame
, 1),
1090 CreateMockRead(*resp
),
1091 CreateMockRead(*body
),
1092 CreateMockRead(*fbody
),
1093 CreateMockRead(*resp2
, 7),
1094 CreateMockRead(*body2
),
1095 CreateMockRead(*fbody2
),
1096 CreateMockRead(*resp4
, 13),
1097 CreateMockRead(*fbody4
),
1098 CreateMockRead(*resp3
, 16),
1099 CreateMockRead(*body3
),
1100 CreateMockRead(*fbody3
),
1102 MockRead(ASYNC
, 0, 0), // EOF
1105 scoped_ptr
<OrderedSocketData
> data(
1106 new OrderedSocketData(reads
, arraysize(reads
),
1107 writes
, arraysize(writes
)));
1108 scoped_ptr
<OrderedSocketData
> data_placeholder(
1109 new OrderedSocketData(NULL
, 0, NULL
, 0));
1112 TransactionHelperResult out
;
1113 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
1114 BoundNetLog(), GetParam());
1115 helper
.RunPreTestSetup();
1116 helper
.AddData(data
.get());
1117 // We require placeholder data because four get requests are sent out, so
1118 // there needs to be four sets of SSL connection data.
1119 helper
.AddData(data_placeholder
.get());
1120 helper
.AddData(data_placeholder
.get());
1121 helper
.AddData(data_placeholder
.get());
1122 scoped_ptr
<HttpNetworkTransaction
> trans1(
1123 new HttpNetworkTransaction(helper
.session()));
1124 scoped_ptr
<HttpNetworkTransaction
> trans2(
1125 new HttpNetworkTransaction(helper
.session()));
1126 scoped_ptr
<HttpNetworkTransaction
> trans3(
1127 new HttpNetworkTransaction(helper
.session()));
1128 scoped_ptr
<HttpNetworkTransaction
> trans4(
1129 new HttpNetworkTransaction(helper
.session()));
1131 TestCompletionCallback callback1
;
1132 TestCompletionCallback callback2
;
1133 TestCompletionCallback callback3
;
1134 TestCompletionCallback callback4
;
1136 HttpRequestInfo httpreq1
= CreateGetRequest();
1137 HttpRequestInfo httpreq2
= CreateGetRequest();
1138 HttpRequestInfo httpreq3
= CreateGetRequest();
1139 HttpRequestInfo httpreq4
= CreateGetRequest();
1140 httpreq4
.priority
= HIGHEST
;
1142 out
.rv
= trans1
->Start(&httpreq1
, callback1
.callback(), log
);
1143 ASSERT_EQ(ERR_IO_PENDING
, out
.rv
);
1144 // run transaction 1 through quickly to force a read of our SETTINGS
1146 out
.rv
= callback1
.WaitForResult();
1147 ASSERT_EQ(OK
, out
.rv
);
1149 out
.rv
= trans2
->Start(&httpreq2
, callback2
.callback(), log
);
1150 ASSERT_EQ(ERR_IO_PENDING
, out
.rv
);
1151 out
.rv
= trans3
->Start(&httpreq3
, callback3
.callback(), log
);
1152 ASSERT_EQ(ERR_IO_PENDING
, out
.rv
);
1153 out
.rv
= trans4
->Start(&httpreq4
, callback4
.callback(), log
);
1154 ASSERT_EQ(ERR_IO_PENDING
, out
.rv
);
1156 out
.rv
= callback2
.WaitForResult();
1157 ASSERT_EQ(OK
, out
.rv
);
1158 EXPECT_EQ(data
->read_index(), 7U); // i.e. the third & fourth trans queued
1160 out
.rv
= callback3
.WaitForResult();
1161 ASSERT_EQ(OK
, out
.rv
);
1163 const HttpResponseInfo
* response1
= trans1
->GetResponseInfo();
1164 EXPECT_TRUE(response1
->headers
!= NULL
);
1165 EXPECT_TRUE(response1
->was_fetched_via_spdy
);
1166 out
.status_line
= response1
->headers
->GetStatusLine();
1167 out
.response_info
= *response1
;
1168 out
.rv
= ReadTransaction(trans1
.get(), &out
.response_data
);
1169 EXPECT_EQ(OK
, out
.rv
);
1170 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1171 EXPECT_EQ("hello!hello!", out
.response_data
);
1173 const HttpResponseInfo
* response2
= trans2
->GetResponseInfo();
1174 out
.status_line
= response2
->headers
->GetStatusLine();
1175 out
.response_info
= *response2
;
1176 out
.rv
= ReadTransaction(trans2
.get(), &out
.response_data
);
1177 EXPECT_EQ(OK
, out
.rv
);
1178 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1179 EXPECT_EQ("hello!hello!", out
.response_data
);
1181 // notice: response3 gets two hellos, response4 gets one
1182 // hello, so we know dequeuing priority was respected.
1183 const HttpResponseInfo
* response3
= trans3
->GetResponseInfo();
1184 out
.status_line
= response3
->headers
->GetStatusLine();
1185 out
.response_info
= *response3
;
1186 out
.rv
= ReadTransaction(trans3
.get(), &out
.response_data
);
1187 EXPECT_EQ(OK
, out
.rv
);
1188 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1189 EXPECT_EQ("hello!hello!", out
.response_data
);
1191 out
.rv
= callback4
.WaitForResult();
1192 EXPECT_EQ(OK
, out
.rv
);
1193 const HttpResponseInfo
* response4
= trans4
->GetResponseInfo();
1194 out
.status_line
= response4
->headers
->GetStatusLine();
1195 out
.response_info
= *response4
;
1196 out
.rv
= ReadTransaction(trans4
.get(), &out
.response_data
);
1197 EXPECT_EQ(OK
, out
.rv
);
1198 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1199 EXPECT_EQ("hello!", out
.response_data
);
1200 helper
.VerifyDataConsumed();
1201 EXPECT_EQ(OK
, out
.rv
);
1204 // Similar to ThreeGetsMaxConcurrrent above, however, this test
1205 // deletes a session in the middle of the transaction to insure
1206 // that we properly remove pendingcreatestream objects from
1208 TEST_P(SpdyNetworkTransactionTest
, ThreeGetsWithMaxConcurrentDelete
) {
1209 // Construct the request.
1210 scoped_ptr
<spdy::SpdyFrame
> req(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
1211 scoped_ptr
<spdy::SpdyFrame
> resp(ConstructSpdyGetSynReply(NULL
, 0, 1));
1212 scoped_ptr
<spdy::SpdyFrame
> body(ConstructSpdyBodyFrame(1, false));
1213 scoped_ptr
<spdy::SpdyFrame
> fbody(ConstructSpdyBodyFrame(1, true));
1215 scoped_ptr
<spdy::SpdyFrame
> req2(ConstructSpdyGet(NULL
, 0, false, 3, LOWEST
));
1216 scoped_ptr
<spdy::SpdyFrame
> resp2(ConstructSpdyGetSynReply(NULL
, 0, 3));
1217 scoped_ptr
<spdy::SpdyFrame
> body2(ConstructSpdyBodyFrame(3, false));
1218 scoped_ptr
<spdy::SpdyFrame
> fbody2(ConstructSpdyBodyFrame(3, true));
1220 spdy::SpdySettings settings
;
1221 spdy::SettingsFlagsAndId
id(0);
1222 id
.set_id(spdy::SETTINGS_MAX_CONCURRENT_STREAMS
);
1223 const size_t max_concurrent_streams
= 1;
1225 settings
.push_back(spdy::SpdySetting(id
, max_concurrent_streams
));
1226 scoped_ptr
<spdy::SpdyFrame
> settings_frame(ConstructSpdySettings(settings
));
1228 MockWrite writes
[] = { CreateMockWrite(*req
),
1229 CreateMockWrite(*req2
),
1231 MockRead reads
[] = {
1232 CreateMockRead(*settings_frame
, 1),
1233 CreateMockRead(*resp
),
1234 CreateMockRead(*body
),
1235 CreateMockRead(*fbody
),
1236 CreateMockRead(*resp2
, 7),
1237 CreateMockRead(*body2
),
1238 CreateMockRead(*fbody2
),
1239 MockRead(ASYNC
, 0, 0), // EOF
1242 scoped_ptr
<OrderedSocketData
> data(
1243 new OrderedSocketData(reads
, arraysize(reads
),
1244 writes
, arraysize(writes
)));
1245 scoped_ptr
<OrderedSocketData
> data_placeholder(
1246 new OrderedSocketData(NULL
, 0, NULL
, 0));
1249 TransactionHelperResult out
;
1250 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
1251 BoundNetLog(), GetParam());
1252 helper
.RunPreTestSetup();
1253 helper
.AddData(data
.get());
1254 // We require placeholder data because three get requests are sent out, so
1255 // there needs to be three sets of SSL connection data.
1256 helper
.AddData(data_placeholder
.get());
1257 helper
.AddData(data_placeholder
.get());
1258 scoped_ptr
<HttpNetworkTransaction
> trans1(
1259 new HttpNetworkTransaction(helper
.session()));
1260 scoped_ptr
<HttpNetworkTransaction
> trans2(
1261 new HttpNetworkTransaction(helper
.session()));
1262 scoped_ptr
<HttpNetworkTransaction
> trans3(
1263 new HttpNetworkTransaction(helper
.session()));
1265 TestCompletionCallback callback1
;
1266 TestCompletionCallback callback2
;
1267 TestCompletionCallback callback3
;
1269 HttpRequestInfo httpreq1
= CreateGetRequest();
1270 HttpRequestInfo httpreq2
= CreateGetRequest();
1271 HttpRequestInfo httpreq3
= CreateGetRequest();
1273 out
.rv
= trans1
->Start(&httpreq1
, callback1
.callback(), log
);
1274 ASSERT_EQ(out
.rv
, ERR_IO_PENDING
);
1275 // run transaction 1 through quickly to force a read of our SETTINGS
1277 out
.rv
= callback1
.WaitForResult();
1278 ASSERT_EQ(OK
, out
.rv
);
1280 out
.rv
= trans2
->Start(&httpreq2
, callback2
.callback(), log
);
1281 ASSERT_EQ(out
.rv
, ERR_IO_PENDING
);
1282 out
.rv
= trans3
->Start(&httpreq3
, callback3
.callback(), log
);
1283 delete trans3
.release();
1284 ASSERT_EQ(out
.rv
, ERR_IO_PENDING
);
1285 out
.rv
= callback2
.WaitForResult();
1286 ASSERT_EQ(OK
, out
.rv
);
1288 EXPECT_EQ(8U, data
->read_index());
1290 const HttpResponseInfo
* response1
= trans1
->GetResponseInfo();
1291 ASSERT_TRUE(response1
!= NULL
);
1292 EXPECT_TRUE(response1
->headers
!= NULL
);
1293 EXPECT_TRUE(response1
->was_fetched_via_spdy
);
1294 out
.status_line
= response1
->headers
->GetStatusLine();
1295 out
.response_info
= *response1
;
1296 out
.rv
= ReadTransaction(trans1
.get(), &out
.response_data
);
1297 EXPECT_EQ(OK
, out
.rv
);
1298 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1299 EXPECT_EQ("hello!hello!", out
.response_data
);
1301 const HttpResponseInfo
* response2
= trans2
->GetResponseInfo();
1302 ASSERT_TRUE(response2
!= NULL
);
1303 out
.status_line
= response2
->headers
->GetStatusLine();
1304 out
.response_info
= *response2
;
1305 out
.rv
= ReadTransaction(trans2
.get(), &out
.response_data
);
1306 EXPECT_EQ(OK
, out
.rv
);
1307 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1308 EXPECT_EQ("hello!hello!", out
.response_data
);
1309 helper
.VerifyDataConsumed();
1310 EXPECT_EQ(OK
, out
.rv
);
1313 // The KillerCallback will delete the transaction on error as part of the
1315 class KillerCallback
: public TestCompletionCallbackBase
{
1317 explicit KillerCallback(HttpNetworkTransaction
* transaction
)
1318 : transaction_(transaction
),
1319 ALLOW_THIS_IN_INITIALIZER_LIST(callback_(
1320 base::Bind(&KillerCallback::OnComplete
, base::Unretained(this)))) {
1323 virtual ~KillerCallback() {}
1325 const CompletionCallback
& callback() const { return callback_
; }
1328 void OnComplete(int result
) {
1330 delete transaction_
;
1335 HttpNetworkTransaction
* transaction_
;
1336 CompletionCallback callback_
;
1339 // Similar to ThreeGetsMaxConcurrrentDelete above, however, this test
1340 // closes the socket while we have a pending transaction waiting for
1341 // a pending stream creation. http://crbug.com/52901
1342 TEST_P(SpdyNetworkTransactionTest
, ThreeGetsWithMaxConcurrentSocketClose
) {
1343 // Construct the request.
1344 scoped_ptr
<spdy::SpdyFrame
> req(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
1345 scoped_ptr
<spdy::SpdyFrame
> resp(ConstructSpdyGetSynReply(NULL
, 0, 1));
1346 scoped_ptr
<spdy::SpdyFrame
> body(ConstructSpdyBodyFrame(1, false));
1347 scoped_ptr
<spdy::SpdyFrame
> fin_body(ConstructSpdyBodyFrame(1, true));
1349 scoped_ptr
<spdy::SpdyFrame
> req2(ConstructSpdyGet(NULL
, 0, false, 3, LOWEST
));
1350 scoped_ptr
<spdy::SpdyFrame
> resp2(ConstructSpdyGetSynReply(NULL
, 0, 3));
1352 spdy::SpdySettings settings
;
1353 spdy::SettingsFlagsAndId
id(0);
1354 id
.set_id(spdy::SETTINGS_MAX_CONCURRENT_STREAMS
);
1355 const size_t max_concurrent_streams
= 1;
1357 settings
.push_back(spdy::SpdySetting(id
, max_concurrent_streams
));
1358 scoped_ptr
<spdy::SpdyFrame
> settings_frame(ConstructSpdySettings(settings
));
1360 MockWrite writes
[] = { CreateMockWrite(*req
),
1361 CreateMockWrite(*req2
),
1363 MockRead reads
[] = {
1364 CreateMockRead(*settings_frame
, 1),
1365 CreateMockRead(*resp
),
1366 CreateMockRead(*body
),
1367 CreateMockRead(*fin_body
),
1368 CreateMockRead(*resp2
, 7),
1369 MockRead(ASYNC
, ERR_CONNECTION_RESET
, 0), // Abort!
1372 scoped_ptr
<OrderedSocketData
> data(
1373 new OrderedSocketData(reads
, arraysize(reads
),
1374 writes
, arraysize(writes
)));
1375 scoped_ptr
<OrderedSocketData
> data_placeholder(
1376 new OrderedSocketData(NULL
, 0, NULL
, 0));
1379 TransactionHelperResult out
;
1380 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
1381 BoundNetLog(), GetParam());
1382 helper
.RunPreTestSetup();
1383 helper
.AddData(data
.get());
1384 // We require placeholder data because three get requests are sent out, so
1385 // there needs to be three sets of SSL connection data.
1386 helper
.AddData(data_placeholder
.get());
1387 helper
.AddData(data_placeholder
.get());
1388 HttpNetworkTransaction
trans1(helper
.session());
1389 HttpNetworkTransaction
trans2(helper
.session());
1390 HttpNetworkTransaction
* trans3(new HttpNetworkTransaction(helper
.session()));
1392 TestCompletionCallback callback1
;
1393 TestCompletionCallback callback2
;
1394 KillerCallback
callback3(trans3
);
1396 HttpRequestInfo httpreq1
= CreateGetRequest();
1397 HttpRequestInfo httpreq2
= CreateGetRequest();
1398 HttpRequestInfo httpreq3
= CreateGetRequest();
1400 out
.rv
= trans1
.Start(&httpreq1
, callback1
.callback(), log
);
1401 ASSERT_EQ(out
.rv
, ERR_IO_PENDING
);
1402 // run transaction 1 through quickly to force a read of our SETTINGS
1404 out
.rv
= callback1
.WaitForResult();
1405 ASSERT_EQ(OK
, out
.rv
);
1407 out
.rv
= trans2
.Start(&httpreq2
, callback2
.callback(), log
);
1408 ASSERT_EQ(out
.rv
, ERR_IO_PENDING
);
1409 out
.rv
= trans3
->Start(&httpreq3
, callback3
.callback(), log
);
1410 ASSERT_EQ(out
.rv
, ERR_IO_PENDING
);
1411 out
.rv
= callback3
.WaitForResult();
1412 ASSERT_EQ(ERR_ABORTED
, out
.rv
);
1414 EXPECT_EQ(6U, data
->read_index());
1416 const HttpResponseInfo
* response1
= trans1
.GetResponseInfo();
1417 ASSERT_TRUE(response1
!= NULL
);
1418 EXPECT_TRUE(response1
->headers
!= NULL
);
1419 EXPECT_TRUE(response1
->was_fetched_via_spdy
);
1420 out
.status_line
= response1
->headers
->GetStatusLine();
1421 out
.response_info
= *response1
;
1422 out
.rv
= ReadTransaction(&trans1
, &out
.response_data
);
1423 EXPECT_EQ(OK
, out
.rv
);
1425 const HttpResponseInfo
* response2
= trans2
.GetResponseInfo();
1426 ASSERT_TRUE(response2
!= NULL
);
1427 out
.status_line
= response2
->headers
->GetStatusLine();
1428 out
.response_info
= *response2
;
1429 out
.rv
= ReadTransaction(&trans2
, &out
.response_data
);
1430 EXPECT_EQ(ERR_CONNECTION_RESET
, out
.rv
);
1432 helper
.VerifyDataConsumed();
1435 // Test that a simple PUT request works.
1436 TEST_P(SpdyNetworkTransactionTest
, Put
) {
1437 // Setup the request
1438 HttpRequestInfo request
;
1439 request
.method
= "PUT";
1440 request
.url
= GURL("http://www.google.com/");
1442 const SpdyHeaderInfo kSynStartHeader
= {
1443 spdy::SYN_STREAM
, // Kind = Syn
1445 0, // Associated stream ID
1446 net::ConvertRequestPriorityToSpdyPriority(LOWEST
), // Priority
1447 spdy::CONTROL_FLAG_FIN
, // Control Flags
1448 false, // Compressed
1449 spdy::INVALID
, // Status
1452 spdy::DATA_FLAG_NONE
// Data Flags
1454 const char* const kPutHeaders
[] = {
1457 "host", "www.google.com",
1459 "version", "HTTP/1.1",
1460 "content-length", "0"
1462 scoped_ptr
<spdy::SpdyFrame
> req(ConstructSpdyPacket(kSynStartHeader
, NULL
, 0,
1463 kPutHeaders
, arraysize(kPutHeaders
) / 2));
1464 MockWrite writes
[] = {
1465 CreateMockWrite(*req
)
1468 scoped_ptr
<spdy::SpdyFrame
> body(ConstructSpdyBodyFrame(1, true));
1469 const SpdyHeaderInfo kSynReplyHeader
= {
1470 spdy::SYN_REPLY
, // Kind = SynReply
1472 0, // Associated stream ID
1473 net::ConvertRequestPriorityToSpdyPriority(LOWEST
), // Priority
1474 spdy::CONTROL_FLAG_NONE
, // Control Flags
1475 false, // Compressed
1476 spdy::INVALID
, // Status
1479 spdy::DATA_FLAG_NONE
// Data Flags
1481 static const char* const kStandardGetHeaders
[] = {
1483 "version", "HTTP/1.1"
1484 "content-length", "1234"
1486 scoped_ptr
<spdy::SpdyFrame
> resp(ConstructSpdyPacket(kSynReplyHeader
,
1487 NULL
, 0, kStandardGetHeaders
, arraysize(kStandardGetHeaders
) / 2));
1488 MockRead reads
[] = {
1489 CreateMockRead(*resp
),
1490 CreateMockRead(*body
),
1491 MockRead(ASYNC
, 0, 0) // EOF
1494 scoped_ptr
<DelayedSocketData
> data(
1495 new DelayedSocketData(1, reads
, arraysize(reads
),
1496 writes
, arraysize(writes
)));
1497 NormalSpdyTransactionHelper
helper(request
,
1498 BoundNetLog(), GetParam());
1499 helper
.RunToCompletion(data
.get());
1500 TransactionHelperResult out
= helper
.output();
1502 EXPECT_EQ(OK
, out
.rv
);
1503 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1506 // Test that a simple HEAD request works.
1507 TEST_P(SpdyNetworkTransactionTest
, Head
) {
1508 // Setup the request
1509 HttpRequestInfo request
;
1510 request
.method
= "HEAD";
1511 request
.url
= GURL("http://www.google.com/");
1513 const SpdyHeaderInfo kSynStartHeader
= {
1514 spdy::SYN_STREAM
, // Kind = Syn
1516 0, // Associated stream ID
1517 net::ConvertRequestPriorityToSpdyPriority(LOWEST
), // Priority
1518 spdy::CONTROL_FLAG_FIN
, // Control Flags
1519 false, // Compressed
1520 spdy::INVALID
, // Status
1523 spdy::DATA_FLAG_NONE
// Data Flags
1525 const char* const kHeadHeaders
[] = {
1528 "host", "www.google.com",
1530 "version", "HTTP/1.1",
1531 "content-length", "0"
1533 scoped_ptr
<spdy::SpdyFrame
> req(ConstructSpdyPacket(kSynStartHeader
, NULL
, 0,
1534 kHeadHeaders
, arraysize(kHeadHeaders
) / 2));
1535 MockWrite writes
[] = {
1536 CreateMockWrite(*req
)
1539 scoped_ptr
<spdy::SpdyFrame
> body(ConstructSpdyBodyFrame(1, true));
1540 const SpdyHeaderInfo kSynReplyHeader
= {
1541 spdy::SYN_REPLY
, // Kind = SynReply
1543 0, // Associated stream ID
1544 net::ConvertRequestPriorityToSpdyPriority(LOWEST
), // Priority
1545 spdy::CONTROL_FLAG_NONE
, // Control Flags
1546 false, // Compressed
1547 spdy::INVALID
, // Status
1550 spdy::DATA_FLAG_NONE
// Data Flags
1552 static const char* const kStandardGetHeaders
[] = {
1554 "version", "HTTP/1.1"
1555 "content-length", "1234"
1557 scoped_ptr
<spdy::SpdyFrame
> resp(ConstructSpdyPacket(kSynReplyHeader
,
1558 NULL
, 0, kStandardGetHeaders
, arraysize(kStandardGetHeaders
) / 2));
1559 MockRead reads
[] = {
1560 CreateMockRead(*resp
),
1561 CreateMockRead(*body
),
1562 MockRead(ASYNC
, 0, 0) // EOF
1565 scoped_ptr
<DelayedSocketData
> data(
1566 new DelayedSocketData(1, reads
, arraysize(reads
),
1567 writes
, arraysize(writes
)));
1568 NormalSpdyTransactionHelper
helper(request
,
1569 BoundNetLog(), GetParam());
1570 helper
.RunToCompletion(data
.get());
1571 TransactionHelperResult out
= helper
.output();
1573 EXPECT_EQ(OK
, out
.rv
);
1574 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1577 // Test that a simple POST works.
1578 TEST_P(SpdyNetworkTransactionTest
, Post
) {
1579 scoped_ptr
<spdy::SpdyFrame
> req(ConstructSpdyPost(kUploadDataSize
, NULL
, 0));
1580 scoped_ptr
<spdy::SpdyFrame
> body(ConstructSpdyBodyFrame(1, true));
1581 MockWrite writes
[] = {
1582 CreateMockWrite(*req
),
1583 CreateMockWrite(*body
), // POST upload frame
1586 scoped_ptr
<spdy::SpdyFrame
> resp(ConstructSpdyPostSynReply(NULL
, 0));
1587 MockRead reads
[] = {
1588 CreateMockRead(*resp
),
1589 CreateMockRead(*body
),
1590 MockRead(ASYNC
, 0, 0) // EOF
1593 scoped_ptr
<DelayedSocketData
> data(
1594 new DelayedSocketData(2, reads
, arraysize(reads
),
1595 writes
, arraysize(writes
)));
1596 NormalSpdyTransactionHelper
helper(CreatePostRequest(),
1597 BoundNetLog(), GetParam());
1598 helper
.RunToCompletion(data
.get());
1599 TransactionHelperResult out
= helper
.output();
1600 EXPECT_EQ(OK
, out
.rv
);
1601 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1602 EXPECT_EQ("hello!", out
.response_data
);
1605 // Test that a chunked POST works.
1606 TEST_P(SpdyNetworkTransactionTest
, ChunkedPost
) {
1607 UploadDataStream::set_merge_chunks(false);
1608 scoped_ptr
<spdy::SpdyFrame
> req(ConstructChunkedSpdyPost(NULL
, 0));
1609 scoped_ptr
<spdy::SpdyFrame
> chunk1(ConstructSpdyBodyFrame(1, false));
1610 scoped_ptr
<spdy::SpdyFrame
> chunk2(ConstructSpdyBodyFrame(1, true));
1611 MockWrite writes
[] = {
1612 CreateMockWrite(*req
),
1613 CreateMockWrite(*chunk1
),
1614 CreateMockWrite(*chunk2
),
1617 scoped_ptr
<spdy::SpdyFrame
> resp(ConstructSpdyPostSynReply(NULL
, 0));
1618 MockRead reads
[] = {
1619 CreateMockRead(*resp
),
1620 CreateMockRead(*chunk1
),
1621 CreateMockRead(*chunk2
),
1622 MockRead(ASYNC
, 0, 0) // EOF
1625 scoped_ptr
<DelayedSocketData
> data(
1626 new DelayedSocketData(2, reads
, arraysize(reads
),
1627 writes
, arraysize(writes
)));
1628 NormalSpdyTransactionHelper
helper(CreateChunkedPostRequest(),
1629 BoundNetLog(), GetParam());
1630 helper
.RunToCompletion(data
.get());
1631 TransactionHelperResult out
= helper
.output();
1632 EXPECT_EQ(OK
, out
.rv
);
1633 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1634 EXPECT_EQ("hello!hello!", out
.response_data
);
1637 // Test that a POST without any post data works.
1638 TEST_P(SpdyNetworkTransactionTest
, NullPost
) {
1639 // Setup the request
1640 HttpRequestInfo request
;
1641 request
.method
= "POST";
1642 request
.url
= GURL("http://www.google.com/");
1643 // Create an empty UploadData.
1644 request
.upload_data
= NULL
;
1646 // When request.upload_data is NULL for post, content-length is
1647 // expected to be 0.
1648 scoped_ptr
<spdy::SpdyFrame
> req(ConstructSpdyPost(0, NULL
, 0));
1649 // Set the FIN bit since there will be no body.
1650 req
->set_flags(spdy::CONTROL_FLAG_FIN
);
1651 MockWrite writes
[] = {
1652 CreateMockWrite(*req
),
1655 scoped_ptr
<spdy::SpdyFrame
> resp(ConstructSpdyPostSynReply(NULL
, 0));
1656 scoped_ptr
<spdy::SpdyFrame
> body(ConstructSpdyBodyFrame(1, true));
1657 MockRead reads
[] = {
1658 CreateMockRead(*resp
),
1659 CreateMockRead(*body
),
1660 MockRead(ASYNC
, 0, 0) // EOF
1663 scoped_ptr
<DelayedSocketData
> data(
1664 new DelayedSocketData(1, reads
, arraysize(reads
),
1665 writes
, arraysize(writes
)));
1667 NormalSpdyTransactionHelper
helper(request
,
1668 BoundNetLog(), GetParam());
1669 helper
.RunToCompletion(data
.get());
1670 TransactionHelperResult out
= helper
.output();
1671 EXPECT_EQ(OK
, out
.rv
);
1672 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1673 EXPECT_EQ("hello!", out
.response_data
);
1676 // Test that a simple POST works.
1677 TEST_P(SpdyNetworkTransactionTest
, EmptyPost
) {
1678 // Setup the request
1679 HttpRequestInfo request
;
1680 request
.method
= "POST";
1681 request
.url
= GURL("http://www.google.com/");
1682 // Create an empty UploadData.
1683 request
.upload_data
= new UploadData();
1685 // Http POST Content-Length is using UploadDataStream::size().
1686 // It is the same as request.upload_data->GetContentLengthSync().
1687 scoped_ptr
<UploadDataStream
> stream(
1688 new UploadDataStream(request
.upload_data
));
1689 ASSERT_EQ(OK
, stream
->Init());
1690 ASSERT_EQ(request
.upload_data
->GetContentLengthSync(),
1693 scoped_ptr
<spdy::SpdyFrame
>
1694 req(ConstructSpdyPost(
1695 request
.upload_data
->GetContentLengthSync(), NULL
, 0));
1696 // Set the FIN bit since there will be no body.
1697 req
->set_flags(spdy::CONTROL_FLAG_FIN
);
1698 MockWrite writes
[] = {
1699 CreateMockWrite(*req
),
1702 scoped_ptr
<spdy::SpdyFrame
> resp(ConstructSpdyPostSynReply(NULL
, 0));
1703 scoped_ptr
<spdy::SpdyFrame
> body(ConstructSpdyBodyFrame(1, true));
1704 MockRead reads
[] = {
1705 CreateMockRead(*resp
),
1706 CreateMockRead(*body
),
1707 MockRead(ASYNC
, 0, 0) // EOF
1710 scoped_ptr
<DelayedSocketData
> data(
1711 new DelayedSocketData(1, reads
, arraysize(reads
),
1712 writes
, arraysize(writes
)));
1714 NormalSpdyTransactionHelper
helper(request
,
1715 BoundNetLog(), GetParam());
1716 helper
.RunToCompletion(data
.get());
1717 TransactionHelperResult out
= helper
.output();
1718 EXPECT_EQ(OK
, out
.rv
);
1719 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1720 EXPECT_EQ("hello!", out
.response_data
);
1723 // While we're doing a post, the server sends back a SYN_REPLY.
1724 TEST_P(SpdyNetworkTransactionTest
, PostWithEarlySynReply
) {
1725 static const char upload
[] = { "hello!" };
1727 // Setup the request
1728 HttpRequestInfo request
;
1729 request
.method
= "POST";
1730 request
.url
= GURL("http://www.google.com/");
1731 request
.upload_data
= new UploadData();
1732 request
.upload_data
->AppendBytes(upload
, sizeof(upload
));
1734 // Http POST Content-Length is using UploadDataStream::size().
1735 // It is the same as request.upload_data->GetContentLengthSync().
1736 scoped_ptr
<UploadDataStream
> stream(
1737 new UploadDataStream(request
.upload_data
));
1738 ASSERT_EQ(OK
, stream
->Init());
1739 ASSERT_EQ(request
.upload_data
->GetContentLengthSync(),
1741 scoped_ptr
<spdy::SpdyFrame
> stream_reply(ConstructSpdyPostSynReply(NULL
, 0));
1742 scoped_ptr
<spdy::SpdyFrame
> stream_body(ConstructSpdyBodyFrame(1, true));
1743 MockRead reads
[] = {
1744 CreateMockRead(*stream_reply
, 2),
1745 CreateMockRead(*stream_body
, 3),
1746 MockRead(SYNCHRONOUS
, 0, 0) // EOF
1749 scoped_ptr
<DelayedSocketData
> data(
1750 new DelayedSocketData(0, reads
, arraysize(reads
), NULL
, 0));
1751 NormalSpdyTransactionHelper
helper(request
,
1752 BoundNetLog(), GetParam());
1753 helper
.RunPreTestSetup();
1754 helper
.AddData(data
.get());
1755 helper
.RunDefaultTest();
1756 helper
.VerifyDataConsumed();
1758 TransactionHelperResult out
= helper
.output();
1759 EXPECT_EQ(ERR_SYN_REPLY_NOT_RECEIVED
, out
.rv
);
1762 // The client upon cancellation tries to send a RST_STREAM frame. The mock
1763 // socket causes the TCP write to return zero. This test checks that the client
1764 // tries to queue up the RST_STREAM frame again.
1765 TEST_P(SpdyNetworkTransactionTest
, SocketWriteReturnsZero
) {
1766 scoped_ptr
<spdy::SpdyFrame
> req(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
1767 scoped_ptr
<spdy::SpdyFrame
> rst(
1768 ConstructSpdyRstStream(1, spdy::CANCEL
));
1769 MockWrite writes
[] = {
1770 CreateMockWrite(*req
.get(), 0, SYNCHRONOUS
),
1771 MockWrite(SYNCHRONOUS
, 0, 0, 2),
1772 CreateMockWrite(*rst
.get(), 3, SYNCHRONOUS
),
1775 scoped_ptr
<spdy::SpdyFrame
> resp(ConstructSpdyGetSynReply(NULL
, 0, 1));
1776 MockRead reads
[] = {
1777 CreateMockRead(*resp
.get(), 1, ASYNC
),
1778 MockRead(ASYNC
, 0, 0, 4) // EOF
1781 scoped_refptr
<DeterministicSocketData
> data(
1782 new DeterministicSocketData(reads
, arraysize(reads
),
1783 writes
, arraysize(writes
)));
1784 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
1785 BoundNetLog(), GetParam());
1786 helper
.SetDeterministic();
1787 helper
.RunPreTestSetup();
1788 helper
.AddDeterministicData(data
.get());
1789 HttpNetworkTransaction
* trans
= helper
.trans();
1791 TestCompletionCallback callback
;
1792 int rv
= trans
->Start(
1793 &CreateGetRequest(), callback
.callback(), BoundNetLog());
1794 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1798 helper
.ResetTrans();
1802 helper
.VerifyDataConsumed();
1805 // Test that the transaction doesn't crash when we don't have a reply.
1806 TEST_P(SpdyNetworkTransactionTest
, ResponseWithoutSynReply
) {
1807 scoped_ptr
<spdy::SpdyFrame
> body(ConstructSpdyBodyFrame(1, true));
1808 MockRead reads
[] = {
1809 CreateMockRead(*body
),
1810 MockRead(ASYNC
, 0, 0) // EOF
1813 scoped_ptr
<DelayedSocketData
> data(
1814 new DelayedSocketData(1, reads
, arraysize(reads
), NULL
, 0));
1815 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
1816 BoundNetLog(), GetParam());
1817 helper
.RunToCompletion(data
.get());
1818 TransactionHelperResult out
= helper
.output();
1819 EXPECT_EQ(ERR_SYN_REPLY_NOT_RECEIVED
, out
.rv
);
1822 // Test that the transaction doesn't crash when we get two replies on the same
1823 // stream ID. See http://crbug.com/45639.
1824 TEST_P(SpdyNetworkTransactionTest
, ResponseWithTwoSynReplies
) {
1825 scoped_ptr
<spdy::SpdyFrame
> req(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
1826 MockWrite writes
[] = { CreateMockWrite(*req
) };
1828 scoped_ptr
<spdy::SpdyFrame
> resp(ConstructSpdyGetSynReply(NULL
, 0, 1));
1829 scoped_ptr
<spdy::SpdyFrame
> body(ConstructSpdyBodyFrame(1, true));
1830 MockRead reads
[] = {
1831 CreateMockRead(*resp
),
1832 CreateMockRead(*resp
),
1833 CreateMockRead(*body
),
1834 MockRead(ASYNC
, 0, 0) // EOF
1837 scoped_ptr
<DelayedSocketData
> data(
1838 new DelayedSocketData(1, reads
, arraysize(reads
),
1839 writes
, arraysize(writes
)));
1841 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
1842 BoundNetLog(), GetParam());
1843 helper
.RunPreTestSetup();
1844 helper
.AddData(data
.get());
1846 HttpNetworkTransaction
* trans
= helper
.trans();
1848 TestCompletionCallback callback
;
1849 int rv
= trans
->Start(&helper
.request(), callback
.callback(), BoundNetLog());
1850 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1851 rv
= callback
.WaitForResult();
1854 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1855 ASSERT_TRUE(response
!= NULL
);
1856 EXPECT_TRUE(response
->headers
!= NULL
);
1857 EXPECT_TRUE(response
->was_fetched_via_spdy
);
1858 std::string response_data
;
1859 rv
= ReadTransaction(trans
, &response_data
);
1860 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR
, rv
);
1862 helper
.VerifyDataConsumed();
1865 // Test that sent data frames and received WINDOW_UPDATE frames change
1866 // the send_window_size_ correctly.
1868 // WINDOW_UPDATE is different than most other frames in that it can arrive
1869 // while the client is still sending the request body. In order to enforce
1870 // this scenario, we feed a couple of dummy frames and give a delay of 0 to
1871 // socket data provider, so that initial read that is done as soon as the
1872 // stream is created, succeeds and schedules another read. This way reads
1873 // and writes are interleaved; after doing a full frame write, SpdyStream
1874 // will break out of DoLoop and will read and process a WINDOW_UPDATE.
1875 // Once our WINDOW_UPDATE is read, we cannot send SYN_REPLY right away
1876 // since request has not been completely written, therefore we feed
1877 // enough number of WINDOW_UPDATEs to finish the first read and cause a
1878 // write, leading to a complete write of request body; after that we send
1879 // a reply with a body, to cause a graceful shutdown.
1881 // TODO(agayev): develop a socket data provider where both, reads and
1882 // writes are ordered so that writing tests like these are easy and rewrite
1883 // all these tests using it. Right now we are working around the
1884 // limitations as described above and it's not deterministic, tests may
1885 // fail under specific circumstances.
1886 TEST_P(SpdyNetworkTransactionTest
, WindowUpdateReceived
) {
1887 SpdySession::set_use_flow_control(SpdySession::kEnableFlowControl
);
1889 static int kFrameCount
= 2;
1890 scoped_ptr
<std::string
> content(
1891 new std::string(kMaxSpdyFrameChunkSize
, 'a'));
1892 scoped_ptr
<spdy::SpdyFrame
> req(ConstructSpdyPost(
1893 kMaxSpdyFrameChunkSize
* kFrameCount
, NULL
, 0));
1894 scoped_ptr
<spdy::SpdyFrame
> body(
1895 ConstructSpdyBodyFrame(1, content
->c_str(), content
->size(), false));
1896 scoped_ptr
<spdy::SpdyFrame
> body_end(
1897 ConstructSpdyBodyFrame(1, content
->c_str(), content
->size(), true));
1899 MockWrite writes
[] = {
1900 CreateMockWrite(*req
),
1901 CreateMockWrite(*body
),
1902 CreateMockWrite(*body_end
),
1905 static const int32 kDeltaWindowSize
= 0xff;
1906 static const int kDeltaCount
= 4;
1907 scoped_ptr
<spdy::SpdyFrame
> window_update(
1908 ConstructSpdyWindowUpdate(1, kDeltaWindowSize
));
1909 scoped_ptr
<spdy::SpdyFrame
> window_update_dummy(
1910 ConstructSpdyWindowUpdate(2, kDeltaWindowSize
));
1911 scoped_ptr
<spdy::SpdyFrame
> resp(ConstructSpdyPostSynReply(NULL
, 0));
1912 MockRead reads
[] = {
1913 CreateMockRead(*window_update_dummy
),
1914 CreateMockRead(*window_update_dummy
),
1915 CreateMockRead(*window_update_dummy
),
1916 CreateMockRead(*window_update
), // Four updates, therefore window
1917 CreateMockRead(*window_update
), // size should increase by
1918 CreateMockRead(*window_update
), // kDeltaWindowSize * 4
1919 CreateMockRead(*window_update
),
1920 CreateMockRead(*resp
),
1921 CreateMockRead(*body_end
),
1922 MockRead(ASYNC
, 0, 0) // EOF
1925 scoped_ptr
<DelayedSocketData
> data(
1926 new DelayedSocketData(0, reads
, arraysize(reads
),
1927 writes
, arraysize(writes
)));
1929 // Setup the request
1930 HttpRequestInfo request
;
1931 request
.method
= "POST";
1932 request
.url
= GURL(kDefaultURL
);
1933 request
.upload_data
= new UploadData();
1934 for (int i
= 0; i
< kFrameCount
; ++i
)
1935 request
.upload_data
->AppendBytes(content
->c_str(), content
->size());
1937 NormalSpdyTransactionHelper
helper(request
, BoundNetLog(), GetParam());
1938 helper
.AddData(data
.get());
1939 helper
.RunPreTestSetup();
1941 HttpNetworkTransaction
* trans
= helper
.trans();
1943 TestCompletionCallback callback
;
1944 int rv
= trans
->Start(&helper
.request(), callback
.callback(), BoundNetLog());
1946 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1947 rv
= callback
.WaitForResult();
1950 SpdyHttpStream
* stream
= static_cast<SpdyHttpStream
*>(trans
->stream_
.get());
1951 ASSERT_TRUE(stream
!= NULL
);
1952 ASSERT_TRUE(stream
->stream() != NULL
);
1953 EXPECT_EQ(static_cast<int>(spdy::kSpdyStreamInitialWindowSize
) +
1954 kDeltaWindowSize
* kDeltaCount
-
1955 kMaxSpdyFrameChunkSize
* kFrameCount
,
1956 stream
->stream()->send_window_size());
1957 helper
.VerifyDataConsumed();
1959 SpdySession::set_use_flow_control(SpdySession::kFlowControlBasedOnNPN
);
1962 // Test that received data frames and sent WINDOW_UPDATE frames change
1963 // the recv_window_size_ correctly.
1964 TEST_P(SpdyNetworkTransactionTest
, WindowUpdateSent
) {
1965 SpdySession::set_use_flow_control(SpdySession::kEnableFlowControl
);
1967 scoped_ptr
<spdy::SpdyFrame
> req(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
1968 scoped_ptr
<spdy::SpdyFrame
> window_update(
1969 ConstructSpdyWindowUpdate(1, kUploadDataSize
));
1971 MockWrite writes
[] = {
1972 CreateMockWrite(*req
),
1973 CreateMockWrite(*window_update
),
1976 scoped_ptr
<spdy::SpdyFrame
> resp(
1977 ConstructSpdyGetSynReply(NULL
, 0, 1));
1978 scoped_ptr
<spdy::SpdyFrame
> body_no_fin(
1979 ConstructSpdyBodyFrame(1, false));
1980 scoped_ptr
<spdy::SpdyFrame
> body_fin(
1981 ConstructSpdyBodyFrame(1, NULL
, 0, true));
1982 MockRead reads
[] = {
1983 CreateMockRead(*resp
),
1984 CreateMockRead(*body_no_fin
),
1985 MockRead(ASYNC
, ERR_IO_PENDING
, 0), // Force a pause
1986 CreateMockRead(*body_fin
),
1987 MockRead(ASYNC
, ERR_IO_PENDING
, 0), // Force a pause
1988 MockRead(ASYNC
, 0, 0) // EOF
1991 scoped_ptr
<DelayedSocketData
> data(
1992 new DelayedSocketData(1, reads
, arraysize(reads
),
1993 writes
, arraysize(writes
)));
1995 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
1996 BoundNetLog(), GetParam());
1997 helper
.AddData(data
.get());
1998 helper
.RunPreTestSetup();
1999 HttpNetworkTransaction
* trans
= helper
.trans();
2001 TestCompletionCallback callback
;
2002 int rv
= trans
->Start(&helper
.request(), callback
.callback(), BoundNetLog());
2004 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2005 rv
= callback
.WaitForResult();
2008 SpdyHttpStream
* stream
=
2009 static_cast<SpdyHttpStream
*>(trans
->stream_
.get());
2010 ASSERT_TRUE(stream
!= NULL
);
2011 ASSERT_TRUE(stream
->stream() != NULL
);
2014 static_cast<int>(spdy::kSpdyStreamInitialWindowSize
) - kUploadDataSize
,
2015 stream
->stream()->recv_window_size());
2017 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2018 ASSERT_TRUE(response
!= NULL
);
2019 ASSERT_TRUE(response
->headers
!= NULL
);
2020 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
2021 EXPECT_TRUE(response
->was_fetched_via_spdy
);
2023 // Issue a read which will cause a WINDOW_UPDATE to be sent and window
2024 // size increased to default.
2025 scoped_refptr
<net::IOBuffer
> buf(new net::IOBuffer(kUploadDataSize
));
2026 rv
= trans
->Read(buf
, kUploadDataSize
, CompletionCallback());
2027 EXPECT_EQ(kUploadDataSize
, rv
);
2028 std::string
content(buf
->data(), buf
->data()+kUploadDataSize
);
2029 EXPECT_STREQ(kUploadData
, content
.c_str());
2031 // Schedule the reading of empty data frame with FIN
2032 data
->CompleteRead();
2034 // Force write of WINDOW_UPDATE which was scheduled during the above
2036 MessageLoop::current()->RunAllPending();
2039 data
->CompleteRead();
2041 helper
.VerifyDataConsumed();
2043 SpdySession::set_use_flow_control(SpdySession::kFlowControlBasedOnNPN
);
2046 // Test that WINDOW_UPDATE frame causing overflow is handled correctly. We
2047 // use the same trick as in the above test to enforce our scenario.
2048 TEST_P(SpdyNetworkTransactionTest
, WindowUpdateOverflow
) {
2049 SpdySession::set_use_flow_control(SpdySession::kEnableFlowControl
);
2051 // number of full frames we hope to write (but will not, used to
2052 // set content-length header correctly)
2053 static int kFrameCount
= 3;
2055 scoped_ptr
<std::string
> content(
2056 new std::string(kMaxSpdyFrameChunkSize
, 'a'));
2057 scoped_ptr
<spdy::SpdyFrame
> req(ConstructSpdyPost(
2058 kMaxSpdyFrameChunkSize
* kFrameCount
, NULL
, 0));
2059 scoped_ptr
<spdy::SpdyFrame
> body(
2060 ConstructSpdyBodyFrame(1, content
->c_str(), content
->size(), false));
2061 scoped_ptr
<spdy::SpdyFrame
> rst(
2062 ConstructSpdyRstStream(1, spdy::FLOW_CONTROL_ERROR
));
2064 // We're not going to write a data frame with FIN, we'll receive a bad
2065 // WINDOW_UPDATE while sending a request and will send a RST_STREAM frame.
2066 MockWrite writes
[] = {
2067 CreateMockWrite(*req
),
2068 CreateMockWrite(*body
),
2069 CreateMockWrite(*rst
),
2072 static const int32 kDeltaWindowSize
= 0x7fffffff; // cause an overflow
2073 scoped_ptr
<spdy::SpdyFrame
> window_update(
2074 ConstructSpdyWindowUpdate(1, kDeltaWindowSize
));
2075 scoped_ptr
<spdy::SpdyFrame
> window_update2(
2076 ConstructSpdyWindowUpdate(2, kDeltaWindowSize
));
2077 scoped_ptr
<spdy::SpdyFrame
> reply(ConstructSpdyPostSynReply(NULL
, 0));
2079 MockRead reads
[] = {
2080 CreateMockRead(*window_update2
),
2081 CreateMockRead(*window_update2
),
2082 CreateMockRead(*window_update
),
2083 CreateMockRead(*window_update
),
2084 CreateMockRead(*window_update
),
2085 MockRead(ASYNC
, ERR_IO_PENDING
, 0), // Wait for the RST to be written.
2086 MockRead(ASYNC
, 0, 0) // EOF
2089 scoped_ptr
<DelayedSocketData
> data(
2090 new DelayedSocketData(0, reads
, arraysize(reads
),
2091 writes
, arraysize(writes
)));
2093 // Setup the request
2094 HttpRequestInfo request
;
2095 request
.method
= "POST";
2096 request
.url
= GURL("http://www.google.com/");
2097 request
.upload_data
= new UploadData();
2098 for (int i
= 0; i
< kFrameCount
; ++i
)
2099 request
.upload_data
->AppendBytes(content
->c_str(), content
->size());
2101 NormalSpdyTransactionHelper
helper(request
,
2102 BoundNetLog(), GetParam());
2103 helper
.AddData(data
.get());
2104 helper
.RunPreTestSetup();
2106 HttpNetworkTransaction
* trans
= helper
.trans();
2108 TestCompletionCallback callback
;
2109 int rv
= trans
->Start(&helper
.request(), callback
.callback(), BoundNetLog());
2111 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2112 rv
= callback
.WaitForResult();
2113 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR
, rv
);
2115 data
->CompleteRead();
2117 ASSERT_TRUE(helper
.session() != NULL
);
2118 ASSERT_TRUE(helper
.session()->spdy_session_pool() != NULL
);
2119 helper
.session()->spdy_session_pool()->CloseAllSessions();
2120 helper
.VerifyDataConsumed();
2122 SpdySession::set_use_flow_control(SpdySession::kFlowControlBasedOnNPN
);
2125 // Test that after hitting a send window size of 0, the write process
2126 // stalls and upon receiving WINDOW_UPDATE frame write resumes.
2128 // This test constructs a POST request followed by enough data frames
2129 // containing 'a' that would make the window size 0, followed by another
2130 // data frame containing default content (which is "hello!") and this frame
2131 // also contains a FIN flag. DelayedSocketData is used to enforce all
2132 // writes go through before a read could happen. However, the last frame
2133 // ("hello!") is not supposed to go through since by the time its turn
2134 // arrives, window size is 0. At this point MessageLoop::Run() called via
2135 // callback would block. Therefore we call MessageLoop::RunAllPending()
2136 // which returns after performing all possible writes. We use DCHECKS to
2137 // ensure that last data frame is still there and stream has stalled.
2138 // After that, next read is artifically enforced, which causes a
2139 // WINDOW_UPDATE to be read and I/O process resumes.
2140 TEST_P(SpdyNetworkTransactionTest
, FlowControlStallResume
) {
2141 SpdySession::set_use_flow_control(SpdySession::kEnableFlowControl
);
2143 // Number of frames we need to send to zero out the window size: data
2144 // frames plus SYN_STREAM plus the last data frame; also we need another
2145 // data frame that we will send once the WINDOW_UPDATE is received,
2148 spdy::kSpdyStreamInitialWindowSize
/ kMaxSpdyFrameChunkSize
+ 3;
2150 // Calculate last frame's size; 0 size data frame is legal.
2151 size_t last_frame_size
=
2152 spdy::kSpdyStreamInitialWindowSize
% kMaxSpdyFrameChunkSize
;
2154 // Construct content for a data frame of maximum size.
2155 scoped_ptr
<std::string
> content(
2156 new std::string(kMaxSpdyFrameChunkSize
, 'a'));
2158 scoped_ptr
<spdy::SpdyFrame
> req(ConstructSpdyPost(
2159 spdy::kSpdyStreamInitialWindowSize
+ kUploadDataSize
, NULL
, 0));
2162 scoped_ptr
<spdy::SpdyFrame
> body1(
2163 ConstructSpdyBodyFrame(1, content
->c_str(), content
->size(), false));
2165 // Last frame to zero out the window size.
2166 scoped_ptr
<spdy::SpdyFrame
> body2(
2167 ConstructSpdyBodyFrame(1, content
->c_str(), last_frame_size
, false));
2169 // Data frame to be sent once WINDOW_UPDATE frame is received.
2170 scoped_ptr
<spdy::SpdyFrame
> body3(ConstructSpdyBodyFrame(1, true));
2172 // Fill in mock writes.
2173 scoped_array
<MockWrite
> writes(new MockWrite
[nwrites
]);
2175 writes
[i
] = CreateMockWrite(*req
);
2176 for (i
= 1; i
< nwrites
-2; i
++)
2177 writes
[i
] = CreateMockWrite(*body1
);
2178 writes
[i
++] = CreateMockWrite(*body2
);
2179 writes
[i
] = CreateMockWrite(*body3
);
2181 // Construct read frame, give enough space to upload the rest of the
2183 scoped_ptr
<spdy::SpdyFrame
> window_update(
2184 ConstructSpdyWindowUpdate(1, kUploadDataSize
));
2185 scoped_ptr
<spdy::SpdyFrame
> reply(ConstructSpdyPostSynReply(NULL
, 0));
2186 MockRead reads
[] = {
2187 CreateMockRead(*window_update
),
2188 CreateMockRead(*window_update
),
2189 CreateMockRead(*reply
),
2190 CreateMockRead(*body2
),
2191 CreateMockRead(*body3
),
2192 MockRead(ASYNC
, 0, 0) // EOF
2195 // Force all writes to happen before any read, last write will not
2196 // actually queue a frame, due to window size being 0.
2197 scoped_ptr
<DelayedSocketData
> data(
2198 new DelayedSocketData(nwrites
, reads
, arraysize(reads
),
2199 writes
.get(), nwrites
));
2201 HttpRequestInfo request
;
2202 request
.method
= "POST";
2203 request
.url
= GURL("http://www.google.com/");
2204 request
.upload_data
= new UploadData();
2205 scoped_ptr
<std::string
> upload_data(
2206 new std::string(spdy::kSpdyStreamInitialWindowSize
, 'a'));
2207 upload_data
->append(kUploadData
, kUploadDataSize
);
2208 request
.upload_data
->AppendBytes(upload_data
->c_str(), upload_data
->size());
2209 NormalSpdyTransactionHelper
helper(request
,
2210 BoundNetLog(), GetParam());
2211 helper
.AddData(data
.get());
2212 helper
.RunPreTestSetup();
2214 HttpNetworkTransaction
* trans
= helper
.trans();
2216 TestCompletionCallback callback
;
2217 int rv
= trans
->Start(&helper
.request(), callback
.callback(), BoundNetLog());
2218 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2220 MessageLoop::current()->RunAllPending(); // Write as much as we can.
2222 SpdyHttpStream
* stream
= static_cast<SpdyHttpStream
*>(trans
->stream_
.get());
2223 ASSERT_TRUE(stream
!= NULL
);
2224 ASSERT_TRUE(stream
->stream() != NULL
);
2225 EXPECT_EQ(0, stream
->stream()->send_window_size());
2226 // All the body data should have been read.
2227 // TODO(satorux): This is because of the weirdness in reading the request
2228 // body in OnSendBodyComplete(). See crbug.com/113107.
2229 EXPECT_TRUE(stream
->request_body_stream_
->IsEOF());
2230 // But the body is not yet fully sent ("hello!" is not yet sent).
2231 EXPECT_FALSE(stream
->stream()->body_sent());
2233 data
->ForceNextRead(); // Read in WINDOW_UPDATE frame.
2234 rv
= callback
.WaitForResult();
2235 helper
.VerifyDataConsumed();
2237 SpdySession::set_use_flow_control(SpdySession::kFlowControlBasedOnNPN
);
2240 TEST_P(SpdyNetworkTransactionTest
, CancelledTransaction
) {
2241 // Construct the request.
2242 scoped_ptr
<spdy::SpdyFrame
> req(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
2243 MockWrite writes
[] = {
2244 CreateMockWrite(*req
),
2247 scoped_ptr
<spdy::SpdyFrame
> resp(ConstructSpdyGetSynReply(NULL
, 0, 1));
2248 MockRead reads
[] = {
2249 CreateMockRead(*resp
),
2250 // This following read isn't used by the test, except during the
2251 // RunAllPending() call at the end since the SpdySession survives the
2252 // HttpNetworkTransaction and still tries to continue Read()'ing. Any
2253 // MockRead will do here.
2254 MockRead(ASYNC
, 0, 0) // EOF
2257 StaticSocketDataProvider
data(reads
, arraysize(reads
),
2258 writes
, arraysize(writes
));
2260 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
2261 BoundNetLog(), GetParam());
2262 helper
.RunPreTestSetup();
2263 helper
.AddData(&data
);
2264 HttpNetworkTransaction
* trans
= helper
.trans();
2266 TestCompletionCallback callback
;
2267 int rv
= trans
->Start(
2268 &CreateGetRequest(), callback
.callback(), BoundNetLog());
2269 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2270 helper
.ResetTrans(); // Cancel the transaction.
2272 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
2273 // MockClientSocketFactory) are still alive.
2274 MessageLoop::current()->RunAllPending();
2275 helper
.VerifyDataNotConsumed();
2278 // Verify that the client sends a Rst Frame upon cancelling the stream.
2279 TEST_P(SpdyNetworkTransactionTest
, CancelledTransactionSendRst
) {
2280 scoped_ptr
<spdy::SpdyFrame
> req(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
2281 scoped_ptr
<spdy::SpdyFrame
> rst(
2282 ConstructSpdyRstStream(1, spdy::CANCEL
));
2283 MockWrite writes
[] = {
2284 CreateMockWrite(*req
, 0, SYNCHRONOUS
),
2285 CreateMockWrite(*rst
, 2, SYNCHRONOUS
),
2288 scoped_ptr
<spdy::SpdyFrame
> resp(ConstructSpdyGetSynReply(NULL
, 0, 1));
2289 MockRead reads
[] = {
2290 CreateMockRead(*resp
, 1, ASYNC
),
2291 MockRead(ASYNC
, 0, 0, 3) // EOF
2294 scoped_refptr
<DeterministicSocketData
> data(
2295 new DeterministicSocketData(reads
, arraysize(reads
),
2296 writes
, arraysize(writes
)));
2298 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
2301 helper
.SetDeterministic();
2302 helper
.RunPreTestSetup();
2303 helper
.AddDeterministicData(data
.get());
2304 HttpNetworkTransaction
* trans
= helper
.trans();
2306 TestCompletionCallback callback
;
2308 int rv
= trans
->Start(
2309 &CreateGetRequest(), callback
.callback(), BoundNetLog());
2310 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2314 helper
.ResetTrans();
2318 helper
.VerifyDataConsumed();
2321 // Verify that the client can correctly deal with the user callback attempting
2322 // to start another transaction on a session that is closing down. See
2323 // http://crbug.com/47455
2324 TEST_P(SpdyNetworkTransactionTest
, StartTransactionOnReadCallback
) {
2325 scoped_ptr
<spdy::SpdyFrame
> req(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
2326 MockWrite writes
[] = { CreateMockWrite(*req
) };
2327 MockWrite writes2
[] = { CreateMockWrite(*req
) };
2329 // The indicated length of this packet is longer than its actual length. When
2330 // the session receives an empty packet after this one, it shuts down the
2331 // session, and calls the read callback with the incomplete data.
2332 const uint8 kGetBodyFrame2
[] = {
2333 0x00, 0x00, 0x00, 0x01,
2334 0x01, 0x00, 0x00, 0x07,
2335 'h', 'e', 'l', 'l', 'o', '!',
2338 scoped_ptr
<spdy::SpdyFrame
> resp(ConstructSpdyGetSynReply(NULL
, 0, 1));
2339 MockRead reads
[] = {
2340 CreateMockRead(*resp
, 2),
2341 MockRead(ASYNC
, ERR_IO_PENDING
, 3), // Force a pause
2342 MockRead(ASYNC
, reinterpret_cast<const char*>(kGetBodyFrame2
),
2343 arraysize(kGetBodyFrame2
), 4),
2344 MockRead(ASYNC
, ERR_IO_PENDING
, 5), // Force a pause
2345 MockRead(ASYNC
, 0, 0, 6), // EOF
2347 MockRead reads2
[] = {
2348 CreateMockRead(*resp
, 2),
2349 MockRead(ASYNC
, 0, 0, 3), // EOF
2352 scoped_ptr
<OrderedSocketData
> data(
2353 new OrderedSocketData(reads
, arraysize(reads
),
2354 writes
, arraysize(writes
)));
2355 scoped_ptr
<DelayedSocketData
> data2(
2356 new DelayedSocketData(1, reads2
, arraysize(reads2
),
2357 writes2
, arraysize(writes2
)));
2359 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
2360 BoundNetLog(), GetParam());
2361 helper
.RunPreTestSetup();
2362 helper
.AddData(data
.get());
2363 helper
.AddData(data2
.get());
2364 HttpNetworkTransaction
* trans
= helper
.trans();
2366 // Start the transaction with basic parameters.
2367 TestCompletionCallback callback
;
2368 int rv
= trans
->Start(&helper
.request(), callback
.callback(), BoundNetLog());
2369 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2370 rv
= callback
.WaitForResult();
2372 const int kSize
= 3000;
2373 scoped_refptr
<net::IOBuffer
> buf(new net::IOBuffer(kSize
));
2376 base::Bind(&SpdyNetworkTransactionTest::StartTransactionCallback
,
2378 // This forces an err_IO_pending, which sets the callback.
2379 data
->CompleteRead();
2380 // This finishes the read.
2381 data
->CompleteRead();
2382 helper
.VerifyDataConsumed();
2385 // Verify that the client can correctly deal with the user callback deleting the
2386 // transaction. Failures will usually be valgrind errors. See
2387 // http://crbug.com/46925
2388 TEST_P(SpdyNetworkTransactionTest
, DeleteSessionOnReadCallback
) {
2389 scoped_ptr
<spdy::SpdyFrame
> req(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
2390 MockWrite writes
[] = { CreateMockWrite(*req
) };
2392 scoped_ptr
<spdy::SpdyFrame
> resp(ConstructSpdyGetSynReply(NULL
, 0, 1));
2393 scoped_ptr
<spdy::SpdyFrame
> body(ConstructSpdyBodyFrame(1, true));
2394 MockRead reads
[] = {
2395 CreateMockRead(*resp
.get(), 2),
2396 MockRead(ASYNC
, ERR_IO_PENDING
, 3), // Force a pause
2397 CreateMockRead(*body
.get(), 4),
2398 MockRead(ASYNC
, 0, 0, 5), // EOF
2401 scoped_ptr
<OrderedSocketData
> data(
2402 new OrderedSocketData(reads
, arraysize(reads
),
2403 writes
, arraysize(writes
)));
2405 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
2406 BoundNetLog(), GetParam());
2407 helper
.RunPreTestSetup();
2408 helper
.AddData(data
.get());
2409 HttpNetworkTransaction
* trans
= helper
.trans();
2411 // Start the transaction with basic parameters.
2412 TestCompletionCallback callback
;
2413 int rv
= trans
->Start(&helper
.request(), callback
.callback(), BoundNetLog());
2414 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2415 rv
= callback
.WaitForResult();
2417 // Setup a user callback which will delete the session, and clear out the
2418 // memory holding the stream object. Note that the callback deletes trans.
2419 const int kSize
= 3000;
2420 scoped_refptr
<net::IOBuffer
> buf(new net::IOBuffer(kSize
));
2423 base::Bind(&SpdyNetworkTransactionTest::DeleteSessionCallback
,
2424 base::Unretained(&helper
)));
2425 ASSERT_EQ(ERR_IO_PENDING
, rv
);
2426 data
->CompleteRead();
2428 // Finish running rest of tasks.
2429 MessageLoop::current()->RunAllPending();
2430 helper
.VerifyDataConsumed();
2433 // Send a spdy request to www.google.com that gets redirected to www.foo.com.
2434 TEST_P(SpdyNetworkTransactionTest
, RedirectGetRequest
) {
2435 // These are headers which the net::URLRequest tacks on.
2436 const char* const kExtraHeaders
[] = {
2440 const SpdyHeaderInfo kSynStartHeader
= MakeSpdyHeader(spdy::SYN_STREAM
);
2441 const char* const kStandardGetHeaders
[] = {
2455 const char* const kStandardGetHeaders2
[] = {
2470 // Setup writes/reads to www.google.com
2471 scoped_ptr
<spdy::SpdyFrame
> req(ConstructSpdyPacket(
2472 kSynStartHeader
, kExtraHeaders
, arraysize(kExtraHeaders
) / 2,
2473 kStandardGetHeaders
, arraysize(kStandardGetHeaders
) / 2));
2474 scoped_ptr
<spdy::SpdyFrame
> req2(ConstructSpdyPacket(
2475 kSynStartHeader
, kExtraHeaders
, arraysize(kExtraHeaders
) / 2,
2476 kStandardGetHeaders2
, arraysize(kStandardGetHeaders2
) / 2));
2477 scoped_ptr
<spdy::SpdyFrame
> resp(ConstructSpdyGetSynReplyRedirect(1));
2478 MockWrite writes
[] = {
2479 CreateMockWrite(*req
, 1),
2481 MockRead reads
[] = {
2482 CreateMockRead(*resp
, 2),
2483 MockRead(ASYNC
, 0, 0, 3) // EOF
2486 // Setup writes/reads to www.foo.com
2487 scoped_ptr
<spdy::SpdyFrame
> resp2(ConstructSpdyGetSynReply(NULL
, 0, 1));
2488 scoped_ptr
<spdy::SpdyFrame
> body2(ConstructSpdyBodyFrame(1, true));
2489 MockWrite writes2
[] = {
2490 CreateMockWrite(*req2
, 1),
2492 MockRead reads2
[] = {
2493 CreateMockRead(*resp2
, 2),
2494 CreateMockRead(*body2
, 3),
2495 MockRead(ASYNC
, 0, 0, 4) // EOF
2497 scoped_ptr
<OrderedSocketData
> data(
2498 new OrderedSocketData(reads
, arraysize(reads
),
2499 writes
, arraysize(writes
)));
2500 scoped_ptr
<OrderedSocketData
> data2(
2501 new OrderedSocketData(reads2
, arraysize(reads2
),
2502 writes2
, arraysize(writes2
)));
2504 // TODO(erikchen): Make test support SPDYSSL, SPDYNPN
2505 HttpStreamFactory::set_force_spdy_over_ssl(false);
2506 HttpStreamFactory::set_force_spdy_always(true);
2509 net::URLRequest
r(GURL("http://www.google.com/"), &d
);
2510 SpdyURLRequestContext
* spdy_url_request_context
=
2511 new SpdyURLRequestContext();
2512 r
.set_context(spdy_url_request_context
);
2513 spdy_url_request_context
->socket_factory().
2514 AddSocketDataProvider(data
.get());
2515 spdy_url_request_context
->socket_factory().
2516 AddSocketDataProvider(data2
.get());
2518 d
.set_quit_on_redirect(true);
2520 MessageLoop::current()->Run();
2522 EXPECT_EQ(1, d
.received_redirect_count());
2524 r
.FollowDeferredRedirect();
2525 MessageLoop::current()->Run();
2526 EXPECT_EQ(1, d
.response_started_count());
2527 EXPECT_FALSE(d
.received_data_before_response());
2528 EXPECT_EQ(net::URLRequestStatus::SUCCESS
, r
.status().status());
2529 std::string
contents("hello!");
2530 EXPECT_EQ(contents
, d
.data_received());
2532 EXPECT_TRUE(data
->at_read_eof());
2533 EXPECT_TRUE(data
->at_write_eof());
2534 EXPECT_TRUE(data2
->at_read_eof());
2535 EXPECT_TRUE(data2
->at_write_eof());
2538 // Detect response with upper case headers and reset the stream.
2539 TEST_P(SpdyNetworkTransactionTest
, UpperCaseHeaders
) {
2540 scoped_ptr
<spdy::SpdyFrame
>
2541 syn(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
2542 scoped_ptr
<spdy::SpdyFrame
>
2543 rst(ConstructSpdyRstStream(1, spdy::PROTOCOL_ERROR
));
2544 MockWrite writes
[] = {
2545 CreateMockWrite(*syn
, 0),
2546 CreateMockWrite(*rst
, 2),
2549 const char* const kExtraHeaders
[] = {"X-UpperCase", "yes"};
2550 scoped_ptr
<spdy::SpdyFrame
>
2551 reply(ConstructSpdyGetSynReply(kExtraHeaders
, 1, 1));
2552 MockRead reads
[] = {
2553 CreateMockRead(*reply
, 1),
2554 MockRead(ASYNC
, ERR_IO_PENDING
, 3), // Force a pause
2557 HttpResponseInfo response
;
2558 HttpResponseInfo response2
;
2559 scoped_ptr
<OrderedSocketData
> data(new OrderedSocketData(
2563 arraysize(writes
)));
2564 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
2565 BoundNetLog(), GetParam());
2566 helper
.RunToCompletion(data
.get());
2567 TransactionHelperResult out
= helper
.output();
2568 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR
, out
.rv
);
2571 // Detect response with upper case headers in a HEADERS frame and reset the
2573 TEST_P(SpdyNetworkTransactionTest
, UpperCaseHeadersInHeadersFrame
) {
2574 scoped_ptr
<spdy::SpdyFrame
>
2575 syn(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
2576 scoped_ptr
<spdy::SpdyFrame
>
2577 rst(ConstructSpdyRstStream(1, spdy::PROTOCOL_ERROR
));
2578 MockWrite writes
[] = {
2579 CreateMockWrite(*syn
, 0),
2580 CreateMockWrite(*rst
, 2),
2583 static const char* const kInitialHeaders
[] = {
2585 "version", "HTTP/1.1"
2587 static const char* const kLateHeaders
[] = {
2588 "X-UpperCase", "yes",
2590 scoped_ptr
<spdy::SpdyFrame
>
2591 stream1_reply(ConstructSpdyControlFrame(kInitialHeaders
,
2592 arraysize(kInitialHeaders
) / 2,
2597 spdy::CONTROL_FLAG_NONE
,
2601 scoped_ptr
<spdy::SpdyFrame
>
2602 stream1_headers(ConstructSpdyControlFrame(kLateHeaders
,
2603 arraysize(kLateHeaders
) / 2,
2608 spdy::CONTROL_FLAG_NONE
,
2612 scoped_ptr
<spdy::SpdyFrame
> stream1_body(ConstructSpdyBodyFrame(1, true));
2613 MockRead reads
[] = {
2614 CreateMockRead(*stream1_reply
),
2615 CreateMockRead(*stream1_headers
),
2616 CreateMockRead(*stream1_body
),
2617 MockRead(ASYNC
, 0, 0) // EOF
2620 scoped_ptr
<DelayedSocketData
> data(
2621 new DelayedSocketData(1, reads
, arraysize(reads
),
2622 writes
, arraysize(writes
)));
2623 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
2624 BoundNetLog(), GetParam());
2625 helper
.RunToCompletion(data
.get());
2626 TransactionHelperResult out
= helper
.output();
2627 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR
, out
.rv
);
2630 // Detect push stream with upper case headers and reset the stream.
2631 TEST_P(SpdyNetworkTransactionTest
, UpperCaseHeadersOnPush
) {
2632 scoped_ptr
<spdy::SpdyFrame
>
2633 syn(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
2634 scoped_ptr
<spdy::SpdyFrame
>
2635 rst(ConstructSpdyRstStream(2, spdy::PROTOCOL_ERROR
));
2636 MockWrite writes
[] = {
2637 CreateMockWrite(*syn
, 0),
2638 CreateMockWrite(*rst
, 2),
2641 scoped_ptr
<spdy::SpdyFrame
>
2642 reply(ConstructSpdyGetSynReply(NULL
, 0, 1));
2643 const char* const extra_headers
[] = {"X-UpperCase", "yes"};
2644 scoped_ptr
<spdy::SpdyFrame
>
2645 push(ConstructSpdyPush(extra_headers
, 1, 2, 1));
2646 scoped_ptr
<spdy::SpdyFrame
> body(ConstructSpdyBodyFrame(1, true));
2647 MockRead reads
[] = {
2648 CreateMockRead(*reply
, 1),
2649 CreateMockRead(*push
, 1),
2650 CreateMockRead(*body
, 1),
2651 MockRead(ASYNC
, ERR_IO_PENDING
, 3), // Force a pause
2654 HttpResponseInfo response
;
2655 HttpResponseInfo response2
;
2656 scoped_ptr
<OrderedSocketData
> data(new OrderedSocketData(
2660 arraysize(writes
)));
2661 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
2662 BoundNetLog(), GetParam());
2663 helper
.RunToCompletion(data
.get());
2664 TransactionHelperResult out
= helper
.output();
2665 EXPECT_EQ(OK
, out
.rv
);
2668 // Send a spdy request to www.google.com. Get a pushed stream that redirects to
2670 TEST_P(SpdyNetworkTransactionTest
, RedirectServerPush
) {
2671 // These are headers which the net::URLRequest tacks on.
2672 const char* const kExtraHeaders
[] = {
2676 const SpdyHeaderInfo kSynStartHeader
= MakeSpdyHeader(spdy::SYN_STREAM
);
2677 const char* const kStandardGetHeaders
[] = {
2692 // Setup writes/reads to www.google.com
2693 scoped_ptr
<spdy::SpdyFrame
> req(
2694 ConstructSpdyPacket(kSynStartHeader
,
2696 arraysize(kExtraHeaders
) / 2,
2697 kStandardGetHeaders
,
2698 arraysize(kStandardGetHeaders
) / 2));
2699 scoped_ptr
<spdy::SpdyFrame
> resp(ConstructSpdyGetSynReply(NULL
, 0, 1));
2700 scoped_ptr
<spdy::SpdyFrame
> rep(
2701 ConstructSpdyPush(NULL
,
2705 "http://www.google.com/foo.dat",
2706 "301 Moved Permanently",
2707 "http://www.foo.com/index.php"));
2708 scoped_ptr
<spdy::SpdyFrame
> body(ConstructSpdyBodyFrame(1, true));
2709 scoped_ptr
<spdy::SpdyFrame
> rst(ConstructSpdyRstStream(2, spdy::CANCEL
));
2710 MockWrite writes
[] = {
2711 CreateMockWrite(*req
, 1),
2712 CreateMockWrite(*rst
, 6),
2714 MockRead reads
[] = {
2715 CreateMockRead(*resp
, 2),
2716 CreateMockRead(*rep
, 3),
2717 CreateMockRead(*body
, 4),
2718 MockRead(ASYNC
, ERR_IO_PENDING
, 5), // Force a pause
2719 MockRead(ASYNC
, 0, 0, 7) // EOF
2722 // Setup writes/reads to www.foo.com
2723 const char* const kStandardGetHeaders2
[] = {
2737 scoped_ptr
<spdy::SpdyFrame
> req2(
2738 ConstructSpdyPacket(kSynStartHeader
,
2740 arraysize(kExtraHeaders
) / 2,
2741 kStandardGetHeaders2
,
2742 arraysize(kStandardGetHeaders2
) / 2));
2743 scoped_ptr
<spdy::SpdyFrame
> resp2(ConstructSpdyGetSynReply(NULL
, 0, 1));
2744 scoped_ptr
<spdy::SpdyFrame
> body2(ConstructSpdyBodyFrame(1, true));
2745 MockWrite writes2
[] = {
2746 CreateMockWrite(*req2
, 1),
2748 MockRead reads2
[] = {
2749 CreateMockRead(*resp2
, 2),
2750 CreateMockRead(*body2
, 3),
2751 MockRead(ASYNC
, 0, 0, 5) // EOF
2753 scoped_ptr
<OrderedSocketData
> data(
2754 new OrderedSocketData(reads
, arraysize(reads
),
2755 writes
, arraysize(writes
)));
2756 scoped_ptr
<OrderedSocketData
> data2(
2757 new OrderedSocketData(reads2
, arraysize(reads2
),
2758 writes2
, arraysize(writes2
)));
2760 // TODO(erikchen): Make test support SPDYSSL, SPDYNPN
2761 HttpStreamFactory::set_force_spdy_over_ssl(false);
2762 HttpStreamFactory::set_force_spdy_always(true);
2765 scoped_refptr
<SpdyURLRequestContext
> spdy_url_request_context(
2766 new SpdyURLRequestContext());
2768 net::URLRequest
r(GURL("http://www.google.com/"), &d
);
2769 r
.set_context(spdy_url_request_context
);
2770 spdy_url_request_context
->socket_factory().
2771 AddSocketDataProvider(data
.get());
2774 MessageLoop::current()->Run();
2776 EXPECT_EQ(0, d
.received_redirect_count());
2777 std::string
contents("hello!");
2778 EXPECT_EQ(contents
, d
.data_received());
2780 net::URLRequest
r2(GURL("http://www.google.com/foo.dat"), &d2
);
2781 r2
.set_context(spdy_url_request_context
);
2782 spdy_url_request_context
->socket_factory().
2783 AddSocketDataProvider(data2
.get());
2785 d2
.set_quit_on_redirect(true);
2787 MessageLoop::current()->Run();
2788 EXPECT_EQ(1, d2
.received_redirect_count());
2790 r2
.FollowDeferredRedirect();
2791 MessageLoop::current()->Run();
2792 EXPECT_EQ(1, d2
.response_started_count());
2793 EXPECT_FALSE(d2
.received_data_before_response());
2794 EXPECT_EQ(net::URLRequestStatus::SUCCESS
, r2
.status().status());
2795 std::string
contents2("hello!");
2796 EXPECT_EQ(contents2
, d2
.data_received());
2798 data
->CompleteRead();
2799 data2
->CompleteRead();
2800 EXPECT_TRUE(data
->at_read_eof());
2801 EXPECT_TRUE(data
->at_write_eof());
2802 EXPECT_TRUE(data2
->at_read_eof());
2803 EXPECT_TRUE(data2
->at_write_eof());
2806 TEST_P(SpdyNetworkTransactionTest
, ServerPushSingleDataFrame
) {
2807 static const unsigned char kPushBodyFrame
[] = {
2808 0x00, 0x00, 0x00, 0x02, // header, ID
2809 0x01, 0x00, 0x00, 0x06, // FIN, length
2810 'p', 'u', 's', 'h', 'e', 'd' // "pushed"
2812 scoped_ptr
<spdy::SpdyFrame
>
2813 stream1_syn(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
2814 scoped_ptr
<spdy::SpdyFrame
>
2815 stream1_body(ConstructSpdyBodyFrame(1, true));
2816 MockWrite writes
[] = {
2817 CreateMockWrite(*stream1_syn
, 1),
2820 scoped_ptr
<spdy::SpdyFrame
>
2821 stream1_reply(ConstructSpdyGetSynReply(NULL
, 0, 1));
2822 scoped_ptr
<spdy::SpdyFrame
>
2823 stream2_syn(ConstructSpdyPush(NULL
,
2827 "http://www.google.com/foo.dat"));
2828 MockRead reads
[] = {
2829 CreateMockRead(*stream1_reply
, 2),
2830 CreateMockRead(*stream2_syn
, 3),
2831 CreateMockRead(*stream1_body
, 4, SYNCHRONOUS
),
2832 MockRead(ASYNC
, reinterpret_cast<const char*>(kPushBodyFrame
),
2833 arraysize(kPushBodyFrame
), 5),
2834 MockRead(ASYNC
, ERR_IO_PENDING
, 6), // Force a pause
2837 HttpResponseInfo response
;
2838 HttpResponseInfo response2
;
2839 std::string
expected_push_result("pushed");
2840 scoped_ptr
<OrderedSocketData
> data(new OrderedSocketData(
2844 arraysize(writes
)));
2845 RunServerPushTest(data
.get(),
2848 expected_push_result
);
2850 // Verify the SYN_REPLY.
2851 EXPECT_TRUE(response
.headers
!= NULL
);
2852 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
2854 // Verify the pushed stream.
2855 EXPECT_TRUE(response2
.headers
!= NULL
);
2856 EXPECT_EQ("HTTP/1.1 200 OK", response2
.headers
->GetStatusLine());
2859 TEST_P(SpdyNetworkTransactionTest
, ServerPushSingleDataFrame2
) {
2860 static const unsigned char kPushBodyFrame
[] = {
2861 0x00, 0x00, 0x00, 0x02, // header, ID
2862 0x01, 0x00, 0x00, 0x06, // FIN, length
2863 'p', 'u', 's', 'h', 'e', 'd' // "pushed"
2865 scoped_ptr
<spdy::SpdyFrame
>
2866 stream1_syn(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
2867 MockWrite writes
[] = {
2868 CreateMockWrite(*stream1_syn
, 1),
2871 scoped_ptr
<spdy::SpdyFrame
>
2872 stream1_reply(ConstructSpdyGetSynReply(NULL
, 0, 1));
2873 scoped_ptr
<spdy::SpdyFrame
>
2874 stream2_syn(ConstructSpdyPush(NULL
,
2878 "http://www.google.com/foo.dat"));
2879 scoped_ptr
<spdy::SpdyFrame
>
2880 stream1_body(ConstructSpdyBodyFrame(1, true));
2881 MockRead reads
[] = {
2882 CreateMockRead(*stream1_reply
, 2),
2883 CreateMockRead(*stream2_syn
, 3),
2884 MockRead(ASYNC
, reinterpret_cast<const char*>(kPushBodyFrame
),
2885 arraysize(kPushBodyFrame
), 5),
2886 CreateMockRead(*stream1_body
, 4, SYNCHRONOUS
),
2887 MockRead(ASYNC
, ERR_IO_PENDING
, 6), // Force a pause
2890 HttpResponseInfo response
;
2891 HttpResponseInfo response2
;
2892 std::string
expected_push_result("pushed");
2893 scoped_ptr
<OrderedSocketData
> data(new OrderedSocketData(
2897 arraysize(writes
)));
2898 RunServerPushTest(data
.get(),
2901 expected_push_result
);
2903 // Verify the SYN_REPLY.
2904 EXPECT_TRUE(response
.headers
!= NULL
);
2905 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
2907 // Verify the pushed stream.
2908 EXPECT_TRUE(response2
.headers
!= NULL
);
2909 EXPECT_EQ("HTTP/1.1 200 OK", response2
.headers
->GetStatusLine());
2912 TEST_P(SpdyNetworkTransactionTest
, ServerPushServerAborted
) {
2913 scoped_ptr
<spdy::SpdyFrame
>
2914 stream1_syn(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
2915 scoped_ptr
<spdy::SpdyFrame
>
2916 stream1_body(ConstructSpdyBodyFrame(1, true));
2917 MockWrite writes
[] = {
2918 CreateMockWrite(*stream1_syn
, 1),
2921 scoped_ptr
<spdy::SpdyFrame
>
2922 stream1_reply(ConstructSpdyGetSynReply(NULL
, 0, 1));
2923 scoped_ptr
<spdy::SpdyFrame
>
2924 stream2_syn(ConstructSpdyPush(NULL
,
2928 "http://www.google.com/foo.dat"));
2929 scoped_ptr
<spdy::SpdyFrame
>
2930 stream2_rst(ConstructSpdyRstStream(2, spdy::PROTOCOL_ERROR
));
2931 MockRead reads
[] = {
2932 CreateMockRead(*stream1_reply
, 2),
2933 CreateMockRead(*stream2_syn
, 3),
2934 CreateMockRead(*stream2_rst
, 4),
2935 CreateMockRead(*stream1_body
, 5, SYNCHRONOUS
),
2936 MockRead(ASYNC
, ERR_IO_PENDING
, 6), // Force a pause
2939 scoped_ptr
<OrderedSocketData
> data(
2940 new OrderedSocketData(reads
, arraysize(reads
),
2941 writes
, arraysize(writes
)));
2942 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
2943 BoundNetLog(), GetParam());
2945 helper
.RunPreTestSetup();
2946 helper
.AddData(data
.get());
2948 HttpNetworkTransaction
* trans
= helper
.trans();
2950 // Start the transaction with basic parameters.
2951 TestCompletionCallback callback
;
2952 int rv
= trans
->Start(
2953 &CreateGetRequest(), callback
.callback(), BoundNetLog());
2954 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2955 rv
= callback
.WaitForResult();
2958 // Verify that we consumed all test data.
2959 EXPECT_TRUE(data
->at_read_eof()) << "Read count: "
2960 << data
->read_count()
2962 << data
->read_index();
2963 EXPECT_TRUE(data
->at_write_eof()) << "Write count: "
2964 << data
->write_count()
2966 << data
->write_index();
2968 // Verify the SYN_REPLY.
2969 HttpResponseInfo response
= *trans
->GetResponseInfo();
2970 EXPECT_TRUE(response
.headers
!= NULL
);
2971 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
2974 TEST_P(SpdyNetworkTransactionTest
, ServerPushDuplicate
) {
2975 // Verify that we don't leak streams and that we properly send a reset
2976 // if the server pushes the same stream twice.
2977 static const unsigned char kPushBodyFrame
[] = {
2978 0x00, 0x00, 0x00, 0x02, // header, ID
2979 0x01, 0x00, 0x00, 0x06, // FIN, length
2980 'p', 'u', 's', 'h', 'e', 'd' // "pushed"
2983 scoped_ptr
<spdy::SpdyFrame
>
2984 stream1_syn(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
2985 scoped_ptr
<spdy::SpdyFrame
>
2986 stream1_body(ConstructSpdyBodyFrame(1, true));
2987 scoped_ptr
<spdy::SpdyFrame
>
2988 stream3_rst(ConstructSpdyRstStream(4, spdy::PROTOCOL_ERROR
));
2989 MockWrite writes
[] = {
2990 CreateMockWrite(*stream1_syn
, 1),
2991 CreateMockWrite(*stream3_rst
, 5),
2994 scoped_ptr
<spdy::SpdyFrame
>
2995 stream1_reply(ConstructSpdyGetSynReply(NULL
, 0, 1));
2996 scoped_ptr
<spdy::SpdyFrame
>
2997 stream2_syn(ConstructSpdyPush(NULL
,
3001 "http://www.google.com/foo.dat"));
3002 scoped_ptr
<spdy::SpdyFrame
>
3003 stream3_syn(ConstructSpdyPush(NULL
,
3007 "http://www.google.com/foo.dat"));
3008 MockRead reads
[] = {
3009 CreateMockRead(*stream1_reply
, 2),
3010 CreateMockRead(*stream2_syn
, 3),
3011 CreateMockRead(*stream3_syn
, 4),
3012 CreateMockRead(*stream1_body
, 6, SYNCHRONOUS
),
3013 MockRead(ASYNC
, reinterpret_cast<const char*>(kPushBodyFrame
),
3014 arraysize(kPushBodyFrame
), 7),
3015 MockRead(ASYNC
, ERR_IO_PENDING
, 8), // Force a pause
3018 HttpResponseInfo response
;
3019 HttpResponseInfo response2
;
3020 std::string
expected_push_result("pushed");
3021 scoped_ptr
<OrderedSocketData
> data(new OrderedSocketData(
3025 arraysize(writes
)));
3026 RunServerPushTest(data
.get(),
3029 expected_push_result
);
3031 // Verify the SYN_REPLY.
3032 EXPECT_TRUE(response
.headers
!= NULL
);
3033 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
3035 // Verify the pushed stream.
3036 EXPECT_TRUE(response2
.headers
!= NULL
);
3037 EXPECT_EQ("HTTP/1.1 200 OK", response2
.headers
->GetStatusLine());
3040 TEST_P(SpdyNetworkTransactionTest
, ServerPushMultipleDataFrame
) {
3041 static const unsigned char kPushBodyFrame1
[] = {
3042 0x00, 0x00, 0x00, 0x02, // header, ID
3043 0x01, 0x00, 0x00, 0x1F, // FIN, length
3044 'p', 'u', 's', 'h', 'e', 'd' // "pushed"
3046 static const char kPushBodyFrame2
[] = " my darling";
3047 static const char kPushBodyFrame3
[] = " hello";
3048 static const char kPushBodyFrame4
[] = " my baby";
3050 scoped_ptr
<spdy::SpdyFrame
>
3051 stream1_syn(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
3052 scoped_ptr
<spdy::SpdyFrame
>
3053 stream1_body(ConstructSpdyBodyFrame(1, true));
3054 MockWrite writes
[] = {
3055 CreateMockWrite(*stream1_syn
, 1),
3058 scoped_ptr
<spdy::SpdyFrame
>
3059 stream1_reply(ConstructSpdyGetSynReply(NULL
, 0, 1));
3060 scoped_ptr
<spdy::SpdyFrame
>
3061 stream2_syn(ConstructSpdyPush(NULL
,
3065 "http://www.google.com/foo.dat"));
3066 MockRead reads
[] = {
3067 CreateMockRead(*stream1_reply
, 2),
3068 CreateMockRead(*stream2_syn
, 3),
3069 MockRead(ASYNC
, reinterpret_cast<const char*>(kPushBodyFrame1
),
3070 arraysize(kPushBodyFrame1
), 4),
3071 MockRead(ASYNC
, reinterpret_cast<const char*>(kPushBodyFrame2
),
3072 arraysize(kPushBodyFrame2
) - 1, 5),
3073 MockRead(ASYNC
, reinterpret_cast<const char*>(kPushBodyFrame3
),
3074 arraysize(kPushBodyFrame3
) - 1, 6),
3075 MockRead(ASYNC
, reinterpret_cast<const char*>(kPushBodyFrame4
),
3076 arraysize(kPushBodyFrame4
) - 1, 7),
3077 CreateMockRead(*stream1_body
, 8, SYNCHRONOUS
),
3078 MockRead(ASYNC
, ERR_IO_PENDING
, 9), // Force a pause
3081 HttpResponseInfo response
;
3082 HttpResponseInfo response2
;
3083 std::string
expected_push_result("pushed my darling hello my baby");
3084 scoped_ptr
<OrderedSocketData
> data(new OrderedSocketData(
3088 arraysize(writes
)));
3089 RunServerPushTest(data
.get(),
3092 expected_push_result
);
3094 // Verify the SYN_REPLY.
3095 EXPECT_TRUE(response
.headers
!= NULL
);
3096 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
3098 // Verify the pushed stream.
3099 EXPECT_TRUE(response2
.headers
!= NULL
);
3100 EXPECT_EQ("HTTP/1.1 200 OK", response2
.headers
->GetStatusLine());
3103 TEST_P(SpdyNetworkTransactionTest
, ServerPushMultipleDataFrameInterrupted
) {
3104 SpdySession::set_use_flow_control(SpdySession::kDisableFlowControl
);
3106 static const unsigned char kPushBodyFrame1
[] = {
3107 0x00, 0x00, 0x00, 0x02, // header, ID
3108 0x01, 0x00, 0x00, 0x1F, // FIN, length
3109 'p', 'u', 's', 'h', 'e', 'd' // "pushed"
3111 static const char kPushBodyFrame2
[] = " my darling";
3112 static const char kPushBodyFrame3
[] = " hello";
3113 static const char kPushBodyFrame4
[] = " my baby";
3115 scoped_ptr
<spdy::SpdyFrame
>
3116 stream1_syn(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
3117 scoped_ptr
<spdy::SpdyFrame
>
3118 stream1_body(ConstructSpdyBodyFrame(1, true));
3119 MockWrite writes
[] = {
3120 CreateMockWrite(*stream1_syn
, 1),
3123 scoped_ptr
<spdy::SpdyFrame
>
3124 stream1_reply(ConstructSpdyGetSynReply(NULL
, 0, 1));
3125 scoped_ptr
<spdy::SpdyFrame
>
3126 stream2_syn(ConstructSpdyPush(NULL
,
3130 "http://www.google.com/foo.dat"));
3131 MockRead reads
[] = {
3132 CreateMockRead(*stream1_reply
, 2),
3133 CreateMockRead(*stream2_syn
, 3),
3134 MockRead(ASYNC
, reinterpret_cast<const char*>(kPushBodyFrame1
),
3135 arraysize(kPushBodyFrame1
), 4),
3136 MockRead(ASYNC
, reinterpret_cast<const char*>(kPushBodyFrame2
),
3137 arraysize(kPushBodyFrame2
) - 1, 5),
3138 MockRead(ASYNC
, ERR_IO_PENDING
, 6), // Force a pause
3139 MockRead(ASYNC
, reinterpret_cast<const char*>(kPushBodyFrame3
),
3140 arraysize(kPushBodyFrame3
) - 1, 7),
3141 MockRead(ASYNC
, reinterpret_cast<const char*>(kPushBodyFrame4
),
3142 arraysize(kPushBodyFrame4
) - 1, 8),
3143 CreateMockRead(*stream1_body
.get(), 9, SYNCHRONOUS
),
3144 MockRead(ASYNC
, ERR_IO_PENDING
, 10) // Force a pause.
3147 HttpResponseInfo response
;
3148 HttpResponseInfo response2
;
3149 std::string
expected_push_result("pushed my darling hello my baby");
3150 scoped_ptr
<OrderedSocketData
> data(new OrderedSocketData(
3154 arraysize(writes
)));
3155 RunServerPushTest(data
.get(),
3158 expected_push_result
);
3160 // Verify the SYN_REPLY.
3161 EXPECT_TRUE(response
.headers
!= NULL
);
3162 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
3164 // Verify the pushed stream.
3165 EXPECT_TRUE(response2
.headers
!= NULL
);
3166 EXPECT_EQ("HTTP/1.1 200 OK", response2
.headers
->GetStatusLine());
3168 SpdySession::set_use_flow_control(SpdySession::kFlowControlBasedOnNPN
);
3171 TEST_P(SpdyNetworkTransactionTest
, ServerPushInvalidAssociatedStreamID0
) {
3172 scoped_ptr
<spdy::SpdyFrame
>
3173 stream1_syn(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
3174 scoped_ptr
<spdy::SpdyFrame
>
3175 stream1_body(ConstructSpdyBodyFrame(1, true));
3176 scoped_ptr
<spdy::SpdyFrame
>
3177 stream2_rst(ConstructSpdyRstStream(2, spdy::INVALID_STREAM
));
3178 MockWrite writes
[] = {
3179 CreateMockWrite(*stream1_syn
, 1),
3180 CreateMockWrite(*stream2_rst
, 4),
3183 scoped_ptr
<spdy::SpdyFrame
>
3184 stream1_reply(ConstructSpdyGetSynReply(NULL
, 0, 1));
3185 scoped_ptr
<spdy::SpdyFrame
>
3186 stream2_syn(ConstructSpdyPush(NULL
,
3190 "http://www.google.com/foo.dat"));
3191 MockRead reads
[] = {
3192 CreateMockRead(*stream1_reply
, 2),
3193 CreateMockRead(*stream2_syn
, 3),
3194 CreateMockRead(*stream1_body
, 4),
3195 MockRead(ASYNC
, ERR_IO_PENDING
, 5) // Force a pause
3198 scoped_ptr
<OrderedSocketData
> data(
3199 new OrderedSocketData(reads
, arraysize(reads
),
3200 writes
, arraysize(writes
)));
3201 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
3202 BoundNetLog(), GetParam());
3204 helper
.RunPreTestSetup();
3205 helper
.AddData(data
.get());
3207 HttpNetworkTransaction
* trans
= helper
.trans();
3209 // Start the transaction with basic parameters.
3210 TestCompletionCallback callback
;
3211 int rv
= trans
->Start(
3212 &CreateGetRequest(), callback
.callback(), BoundNetLog());
3213 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3214 rv
= callback
.WaitForResult();
3217 // Verify that we consumed all test data.
3218 EXPECT_TRUE(data
->at_read_eof()) << "Read count: "
3219 << data
->read_count()
3221 << data
->read_index();
3222 EXPECT_TRUE(data
->at_write_eof()) << "Write count: "
3223 << data
->write_count()
3225 << data
->write_index();
3227 // Verify the SYN_REPLY.
3228 HttpResponseInfo response
= *trans
->GetResponseInfo();
3229 EXPECT_TRUE(response
.headers
!= NULL
);
3230 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
3233 TEST_P(SpdyNetworkTransactionTest
, ServerPushInvalidAssociatedStreamID9
) {
3234 scoped_ptr
<spdy::SpdyFrame
>
3235 stream1_syn(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
3236 scoped_ptr
<spdy::SpdyFrame
>
3237 stream1_body(ConstructSpdyBodyFrame(1, true));
3238 scoped_ptr
<spdy::SpdyFrame
>
3239 stream2_rst(ConstructSpdyRstStream(2, spdy::INVALID_ASSOCIATED_STREAM
));
3240 MockWrite writes
[] = {
3241 CreateMockWrite(*stream1_syn
, 1),
3242 CreateMockWrite(*stream2_rst
, 4),
3245 scoped_ptr
<spdy::SpdyFrame
>
3246 stream1_reply(ConstructSpdyGetSynReply(NULL
, 0, 1));
3247 scoped_ptr
<spdy::SpdyFrame
>
3248 stream2_syn(ConstructSpdyPush(NULL
,
3252 "http://www.google.com/foo.dat"));
3253 MockRead reads
[] = {
3254 CreateMockRead(*stream1_reply
, 2),
3255 CreateMockRead(*stream2_syn
, 3),
3256 CreateMockRead(*stream1_body
, 4),
3257 MockRead(ASYNC
, ERR_IO_PENDING
, 5), // Force a pause
3260 scoped_ptr
<OrderedSocketData
> data(
3261 new OrderedSocketData(reads
, arraysize(reads
),
3262 writes
, arraysize(writes
)));
3263 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
3264 BoundNetLog(), GetParam());
3266 helper
.RunPreTestSetup();
3267 helper
.AddData(data
.get());
3269 HttpNetworkTransaction
* trans
= helper
.trans();
3271 // Start the transaction with basic parameters.
3272 TestCompletionCallback callback
;
3273 int rv
= trans
->Start(
3274 &CreateGetRequest(), callback
.callback(), BoundNetLog());
3275 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3276 rv
= callback
.WaitForResult();
3279 // Verify that we consumed all test data.
3280 EXPECT_TRUE(data
->at_read_eof()) << "Read count: "
3281 << data
->read_count()
3283 << data
->read_index();
3284 EXPECT_TRUE(data
->at_write_eof()) << "Write count: "
3285 << data
->write_count()
3287 << data
->write_index();
3289 // Verify the SYN_REPLY.
3290 HttpResponseInfo response
= *trans
->GetResponseInfo();
3291 EXPECT_TRUE(response
.headers
!= NULL
);
3292 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
3295 TEST_P(SpdyNetworkTransactionTest
, ServerPushNoURL
) {
3296 scoped_ptr
<spdy::SpdyFrame
>
3297 stream1_syn(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
3298 scoped_ptr
<spdy::SpdyFrame
>
3299 stream1_body(ConstructSpdyBodyFrame(1, true));
3300 scoped_ptr
<spdy::SpdyFrame
>
3301 stream2_rst(ConstructSpdyRstStream(2, spdy::PROTOCOL_ERROR
));
3302 MockWrite writes
[] = {
3303 CreateMockWrite(*stream1_syn
, 1),
3304 CreateMockWrite(*stream2_rst
, 4),
3307 scoped_ptr
<spdy::SpdyFrame
>
3308 stream1_reply(ConstructSpdyGetSynReply(NULL
, 0, 1));
3309 scoped_ptr
<spdy::SpdyFrame
>
3310 stream2_syn(ConstructSpdyPush(NULL
, 0, 2, 1));
3311 MockRead reads
[] = {
3312 CreateMockRead(*stream1_reply
, 2),
3313 CreateMockRead(*stream2_syn
, 3),
3314 CreateMockRead(*stream1_body
, 4),
3315 MockRead(ASYNC
, ERR_IO_PENDING
, 5) // Force a pause
3318 scoped_ptr
<OrderedSocketData
> data(
3319 new OrderedSocketData(reads
, arraysize(reads
),
3320 writes
, arraysize(writes
)));
3321 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
3322 BoundNetLog(), GetParam());
3324 helper
.RunPreTestSetup();
3325 helper
.AddData(data
.get());
3327 HttpNetworkTransaction
* trans
= helper
.trans();
3329 // Start the transaction with basic parameters.
3330 TestCompletionCallback callback
;
3331 int rv
= trans
->Start(
3332 &CreateGetRequest(), callback
.callback(), BoundNetLog());
3333 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3334 rv
= callback
.WaitForResult();
3336 // Verify that we consumed all test data.
3337 EXPECT_TRUE(data
->at_read_eof()) << "Read count: "
3338 << data
->read_count()
3340 << data
->read_index();
3341 EXPECT_TRUE(data
->at_write_eof()) << "Write count: "
3342 << data
->write_count()
3344 << data
->write_index();
3346 // Verify the SYN_REPLY.
3347 HttpResponseInfo response
= *trans
->GetResponseInfo();
3348 EXPECT_TRUE(response
.headers
!= NULL
);
3349 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
3352 // Verify that various SynReply headers parse correctly through the
3354 TEST_P(SpdyNetworkTransactionTest
, SynReplyHeaders
) {
3355 struct SynReplyHeadersTests
{
3357 const char* extra_headers
[5];
3358 const char* expected_headers
;
3360 // This uses a multi-valued cookie header.
3363 "cookie", "val2", // will get appended separated by NULL
3370 "version: HTTP/1.1\n"
3372 // This is the minimalist set of headers.
3377 "version: HTTP/1.1\n"
3379 // Headers with a comma separated list.
3381 { "cookie", "val1,val2",
3384 "cookie: val1,val2\n"
3387 "version: HTTP/1.1\n"
3391 for (size_t i
= 0; i
< ARRAYSIZE_UNSAFE(test_cases
); ++i
) {
3392 scoped_ptr
<spdy::SpdyFrame
> req(
3393 ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
3394 MockWrite writes
[] = { CreateMockWrite(*req
) };
3396 scoped_ptr
<spdy::SpdyFrame
> resp(
3397 ConstructSpdyGetSynReply(test_cases
[i
].extra_headers
,
3398 test_cases
[i
].num_headers
,
3400 scoped_ptr
<spdy::SpdyFrame
> body(ConstructSpdyBodyFrame(1, true));
3401 MockRead reads
[] = {
3402 CreateMockRead(*resp
),
3403 CreateMockRead(*body
),
3404 MockRead(ASYNC
, 0, 0) // EOF
3407 scoped_ptr
<DelayedSocketData
> data(
3408 new DelayedSocketData(1, reads
, arraysize(reads
),
3409 writes
, arraysize(writes
)));
3410 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
3411 BoundNetLog(), GetParam());
3412 helper
.RunToCompletion(data
.get());
3413 TransactionHelperResult out
= helper
.output();
3415 EXPECT_EQ(OK
, out
.rv
);
3416 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
3417 EXPECT_EQ("hello!", out
.response_data
);
3419 scoped_refptr
<HttpResponseHeaders
> headers
= out
.response_info
.headers
;
3420 EXPECT_TRUE(headers
.get() != NULL
);
3422 std::string name
, value
, lines
;
3423 while (headers
->EnumerateHeaderLines(&iter
, &name
, &value
)) {
3426 lines
.append(value
);
3429 EXPECT_EQ(std::string(test_cases
[i
].expected_headers
), lines
);
3433 // Verify that various SynReply headers parse vary fields correctly
3434 // through the HTTP layer, and the response matches the request.
3435 TEST_P(SpdyNetworkTransactionTest
, SynReplyHeadersVary
) {
3436 static const SpdyHeaderInfo syn_reply_info
= {
3437 spdy::SYN_REPLY
, // Syn Reply
3439 0, // Associated Stream ID
3440 net::ConvertRequestPriorityToSpdyPriority(LOWEST
),
3442 spdy::CONTROL_FLAG_NONE
, // Control Flags
3443 false, // Compressed
3444 spdy::INVALID
, // Status
3447 spdy::DATA_FLAG_NONE
// Data Flags
3449 // Modify the following data to change/add test cases:
3450 struct SynReplyTests
{
3451 const SpdyHeaderInfo
* syn_reply
;
3454 const char* extra_headers
[2][16];
3456 // Test the case of a multi-valued cookie. When the value is delimited
3457 // with NUL characters, it needs to be unfolded into multiple headers.
3462 { { "cookie", "val1,val2",
3467 "url", "/index.php",
3468 "version", "HTTP/1.1",
3472 }, { // Multiple vary fields.
3476 { { "friend", "barney",
3477 "enemy", "snaggletooth",
3483 "url", "/index.php",
3484 "version", "HTTP/1.1",
3488 }, { // Test a '*' vary field.
3492 { { "cookie", "val1,val2",
3497 "url", "/index.php",
3498 "version", "HTTP/1.1",
3502 }, { // Multiple comma-separated vary fields.
3506 { { "friend", "barney",
3507 "enemy", "snaggletooth",
3510 { "vary", "friend,enemy",
3512 "url", "/index.php",
3513 "version", "HTTP/1.1",
3520 for (size_t i
= 0; i
< ARRAYSIZE_UNSAFE(test_cases
); ++i
) {
3521 // Construct the request.
3522 scoped_ptr
<spdy::SpdyFrame
> frame_req(
3523 ConstructSpdyGet(test_cases
[i
].extra_headers
[0],
3524 test_cases
[i
].num_headers
[0],
3527 MockWrite writes
[] = {
3528 CreateMockWrite(*frame_req
),
3531 // Construct the reply.
3532 scoped_ptr
<spdy::SpdyFrame
> frame_reply(
3533 ConstructSpdyPacket(*test_cases
[i
].syn_reply
,
3534 test_cases
[i
].extra_headers
[1],
3535 test_cases
[i
].num_headers
[1],
3539 scoped_ptr
<spdy::SpdyFrame
> body(ConstructSpdyBodyFrame(1, true));
3540 MockRead reads
[] = {
3541 CreateMockRead(*frame_reply
),
3542 CreateMockRead(*body
),
3543 MockRead(ASYNC
, 0, 0) // EOF
3546 // Attach the headers to the request.
3547 int header_count
= test_cases
[i
].num_headers
[0];
3549 HttpRequestInfo request
= CreateGetRequest();
3550 for (int ct
= 0; ct
< header_count
; ct
++) {
3551 const char* header_key
= test_cases
[i
].extra_headers
[0][ct
* 2];
3552 const char* header_value
= test_cases
[i
].extra_headers
[0][ct
* 2 + 1];
3553 request
.extra_headers
.SetHeader(header_key
, header_value
);
3556 scoped_ptr
<DelayedSocketData
> data(
3557 new DelayedSocketData(1, reads
, arraysize(reads
),
3558 writes
, arraysize(writes
)));
3559 NormalSpdyTransactionHelper
helper(request
,
3560 BoundNetLog(), GetParam());
3561 helper
.RunToCompletion(data
.get());
3562 TransactionHelperResult out
= helper
.output();
3564 EXPECT_EQ(OK
, out
.rv
) << i
;
3565 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
) << i
;
3566 EXPECT_EQ("hello!", out
.response_data
) << i
;
3568 // Test the response information.
3569 EXPECT_TRUE(out
.response_info
.response_time
>
3570 out
.response_info
.request_time
) << i
;
3571 base::TimeDelta test_delay
= out
.response_info
.response_time
-
3572 out
.response_info
.request_time
;
3573 base::TimeDelta min_expected_delay
;
3574 min_expected_delay
.FromMilliseconds(10);
3575 EXPECT_GT(test_delay
.InMillisecondsF(),
3576 min_expected_delay
.InMillisecondsF()) << i
;
3577 EXPECT_EQ(out
.response_info
.vary_data
.is_valid(),
3578 test_cases
[i
].vary_matches
) << i
;
3580 // Check the headers.
3581 scoped_refptr
<HttpResponseHeaders
> headers
= out
.response_info
.headers
;
3582 ASSERT_TRUE(headers
.get() != NULL
) << i
;
3584 std::string name
, value
, lines
;
3585 while (headers
->EnumerateHeaderLines(&iter
, &name
, &value
)) {
3588 lines
.append(value
);
3592 // Construct the expected header reply string.
3593 char reply_buffer
[256] = "";
3594 ConstructSpdyReplyString(test_cases
[i
].extra_headers
[1],
3595 test_cases
[i
].num_headers
[1],
3599 EXPECT_EQ(std::string(reply_buffer
), lines
) << i
;
3603 // Verify that we don't crash on invalid SynReply responses.
3604 TEST_P(SpdyNetworkTransactionTest
, InvalidSynReply
) {
3605 const SpdyHeaderInfo kSynStartHeader
= {
3606 spdy::SYN_REPLY
, // Kind = SynReply
3608 0, // Associated stream ID
3609 net::ConvertRequestPriorityToSpdyPriority(LOWEST
),
3611 spdy::CONTROL_FLAG_NONE
, // Control Flags
3612 false, // Compressed
3613 spdy::INVALID
, // Status
3616 spdy::DATA_FLAG_NONE
// Data Flags
3619 struct InvalidSynReplyTests
{
3621 const char* headers
[10];
3623 // SYN_REPLY missing status header
3627 "url", "/index.php",
3628 "version", "HTTP/1.1",
3632 // SYN_REPLY missing version header
3635 "url", "/index.php",
3639 // SYN_REPLY with no headers
3643 for (size_t i
= 0; i
< ARRAYSIZE_UNSAFE(test_cases
); ++i
) {
3644 scoped_ptr
<spdy::SpdyFrame
> req(
3645 ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
3646 MockWrite writes
[] = {
3647 CreateMockWrite(*req
),
3650 scoped_ptr
<spdy::SpdyFrame
> resp(
3651 ConstructSpdyPacket(kSynStartHeader
,
3653 test_cases
[i
].headers
,
3654 test_cases
[i
].num_headers
));
3655 scoped_ptr
<spdy::SpdyFrame
> body(ConstructSpdyBodyFrame(1, true));
3656 MockRead reads
[] = {
3657 CreateMockRead(*resp
),
3658 CreateMockRead(*body
),
3659 MockRead(ASYNC
, 0, 0) // EOF
3662 scoped_ptr
<DelayedSocketData
> data(
3663 new DelayedSocketData(1, reads
, arraysize(reads
),
3664 writes
, arraysize(writes
)));
3665 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
3666 BoundNetLog(), GetParam());
3667 helper
.RunToCompletion(data
.get());
3668 TransactionHelperResult out
= helper
.output();
3669 EXPECT_EQ(ERR_INCOMPLETE_SPDY_HEADERS
, out
.rv
);
3673 // Verify that we don't crash on some corrupt frames.
3674 TEST_P(SpdyNetworkTransactionTest
, CorruptFrameSessionError
) {
3675 // This is the length field that's too short.
3676 scoped_ptr
<spdy::SpdyFrame
> syn_reply_wrong_length(
3677 ConstructSpdyGetSynReply(NULL
, 0, 1));
3678 syn_reply_wrong_length
->set_length(syn_reply_wrong_length
->length() - 4);
3680 struct SynReplyTests
{
3681 const spdy::SpdyFrame
* syn_reply
;
3683 { syn_reply_wrong_length
.get(), },
3686 for (size_t i
= 0; i
< ARRAYSIZE_UNSAFE(test_cases
); ++i
) {
3687 scoped_ptr
<spdy::SpdyFrame
> req(
3688 ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
3689 MockWrite writes
[] = {
3690 CreateMockWrite(*req
),
3691 MockWrite(ASYNC
, 0, 0) // EOF
3694 scoped_ptr
<spdy::SpdyFrame
> body(ConstructSpdyBodyFrame(1, true));
3695 MockRead reads
[] = {
3696 CreateMockRead(*test_cases
[i
].syn_reply
),
3697 CreateMockRead(*body
),
3698 MockRead(ASYNC
, 0, 0) // EOF
3701 scoped_ptr
<DelayedSocketData
> data(
3702 new DelayedSocketData(1, reads
, arraysize(reads
),
3703 writes
, arraysize(writes
)));
3704 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
3705 BoundNetLog(), GetParam());
3706 helper
.RunToCompletion(data
.get());
3707 TransactionHelperResult out
= helper
.output();
3708 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR
, out
.rv
);
3712 // Test that we shutdown correctly on write errors.
3713 TEST_P(SpdyNetworkTransactionTest
, WriteError
) {
3714 scoped_ptr
<spdy::SpdyFrame
> req(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
3715 MockWrite writes
[] = {
3716 // We'll write 10 bytes successfully
3717 MockWrite(ASYNC
, req
->data(), 10),
3718 // Followed by ERROR!
3719 MockWrite(ASYNC
, ERR_FAILED
),
3722 scoped_ptr
<DelayedSocketData
> data(
3723 new DelayedSocketData(2, NULL
, 0,
3724 writes
, arraysize(writes
)));
3725 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
3726 BoundNetLog(), GetParam());
3727 helper
.RunToCompletion(data
.get());
3728 TransactionHelperResult out
= helper
.output();
3729 EXPECT_EQ(ERR_FAILED
, out
.rv
);
3733 // Test that partial writes work.
3734 TEST_P(SpdyNetworkTransactionTest
, PartialWrite
) {
3735 // Chop the SYN_STREAM frame into 5 chunks.
3736 scoped_ptr
<spdy::SpdyFrame
> req(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
3737 const int kChunks
= 5;
3738 scoped_array
<MockWrite
> writes(ChopWriteFrame(*req
.get(), kChunks
));
3740 scoped_ptr
<spdy::SpdyFrame
> resp(ConstructSpdyGetSynReply(NULL
, 0, 1));
3741 scoped_ptr
<spdy::SpdyFrame
> body(ConstructSpdyBodyFrame(1, true));
3742 MockRead reads
[] = {
3743 CreateMockRead(*resp
),
3744 CreateMockRead(*body
),
3745 MockRead(ASYNC
, 0, 0) // EOF
3748 scoped_ptr
<DelayedSocketData
> data(
3749 new DelayedSocketData(kChunks
, reads
, arraysize(reads
),
3750 writes
.get(), kChunks
));
3751 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
3752 BoundNetLog(), GetParam());
3753 helper
.RunToCompletion(data
.get());
3754 TransactionHelperResult out
= helper
.output();
3755 EXPECT_EQ(OK
, out
.rv
);
3756 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
3757 EXPECT_EQ("hello!", out
.response_data
);
3760 // In this test, we enable compression, but get a uncompressed SynReply from
3761 // the server. Verify that teardown is all clean.
3762 TEST_P(SpdyNetworkTransactionTest
, DecompressFailureOnSynReply
) {
3763 // For this test, we turn on the normal compression.
3764 EnableCompression(true);
3766 scoped_ptr
<spdy::SpdyFrame
> compressed(
3767 ConstructSpdyGet(NULL
, 0, true, 1, LOWEST
));
3768 scoped_ptr
<spdy::SpdyFrame
> rst(
3769 ConstructSpdyRstStream(1, spdy::PROTOCOL_ERROR
));
3770 MockWrite writes
[] = {
3771 CreateMockWrite(*compressed
),
3774 scoped_ptr
<spdy::SpdyFrame
> resp(ConstructSpdyGetSynReply(NULL
, 0, 1));
3775 scoped_ptr
<spdy::SpdyFrame
> body(ConstructSpdyBodyFrame(1, true));
3776 MockRead reads
[] = {
3777 CreateMockRead(*resp
),
3780 scoped_ptr
<DelayedSocketData
> data(
3781 new DelayedSocketData(1, reads
, arraysize(reads
),
3782 writes
, arraysize(writes
)));
3783 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
3784 BoundNetLog(), GetParam());
3785 helper
.RunToCompletion(data
.get());
3786 TransactionHelperResult out
= helper
.output();
3787 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR
, out
.rv
);
3790 EnableCompression(false);
3793 // Test that the NetLog contains good data for a simple GET request.
3794 TEST_P(SpdyNetworkTransactionTest
, NetLog
) {
3795 static const char* const kExtraHeaders
[] = {
3796 "user-agent", "Chrome",
3798 scoped_ptr
<spdy::SpdyFrame
> req(ConstructSpdyGet(kExtraHeaders
, 1, false, 1,
3800 MockWrite writes
[] = { CreateMockWrite(*req
) };
3802 scoped_ptr
<spdy::SpdyFrame
> resp(ConstructSpdyGetSynReply(NULL
, 0, 1));
3803 scoped_ptr
<spdy::SpdyFrame
> body(ConstructSpdyBodyFrame(1, true));
3804 MockRead reads
[] = {
3805 CreateMockRead(*resp
),
3806 CreateMockRead(*body
),
3807 MockRead(ASYNC
, 0, 0) // EOF
3810 net::CapturingBoundNetLog
log(net::CapturingNetLog::kUnbounded
);
3812 scoped_ptr
<DelayedSocketData
> data(
3813 new DelayedSocketData(1, reads
, arraysize(reads
),
3814 writes
, arraysize(writes
)));
3815 NormalSpdyTransactionHelper
helper(CreateGetRequestWithUserAgent(),
3816 log
.bound(), GetParam());
3817 helper
.RunToCompletion(data
.get());
3818 TransactionHelperResult out
= helper
.output();
3819 EXPECT_EQ(OK
, out
.rv
);
3820 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
3821 EXPECT_EQ("hello!", out
.response_data
);
3823 // Check that the NetLog was filled reasonably.
3824 // This test is intentionally non-specific about the exact ordering of the
3825 // log; instead we just check to make sure that certain events exist, and that
3826 // they are in the right order.
3827 net::CapturingNetLog::EntryList entries
;
3828 log
.GetEntries(&entries
);
3830 EXPECT_LT(0u, entries
.size());
3832 pos
= net::ExpectLogContainsSomewhere(entries
, 0,
3833 net::NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST
,
3834 net::NetLog::PHASE_BEGIN
);
3835 pos
= net::ExpectLogContainsSomewhere(entries
, pos
+ 1,
3836 net::NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST
,
3837 net::NetLog::PHASE_END
);
3838 pos
= net::ExpectLogContainsSomewhere(entries
, pos
+ 1,
3839 net::NetLog::TYPE_HTTP_TRANSACTION_READ_HEADERS
,
3840 net::NetLog::PHASE_BEGIN
);
3841 pos
= net::ExpectLogContainsSomewhere(entries
, pos
+ 1,
3842 net::NetLog::TYPE_HTTP_TRANSACTION_READ_HEADERS
,
3843 net::NetLog::PHASE_END
);
3844 pos
= net::ExpectLogContainsSomewhere(entries
, pos
+ 1,
3845 net::NetLog::TYPE_HTTP_TRANSACTION_READ_BODY
,
3846 net::NetLog::PHASE_BEGIN
);
3847 pos
= net::ExpectLogContainsSomewhere(entries
, pos
+ 1,
3848 net::NetLog::TYPE_HTTP_TRANSACTION_READ_BODY
,
3849 net::NetLog::PHASE_END
);
3851 // Check that we logged all the headers correctly
3852 pos
= net::ExpectLogContainsSomewhere(
3854 net::NetLog::TYPE_SPDY_SESSION_SYN_STREAM
,
3855 net::NetLog::PHASE_NONE
);
3856 CapturingNetLog::Entry entry
= entries
[pos
];
3857 NetLogSpdySynParameter
* request_params
=
3858 static_cast<NetLogSpdySynParameter
*>(entry
.extra_parameters
.get());
3859 spdy::SpdyHeaderBlock
* headers
=
3860 request_params
->GetHeaders().get();
3862 spdy::SpdyHeaderBlock expected
;
3863 expected
["host"] = "www.google.com";
3864 expected
["url"] = "/";
3865 expected
["scheme"] = "http";
3866 expected
["version"] = "HTTP/1.1";
3867 expected
["method"] = "GET";
3868 expected
["user-agent"] = "Chrome";
3869 EXPECT_EQ(expected
.size(), headers
->size());
3870 spdy::SpdyHeaderBlock::const_iterator end
= expected
.end();
3871 for (spdy::SpdyHeaderBlock::const_iterator it
= expected
.begin();
3874 EXPECT_EQ(it
->second
, (*headers
)[it
->first
]);
3878 // Since we buffer the IO from the stream to the renderer, this test verifies
3879 // that when we read out the maximum amount of data (e.g. we received 50 bytes
3880 // on the network, but issued a Read for only 5 of those bytes) that the data
3881 // flow still works correctly.
3882 TEST_P(SpdyNetworkTransactionTest
, BufferFull
) {
3883 SpdySession::set_use_flow_control(SpdySession::kDisableFlowControl
);
3885 spdy::SpdyFramer framer
;
3887 scoped_ptr
<spdy::SpdyFrame
> req(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
3888 MockWrite writes
[] = { CreateMockWrite(*req
) };
3890 // 2 data frames in a single read.
3891 scoped_ptr
<spdy::SpdyFrame
> data_frame_1(
3892 framer
.CreateDataFrame(1, "goodby", 6, spdy::DATA_FLAG_NONE
));
3893 scoped_ptr
<spdy::SpdyFrame
> data_frame_2(
3894 framer
.CreateDataFrame(1, "e worl", 6, spdy::DATA_FLAG_NONE
));
3895 const spdy::SpdyFrame
* data_frames
[2] = {
3899 char combined_data_frames
[100];
3900 int combined_data_frames_len
=
3901 CombineFrames(data_frames
, arraysize(data_frames
),
3902 combined_data_frames
, arraysize(combined_data_frames
));
3903 scoped_ptr
<spdy::SpdyFrame
> last_frame(
3904 framer
.CreateDataFrame(1, "d", 1, spdy::DATA_FLAG_FIN
));
3906 scoped_ptr
<spdy::SpdyFrame
> resp(ConstructSpdyGetSynReply(NULL
, 0, 1));
3907 MockRead reads
[] = {
3908 CreateMockRead(*resp
),
3909 MockRead(ASYNC
, ERR_IO_PENDING
), // Force a pause
3910 MockRead(ASYNC
, combined_data_frames
, combined_data_frames_len
),
3911 MockRead(ASYNC
, ERR_IO_PENDING
), // Force a pause
3912 CreateMockRead(*last_frame
),
3913 MockRead(ASYNC
, 0, 0) // EOF
3916 scoped_ptr
<DelayedSocketData
> data(
3917 new DelayedSocketData(1, reads
, arraysize(reads
),
3918 writes
, arraysize(writes
)));
3921 TestCompletionCallback callback
;
3923 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
3924 BoundNetLog(), GetParam());
3925 helper
.RunPreTestSetup();
3926 helper
.AddData(data
.get());
3927 HttpNetworkTransaction
* trans
= helper
.trans();
3928 int rv
= trans
->Start(
3929 &CreateGetRequest(), callback
.callback(), BoundNetLog());
3930 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3932 TransactionHelperResult out
= helper
.output();
3933 out
.rv
= callback
.WaitForResult();
3934 EXPECT_EQ(out
.rv
, OK
);
3936 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3937 EXPECT_TRUE(response
->headers
!= NULL
);
3938 EXPECT_TRUE(response
->was_fetched_via_spdy
);
3939 out
.status_line
= response
->headers
->GetStatusLine();
3940 out
.response_info
= *response
; // Make a copy so we can verify.
3943 TestCompletionCallback read_callback
;
3945 std::string content
;
3947 // Read small chunks at a time.
3948 const int kSmallReadSize
= 3;
3949 scoped_refptr
<net::IOBuffer
> buf(new net::IOBuffer(kSmallReadSize
));
3950 rv
= trans
->Read(buf
, kSmallReadSize
, read_callback
.callback());
3951 if (rv
== net::ERR_IO_PENDING
) {
3952 data
->CompleteRead();
3953 rv
= read_callback
.WaitForResult();
3956 content
.append(buf
->data(), rv
);
3957 } else if (rv
< 0) {
3962 out
.response_data
.swap(content
);
3964 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
3965 // MockClientSocketFactory) are still alive.
3966 MessageLoop::current()->RunAllPending();
3968 // Verify that we consumed all test data.
3969 helper
.VerifyDataConsumed();
3971 EXPECT_EQ(OK
, out
.rv
);
3972 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
3973 EXPECT_EQ("goodbye world", out
.response_data
);
3975 SpdySession::set_use_flow_control(SpdySession::kFlowControlBasedOnNPN
);
3978 // Verify that basic buffering works; when multiple data frames arrive
3979 // at the same time, ensure that we don't notify a read completion for
3980 // each data frame individually.
3981 TEST_P(SpdyNetworkTransactionTest
, Buffering
) {
3982 SpdySession::set_use_flow_control(SpdySession::kDisableFlowControl
);
3984 spdy::SpdyFramer framer
;
3986 scoped_ptr
<spdy::SpdyFrame
> req(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
3987 MockWrite writes
[] = { CreateMockWrite(*req
) };
3989 // 4 data frames in a single read.
3990 scoped_ptr
<spdy::SpdyFrame
> data_frame(
3991 framer
.CreateDataFrame(1, "message", 7, spdy::DATA_FLAG_NONE
));
3992 scoped_ptr
<spdy::SpdyFrame
> data_frame_fin(
3993 framer
.CreateDataFrame(1, "message", 7, spdy::DATA_FLAG_FIN
));
3994 const spdy::SpdyFrame
* data_frames
[4] = {
3998 data_frame_fin
.get()
4000 char combined_data_frames
[100];
4001 int combined_data_frames_len
=
4002 CombineFrames(data_frames
, arraysize(data_frames
),
4003 combined_data_frames
, arraysize(combined_data_frames
));
4005 scoped_ptr
<spdy::SpdyFrame
> resp(ConstructSpdyGetSynReply(NULL
, 0, 1));
4006 MockRead reads
[] = {
4007 CreateMockRead(*resp
),
4008 MockRead(ASYNC
, ERR_IO_PENDING
), // Force a pause
4009 MockRead(ASYNC
, combined_data_frames
, combined_data_frames_len
),
4010 MockRead(ASYNC
, 0, 0) // EOF
4013 scoped_ptr
<DelayedSocketData
> data(
4014 new DelayedSocketData(1, reads
, arraysize(reads
),
4015 writes
, arraysize(writes
)));
4017 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
4018 BoundNetLog(), GetParam());
4019 helper
.RunPreTestSetup();
4020 helper
.AddData(data
.get());
4021 HttpNetworkTransaction
* trans
= helper
.trans();
4023 TestCompletionCallback callback
;
4024 int rv
= trans
->Start(
4025 &CreateGetRequest(), callback
.callback(), BoundNetLog());
4026 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4028 TransactionHelperResult out
= helper
.output();
4029 out
.rv
= callback
.WaitForResult();
4030 EXPECT_EQ(out
.rv
, OK
);
4032 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4033 EXPECT_TRUE(response
->headers
!= NULL
);
4034 EXPECT_TRUE(response
->was_fetched_via_spdy
);
4035 out
.status_line
= response
->headers
->GetStatusLine();
4036 out
.response_info
= *response
; // Make a copy so we can verify.
4039 TestCompletionCallback read_callback
;
4041 std::string content
;
4042 int reads_completed
= 0;
4044 // Read small chunks at a time.
4045 const int kSmallReadSize
= 14;
4046 scoped_refptr
<net::IOBuffer
> buf(new net::IOBuffer(kSmallReadSize
));
4047 rv
= trans
->Read(buf
, kSmallReadSize
, read_callback
.callback());
4048 if (rv
== net::ERR_IO_PENDING
) {
4049 data
->CompleteRead();
4050 rv
= read_callback
.WaitForResult();
4053 EXPECT_EQ(kSmallReadSize
, rv
);
4054 content
.append(buf
->data(), rv
);
4055 } else if (rv
< 0) {
4056 FAIL() << "Unexpected read error: " << rv
;
4061 EXPECT_EQ(3, reads_completed
); // Reads are: 14 bytes, 14 bytes, 0 bytes.
4063 out
.response_data
.swap(content
);
4065 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
4066 // MockClientSocketFactory) are still alive.
4067 MessageLoop::current()->RunAllPending();
4069 // Verify that we consumed all test data.
4070 helper
.VerifyDataConsumed();
4072 EXPECT_EQ(OK
, out
.rv
);
4073 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
4074 EXPECT_EQ("messagemessagemessagemessage", out
.response_data
);
4076 SpdySession::set_use_flow_control(SpdySession::kFlowControlBasedOnNPN
);
4079 // Verify the case where we buffer data but read it after it has been buffered.
4080 TEST_P(SpdyNetworkTransactionTest
, BufferedAll
) {
4081 spdy::SpdyFramer framer
;
4083 scoped_ptr
<spdy::SpdyFrame
> req(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
4084 MockWrite writes
[] = { CreateMockWrite(*req
) };
4086 // 5 data frames in a single read.
4087 scoped_ptr
<spdy::SpdyFrame
> syn_reply(
4088 ConstructSpdyGetSynReply(NULL
, 0, 1));
4089 syn_reply
->set_flags(spdy::CONTROL_FLAG_NONE
); // turn off FIN bit
4090 scoped_ptr
<spdy::SpdyFrame
> data_frame(
4091 framer
.CreateDataFrame(1, "message", 7, spdy::DATA_FLAG_NONE
));
4092 scoped_ptr
<spdy::SpdyFrame
> data_frame_fin(
4093 framer
.CreateDataFrame(1, "message", 7, spdy::DATA_FLAG_FIN
));
4094 const spdy::SpdyFrame
* frames
[5] = {
4099 data_frame_fin
.get()
4101 char combined_frames
[200];
4102 int combined_frames_len
=
4103 CombineFrames(frames
, arraysize(frames
),
4104 combined_frames
, arraysize(combined_frames
));
4106 MockRead reads
[] = {
4107 MockRead(ASYNC
, combined_frames
, combined_frames_len
),
4108 MockRead(ASYNC
, 0, 0) // EOF
4111 scoped_ptr
<DelayedSocketData
> data(
4112 new DelayedSocketData(1, reads
, arraysize(reads
),
4113 writes
, arraysize(writes
)));
4115 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
4116 BoundNetLog(), GetParam());
4117 helper
.RunPreTestSetup();
4118 helper
.AddData(data
.get());
4119 HttpNetworkTransaction
* trans
= helper
.trans();
4121 TestCompletionCallback callback
;
4122 int rv
= trans
->Start(
4123 &CreateGetRequest(), callback
.callback(), BoundNetLog());
4124 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4126 TransactionHelperResult out
= helper
.output();
4127 out
.rv
= callback
.WaitForResult();
4128 EXPECT_EQ(out
.rv
, OK
);
4130 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4131 EXPECT_TRUE(response
->headers
!= NULL
);
4132 EXPECT_TRUE(response
->was_fetched_via_spdy
);
4133 out
.status_line
= response
->headers
->GetStatusLine();
4134 out
.response_info
= *response
; // Make a copy so we can verify.
4137 TestCompletionCallback read_callback
;
4139 std::string content
;
4140 int reads_completed
= 0;
4142 // Read small chunks at a time.
4143 const int kSmallReadSize
= 14;
4144 scoped_refptr
<net::IOBuffer
> buf(new net::IOBuffer(kSmallReadSize
));
4145 rv
= trans
->Read(buf
, kSmallReadSize
, read_callback
.callback());
4147 EXPECT_EQ(kSmallReadSize
, rv
);
4148 content
.append(buf
->data(), rv
);
4149 } else if (rv
< 0) {
4150 FAIL() << "Unexpected read error: " << rv
;
4155 EXPECT_EQ(3, reads_completed
);
4157 out
.response_data
.swap(content
);
4159 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
4160 // MockClientSocketFactory) are still alive.
4161 MessageLoop::current()->RunAllPending();
4163 // Verify that we consumed all test data.
4164 helper
.VerifyDataConsumed();
4166 EXPECT_EQ(OK
, out
.rv
);
4167 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
4168 EXPECT_EQ("messagemessagemessagemessage", out
.response_data
);
4171 // Verify the case where we buffer data and close the connection.
4172 TEST_P(SpdyNetworkTransactionTest
, BufferedClosed
) {
4173 spdy::SpdyFramer framer
;
4175 scoped_ptr
<spdy::SpdyFrame
> req(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
4176 MockWrite writes
[] = { CreateMockWrite(*req
) };
4178 // All data frames in a single read.
4179 // NOTE: We don't FIN the stream.
4180 scoped_ptr
<spdy::SpdyFrame
> data_frame(
4181 framer
.CreateDataFrame(1, "message", 7, spdy::DATA_FLAG_NONE
));
4182 const spdy::SpdyFrame
* data_frames
[4] = {
4188 char combined_data_frames
[100];
4189 int combined_data_frames_len
=
4190 CombineFrames(data_frames
, arraysize(data_frames
),
4191 combined_data_frames
, arraysize(combined_data_frames
));
4192 scoped_ptr
<spdy::SpdyFrame
> resp(ConstructSpdyGetSynReply(NULL
, 0, 1));
4193 MockRead reads
[] = {
4194 CreateMockRead(*resp
),
4195 MockRead(ASYNC
, ERR_IO_PENDING
), // Force a wait
4196 MockRead(ASYNC
, combined_data_frames
, combined_data_frames_len
),
4197 MockRead(ASYNC
, 0, 0) // EOF
4200 scoped_ptr
<DelayedSocketData
> data(
4201 new DelayedSocketData(1, reads
, arraysize(reads
),
4202 writes
, arraysize(writes
)));
4204 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
4205 BoundNetLog(), GetParam());
4206 helper
.RunPreTestSetup();
4207 helper
.AddData(data
.get());
4208 HttpNetworkTransaction
* trans
= helper
.trans();
4210 TestCompletionCallback callback
;
4212 int rv
= trans
->Start(
4213 &CreateGetRequest(), callback
.callback(), BoundNetLog());
4214 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4216 TransactionHelperResult out
= helper
.output();
4217 out
.rv
= callback
.WaitForResult();
4218 EXPECT_EQ(out
.rv
, OK
);
4220 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4221 EXPECT_TRUE(response
->headers
!= NULL
);
4222 EXPECT_TRUE(response
->was_fetched_via_spdy
);
4223 out
.status_line
= response
->headers
->GetStatusLine();
4224 out
.response_info
= *response
; // Make a copy so we can verify.
4227 TestCompletionCallback read_callback
;
4229 std::string content
;
4230 int reads_completed
= 0;
4232 // Read small chunks at a time.
4233 const int kSmallReadSize
= 14;
4234 scoped_refptr
<net::IOBuffer
> buf(new net::IOBuffer(kSmallReadSize
));
4235 rv
= trans
->Read(buf
, kSmallReadSize
, read_callback
.callback());
4236 if (rv
== net::ERR_IO_PENDING
) {
4237 data
->CompleteRead();
4238 rv
= read_callback
.WaitForResult();
4241 content
.append(buf
->data(), rv
);
4242 } else if (rv
< 0) {
4243 // This test intentionally closes the connection, and will get an error.
4244 EXPECT_EQ(ERR_CONNECTION_CLOSED
, rv
);
4250 EXPECT_EQ(0, reads_completed
);
4252 out
.response_data
.swap(content
);
4254 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
4255 // MockClientSocketFactory) are still alive.
4256 MessageLoop::current()->RunAllPending();
4258 // Verify that we consumed all test data.
4259 helper
.VerifyDataConsumed();
4262 // Verify the case where we buffer data and cancel the transaction.
4263 TEST_P(SpdyNetworkTransactionTest
, BufferedCancelled
) {
4264 spdy::SpdyFramer framer
;
4266 scoped_ptr
<spdy::SpdyFrame
> req(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
4267 MockWrite writes
[] = { CreateMockWrite(*req
) };
4269 // NOTE: We don't FIN the stream.
4270 scoped_ptr
<spdy::SpdyFrame
> data_frame(
4271 framer
.CreateDataFrame(1, "message", 7, spdy::DATA_FLAG_NONE
));
4273 scoped_ptr
<spdy::SpdyFrame
> resp(ConstructSpdyGetSynReply(NULL
, 0, 1));
4274 MockRead reads
[] = {
4275 CreateMockRead(*resp
),
4276 MockRead(ASYNC
, ERR_IO_PENDING
), // Force a wait
4277 CreateMockRead(*data_frame
),
4278 MockRead(ASYNC
, 0, 0) // EOF
4281 scoped_ptr
<DelayedSocketData
> data(
4282 new DelayedSocketData(1, reads
, arraysize(reads
),
4283 writes
, arraysize(writes
)));
4285 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
4286 BoundNetLog(), GetParam());
4287 helper
.RunPreTestSetup();
4288 helper
.AddData(data
.get());
4289 HttpNetworkTransaction
* trans
= helper
.trans();
4290 TestCompletionCallback callback
;
4292 int rv
= trans
->Start(
4293 &CreateGetRequest(), callback
.callback(), BoundNetLog());
4294 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4296 TransactionHelperResult out
= helper
.output();
4297 out
.rv
= callback
.WaitForResult();
4298 EXPECT_EQ(out
.rv
, OK
);
4300 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4301 EXPECT_TRUE(response
->headers
!= NULL
);
4302 EXPECT_TRUE(response
->was_fetched_via_spdy
);
4303 out
.status_line
= response
->headers
->GetStatusLine();
4304 out
.response_info
= *response
; // Make a copy so we can verify.
4307 TestCompletionCallback read_callback
;
4310 const int kReadSize
= 256;
4311 scoped_refptr
<net::IOBuffer
> buf(new net::IOBuffer(kReadSize
));
4312 rv
= trans
->Read(buf
, kReadSize
, read_callback
.callback());
4313 if (rv
== net::ERR_IO_PENDING
) {
4314 // Complete the read now, which causes buffering to start.
4315 data
->CompleteRead();
4316 // Destroy the transaction, causing the stream to get cancelled
4317 // and orphaning the buffered IO task.
4318 helper
.ResetTrans();
4321 // We shouldn't get here in this test.
4322 FAIL() << "Unexpected read: " << rv
;
4325 // Flush the MessageLoop; this will cause the buffered IO task
4326 // to run for the final time.
4327 MessageLoop::current()->RunAllPending();
4329 // Verify that we consumed all test data.
4330 helper
.VerifyDataConsumed();
4333 // Test that if the server requests persistence of settings, that we save
4334 // the settings in the SpdySettingsStorage.
4335 TEST_P(SpdyNetworkTransactionTest
, SettingsSaved
) {
4336 static const SpdyHeaderInfo kSynReplyInfo
= {
4337 spdy::SYN_REPLY
, // Syn Reply
4339 0, // Associated Stream ID
4340 net::ConvertRequestPriorityToSpdyPriority(LOWEST
),
4342 spdy::CONTROL_FLAG_NONE
, // Control Flags
4343 false, // Compressed
4344 spdy::INVALID
, // Status
4347 spdy::DATA_FLAG_NONE
// Data Flags
4349 static const char* const kExtraHeaders
[] = {
4351 "version", "HTTP/1.1"
4354 BoundNetLog net_log
;
4355 NormalSpdyTransactionHelper
helper(CreateGetRequest(), net_log
, GetParam());
4356 helper
.RunPreTestSetup();
4358 // Verify that no settings exist initially.
4359 HostPortPair
host_port_pair("www.google.com", helper
.port());
4360 SpdySessionPool
* spdy_session_pool
= helper
.session()->spdy_session_pool();
4361 EXPECT_TRUE(spdy_session_pool
->http_server_properties()->GetSpdySettings(
4362 host_port_pair
).empty());
4364 // Construct the request.
4365 scoped_ptr
<spdy::SpdyFrame
> req(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
4366 MockWrite writes
[] = { CreateMockWrite(*req
) };
4368 // Construct the reply.
4369 scoped_ptr
<spdy::SpdyFrame
> reply(
4370 ConstructSpdyPacket(kSynReplyInfo
,
4372 arraysize(kExtraHeaders
) / 2,
4376 unsigned int kSampleId1
= 0x1;
4377 unsigned int kSampleValue1
= 0x0a0a0a0a;
4378 unsigned int kSampleId2
= 0x2;
4379 unsigned int kSampleValue2
= 0x0b0b0b0b;
4380 unsigned int kSampleId3
= 0xababab;
4381 unsigned int kSampleValue3
= 0x0c0c0c0c;
4382 scoped_ptr
<spdy::SpdyFrame
> settings_frame
;
4384 // Construct the SETTINGS frame.
4385 spdy::SpdySettings settings
;
4386 spdy::SettingsFlagsAndId
setting(0);
4387 // First add a persisted setting
4388 setting
.set_flags(spdy::SETTINGS_FLAG_PLEASE_PERSIST
);
4389 setting
.set_id(kSampleId1
);
4390 settings
.push_back(std::make_pair(setting
, kSampleValue1
));
4391 // Next add a non-persisted setting
4392 setting
.set_flags(0);
4393 setting
.set_id(kSampleId2
);
4394 settings
.push_back(std::make_pair(setting
, kSampleValue2
));
4395 // Next add another persisted setting
4396 setting
.set_flags(spdy::SETTINGS_FLAG_PLEASE_PERSIST
);
4397 setting
.set_id(kSampleId3
);
4398 settings
.push_back(std::make_pair(setting
, kSampleValue3
));
4399 settings_frame
.reset(ConstructSpdySettings(settings
));
4402 scoped_ptr
<spdy::SpdyFrame
> body(ConstructSpdyBodyFrame(1, true));
4403 MockRead reads
[] = {
4404 CreateMockRead(*reply
),
4405 CreateMockRead(*body
),
4406 CreateMockRead(*settings_frame
),
4407 MockRead(ASYNC
, 0, 0) // EOF
4410 scoped_ptr
<DelayedSocketData
> data(
4411 new DelayedSocketData(1, reads
, arraysize(reads
),
4412 writes
, arraysize(writes
)));
4413 helper
.AddData(data
.get());
4414 helper
.RunDefaultTest();
4415 helper
.VerifyDataConsumed();
4416 TransactionHelperResult out
= helper
.output();
4417 EXPECT_EQ(OK
, out
.rv
);
4418 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
4419 EXPECT_EQ("hello!", out
.response_data
);
4422 // Verify we had two persisted settings.
4423 spdy::SpdySettings saved_settings
=
4424 spdy_session_pool
->http_server_properties()->GetSpdySettings(
4426 ASSERT_EQ(2u, saved_settings
.size());
4428 // Verify the first persisted setting.
4429 spdy::SpdySetting setting
= saved_settings
.front();
4430 saved_settings
.pop_front();
4431 EXPECT_EQ(spdy::SETTINGS_FLAG_PERSISTED
, setting
.first
.flags());
4432 EXPECT_EQ(kSampleId1
, setting
.first
.id());
4433 EXPECT_EQ(kSampleValue1
, setting
.second
);
4435 // Verify the second persisted setting.
4436 setting
= saved_settings
.front();
4437 saved_settings
.pop_front();
4438 EXPECT_EQ(spdy::SETTINGS_FLAG_PERSISTED
, setting
.first
.flags());
4439 EXPECT_EQ(kSampleId3
, setting
.first
.id());
4440 EXPECT_EQ(kSampleValue3
, setting
.second
);
4444 // Test that when there are settings saved that they are sent back to the
4445 // server upon session establishment.
4446 TEST_P(SpdyNetworkTransactionTest
, SettingsPlayback
) {
4447 static const SpdyHeaderInfo kSynReplyInfo
= {
4448 spdy::SYN_REPLY
, // Syn Reply
4450 0, // Associated Stream ID
4451 net::ConvertRequestPriorityToSpdyPriority(LOWEST
),
4453 spdy::CONTROL_FLAG_NONE
, // Control Flags
4454 false, // Compressed
4455 spdy::INVALID
, // Status
4458 spdy::DATA_FLAG_NONE
// Data Flags
4460 static const char* kExtraHeaders
[] = {
4462 "version", "HTTP/1.1"
4465 BoundNetLog net_log
;
4466 NormalSpdyTransactionHelper
helper(CreateGetRequest(), net_log
, GetParam());
4467 helper
.RunPreTestSetup();
4469 // Verify that no settings exist initially.
4470 HostPortPair
host_port_pair("www.google.com", helper
.port());
4471 SpdySessionPool
* spdy_session_pool
= helper
.session()->spdy_session_pool();
4472 EXPECT_TRUE(spdy_session_pool
->http_server_properties()->GetSpdySettings(
4473 host_port_pair
).empty());
4475 unsigned int kSampleId1
= 0x1;
4476 unsigned int kSampleValue1
= 0x0a0a0a0a;
4477 unsigned int kSampleId2
= 0xababab;
4478 unsigned int kSampleValue2
= 0x0c0c0c0c;
4479 // Manually insert settings into the SpdySettingsStorage here.
4481 spdy::SpdySettings settings
;
4482 spdy::SettingsFlagsAndId
setting(0);
4483 // First add a persisted setting
4484 setting
.set_flags(spdy::SETTINGS_FLAG_PLEASE_PERSIST
);
4485 setting
.set_id(kSampleId1
);
4486 settings
.push_back(std::make_pair(setting
, kSampleValue1
));
4487 // Next add another persisted setting
4488 setting
.set_flags(spdy::SETTINGS_FLAG_PLEASE_PERSIST
);
4489 setting
.set_id(kSampleId2
);
4490 settings
.push_back(std::make_pair(setting
, kSampleValue2
));
4492 spdy_session_pool
->http_server_properties()->SetSpdySettings(
4493 host_port_pair
, settings
);
4496 EXPECT_EQ(2u, spdy_session_pool
->http_server_properties()->GetSpdySettings(
4497 host_port_pair
).size());
4499 // Construct the SETTINGS frame.
4500 const spdy::SpdySettings
& settings
=
4501 spdy_session_pool
->http_server_properties()->GetSpdySettings(
4503 scoped_ptr
<spdy::SpdyFrame
> settings_frame(ConstructSpdySettings(settings
));
4505 // Construct the request.
4506 scoped_ptr
<spdy::SpdyFrame
> req(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
4508 MockWrite writes
[] = {
4509 CreateMockWrite(*settings_frame
),
4510 CreateMockWrite(*req
),
4513 // Construct the reply.
4514 scoped_ptr
<spdy::SpdyFrame
> reply(
4515 ConstructSpdyPacket(kSynReplyInfo
,
4517 arraysize(kExtraHeaders
) / 2,
4521 scoped_ptr
<spdy::SpdyFrame
> body(ConstructSpdyBodyFrame(1, true));
4522 MockRead reads
[] = {
4523 CreateMockRead(*reply
),
4524 CreateMockRead(*body
),
4525 MockRead(ASYNC
, 0, 0) // EOF
4528 scoped_ptr
<DelayedSocketData
> data(
4529 new DelayedSocketData(2, reads
, arraysize(reads
),
4530 writes
, arraysize(writes
)));
4531 helper
.AddData(data
.get());
4532 helper
.RunDefaultTest();
4533 helper
.VerifyDataConsumed();
4534 TransactionHelperResult out
= helper
.output();
4535 EXPECT_EQ(OK
, out
.rv
);
4536 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
4537 EXPECT_EQ("hello!", out
.response_data
);
4540 // Verify we had two persisted settings.
4541 spdy::SpdySettings saved_settings
=
4542 spdy_session_pool
->http_server_properties()->GetSpdySettings(
4544 ASSERT_EQ(2u, saved_settings
.size());
4546 // Verify the first persisted setting.
4547 spdy::SpdySetting setting
= saved_settings
.front();
4548 saved_settings
.pop_front();
4549 EXPECT_EQ(spdy::SETTINGS_FLAG_PERSISTED
, setting
.first
.flags());
4550 EXPECT_EQ(kSampleId1
, setting
.first
.id());
4551 EXPECT_EQ(kSampleValue1
, setting
.second
);
4553 // Verify the second persisted setting.
4554 setting
= saved_settings
.front();
4555 saved_settings
.pop_front();
4556 EXPECT_EQ(spdy::SETTINGS_FLAG_PERSISTED
, setting
.first
.flags());
4557 EXPECT_EQ(kSampleId2
, setting
.first
.id());
4558 EXPECT_EQ(kSampleValue2
, setting
.second
);
4562 TEST_P(SpdyNetworkTransactionTest
, GoAwayWithActiveStream
) {
4563 scoped_ptr
<spdy::SpdyFrame
> req(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
4564 MockWrite writes
[] = { CreateMockWrite(*req
) };
4566 scoped_ptr
<spdy::SpdyFrame
> go_away(ConstructSpdyGoAway());
4567 MockRead reads
[] = {
4568 CreateMockRead(*go_away
),
4569 MockRead(ASYNC
, 0, 0), // EOF
4572 scoped_ptr
<DelayedSocketData
> data(
4573 new DelayedSocketData(1, reads
, arraysize(reads
),
4574 writes
, arraysize(writes
)));
4575 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
4576 BoundNetLog(), GetParam());
4577 helper
.AddData(data
.get());
4578 helper
.RunToCompletion(data
.get());
4579 TransactionHelperResult out
= helper
.output();
4580 EXPECT_EQ(ERR_ABORTED
, out
.rv
);
4583 TEST_P(SpdyNetworkTransactionTest
, CloseWithActiveStream
) {
4584 scoped_ptr
<spdy::SpdyFrame
> req(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
4585 MockWrite writes
[] = { CreateMockWrite(*req
) };
4587 scoped_ptr
<spdy::SpdyFrame
> resp(ConstructSpdyGetSynReply(NULL
, 0, 1));
4588 MockRead reads
[] = {
4589 CreateMockRead(*resp
),
4590 MockRead(SYNCHRONOUS
, 0, 0) // EOF
4593 scoped_ptr
<DelayedSocketData
> data(
4594 new DelayedSocketData(1, reads
, arraysize(reads
),
4595 writes
, arraysize(writes
)));
4597 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
4599 helper
.RunPreTestSetup();
4600 helper
.AddData(data
.get());
4601 HttpNetworkTransaction
* trans
= helper
.trans();
4603 TestCompletionCallback callback
;
4604 TransactionHelperResult out
;
4605 out
.rv
= trans
->Start(&CreateGetRequest(), callback
.callback(), log
);
4607 EXPECT_EQ(out
.rv
, ERR_IO_PENDING
);
4608 out
.rv
= callback
.WaitForResult();
4609 EXPECT_EQ(out
.rv
, OK
);
4611 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4612 EXPECT_TRUE(response
->headers
!= NULL
);
4613 EXPECT_TRUE(response
->was_fetched_via_spdy
);
4614 out
.rv
= ReadTransaction(trans
, &out
.response_data
);
4615 EXPECT_EQ(ERR_CONNECTION_CLOSED
, out
.rv
);
4617 // Verify that we consumed all test data.
4618 helper
.VerifyDataConsumed();
4621 // Test to make sure we can correctly connect through a proxy.
4622 TEST_P(SpdyNetworkTransactionTest
, ProxyConnect
) {
4623 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
4624 BoundNetLog(), GetParam());
4625 helper
.session_deps().reset(new SpdySessionDependencies(
4626 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70")));
4627 helper
.SetSession(make_scoped_refptr(
4628 SpdySessionDependencies::SpdyCreateSession(helper
.session_deps().get())));
4629 helper
.RunPreTestSetup();
4630 HttpNetworkTransaction
* trans
= helper
.trans();
4632 const char kConnect443
[] = {"CONNECT www.google.com:443 HTTP/1.1\r\n"
4633 "Host: www.google.com\r\n"
4634 "Proxy-Connection: keep-alive\r\n\r\n"};
4635 const char kConnect80
[] = {"CONNECT www.google.com:80 HTTP/1.1\r\n"
4636 "Host: www.google.com\r\n"
4637 "Proxy-Connection: keep-alive\r\n\r\n"};
4638 const char kHTTP200
[] = {"HTTP/1.1 200 OK\r\n\r\n"};
4639 scoped_ptr
<spdy::SpdyFrame
> req(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
4640 scoped_ptr
<spdy::SpdyFrame
> resp(ConstructSpdyGetSynReply(NULL
, 0, 1));
4641 scoped_ptr
<spdy::SpdyFrame
> body(ConstructSpdyBodyFrame(1, true));
4643 MockWrite writes_SPDYNPN
[] = {
4644 MockWrite(SYNCHRONOUS
, kConnect443
, arraysize(kConnect443
) - 1, 0),
4645 CreateMockWrite(*req
, 2),
4647 MockRead reads_SPDYNPN
[] = {
4648 MockRead(SYNCHRONOUS
, kHTTP200
, arraysize(kHTTP200
) - 1, 1),
4649 CreateMockRead(*resp
, 3),
4650 CreateMockRead(*body
.get(), 4),
4651 MockRead(ASYNC
, 0, 0, 5),
4654 MockWrite writes_SPDYSSL
[] = {
4655 MockWrite(SYNCHRONOUS
, kConnect80
, arraysize(kConnect80
) - 1, 0),
4656 CreateMockWrite(*req
, 2),
4658 MockRead reads_SPDYSSL
[] = {
4659 MockRead(SYNCHRONOUS
, kHTTP200
, arraysize(kHTTP200
) - 1, 1),
4660 CreateMockRead(*resp
, 3),
4661 CreateMockRead(*body
.get(), 4),
4662 MockRead(ASYNC
, 0, 0, 5),
4665 MockWrite writes_SPDYNOSSL
[] = {
4666 CreateMockWrite(*req
, 0),
4669 MockRead reads_SPDYNOSSL
[] = {
4670 CreateMockRead(*resp
, 1),
4671 CreateMockRead(*body
.get(), 2),
4672 MockRead(ASYNC
, 0, 0, 3),
4675 scoped_ptr
<OrderedSocketData
> data
;
4676 switch(GetParam()) {
4678 data
.reset(new OrderedSocketData(reads_SPDYNOSSL
,
4679 arraysize(reads_SPDYNOSSL
),
4681 arraysize(writes_SPDYNOSSL
)));
4684 data
.reset(new OrderedSocketData(reads_SPDYSSL
,
4685 arraysize(reads_SPDYSSL
),
4687 arraysize(writes_SPDYSSL
)));
4690 data
.reset(new OrderedSocketData(reads_SPDYNPN
,
4691 arraysize(reads_SPDYNPN
),
4693 arraysize(writes_SPDYNPN
)));
4699 helper
.AddData(data
.get());
4700 TestCompletionCallback callback
;
4702 int rv
= trans
->Start(
4703 &CreateGetRequest(), callback
.callback(), BoundNetLog());
4704 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4706 rv
= callback
.WaitForResult();
4709 // Verify the SYN_REPLY.
4710 HttpResponseInfo response
= *trans
->GetResponseInfo();
4711 EXPECT_TRUE(response
.headers
!= NULL
);
4712 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
4714 std::string response_data
;
4715 ASSERT_EQ(OK
, ReadTransaction(trans
, &response_data
));
4716 EXPECT_EQ("hello!", response_data
);
4717 helper
.VerifyDataConsumed();
4720 // Test to make sure we can correctly connect through a proxy to www.google.com,
4721 // if there already exists a direct spdy connection to www.google.com. See
4722 // http://crbug.com/49874
4723 TEST_P(SpdyNetworkTransactionTest
, DirectConnectProxyReconnect
) {
4724 // When setting up the first transaction, we store the SpdySessionPool so that
4725 // we can use the same pool in the second transaction.
4726 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
4727 BoundNetLog(), GetParam());
4729 // Use a proxy service which returns a proxy fallback list from DIRECT to
4730 // myproxy:70. For this test there will be no fallback, so it is equivalent
4731 // to simply DIRECT. The reason for appending the second proxy is to verify
4732 // that the session pool key used does is just "DIRECT".
4733 helper
.session_deps().reset(new SpdySessionDependencies(
4734 ProxyService::CreateFixedFromPacResult("DIRECT; PROXY myproxy:70")));
4735 helper
.SetSession(make_scoped_refptr(
4736 SpdySessionDependencies::SpdyCreateSession(helper
.session_deps().get())));
4738 SpdySessionPool
* spdy_session_pool
= helper
.session()->spdy_session_pool();
4739 helper
.RunPreTestSetup();
4741 // Construct and send a simple GET request.
4742 scoped_ptr
<spdy::SpdyFrame
> req(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
4743 MockWrite writes
[] = {
4744 CreateMockWrite(*req
, 1),
4747 scoped_ptr
<spdy::SpdyFrame
> resp(ConstructSpdyGetSynReply(NULL
, 0, 1));
4748 scoped_ptr
<spdy::SpdyFrame
> body(ConstructSpdyBodyFrame(1, true));
4749 MockRead reads
[] = {
4750 CreateMockRead(*resp
, 2),
4751 CreateMockRead(*body
, 3),
4752 MockRead(ASYNC
, ERR_IO_PENDING
, 4), // Force a pause
4753 MockRead(ASYNC
, 0, 5) // EOF
4755 scoped_ptr
<OrderedSocketData
> data(
4756 new OrderedSocketData(reads
, arraysize(reads
),
4757 writes
, arraysize(writes
)));
4758 helper
.AddData(data
.get());
4759 HttpNetworkTransaction
* trans
= helper
.trans();
4761 TestCompletionCallback callback
;
4762 TransactionHelperResult out
;
4763 out
.rv
= trans
->Start(
4764 &CreateGetRequest(), callback
.callback(), BoundNetLog());
4766 EXPECT_EQ(out
.rv
, ERR_IO_PENDING
);
4767 out
.rv
= callback
.WaitForResult();
4768 EXPECT_EQ(out
.rv
, OK
);
4770 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4771 EXPECT_TRUE(response
->headers
!= NULL
);
4772 EXPECT_TRUE(response
->was_fetched_via_spdy
);
4773 out
.rv
= ReadTransaction(trans
, &out
.response_data
);
4774 EXPECT_EQ(OK
, out
.rv
);
4775 out
.status_line
= response
->headers
->GetStatusLine();
4776 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
4777 EXPECT_EQ("hello!", out
.response_data
);
4779 // Check that the SpdySession is still in the SpdySessionPool.
4780 HostPortPair
host_port_pair("www.google.com", helper
.port());
4781 HostPortProxyPair
session_pool_key_direct(
4782 host_port_pair
, ProxyServer::Direct());
4783 EXPECT_TRUE(spdy_session_pool
->HasSession(session_pool_key_direct
));
4784 HostPortProxyPair
session_pool_key_proxy(
4786 ProxyServer::FromURI("www.foo.com", ProxyServer::SCHEME_HTTP
));
4787 EXPECT_FALSE(spdy_session_pool
->HasSession(session_pool_key_proxy
));
4789 // Set up data for the proxy connection.
4790 const char kConnect443
[] = {"CONNECT www.google.com:443 HTTP/1.1\r\n"
4791 "Host: www.google.com\r\n"
4792 "Proxy-Connection: keep-alive\r\n\r\n"};
4793 const char kConnect80
[] = {"CONNECT www.google.com:80 HTTP/1.1\r\n"
4794 "Host: www.google.com\r\n"
4795 "Proxy-Connection: keep-alive\r\n\r\n"};
4796 const char kHTTP200
[] = {"HTTP/1.1 200 OK\r\n\r\n"};
4797 scoped_ptr
<spdy::SpdyFrame
> req2(ConstructSpdyGet(
4798 "http://www.google.com/foo.dat", false, 1, LOWEST
));
4799 scoped_ptr
<spdy::SpdyFrame
> resp2(ConstructSpdyGetSynReply(NULL
, 0, 1));
4800 scoped_ptr
<spdy::SpdyFrame
> body2(ConstructSpdyBodyFrame(1, true));
4802 MockWrite writes_SPDYNPN
[] = {
4803 MockWrite(SYNCHRONOUS
, kConnect443
, arraysize(kConnect443
) - 1, 0),
4804 CreateMockWrite(*req2
, 2),
4806 MockRead reads_SPDYNPN
[] = {
4807 MockRead(SYNCHRONOUS
, kHTTP200
, arraysize(kHTTP200
) - 1, 1),
4808 CreateMockRead(*resp2
, 3),
4809 CreateMockRead(*body2
, 4),
4810 MockRead(ASYNC
, 0, 5) // EOF
4813 MockWrite writes_SPDYNOSSL
[] = {
4814 CreateMockWrite(*req2
, 0),
4816 MockRead reads_SPDYNOSSL
[] = {
4817 CreateMockRead(*resp2
, 1),
4818 CreateMockRead(*body2
, 2),
4819 MockRead(ASYNC
, 0, 3) // EOF
4822 MockWrite writes_SPDYSSL
[] = {
4823 MockWrite(SYNCHRONOUS
, kConnect80
, arraysize(kConnect80
) - 1, 0),
4824 CreateMockWrite(*req2
, 2),
4826 MockRead reads_SPDYSSL
[] = {
4827 MockRead(SYNCHRONOUS
, kHTTP200
, arraysize(kHTTP200
) - 1, 1),
4828 CreateMockRead(*resp2
, 3),
4829 CreateMockRead(*body2
, 4),
4830 MockRead(ASYNC
, 0, 0, 5),
4833 scoped_ptr
<OrderedSocketData
> data_proxy
;
4834 switch(GetParam()) {
4836 data_proxy
.reset(new OrderedSocketData(reads_SPDYNPN
,
4837 arraysize(reads_SPDYNPN
),
4839 arraysize(writes_SPDYNPN
)));
4842 data_proxy
.reset(new OrderedSocketData(reads_SPDYNOSSL
,
4843 arraysize(reads_SPDYNOSSL
),
4845 arraysize(writes_SPDYNOSSL
)));
4848 data_proxy
.reset(new OrderedSocketData(reads_SPDYSSL
,
4849 arraysize(reads_SPDYSSL
),
4851 arraysize(writes_SPDYSSL
)));
4857 // Create another request to www.google.com, but this time through a proxy.
4858 HttpRequestInfo request_proxy
;
4859 request_proxy
.method
= "GET";
4860 request_proxy
.url
= GURL("http://www.google.com/foo.dat");
4861 request_proxy
.load_flags
= 0;
4862 scoped_ptr
<SpdySessionDependencies
> ssd_proxy(new SpdySessionDependencies());
4863 // Ensure that this transaction uses the same SpdySessionPool.
4864 scoped_refptr
<HttpNetworkSession
> session_proxy(
4865 SpdySessionDependencies::SpdyCreateSession(ssd_proxy
.get()));
4866 NormalSpdyTransactionHelper
helper_proxy(request_proxy
,
4867 BoundNetLog(), GetParam());
4868 HttpNetworkSessionPeer
session_peer(session_proxy
);
4869 scoped_ptr
<net::ProxyService
> proxy_service(
4870 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
4871 session_peer
.SetProxyService(proxy_service
.get());
4872 helper_proxy
.session_deps().swap(ssd_proxy
);
4873 helper_proxy
.SetSession(session_proxy
);
4874 helper_proxy
.RunPreTestSetup();
4875 helper_proxy
.AddData(data_proxy
.get());
4877 HttpNetworkTransaction
* trans_proxy
= helper_proxy
.trans();
4878 TestCompletionCallback callback_proxy
;
4879 int rv
= trans_proxy
->Start(
4880 &request_proxy
, callback_proxy
.callback(), BoundNetLog());
4881 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4882 rv
= callback_proxy
.WaitForResult();
4885 HttpResponseInfo response_proxy
= *trans_proxy
->GetResponseInfo();
4886 EXPECT_TRUE(response_proxy
.headers
!= NULL
);
4887 EXPECT_EQ("HTTP/1.1 200 OK", response_proxy
.headers
->GetStatusLine());
4889 std::string response_data
;
4890 ASSERT_EQ(OK
, ReadTransaction(trans_proxy
, &response_data
));
4891 EXPECT_EQ("hello!", response_data
);
4893 data
->CompleteRead();
4894 helper_proxy
.VerifyDataConsumed();
4897 // When we get a TCP-level RST, we need to retry a HttpNetworkTransaction
4898 // on a new connection, if the connection was previously known to be good.
4899 // This can happen when a server reboots without saying goodbye, or when
4900 // we're behind a NAT that masked the RST.
4901 TEST_P(SpdyNetworkTransactionTest
, VerifyRetryOnConnectionReset
) {
4902 scoped_ptr
<spdy::SpdyFrame
> resp(ConstructSpdyGetSynReply(NULL
, 0, 1));
4903 scoped_ptr
<spdy::SpdyFrame
> body(ConstructSpdyBodyFrame(1, true));
4904 MockRead reads
[] = {
4905 CreateMockRead(*resp
),
4906 CreateMockRead(*body
),
4907 MockRead(ASYNC
, ERR_IO_PENDING
),
4908 MockRead(ASYNC
, ERR_CONNECTION_RESET
),
4911 MockRead reads2
[] = {
4912 CreateMockRead(*resp
),
4913 CreateMockRead(*body
),
4914 MockRead(ASYNC
, 0, 0) // EOF
4917 // This test has a couple of variants.
4919 // Induce the RST while waiting for our transaction to send.
4920 VARIANT_RST_DURING_SEND_COMPLETION
,
4921 // Induce the RST while waiting for our transaction to read.
4922 // In this case, the send completed - everything copied into the SNDBUF.
4923 VARIANT_RST_DURING_READ_COMPLETION
4926 for (int variant
= VARIANT_RST_DURING_SEND_COMPLETION
;
4927 variant
<= VARIANT_RST_DURING_READ_COMPLETION
;
4929 scoped_ptr
<DelayedSocketData
> data1(
4930 new DelayedSocketData(1, reads
, arraysize(reads
),
4933 scoped_ptr
<DelayedSocketData
> data2(
4934 new DelayedSocketData(1, reads2
, arraysize(reads2
),
4937 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
4938 BoundNetLog(), GetParam());
4939 helper
.AddData(data1
.get());
4940 helper
.AddData(data2
.get());
4941 helper
.RunPreTestSetup();
4943 for (int i
= 0; i
< 2; ++i
) {
4944 scoped_ptr
<HttpNetworkTransaction
> trans(
4945 new HttpNetworkTransaction(helper
.session()));
4947 TestCompletionCallback callback
;
4948 int rv
= trans
->Start(
4949 &helper
.request(), callback
.callback(), BoundNetLog());
4950 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4951 // On the second transaction, we trigger the RST.
4953 if (variant
== VARIANT_RST_DURING_READ_COMPLETION
) {
4954 // Writes to the socket complete asynchronously on SPDY by running
4955 // through the message loop. Complete the write here.
4956 MessageLoop::current()->RunAllPending();
4959 // Now schedule the ERR_CONNECTION_RESET.
4960 EXPECT_EQ(3u, data1
->read_index());
4961 data1
->CompleteRead();
4962 EXPECT_EQ(4u, data1
->read_index());
4964 rv
= callback
.WaitForResult();
4967 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4968 ASSERT_TRUE(response
!= NULL
);
4969 EXPECT_TRUE(response
->headers
!= NULL
);
4970 EXPECT_TRUE(response
->was_fetched_via_spdy
);
4971 std::string response_data
;
4972 rv
= ReadTransaction(trans
.get(), &response_data
);
4974 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
4975 EXPECT_EQ("hello!", response_data
);
4978 helper
.VerifyDataConsumed();
4982 // Test that turning SPDY on and off works properly.
4983 TEST_P(SpdyNetworkTransactionTest
, SpdyOnOffToggle
) {
4984 net::HttpStreamFactory::set_spdy_enabled(true);
4985 scoped_ptr
<spdy::SpdyFrame
> req(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
4986 MockWrite spdy_writes
[] = { CreateMockWrite(*req
) };
4988 scoped_ptr
<spdy::SpdyFrame
> resp(ConstructSpdyGetSynReply(NULL
, 0, 1));
4989 scoped_ptr
<spdy::SpdyFrame
> body(ConstructSpdyBodyFrame(1, true));
4990 MockRead spdy_reads
[] = {
4991 CreateMockRead(*resp
),
4992 CreateMockRead(*body
),
4993 MockRead(ASYNC
, 0, 0) // EOF
4996 scoped_ptr
<DelayedSocketData
> data(
4997 new DelayedSocketData(1,
4998 spdy_reads
, arraysize(spdy_reads
),
4999 spdy_writes
, arraysize(spdy_writes
)));
5000 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
5001 BoundNetLog(), GetParam());
5002 helper
.RunToCompletion(data
.get());
5003 TransactionHelperResult out
= helper
.output();
5004 EXPECT_EQ(OK
, out
.rv
);
5005 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
5006 EXPECT_EQ("hello!", out
.response_data
);
5008 net::HttpStreamFactory::set_spdy_enabled(false);
5009 MockRead http_reads
[] = {
5010 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
5011 MockRead("hello from http"),
5012 MockRead(SYNCHRONOUS
, OK
),
5014 scoped_ptr
<DelayedSocketData
> data2(
5015 new DelayedSocketData(1, http_reads
, arraysize(http_reads
),
5017 NormalSpdyTransactionHelper
helper2(CreateGetRequest(),
5018 BoundNetLog(), GetParam());
5019 helper2
.SetSpdyDisabled();
5020 helper2
.RunToCompletion(data2
.get());
5021 TransactionHelperResult out2
= helper2
.output();
5022 EXPECT_EQ(OK
, out2
.rv
);
5023 EXPECT_EQ("HTTP/1.1 200 OK", out2
.status_line
);
5024 EXPECT_EQ("hello from http", out2
.response_data
);
5026 net::HttpStreamFactory::set_spdy_enabled(true);
5029 // Tests that Basic authentication works over SPDY
5030 TEST_P(SpdyNetworkTransactionTest
, SpdyBasicAuth
) {
5031 net::HttpStreamFactory::set_spdy_enabled(true);
5033 // The first request will be a bare GET, the second request will be a
5034 // GET with an Authorization header.
5035 scoped_ptr
<spdy::SpdyFrame
> req_get(
5036 ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
5037 const char* const kExtraAuthorizationHeaders
[] = {
5039 "Basic Zm9vOmJhcg==",
5041 scoped_ptr
<spdy::SpdyFrame
> req_get_authorization(
5043 kExtraAuthorizationHeaders
,
5044 arraysize(kExtraAuthorizationHeaders
) / 2,
5046 MockWrite spdy_writes
[] = {
5047 CreateMockWrite(*req_get
, 1),
5048 CreateMockWrite(*req_get_authorization
, 4),
5051 // The first response is a 401 authentication challenge, and the second
5052 // response will be a 200 response since the second request includes a valid
5053 // Authorization header.
5054 const char* const kExtraAuthenticationHeaders
[] = {
5056 "Basic realm=\"MyRealm\""
5058 scoped_ptr
<spdy::SpdyFrame
> resp_authentication(
5059 ConstructSpdySynReplyError(
5060 "401 Authentication Required",
5061 kExtraAuthenticationHeaders
,
5062 arraysize(kExtraAuthenticationHeaders
) / 2,
5064 scoped_ptr
<spdy::SpdyFrame
> body_authentication(
5065 ConstructSpdyBodyFrame(1, true));
5066 scoped_ptr
<spdy::SpdyFrame
> resp_data(ConstructSpdyGetSynReply(NULL
, 0, 3));
5067 scoped_ptr
<spdy::SpdyFrame
> body_data(ConstructSpdyBodyFrame(3, true));
5068 MockRead spdy_reads
[] = {
5069 CreateMockRead(*resp_authentication
, 2),
5070 CreateMockRead(*body_authentication
, 3),
5071 CreateMockRead(*resp_data
, 5),
5072 CreateMockRead(*body_data
, 6),
5073 MockRead(ASYNC
, 0, 7),
5076 scoped_ptr
<OrderedSocketData
> data(
5077 new OrderedSocketData(spdy_reads
, arraysize(spdy_reads
),
5078 spdy_writes
, arraysize(spdy_writes
)));
5079 HttpRequestInfo
request(CreateGetRequest());
5080 BoundNetLog net_log
;
5081 NormalSpdyTransactionHelper
helper(request
, net_log
, GetParam());
5083 helper
.RunPreTestSetup();
5084 helper
.AddData(data
.get());
5085 HttpNetworkTransaction
* trans
= helper
.trans();
5086 TestCompletionCallback callback
;
5087 const int rv_start
= trans
->Start(&request
, callback
.callback(), net_log
);
5088 EXPECT_EQ(ERR_IO_PENDING
, rv_start
);
5089 const int rv_start_complete
= callback
.WaitForResult();
5090 EXPECT_EQ(OK
, rv_start_complete
);
5092 // Make sure the response has an auth challenge.
5093 const HttpResponseInfo
* const response_start
= trans
->GetResponseInfo();
5094 ASSERT_TRUE(response_start
!= NULL
);
5095 ASSERT_TRUE(response_start
->headers
!= NULL
);
5096 EXPECT_EQ(401, response_start
->headers
->response_code());
5097 EXPECT_TRUE(response_start
->was_fetched_via_spdy
);
5098 AuthChallengeInfo
* auth_challenge
= response_start
->auth_challenge
.get();
5099 ASSERT_TRUE(auth_challenge
!= NULL
);
5100 EXPECT_FALSE(auth_challenge
->is_proxy
);
5101 EXPECT_EQ("basic", auth_challenge
->scheme
);
5102 EXPECT_EQ("MyRealm", auth_challenge
->realm
);
5104 // Restart with a username/password.
5105 AuthCredentials
credentials(ASCIIToUTF16("foo"), ASCIIToUTF16("bar"));
5106 TestCompletionCallback callback_restart
;
5107 const int rv_restart
= trans
->RestartWithAuth(
5108 credentials
, callback_restart
.callback());
5109 EXPECT_EQ(ERR_IO_PENDING
, rv_restart
);
5110 const int rv_restart_complete
= callback_restart
.WaitForResult();
5111 EXPECT_EQ(OK
, rv_restart_complete
);
5112 // TODO(cbentzel): This is actually the same response object as before, but
5113 // data has changed.
5114 const HttpResponseInfo
* const response_restart
= trans
->GetResponseInfo();
5115 ASSERT_TRUE(response_restart
!= NULL
);
5116 ASSERT_TRUE(response_restart
->headers
!= NULL
);
5117 EXPECT_EQ(200, response_restart
->headers
->response_code());
5118 EXPECT_TRUE(response_restart
->auth_challenge
.get() == NULL
);
5121 TEST_P(SpdyNetworkTransactionTest
, ServerPushWithHeaders
) {
5122 static const unsigned char kPushBodyFrame
[] = {
5123 0x00, 0x00, 0x00, 0x02, // header, ID
5124 0x01, 0x00, 0x00, 0x06, // FIN, length
5125 'p', 'u', 's', 'h', 'e', 'd' // "pushed"
5127 scoped_ptr
<spdy::SpdyFrame
>
5128 stream1_syn(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
5129 scoped_ptr
<spdy::SpdyFrame
>
5130 stream1_body(ConstructSpdyBodyFrame(1, true));
5131 MockWrite writes
[] = {
5132 CreateMockWrite(*stream1_syn
, 1),
5135 static const char* const kInitialHeaders
[] = {
5137 "http://www.google.com/foo.dat",
5139 static const char* const kLateHeaders
[] = {
5147 scoped_ptr
<spdy::SpdyFrame
>
5148 stream2_syn(ConstructSpdyControlFrame(kInitialHeaders
,
5149 arraysize(kInitialHeaders
) / 2,
5154 spdy::CONTROL_FLAG_NONE
,
5158 scoped_ptr
<spdy::SpdyFrame
>
5159 stream2_headers(ConstructSpdyControlFrame(kLateHeaders
,
5160 arraysize(kLateHeaders
) / 2,
5165 spdy::CONTROL_FLAG_NONE
,
5170 scoped_ptr
<spdy::SpdyFrame
>
5171 stream1_reply(ConstructSpdyGetSynReply(NULL
, 0, 1));
5172 MockRead reads
[] = {
5173 CreateMockRead(*stream1_reply
, 2),
5174 CreateMockRead(*stream2_syn
, 3),
5175 CreateMockRead(*stream2_headers
, 4),
5176 CreateMockRead(*stream1_body
, 5, SYNCHRONOUS
),
5177 MockRead(ASYNC
, reinterpret_cast<const char*>(kPushBodyFrame
),
5178 arraysize(kPushBodyFrame
), 6),
5179 MockRead(ASYNC
, ERR_IO_PENDING
, 7), // Force a pause
5182 HttpResponseInfo response
;
5183 HttpResponseInfo response2
;
5184 std::string
expected_push_result("pushed");
5185 scoped_ptr
<OrderedSocketData
> data(new OrderedSocketData(
5189 arraysize(writes
)));
5190 RunServerPushTest(data
.get(),
5193 expected_push_result
);
5195 // Verify the SYN_REPLY.
5196 EXPECT_TRUE(response
.headers
!= NULL
);
5197 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
5199 // Verify the pushed stream.
5200 EXPECT_TRUE(response2
.headers
!= NULL
);
5201 EXPECT_EQ("HTTP/1.1 200 OK", response2
.headers
->GetStatusLine());
5204 TEST_P(SpdyNetworkTransactionTest
, ServerPushClaimBeforeHeaders
) {
5205 // We push a stream and attempt to claim it before the headers come down.
5206 static const unsigned char kPushBodyFrame
[] = {
5207 0x00, 0x00, 0x00, 0x02, // header, ID
5208 0x01, 0x00, 0x00, 0x06, // FIN, length
5209 'p', 'u', 's', 'h', 'e', 'd' // "pushed"
5211 scoped_ptr
<spdy::SpdyFrame
>
5212 stream1_syn(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
5213 scoped_ptr
<spdy::SpdyFrame
>
5214 stream1_body(ConstructSpdyBodyFrame(1, true));
5215 MockWrite writes
[] = {
5216 CreateMockWrite(*stream1_syn
, 0, SYNCHRONOUS
),
5219 static const char* const kInitialHeaders
[] = {
5221 "http://www.google.com/foo.dat",
5223 static const char* const kLateHeaders
[] = {
5231 scoped_ptr
<spdy::SpdyFrame
>
5232 stream2_syn(ConstructSpdyControlFrame(kInitialHeaders
,
5233 arraysize(kInitialHeaders
) / 2,
5238 spdy::CONTROL_FLAG_NONE
,
5242 scoped_ptr
<spdy::SpdyFrame
>
5243 stream2_headers(ConstructSpdyControlFrame(kLateHeaders
,
5244 arraysize(kLateHeaders
) / 2,
5249 spdy::CONTROL_FLAG_NONE
,
5254 scoped_ptr
<spdy::SpdyFrame
>
5255 stream1_reply(ConstructSpdyGetSynReply(NULL
, 0, 1));
5256 MockRead reads
[] = {
5257 CreateMockRead(*stream1_reply
, 1),
5258 CreateMockRead(*stream2_syn
, 2),
5259 CreateMockRead(*stream1_body
, 3),
5260 CreateMockRead(*stream2_headers
, 4),
5261 MockRead(ASYNC
, reinterpret_cast<const char*>(kPushBodyFrame
),
5262 arraysize(kPushBodyFrame
), 5),
5263 MockRead(ASYNC
, 0, 5), // EOF
5266 HttpResponseInfo response
;
5267 HttpResponseInfo response2
;
5268 std::string
expected_push_result("pushed");
5269 scoped_refptr
<DeterministicSocketData
> data(new DeterministicSocketData(
5273 arraysize(writes
)));
5275 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
5276 BoundNetLog(), GetParam());
5277 helper
.SetDeterministic();
5278 helper
.AddDeterministicData(static_cast<DeterministicSocketData
*>(data
));
5279 helper
.RunPreTestSetup();
5281 HttpNetworkTransaction
* trans
= helper
.trans();
5283 // Run until we've received the primary SYN_STREAM, the pushed SYN_STREAM,
5284 // and the body of the primary stream, but before we've received the HEADERS
5285 // for the pushed stream.
5288 // Start the transaction.
5289 TestCompletionCallback callback
;
5290 int rv
= trans
->Start(
5291 &CreateGetRequest(), callback
.callback(), BoundNetLog());
5292 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5294 rv
= callback
.WaitForResult();
5297 // Request the pushed path. At this point, we've received the push, but the
5298 // headers are not yet complete.
5299 scoped_ptr
<HttpNetworkTransaction
> trans2(
5300 new HttpNetworkTransaction(helper
.session()));
5302 &CreateGetPushRequest(), callback
.callback(), BoundNetLog());
5303 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5305 MessageLoop::current()->RunAllPending();
5307 // Read the server push body.
5308 std::string result2
;
5309 ReadResult(trans2
.get(), data
.get(), &result2
);
5310 // Read the response body.
5312 ReadResult(trans
, data
, &result
);
5314 // Verify that we consumed all test data.
5315 EXPECT_TRUE(data
->at_read_eof());
5316 EXPECT_TRUE(data
->at_write_eof());
5318 // Verify that the received push data is same as the expected push data.
5319 EXPECT_EQ(result2
.compare(expected_push_result
), 0)
5320 << "Received data: "
5322 << "||||| Expected data: "
5323 << expected_push_result
;
5325 // Verify the SYN_REPLY.
5326 // Copy the response info, because trans goes away.
5327 response
= *trans
->GetResponseInfo();
5328 response2
= *trans2
->GetResponseInfo();
5330 VerifyStreamsClosed(helper
);
5332 // Verify the SYN_REPLY.
5333 EXPECT_TRUE(response
.headers
!= NULL
);
5334 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
5336 // Verify the pushed stream.
5337 EXPECT_TRUE(response2
.headers
!= NULL
);
5338 EXPECT_EQ("HTTP/1.1 200 OK", response2
.headers
->GetStatusLine());
5341 TEST_P(SpdyNetworkTransactionTest
, ServerPushWithTwoHeaderFrames
) {
5342 // We push a stream and attempt to claim it before the headers come down.
5343 static const unsigned char kPushBodyFrame
[] = {
5344 0x00, 0x00, 0x00, 0x02, // header, ID
5345 0x01, 0x00, 0x00, 0x06, // FIN, length
5346 'p', 'u', 's', 'h', 'e', 'd' // "pushed"
5348 scoped_ptr
<spdy::SpdyFrame
>
5349 stream1_syn(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
5350 scoped_ptr
<spdy::SpdyFrame
>
5351 stream1_body(ConstructSpdyBodyFrame(1, true));
5352 MockWrite writes
[] = {
5353 CreateMockWrite(*stream1_syn
, 0, SYNCHRONOUS
),
5356 static const char* const kInitialHeaders
[] = {
5358 "http://www.google.com/foo.dat",
5360 static const char* const kMiddleHeaders
[] = {
5364 static const char* const kLateHeaders
[] = {
5370 scoped_ptr
<spdy::SpdyFrame
>
5371 stream2_syn(ConstructSpdyControlFrame(kInitialHeaders
,
5372 arraysize(kInitialHeaders
) / 2,
5377 spdy::CONTROL_FLAG_NONE
,
5381 scoped_ptr
<spdy::SpdyFrame
>
5382 stream2_headers1(ConstructSpdyControlFrame(kMiddleHeaders
,
5383 arraysize(kMiddleHeaders
) / 2,
5388 spdy::CONTROL_FLAG_NONE
,
5392 scoped_ptr
<spdy::SpdyFrame
>
5393 stream2_headers2(ConstructSpdyControlFrame(kLateHeaders
,
5394 arraysize(kLateHeaders
) / 2,
5399 spdy::CONTROL_FLAG_NONE
,
5404 scoped_ptr
<spdy::SpdyFrame
>
5405 stream1_reply(ConstructSpdyGetSynReply(NULL
, 0, 1));
5406 MockRead reads
[] = {
5407 CreateMockRead(*stream1_reply
, 1),
5408 CreateMockRead(*stream2_syn
, 2),
5409 CreateMockRead(*stream1_body
, 3),
5410 CreateMockRead(*stream2_headers1
, 4),
5411 CreateMockRead(*stream2_headers2
, 5),
5412 MockRead(ASYNC
, reinterpret_cast<const char*>(kPushBodyFrame
),
5413 arraysize(kPushBodyFrame
), 6),
5414 MockRead(ASYNC
, 0, 6), // EOF
5417 HttpResponseInfo response
;
5418 HttpResponseInfo response2
;
5419 std::string
expected_push_result("pushed");
5420 scoped_refptr
<DeterministicSocketData
> data(new DeterministicSocketData(
5424 arraysize(writes
)));
5426 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
5427 BoundNetLog(), GetParam());
5428 helper
.SetDeterministic();
5429 helper
.AddDeterministicData(static_cast<DeterministicSocketData
*>(data
));
5430 helper
.RunPreTestSetup();
5432 HttpNetworkTransaction
* trans
= helper
.trans();
5434 // Run until we've received the primary SYN_STREAM, the pushed SYN_STREAM,
5435 // the first HEADERS frame, and the body of the primary stream, but before
5436 // we've received the final HEADERS for the pushed stream.
5439 // Start the transaction.
5440 TestCompletionCallback callback
;
5441 int rv
= trans
->Start(
5442 &CreateGetRequest(), callback
.callback(), BoundNetLog());
5443 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5445 rv
= callback
.WaitForResult();
5448 // Request the pushed path. At this point, we've received the push, but the
5449 // headers are not yet complete.
5450 scoped_ptr
<HttpNetworkTransaction
> trans2(
5451 new HttpNetworkTransaction(helper
.session()));
5453 &CreateGetPushRequest(), callback
.callback(), BoundNetLog());
5454 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5456 MessageLoop::current()->RunAllPending();
5458 // Read the server push body.
5459 std::string result2
;
5460 ReadResult(trans2
.get(), data
, &result2
);
5461 // Read the response body.
5463 ReadResult(trans
, data
, &result
);
5465 // Verify that we consumed all test data.
5466 EXPECT_TRUE(data
->at_read_eof());
5467 EXPECT_TRUE(data
->at_write_eof());
5469 // Verify that the received push data is same as the expected push data.
5470 EXPECT_EQ(result2
.compare(expected_push_result
), 0)
5471 << "Received data: "
5473 << "||||| Expected data: "
5474 << expected_push_result
;
5476 // Verify the SYN_REPLY.
5477 // Copy the response info, because trans goes away.
5478 response
= *trans
->GetResponseInfo();
5479 response2
= *trans2
->GetResponseInfo();
5481 VerifyStreamsClosed(helper
);
5483 // Verify the SYN_REPLY.
5484 EXPECT_TRUE(response
.headers
!= NULL
);
5485 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
5487 // Verify the pushed stream.
5488 EXPECT_TRUE(response2
.headers
!= NULL
);
5489 EXPECT_EQ("HTTP/1.1 200 OK", response2
.headers
->GetStatusLine());
5491 // Verify we got all the headers
5492 EXPECT_TRUE(response2
.headers
->HasHeaderValue(
5494 "http://www.google.com/foo.dat"));
5495 EXPECT_TRUE(response2
.headers
->HasHeaderValue("hello", "bye"));
5496 EXPECT_TRUE(response2
.headers
->HasHeaderValue("status", "200"));
5497 EXPECT_TRUE(response2
.headers
->HasHeaderValue("version", "HTTP/1.1"));
5500 TEST_P(SpdyNetworkTransactionTest
, SynReplyWithHeaders
) {
5501 scoped_ptr
<spdy::SpdyFrame
> req(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
5502 MockWrite writes
[] = { CreateMockWrite(*req
) };
5504 static const char* const kInitialHeaders
[] = {
5510 static const char* const kLateHeaders
[] = {
5514 scoped_ptr
<spdy::SpdyFrame
>
5515 stream1_reply(ConstructSpdyControlFrame(kInitialHeaders
,
5516 arraysize(kInitialHeaders
) / 2,
5521 spdy::CONTROL_FLAG_NONE
,
5525 scoped_ptr
<spdy::SpdyFrame
>
5526 stream1_headers(ConstructSpdyControlFrame(kLateHeaders
,
5527 arraysize(kLateHeaders
) / 2,
5532 spdy::CONTROL_FLAG_NONE
,
5536 scoped_ptr
<spdy::SpdyFrame
> stream1_body(ConstructSpdyBodyFrame(1, true));
5537 MockRead reads
[] = {
5538 CreateMockRead(*stream1_reply
),
5539 CreateMockRead(*stream1_headers
),
5540 CreateMockRead(*stream1_body
),
5541 MockRead(ASYNC
, 0, 0) // EOF
5544 scoped_ptr
<DelayedSocketData
> data(
5545 new DelayedSocketData(1, reads
, arraysize(reads
),
5546 writes
, arraysize(writes
)));
5547 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
5548 BoundNetLog(), GetParam());
5549 helper
.RunToCompletion(data
.get());
5550 TransactionHelperResult out
= helper
.output();
5551 EXPECT_EQ(OK
, out
.rv
);
5552 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
5553 EXPECT_EQ("hello!", out
.response_data
);
5556 TEST_P(SpdyNetworkTransactionTest
, SynReplyWithLateHeaders
) {
5557 scoped_ptr
<spdy::SpdyFrame
> req(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
5558 MockWrite writes
[] = { CreateMockWrite(*req
) };
5560 static const char* const kInitialHeaders
[] = {
5566 static const char* const kLateHeaders
[] = {
5570 scoped_ptr
<spdy::SpdyFrame
>
5571 stream1_reply(ConstructSpdyControlFrame(kInitialHeaders
,
5572 arraysize(kInitialHeaders
) / 2,
5577 spdy::CONTROL_FLAG_NONE
,
5581 scoped_ptr
<spdy::SpdyFrame
>
5582 stream1_headers(ConstructSpdyControlFrame(kLateHeaders
,
5583 arraysize(kLateHeaders
) / 2,
5588 spdy::CONTROL_FLAG_NONE
,
5592 scoped_ptr
<spdy::SpdyFrame
> stream1_body(ConstructSpdyBodyFrame(1, false));
5593 scoped_ptr
<spdy::SpdyFrame
> stream1_body2(ConstructSpdyBodyFrame(1, true));
5594 MockRead reads
[] = {
5595 CreateMockRead(*stream1_reply
),
5596 CreateMockRead(*stream1_body
),
5597 CreateMockRead(*stream1_headers
),
5598 CreateMockRead(*stream1_body2
),
5599 MockRead(ASYNC
, 0, 0) // EOF
5602 scoped_ptr
<DelayedSocketData
> data(
5603 new DelayedSocketData(1, reads
, arraysize(reads
),
5604 writes
, arraysize(writes
)));
5605 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
5606 BoundNetLog(), GetParam());
5607 helper
.RunToCompletion(data
.get());
5608 TransactionHelperResult out
= helper
.output();
5609 EXPECT_EQ(OK
, out
.rv
);
5610 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
5611 EXPECT_EQ("hello!hello!", out
.response_data
);
5614 TEST_P(SpdyNetworkTransactionTest
, SynReplyWithDuplicateLateHeaders
) {
5615 scoped_ptr
<spdy::SpdyFrame
> req(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
5616 MockWrite writes
[] = { CreateMockWrite(*req
) };
5618 static const char* const kInitialHeaders
[] = {
5624 static const char* const kLateHeaders
[] = {
5628 scoped_ptr
<spdy::SpdyFrame
>
5629 stream1_reply(ConstructSpdyControlFrame(kInitialHeaders
,
5630 arraysize(kInitialHeaders
) / 2,
5635 spdy::CONTROL_FLAG_NONE
,
5639 scoped_ptr
<spdy::SpdyFrame
>
5640 stream1_headers(ConstructSpdyControlFrame(kLateHeaders
,
5641 arraysize(kLateHeaders
) / 2,
5646 spdy::CONTROL_FLAG_NONE
,
5650 scoped_ptr
<spdy::SpdyFrame
> stream1_body(ConstructSpdyBodyFrame(1, false));
5651 scoped_ptr
<spdy::SpdyFrame
> stream1_body2(ConstructSpdyBodyFrame(1, true));
5652 MockRead reads
[] = {
5653 CreateMockRead(*stream1_reply
),
5654 CreateMockRead(*stream1_body
),
5655 CreateMockRead(*stream1_headers
),
5656 CreateMockRead(*stream1_body2
),
5657 MockRead(ASYNC
, 0, 0) // EOF
5660 scoped_ptr
<DelayedSocketData
> data(
5661 new DelayedSocketData(1, reads
, arraysize(reads
),
5662 writes
, arraysize(writes
)));
5663 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
5664 BoundNetLog(), GetParam());
5665 helper
.RunToCompletion(data
.get());
5666 TransactionHelperResult out
= helper
.output();
5667 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR
, out
.rv
);
5670 TEST_P(SpdyNetworkTransactionTest
, ServerPushCrossOriginCorrectness
) {
5671 // In this test we want to verify that we can't accidentally push content
5672 // which can't be pushed by this content server.
5673 // This test assumes that:
5674 // - if we're requesting http://www.foo.com/barbaz
5675 // - the browser has made a connection to "www.foo.com".
5677 // A list of the URL to fetch, followed by the URL being pushed.
5678 static const char* const kTestCases
[] = {
5679 "http://www.google.com/foo.html",
5680 "http://www.google.com:81/foo.js", // Bad port
5682 "http://www.google.com/foo.html",
5683 "https://www.google.com/foo.js", // Bad protocol
5685 "http://www.google.com/foo.html",
5686 "ftp://www.google.com/foo.js", // Invalid Protocol
5688 "http://www.google.com/foo.html",
5689 "http://blat.www.google.com/foo.js", // Cross subdomain
5691 "http://www.google.com/foo.html",
5692 "http://www.foo.com/foo.js", // Cross domain
5696 static const unsigned char kPushBodyFrame
[] = {
5697 0x00, 0x00, 0x00, 0x02, // header, ID
5698 0x01, 0x00, 0x00, 0x06, // FIN, length
5699 'p', 'u', 's', 'h', 'e', 'd' // "pushed"
5702 for (size_t index
= 0; index
< arraysize(kTestCases
); index
+= 2) {
5703 const char* url_to_fetch
= kTestCases
[index
];
5704 const char* url_to_push
= kTestCases
[index
+ 1];
5706 scoped_ptr
<spdy::SpdyFrame
>
5707 stream1_syn(ConstructSpdyGet(url_to_fetch
, false, 1, LOWEST
));
5708 scoped_ptr
<spdy::SpdyFrame
>
5709 stream1_body(ConstructSpdyBodyFrame(1, true));
5710 scoped_ptr
<spdy::SpdyFrame
> push_rst(
5711 ConstructSpdyRstStream(2, spdy::REFUSED_STREAM
));
5712 MockWrite writes
[] = {
5713 CreateMockWrite(*stream1_syn
, 1),
5714 CreateMockWrite(*push_rst
, 4),
5717 scoped_ptr
<spdy::SpdyFrame
>
5718 stream1_reply(ConstructSpdyGetSynReply(NULL
, 0, 1));
5719 scoped_ptr
<spdy::SpdyFrame
>
5720 stream2_syn(ConstructSpdyPush(NULL
,
5725 scoped_ptr
<spdy::SpdyFrame
> rst(
5726 ConstructSpdyRstStream(2, spdy::CANCEL
));
5728 MockRead reads
[] = {
5729 CreateMockRead(*stream1_reply
, 2),
5730 CreateMockRead(*stream2_syn
, 3),
5731 CreateMockRead(*stream1_body
, 5, SYNCHRONOUS
),
5732 MockRead(ASYNC
, reinterpret_cast<const char*>(kPushBodyFrame
),
5733 arraysize(kPushBodyFrame
), 6),
5734 MockRead(ASYNC
, ERR_IO_PENDING
, 7), // Force a pause
5737 HttpResponseInfo response
;
5738 scoped_ptr
<OrderedSocketData
> data(new OrderedSocketData(
5742 arraysize(writes
)));
5744 HttpRequestInfo request
;
5745 request
.method
= "GET";
5746 request
.url
= GURL(url_to_fetch
);
5747 request
.load_flags
= 0;
5748 NormalSpdyTransactionHelper
helper(request
,
5749 BoundNetLog(), GetParam());
5750 helper
.RunPreTestSetup();
5751 helper
.AddData(data
.get());
5753 HttpNetworkTransaction
* trans
= helper
.trans();
5755 // Start the transaction with basic parameters.
5756 TestCompletionCallback callback
;
5758 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
5759 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5760 rv
= callback
.WaitForResult();
5762 // Read the response body.
5764 ReadResult(trans
, data
.get(), &result
);
5766 // Verify that we consumed all test data.
5767 EXPECT_TRUE(data
->at_read_eof());
5768 EXPECT_TRUE(data
->at_write_eof());
5770 // Verify the SYN_REPLY.
5771 // Copy the response info, because trans goes away.
5772 response
= *trans
->GetResponseInfo();
5774 VerifyStreamsClosed(helper
);
5776 // Verify the SYN_REPLY.
5777 EXPECT_TRUE(response
.headers
!= NULL
);
5778 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
5782 TEST_P(SpdyNetworkTransactionTest
, RetryAfterRefused
) {
5783 // Construct the request.
5784 scoped_ptr
<spdy::SpdyFrame
> req(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
5785 scoped_ptr
<spdy::SpdyFrame
> req2(ConstructSpdyGet(NULL
, 0, false, 3, LOWEST
));
5786 MockWrite writes
[] = {
5787 CreateMockWrite(*req
, 1),
5788 CreateMockWrite(*req2
, 3),
5791 scoped_ptr
<spdy::SpdyFrame
> refused(
5792 ConstructSpdyRstStream(1, spdy::REFUSED_STREAM
));
5793 scoped_ptr
<spdy::SpdyFrame
> resp(ConstructSpdyGetSynReply(NULL
, 0, 3));
5794 scoped_ptr
<spdy::SpdyFrame
> body(ConstructSpdyBodyFrame(3, true));
5795 MockRead reads
[] = {
5796 CreateMockRead(*refused
, 2),
5797 CreateMockRead(*resp
, 4),
5798 CreateMockRead(*body
, 5),
5799 MockRead(ASYNC
, 0, 6) // EOF
5802 scoped_ptr
<OrderedSocketData
> data(
5803 new OrderedSocketData(reads
, arraysize(reads
),
5804 writes
, arraysize(writes
)));
5805 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
5806 BoundNetLog(), GetParam());
5808 helper
.RunPreTestSetup();
5809 helper
.AddData(data
.get());
5811 HttpNetworkTransaction
* trans
= helper
.trans();
5813 // Start the transaction with basic parameters.
5814 TestCompletionCallback callback
;
5815 int rv
= trans
->Start(
5816 &CreateGetRequest(), callback
.callback(), BoundNetLog());
5817 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5818 rv
= callback
.WaitForResult();
5821 // Verify that we consumed all test data.
5822 EXPECT_TRUE(data
->at_read_eof()) << "Read count: "
5823 << data
->read_count()
5825 << data
->read_index();
5826 EXPECT_TRUE(data
->at_write_eof()) << "Write count: "
5827 << data
->write_count()
5829 << data
->write_index();
5831 // Verify the SYN_REPLY.
5832 HttpResponseInfo response
= *trans
->GetResponseInfo();
5833 EXPECT_TRUE(response
.headers
!= NULL
);
5834 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());