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