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. 4 5 #include "net/http/http_network_transaction.h" 6 7 #include <string> 8 #include <vector> 9 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" 22 23 //----------------------------------------------------------------------------- 24 25 namespace net { 26 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"; 30 31 enum SpdyNetworkTransactionTestTypes { 32 SPDYNPN, 33 SPDYNOSSL, 34 SPDYSSL, 35 }; 36 class SpdyNetworkTransactionTest 37 : public ::testing::TestWithParam<SpdyNetworkTransactionTestTypes> { 38 protected: 39 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; 46 } 47 48 virtual void TearDown() { 49 // Empty the current queue. 50 MessageLoop::current()->RunAllPending(); 51 } 52 53 struct TransactionHelperResult { 54 int rv; 55 std::string status_line; 56 std::string response_data; 57 HttpResponseInfo response_info; 58 }; 59 60 void EnableCompression(bool enabled) { 61 spdy::SpdyFramer::set_enable_compression_default(enabled); 62 } 63 64 class StartTransactionCallback; 65 class DeleteSessionCallback; 66 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(); 91 } 92 } 93 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. 101 102 // Forcefully close existing sessions here. 103 session()->spdy_session_pool()->CloseAllSessions(); 104 } 105 106 void SetDeterministic() { 107 session_ = SpdySessionDependencies::SpdyCreateSessionDeterministic( 108 session_deps_.get()); 109 deterministic_ = true; 110 } 111 112 void SetSpdyDisabled() { 113 spdy_enabled_ = false; 114 } 115 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(); 143 } 144 145 // We're now ready to use SSL-npn SPDY. 146 trans_.reset(new HttpNetworkTransaction(session_)); 147 } 148 149 // Start the transaction, read some data, finish. 150 void RunDefaultTest() { 151 output_.rv = trans_->Start(&request_, &callback, log_); 152 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; 157 158 output_.rv = callback.WaitForResult(); 159 if (output_.rv != OK) { 160 session_->spdy_session_pool()->CloseCurrentSessions(); 161 return; 162 } 163 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); 174 } 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); 180 } 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); 186 } 187 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(); 202 } 203 } 204 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(); 219 } 220 } 221 222 void RunToCompletion(StaticSocketDataProvider* data) { 223 RunPreTestSetup(); 224 AddData(data); 225 RunDefaultTest(); 226 VerifyDataConsumed(); 227 } 228 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; 238 } 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); 253 } 254 } 255 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; 265 } 266 ssl_vector_.push_back(ssl_); 267 if (test_type_ == SPDYNPN || test_type_ == SPDYSSL) { 268 session_deps_->deterministic_socket_factory-> 269 AddSSLSocketDataProvider(ssl_.get()); 270 } 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); 283 } 284 } 285 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); 291 } 292 void AddDataNoSSL(DeterministicSocketData* data) { 293 DCHECK(deterministic_); 294 session_deps_->deterministic_socket_factory->AddSocketDataProvider(data); 295 } 296 297 void SetSession(const scoped_refptr<HttpNetworkSession>& session) { 298 session_ = session; 299 } 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_; 306 } 307 scoped_ptr<SpdySessionDependencies>& session_deps() { 308 return session_deps_; 309 } 310 int port() const { return port_; } 311 SpdyNetworkTransactionTestTypes test_type() const { return test_type_; } 312 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_; 336 }; 337 338 void ConnectStatusHelperWithExpectedStatus(const MockRead& status, 339 int expected_status); 340 341 void ConnectStatusHelper(const MockRead& status); 342 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_; 348 } 349 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; 356 } 357 return google_get_request_; 358 } 359 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; 367 } 368 return google_get_request_; 369 } 370 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; 379 } 380 return google_post_request_; 381 } 382 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; 394 } 395 return google_chunked_post_request_; 396 } 397 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; 406 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(); 418 } 419 rv = callback.WaitForResult(); 420 } else if (rv <= 0) { 421 break; 422 } 423 result->append(buf->data(), rv); 424 bytes_read += rv; 425 } 426 return bytes_read; 427 } 428 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()); 445 } 446 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); 455 456 HttpNetworkTransaction* trans = helper.trans(); 457 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(); 463 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(); 470 471 // The data for the pushed path may be coming in more than 1 packet. Compile 472 // the results into a single string. 473 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); 480 481 // Verify that we consumed all test data. 482 EXPECT_TRUE(data->at_read_eof()); 483 EXPECT_TRUE(data->at_write_eof()); 484 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; 490 491 // Verify the SYN_REPLY. 492 // Copy the response info, because trans goes away. 493 *response = *trans->GetResponseInfo(); 494 *push_response = *trans2->GetResponseInfo(); 495 496 VerifyStreamsClosed(helper); 497 } 498 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_; 507 }; 508 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)); 515 516 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)); 523 } 524 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) }; 529 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 536 }; 537 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); 548 } 549 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) }; 556 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(); 578 } 579 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 586 }; 587 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; 593 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); 600 } 601 } 602 603 // Start three gets simultaniously; making sure that multiplexed 604 // streams work properly. 605 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. 609 610 // TODO(gavinp): create a working generalized TransactionHelper that 611 // can allow multiple streams in flight. 612 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)); 618 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)); 623 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)); 628 629 MockWrite writes[] = { 630 CreateMockWrite(*req), 631 CreateMockWrite(*req2), 632 CreateMockWrite(*req3), 633 }; 634 MockRead reads[] = { 635 CreateMockRead(*resp, 1), 636 CreateMockRead(*body), 637 CreateMockRead(*resp2, 4), 638 CreateMockRead(*body2), 639 CreateMockRead(*resp3, 7), 640 CreateMockRead(*body3), 641 642 CreateMockRead(*fbody), 643 CreateMockRead(*fbody2), 644 CreateMockRead(*fbody3), 645 646 MockRead(true, 0, 0), // EOF 647 }; 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)); 653 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())); 670 671 TestCompletionCallback callback1; 672 TestCompletionCallback callback2; 673 TestCompletionCallback callback3; 674 675 HttpRequestInfo httpreq1 = CreateGetRequest(); 676 HttpRequestInfo httpreq2 = CreateGetRequest(); 677 HttpRequestInfo httpreq3 = CreateGetRequest(); 678 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); 685 686 out.rv = callback1.WaitForResult(); 687 ASSERT_EQ(OK, out.rv); 688 out.rv = callback3.WaitForResult(); 689 ASSERT_EQ(OK, out.rv); 690 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; 696 697 trans2->GetResponseInfo(); 698 699 out.rv = ReadTransaction(trans1.get(), &out.response_data); 700 helper.VerifyDataConsumed(); 701 EXPECT_EQ(OK, out.rv); 702 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); 706 } 707 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)); 713 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)); 718 719 MockWrite writes[] = { 720 CreateMockWrite(*req), 721 CreateMockWrite(*req2), 722 }; 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 731 }; 732 scoped_refptr<OrderedSocketData> data( 733 new OrderedSocketData(reads, arraysize(reads), 734 writes, arraysize(writes))); 735 736 MockConnect never_finishing_connect(false, ERR_IO_PENDING); 737 738 scoped_refptr<OrderedSocketData> data_placeholder( 739 new OrderedSocketData(NULL, 0, NULL, 0)); 740 data_placeholder->set_connect_data(never_finishing_connect); 741 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())); 755 756 TestCompletionCallback callback1; 757 TestCompletionCallback callback2; 758 759 HttpRequestInfo httpreq1 = CreateGetRequest(); 760 HttpRequestInfo httpreq2 = CreateGetRequest(); 761 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); 766 767 out.rv = callback1.WaitForResult(); 768 ASSERT_EQ(OK, out.rv); 769 out.rv = callback2.WaitForResult(); 770 ASSERT_EQ(OK, out.rv); 771 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); 781 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); 791 792 helper.VerifyDataConsumed(); 793 } 794 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)); 800 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)); 805 806 MockWrite writes[] = { 807 CreateMockWrite(*req), 808 CreateMockWrite(*req2), 809 }; 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 818 }; 819 scoped_refptr<OrderedSocketData> preconnect_data( 820 new OrderedSocketData(reads, arraysize(reads), 821 writes, arraysize(writes))); 822 823 MockConnect never_finishing_connect(true, ERR_IO_PENDING); 824 825 scoped_refptr<OrderedSocketData> data_placeholder( 826 new OrderedSocketData(NULL, 0, NULL, 0)); 827 data_placeholder->set_connect_data(never_finishing_connect); 828 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()); 839 840 scoped_ptr<HttpNetworkTransaction> trans1( 841 new HttpNetworkTransaction(helper.session())); 842 scoped_ptr<HttpNetworkTransaction> trans2( 843 new HttpNetworkTransaction(helper.session())); 844 845 TestCompletionCallback callback1; 846 TestCompletionCallback callback2; 847 848 HttpRequestInfo httpreq = CreateGetRequest(); 849 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(); 857 } 858 859 http_stream_factory->PreconnectStreams( 860 1, httpreq, preconnect_ssl_config, log); 861 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); 866 867 out.rv = callback1.WaitForResult(); 868 ASSERT_EQ(OK, out.rv); 869 out.rv = callback2.WaitForResult(); 870 ASSERT_EQ(OK, out.rv); 871 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); 881 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); 891 892 helper.VerifyDataConsumed(); 893 } 894 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)); 906 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)); 911 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)); 916 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; 921 922 settings.push_back(spdy::SpdySetting(id, max_concurrent_streams)); 923 scoped_ptr<spdy::SpdyFrame> settings_frame(ConstructSpdySettings(settings)); 924 925 MockWrite writes[] = { 926 CreateMockWrite(*req), 927 CreateMockWrite(*req2), 928 CreateMockWrite(*req3), 929 }; 930 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), 942 943 MockRead(true, 0, 0), // EOF 944 }; 945 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)); 951 952 BoundNetLog log; 953 TransactionHelperResult out; 954 { 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())); 969 970 TestCompletionCallback callback1; 971 TestCompletionCallback callback2; 972 TestCompletionCallback callback3; 973 974 HttpRequestInfo httpreq1 = CreateGetRequest(); 975 HttpRequestInfo httpreq2 = CreateGetRequest(); 976 HttpRequestInfo httpreq3 = CreateGetRequest(); 977 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); 984 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 992 993 out.rv = callback3.WaitForResult(); 994 ASSERT_EQ(OK, out.rv); 995 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); 1006 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); 1014 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); 1022 1023 helper.VerifyDataConsumed(); 1024 } 1025 EXPECT_EQ(OK, out.rv); 1026 } 1027 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)); 1039 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)); 1044 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)); 1049 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)); 1054 1055 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; 1060 1061 settings.push_back(spdy::SpdySetting(id, max_concurrent_streams)); 1062 scoped_ptr<spdy::SpdyFrame> settings_frame(ConstructSpdySettings(settings)); 1063 1064 MockWrite writes[] = { CreateMockWrite(*req), 1065 CreateMockWrite(*req2), 1066 CreateMockWrite(*req4), 1067 CreateMockWrite(*req3), 1068 }; 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), 1082 1083 MockRead(true, 0, 0), // EOF 1084 }; 1085 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)); 1091 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())); 1111 1112 TestCompletionCallback callback1; 1113 TestCompletionCallback callback2; 1114 TestCompletionCallback callback3; 1115 TestCompletionCallback callback4; 1116 1117 HttpRequestInfo httpreq1 = CreateGetRequest(); 1118 HttpRequestInfo httpreq2 = CreateGetRequest(); 1119 HttpRequestInfo httpreq3 = CreateGetRequest(); 1120 HttpRequestInfo httpreq4 = CreateGetRequest(); 1121 httpreq4.priority = HIGHEST; 1122 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); 1129 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); 1136 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 1140 1141 out.rv = callback3.WaitForResult(); 1142 ASSERT_EQ(OK, out.rv); 1143 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); 1153 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); 1161 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); 1171 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); 1183 } 1184 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)); 1195 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)); 1200 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; 1205 1206 settings.push_back(spdy::SpdySetting(id, max_concurrent_streams)); 1207 scoped_ptr<spdy::SpdyFrame> settings_frame(ConstructSpdySettings(settings)); 1208 1209 MockWrite writes[] = { CreateMockWrite(*req), 1210 CreateMockWrite(*req2), 1211 }; 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 1221 }; 1222 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)); 1228 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())); 1245 1246 TestCompletionCallback callback1; 1247 TestCompletionCallback callback2; 1248 TestCompletionCallback callback3; 1249 1250 HttpRequestInfo httpreq1 = CreateGetRequest(); 1251 HttpRequestInfo httpreq2 = CreateGetRequest(); 1252 HttpRequestInfo httpreq3 = CreateGetRequest(); 1253 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); 1260 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); 1268 1269 EXPECT_EQ(8U, data->read_index()); 1270 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); 1281 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); 1292 } 1293 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) {} 1300 1301 virtual void RunWithParams(const Tuple1<int>& params) { 1302 if (params.a < 0) 1303 delete transaction_; 1304 TestCompletionCallback::RunWithParams(params); 1305 } 1306 1307 private: 1308 HttpNetworkTransaction* transaction_; 1309 }; 1310 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)); 1320 1321 scoped_ptr<spdy::SpdyFrame> req2(ConstructSpdyGet(NULL, 0, false, 3, LOWEST)); 1322 scoped_ptr<spdy::SpdyFrame> resp2(ConstructSpdyGetSynReply(NULL, 0, 3)); 1323 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; 1328 1329 settings.push_back(spdy::SpdySetting(id, max_concurrent_streams)); 1330 scoped_ptr<spdy::SpdyFrame> settings_frame(ConstructSpdySettings(settings)); 1331 1332 MockWrite writes[] = { CreateMockWrite(*req), 1333 CreateMockWrite(*req2), 1334 }; 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! 1342 }; 1343 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)); 1349 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())); 1363 1364 TestCompletionCallback callback1; 1365 TestCompletionCallback callback2; 1366 KillerCallback callback3(trans3); 1367 1368 HttpRequestInfo httpreq1 = CreateGetRequest(); 1369 HttpRequestInfo httpreq2 = CreateGetRequest(); 1370 HttpRequestInfo httpreq3 = CreateGetRequest(); 1371 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); 1378 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); 1385 1386 EXPECT_EQ(6U, data->read_index()); 1387 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); 1396 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); 1403 1404 helper.VerifyDataConsumed(); 1405 } 1406 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/"); 1413 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 1425 }; 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" 1433 }; 1434 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyPacket(kSynStartHeader, NULL, 0, 1435 kPutHeaders, arraysize(kPutHeaders) / 2)); 1436 MockWrite writes[] = { 1437 CreateMockWrite(*req) 1438 }; 1439 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 1452 }; 1453 static const char* const kStandardGetHeaders[] = { 1454 "status", "200", 1455 "version", "HTTP/1.1" 1456 "content-length", "1234" 1457 }; 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 1464 }; 1465 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(); 1473 1474 EXPECT_EQ(OK, out.rv); 1475 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line); 1476 } 1477 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/"); 1484 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 1496 }; 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" 1504 }; 1505 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyPacket(kSynStartHeader, NULL, 0, 1506 kHeadHeaders, arraysize(kHeadHeaders) / 2)); 1507 MockWrite writes[] = { 1508 CreateMockWrite(*req) 1509 }; 1510 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 1523 }; 1524 static const char* const kStandardGetHeaders[] = { 1525 "status", "200", 1526 "version", "HTTP/1.1" 1527 "content-length", "1234" 1528 }; 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 1535 }; 1536 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(); 1544 1545 EXPECT_EQ(OK, out.rv); 1546 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line); 1547 } 1548 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 1556 }; 1557 1558 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyPostSynReply(NULL, 0)); 1559 MockRead reads[] = { 1560 CreateMockRead(*resp), 1561 CreateMockRead(*body), 1562 MockRead(true, 0, 0) // EOF 1563 }; 1564 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); 1575 } 1576 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), 1587 }; 1588 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 1595 }; 1596 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); 1607 } 1608 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; 1617 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), 1625 }; 1626 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 1633 }; 1634 1635 scoped_refptr<DelayedSocketData> data( 1636 new DelayedSocketData(1, reads, arraysize(reads), 1637 writes, arraysize(writes))); 1638 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); 1646 } 1647 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(); 1656 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()); 1662 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), 1669 }; 1670 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 1677 }; 1678 1679 scoped_refptr<DelayedSocketData> data( 1680 new DelayedSocketData(1, reads, arraysize(reads), 1681 writes, arraysize(writes))); 1682 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); 1690 } 1691 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!" }; 1695 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)); 1702 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 1714 }; 1715 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(); 1724 1725 TransactionHelperResult out = helper.output(); 1726 EXPECT_EQ(ERR_SYN_REPLY_NOT_RECEIVED, out.rv); 1727 } 1728 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), 1740 }; 1741 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 1746 }; 1747 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(); 1757 1758 TestCompletionCallback callback; 1759 int rv = trans->Start(&CreateGetRequest(), &callback, BoundNetLog()); 1760 EXPECT_EQ(ERR_IO_PENDING, rv); 1761 1762 data->SetStop(2); 1763 data->Run(); 1764 helper.ResetTrans(); 1765 data->SetStop(20); 1766 data->Run(); 1767 1768 helper.VerifyDataConsumed(); 1769 } 1770 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 1777 }; 1778 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); 1786 } 1787 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) }; 1793 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 1801 }; 1802 1803 scoped_refptr<DelayedSocketData> data( 1804 new DelayedSocketData(1, reads, arraysize(reads), 1805 writes, arraysize(writes))); 1806 1807 NormalSpdyTransactionHelper helper(CreateGetRequest(), 1808 BoundNetLog(), GetParam()); 1809 helper.RunPreTestSetup(); 1810 helper.AddData(data.get()); 1811 1812 HttpNetworkTransaction* trans = helper.trans(); 1813 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); 1819 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); 1827 1828 helper.VerifyDataConsumed(); 1829 } 1830 1831 // Test that sent data frames and received WINDOW_UPDATE frames change 1832 // the send_window_size_ correctly. 1833 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. 1846 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); 1854 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)); 1864 1865 MockWrite writes[] = { 1866 CreateMockWrite(*req), 1867 CreateMockWrite(*body), 1868 CreateMockWrite(*body_end), 1869 }; 1870 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 1889 }; 1890 1891 scoped_refptr<DelayedSocketData> data( 1892 new DelayedSocketData(0, reads, arraysize(reads), 1893 writes, arraysize(writes))); 1894 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()); 1902 1903 NormalSpdyTransactionHelper helper(request, BoundNetLog(), GetParam()); 1904 helper.AddData(data.get()); 1905 helper.RunPreTestSetup(); 1906 1907 HttpNetworkTransaction* trans = helper.trans(); 1908 1909 TestCompletionCallback callback; 1910 int rv = trans->Start(&helper.request(), &callback, BoundNetLog()); 1911 1912 EXPECT_EQ(ERR_IO_PENDING, rv); 1913 rv = callback.WaitForResult(); 1914 EXPECT_EQ(OK, rv); 1915 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); 1925 } 1926 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); 1931 1932 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST)); 1933 scoped_ptr<spdy::SpdyFrame> window_update( 1934 ConstructSpdyWindowUpdate(1, kUploadDataSize)); 1935 1936 MockWrite writes[] = { 1937 CreateMockWrite(*req), 1938 CreateMockWrite(*window_update), 1939 }; 1940 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 1954 }; 1955 1956 scoped_refptr<DelayedSocketData> data( 1957 new DelayedSocketData(1, reads, arraysize(reads), 1958 writes, arraysize(writes))); 1959 1960 NormalSpdyTransactionHelper helper(CreateGetRequest(), 1961 BoundNetLog(), GetParam()); 1962 helper.AddData(data.get()); 1963 helper.RunPreTestSetup(); 1964 HttpNetworkTransaction* trans = helper.trans(); 1965 1966 TestCompletionCallback callback; 1967 int rv = trans->Start(&helper.request(), &callback, BoundNetLog()); 1968 1969 EXPECT_EQ(ERR_IO_PENDING, rv); 1970 rv = callback.WaitForResult(); 1971 EXPECT_EQ(OK, rv); 1972 1973 SpdyHttpStream* stream = 1974 static_cast<SpdyHttpStream*>(trans->stream_.get()); 1975 ASSERT_TRUE(stream != NULL); 1976 ASSERT_TRUE(stream->stream() != NULL); 1977 1978 EXPECT_EQ( 1979 static_cast<int>(spdy::kSpdyStreamInitialWindowSize) - kUploadDataSize, 1980 stream->stream()->recv_window_size()); 1981 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); 1987 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()); 1995 1996 // Schedule the reading of empty data frame with FIN 1997 data->CompleteRead(); 1998 1999 // Force write of WINDOW_UPDATE which was scheduled during the above 2000 // read. 2001 MessageLoop::current()->RunAllPending(); 2002 2003 // Read EOF. 2004 data->CompleteRead(); 2005 2006 helper.VerifyDataConsumed(); 2007 SpdySession::set_flow_control(false); 2008 } 2009 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); 2014 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; 2018 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)); 2027 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), 2034 }; 2035 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)); 2042 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 2051 }; 2052 2053 scoped_refptr<DelayedSocketData> data( 2054 new DelayedSocketData(0, reads, arraysize(reads), 2055 writes, arraysize(writes))); 2056 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()); 2064 2065 NormalSpdyTransactionHelper helper(request, 2066 BoundNetLog(), GetParam()); 2067 helper.AddData(data.get()); 2068 helper.RunPreTestSetup(); 2069 2070 HttpNetworkTransaction* trans = helper.trans(); 2071 2072 TestCompletionCallback callback; 2073 int rv = trans->Start(&helper.request(), &callback, BoundNetLog()); 2074 2075 EXPECT_EQ(ERR_IO_PENDING, rv); 2076 rv = callback.WaitForResult(); 2077 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, rv); 2078 2079 data->CompleteRead(); 2080 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(); 2085 2086 SpdySession::set_flow_control(false); 2087 } 2088 2089 // Test that after hitting a send window size of 0, the write process 2090 // stalls and upon receiving WINDOW_UPDATE frame write resumes. 2091 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); 2106 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; 2113 2114 // Calculate last frame's size; 0 size data frame is legal. 2115 size_t last_frame_size = 2116 spdy::kSpdyStreamInitialWindowSize % kMaxSpdyFrameChunkSize; 2117 2118 // Construct content for a data frame of maximum size. 2119 scoped_ptr<std::string> content( 2120 new std::string(kMaxSpdyFrameChunkSize, 'a')); 2121 2122 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyPost( 2123 spdy::kSpdyStreamInitialWindowSize + kUploadDataSize, NULL, 0)); 2124 2125 // Full frames. 2126 scoped_ptr<spdy::SpdyFrame> body1( 2127 ConstructSpdyBodyFrame(1, content->c_str(), content->size(), false)); 2128 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)); 2132 2133 // Data frame to be sent once WINDOW_UPDATE frame is received. 2134 scoped_ptr<spdy::SpdyFrame> body3(ConstructSpdyBodyFrame(1, true)); 2135 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); 2144 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 2157 }; 2158 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)); 2164 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(); 2177 2178 HttpNetworkTransaction* trans = helper.trans(); 2179 2180 TestCompletionCallback callback; 2181 int rv = trans->Start(&helper.request(), &callback, BoundNetLog()); 2182 EXPECT_EQ(ERR_IO_PENDING, rv); 2183 2184 MessageLoop::current()->RunAllPending(); // Write as much as we can. 2185 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()); 2191 2192 data->ForceNextRead(); // Read in WINDOW_UPDATE frame. 2193 rv = callback.WaitForResult(); 2194 helper.VerifyDataConsumed(); 2195 2196 SpdySession::set_flow_control(false); 2197 } 2198 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), 2204 }; 2205 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 2214 }; 2215 2216 StaticSocketDataProvider data(reads, arraysize(reads), 2217 writes, arraysize(writes)); 2218 2219 NormalSpdyTransactionHelper helper(CreateGetRequest(), 2220 BoundNetLog(), GetParam()); 2221 helper.RunPreTestSetup(); 2222 helper.AddData(&data); 2223 HttpNetworkTransaction* trans = helper.trans(); 2224 2225 TestCompletionCallback callback; 2226 int rv = trans->Start(&CreateGetRequest(), &callback, BoundNetLog()); 2227 EXPECT_EQ(ERR_IO_PENDING, rv); 2228 helper.ResetTrans(); // Cancel the transaction. 2229 2230 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the 2231 // MockClientSocketFactory) are still alive. 2232 MessageLoop::current()->RunAllPending(); 2233 helper.VerifyDataNotConsumed(); 2234 } 2235 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), 2244 }; 2245 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 2250 }; 2251 2252 scoped_refptr<DeterministicSocketData> data( 2253 new DeterministicSocketData(reads, arraysize(reads), 2254 writes, arraysize(writes))); 2255 2256 NormalSpdyTransactionHelper helper(CreateGetRequest(), 2257 BoundNetLog(), 2258 GetParam()); 2259 helper.SetDeterministic(); 2260 helper.RunPreTestSetup(); 2261 helper.AddDeterministicData(data.get()); 2262 HttpNetworkTransaction* trans = helper.trans(); 2263 2264 TestCompletionCallback callback; 2265 2266 int rv = trans->Start(&CreateGetRequest(), &callback, BoundNetLog()); 2267 EXPECT_EQ(ERR_IO_PENDING, rv); 2268 2269 data->SetStop(2); 2270 data->Run(); 2271 helper.ResetTrans(); 2272 data->SetStop(20); 2273 data->Run(); 2274 2275 helper.VerifyDataConsumed(); 2276 } 2277 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) {} 2285 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(); 2298 } 2299 2300 private: 2301 const scoped_refptr<HttpNetworkSession>& session_; 2302 NormalSpdyTransactionHelper& helper_; 2303 }; 2304 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) }; 2312 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', '!', 2320 }; 2321 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 2330 }; 2331 MockRead reads2[] = { 2332 CreateMockRead(*resp, 2), 2333 MockRead(true, 0, 0, 3), // EOF 2334 }; 2335 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))); 2342 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(); 2349 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(); 2355 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(); 2365 } 2366 2367 class SpdyNetworkTransactionTest::DeleteSessionCallback 2368 : public CallbackRunner< Tuple1<int> > { 2369 public: 2370 explicit DeleteSessionCallback(NormalSpdyTransactionHelper& helper) : 2371 helper_(helper) {} 2372 2373 // We kill the transaction, which deletes the session and stream. 2374 virtual void RunWithParams(const Tuple1<int>& params) { 2375 helper_.ResetTrans(); 2376 } 2377 2378 private: 2379 NormalSpdyTransactionHelper& helper_; 2380 }; 2381 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) }; 2388 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 2396 }; 2397 2398 scoped_refptr<OrderedSocketData> data( 2399 new OrderedSocketData(reads, arraysize(reads), 2400 writes, arraysize(writes))); 2401 2402 NormalSpdyTransactionHelper helper(CreateGetRequest(), 2403 BoundNetLog(), GetParam()); 2404 helper.RunPreTestSetup(); 2405 helper.AddData(data.get()); 2406 HttpNetworkTransaction* trans = helper.trans(); 2407 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(); 2413 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(); 2422 2423 // Finish running rest of tasks. 2424 MessageLoop::current()->RunAllPending(); 2425 helper.VerifyDataConsumed(); 2426 } 2427 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", 2434 }; 2435 const SpdyHeaderInfo kSynStartHeader = make_spdy_header(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", 2446 "", 2447 "version", 2448 "HTTP/1.1" 2449 }; 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", 2460 "", 2461 "version", 2462 "HTTP/1.1" 2463 }; 2464 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), 2475 }; 2476 MockRead reads[] = { 2477 CreateMockRead(*resp, 2), 2478 MockRead(true, 0, 0, 3) // EOF 2479 }; 2480 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), 2486 }; 2487 MockRead reads2[] = { 2488 CreateMockRead(*resp2, 2), 2489 CreateMockRead(*body2, 3), 2490 MockRead(true, 0, 0, 4) // EOF 2491 }; 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))); 2498 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; 2503 { 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()); 2512 2513 d.set_quit_on_redirect(true); 2514 r.Start(); 2515 MessageLoop::current()->Run(); 2516 2517 EXPECT_EQ(1, d.received_redirect_count()); 2518 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()); 2526 } 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()); 2531 } 2532 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", 2540 }; 2541 const SpdyHeaderInfo kSynStartHeader = make_spdy_header(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", 2552 "", 2553 "version", 2554 "HTTP/1.1" 2555 }; 2556 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, 2567 0, 2568 2, 2569 1, 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), 2578 }; 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 2585 }; 2586 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", 2598 "", 2599 "version", 2600 "HTTP/1.1" 2601 }; 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), 2612 }; 2613 MockRead reads2[] = { 2614 CreateMockRead(*resp2, 2), 2615 CreateMockRead(*body2, 3), 2616 MockRead(true, 0, 0, 5) // EOF 2617 }; 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))); 2624 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()); 2632 { 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()); 2637 2638 r.Start(); 2639 MessageLoop::current()->Run(); 2640 2641 EXPECT_EQ(0, d.received_redirect_count()); 2642 std::string contents("hello!"); 2643 EXPECT_EQ(contents, d.data_received()); 2644 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()); 2649 2650 d2.set_quit_on_redirect(true); 2651 r2.Start(); 2652 MessageLoop::current()->Run(); 2653 EXPECT_EQ(1, d2.received_redirect_count()); 2654 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()); 2662 } 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()); 2669 } 2670 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" 2676 }; 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), 2683 }; 2684 2685 scoped_ptr<spdy::SpdyFrame> 2686 stream1_reply(ConstructSpdyGetSynReply(NULL, 0, 1)); 2687 scoped_ptr<spdy::SpdyFrame> 2688 stream2_syn(ConstructSpdyPush(NULL, 2689 0, 2690 2, 2691 1, 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 2700 }; 2701 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); 2714 2715 // Verify the SYN_REPLY. 2716 EXPECT_TRUE(response.headers != NULL); 2717 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine()); 2718 2719 // Verify the pushed stream. 2720 EXPECT_TRUE(response2.headers != NULL); 2721 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine()); 2722 } 2723 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" 2729 }; 2730 scoped_ptr<spdy::SpdyFrame> 2731 stream1_syn(ConstructSpdyGet(NULL, 0, false, 1, LOWEST)); 2732 MockWrite writes[] = { 2733 CreateMockWrite(*stream1_syn, 1), 2734 }; 2735 2736 scoped_ptr<spdy::SpdyFrame> 2737 stream1_reply(ConstructSpdyGetSynReply(NULL, 0, 1)); 2738 scoped_ptr<spdy::SpdyFrame> 2739 stream2_syn(ConstructSpdyPush(NULL, 2740 0, 2741 2, 2742 1, 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 2753 }; 2754 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); 2767 2768 // Verify the SYN_REPLY. 2769 EXPECT_TRUE(response.headers != NULL); 2770 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine()); 2771 2772 // Verify the pushed stream. 2773 EXPECT_TRUE(response2.headers != NULL); 2774 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine()); 2775 } 2776 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), 2784 }; 2785 2786 scoped_ptr<spdy::SpdyFrame> 2787 stream1_reply(ConstructSpdyGetSynReply(NULL, 0, 1)); 2788 scoped_ptr<spdy::SpdyFrame> 2789 stream2_syn(ConstructSpdyPush(NULL, 2790 0, 2791 2, 2792 1, 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 2802 }; 2803 2804 scoped_refptr<OrderedSocketData> data( 2805 new OrderedSocketData(reads, arraysize(reads), 2806 writes, arraysize(writes))); 2807 NormalSpdyTransactionHelper helper(CreateGetRequest(), 2808 BoundNetLog(), GetParam()); 2809 2810 helper.RunPreTestSetup(); 2811 helper.AddData(data.get()); 2812 2813 HttpNetworkTransaction* trans = helper.trans(); 2814 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); 2821 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(); 2831 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()); 2836 } 2837 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" 2845 }; 2846 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), 2856 }; 2857 2858 scoped_ptr<spdy::SpdyFrame> 2859 stream1_reply(ConstructSpdyGetSynReply(NULL, 0, 1)); 2860 scoped_ptr<spdy::SpdyFrame> 2861 stream2_syn(ConstructSpdyPush(NULL, 2862 0, 2863 2, 2864 1, 2865 "http://www.google.com/foo.dat")); 2866 scoped_ptr<spdy::SpdyFrame> 2867 stream3_syn(ConstructSpdyPush(NULL, 2868 0, 2869 4, 2870 1, 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 2880 }; 2881 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); 2894 2895 // Verify the SYN_REPLY. 2896 EXPECT_TRUE(response.headers != NULL); 2897 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine()); 2898 2899 // Verify the pushed stream. 2900 EXPECT_TRUE(response2.headers != NULL); 2901 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine()); 2902 } 2903 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" 2909 }; 2910 static const char kPushBodyFrame2[] = " my darling"; 2911 static const char kPushBodyFrame3[] = " hello"; 2912 static const char kPushBodyFrame4[] = " my baby"; 2913 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), 2920 }; 2921 2922 scoped_ptr<spdy::SpdyFrame> 2923 stream1_reply(ConstructSpdyGetSynReply(NULL, 0, 1)); 2924 scoped_ptr<spdy::SpdyFrame> 2925 stream2_syn(ConstructSpdyPush(NULL, 2926 0, 2927 2, 2928 1, 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 2943 }; 2944 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); 2957 2958 // Verify the SYN_REPLY. 2959 EXPECT_TRUE(response.headers != NULL); 2960 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine()); 2961 2962 // Verify the pushed stream. 2963 EXPECT_TRUE(response2.headers != NULL); 2964 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine()); 2965 } 2966 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" 2972 }; 2973 static const char kPushBodyFrame2[] = " my darling"; 2974 static const char kPushBodyFrame3[] = " hello"; 2975 static const char kPushBodyFrame4[] = " my baby"; 2976 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), 2983 }; 2984 2985 scoped_ptr<spdy::SpdyFrame> 2986 stream1_reply(ConstructSpdyGetSynReply(NULL, 0, 1)); 2987 scoped_ptr<spdy::SpdyFrame> 2988 stream2_syn(ConstructSpdyPush(NULL, 2989 0, 2990 2, 2991 1, 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. 3007 }; 3008 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); 3021 3022 // Verify the SYN_REPLY. 3023 EXPECT_TRUE(response.headers != NULL); 3024 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine()); 3025 3026 // Verify the pushed stream. 3027 EXPECT_TRUE(response2.headers != NULL); 3028 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine()); 3029 } 3030 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), 3041 }; 3042 3043 scoped_ptr<spdy::SpdyFrame> 3044 stream1_reply(ConstructSpdyGetSynReply(NULL, 0, 1)); 3045 scoped_ptr<spdy::SpdyFrame> 3046 stream2_syn(ConstructSpdyPush(NULL, 3047 0, 3048 2, 3049 0, 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 3056 }; 3057 3058 scoped_refptr<OrderedSocketData> data( 3059 new OrderedSocketData(reads, arraysize(reads), 3060 writes, arraysize(writes))); 3061 NormalSpdyTransactionHelper helper(CreateGetRequest(), 3062 BoundNetLog(), GetParam()); 3063 3064 helper.RunPreTestSetup(); 3065 helper.AddData(data.get()); 3066 3067 HttpNetworkTransaction* trans = helper.trans(); 3068 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); 3075 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(); 3085 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()); 3090 } 3091 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), 3102 }; 3103 3104 scoped_ptr<spdy::SpdyFrame> 3105 stream1_reply(ConstructSpdyGetSynReply(NULL, 0, 1)); 3106 scoped_ptr<spdy::SpdyFrame> 3107 stream2_syn(ConstructSpdyPush(NULL, 3108 0, 3109 2, 3110 9, 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 3117 }; 3118 3119 scoped_refptr<OrderedSocketData> data( 3120 new OrderedSocketData(reads, arraysize(reads), 3121 writes, arraysize(writes))); 3122 NormalSpdyTransactionHelper helper(CreateGetRequest(), 3123 BoundNetLog(), GetParam()); 3124 3125 helper.RunPreTestSetup(); 3126 helper.AddData(data.get()); 3127 3128 HttpNetworkTransaction* trans = helper.trans(); 3129 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); 3136 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(); 3146 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()); 3151 } 3152 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), 3163 }; 3164 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 3174 }; 3175 3176 scoped_refptr<OrderedSocketData> data( 3177 new OrderedSocketData(reads, arraysize(reads), 3178 writes, arraysize(writes))); 3179 NormalSpdyTransactionHelper helper(CreateGetRequest(), 3180 BoundNetLog(), GetParam()); 3181 3182 helper.RunPreTestSetup(); 3183 helper.AddData(data.get()); 3184 3185 HttpNetworkTransaction* trans = helper.trans(); 3186 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(); 3202 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()); 3207 } 3208 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 3222 }, 3223 "cookie: val1\n" 3224 "cookie: val2\n" 3225 "hello: bye\n" 3226 "status: 200\n" 3227 "version: HTTP/1.1\n" 3228 }, 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" 3235 }, 3236 // Headers with a comma separated list. 3237 { 1, 3238 { "cookie", "val1,val2", 3239 NULL 3240 }, 3241 "cookie: val1,val2\n" 3242 "hello: bye\n" 3243 "status: 200\n" 3244 "version: HTTP/1.1\n" 3245 } 3246 }; 3247 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) }; 3252 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 3262 }; 3263 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(); 3271 3272 EXPECT_EQ(OK, out.rv); 3273 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line); 3274 EXPECT_EQ("hello!", out.response_data); 3275 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"); 3285 } 3286 EXPECT_EQ(std::string(test_cases[i].expected_headers), lines); 3287 } 3288 } 3289 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 3305 }; 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. 3315 { 3316 &syn_reply_info, 3317 true, 3318 { 1, 4 }, 3319 { { "cookie", "val1,val2", 3320 NULL 3321 }, 3322 { "vary", "cookie", 3323 "status", "200", 3324 "url", "/index.php", 3325 "version", "HTTP/1.1", 3326 NULL 3327 } 3328 } 3329 }, { // Multiple vary fields. 3330 &syn_reply_info, 3331 true, 3332 { 2, 5 }, 3333 { { "friend", "barney", 3334 "enemy", "snaggletooth", 3335 NULL 3336 }, 3337 { "vary", "friend", 3338 "vary", "enemy", 3339 "status", "200", 3340 "url", "/index.php", 3341 "version", "HTTP/1.1", 3342 NULL 3343 } 3344 } 3345 }, { // Test a '*' vary field. 3346 &syn_reply_info, 3347 false, 3348 { 1, 4 }, 3349 { { "cookie", "val1,val2", 3350 NULL 3351 }, 3352 { "vary", "*", 3353 "status", "200", 3354 "url", "/index.php", 3355 "version", "HTTP/1.1", 3356 NULL 3357 } 3358 } 3359 }, { // Multiple comma-separated vary fields. 3360 &syn_reply_info, 3361 true, 3362 { 2, 4 }, 3363 { { "friend", "barney", 3364 "enemy", "snaggletooth", 3365 NULL 3366 }, 3367 { "vary", "friend,enemy", 3368 "status", "200", 3369 "url", "/index.php", 3370 "version", "HTTP/1.1", 3371 NULL 3372 } 3373 } 3374 } 3375 }; 3376 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)); 3383 3384 MockWrite writes[] = { 3385 CreateMockWrite(*frame_req), 3386 }; 3387 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)); 3395 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 3401 }; 3402 3403 // Attach the headers to the request. 3404 int header_count = test_cases[i].num_headers[0]; 3405 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); 3411 } 3412 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(); 3420 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; 3424 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; 3436 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"); 3447 } 3448 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); 3455 3456 EXPECT_EQ(std::string(reply_buffer), lines) << i; 3457 } 3458 } 3459 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 3474 }; 3475 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 3487 }, 3488 }, 3489 // SYN_REPLY missing version header 3490 { 2, 3491 { "status", "200", 3492 "url", "/index.php", 3493 NULL 3494 }, 3495 }, 3496 // SYN_REPLY with no headers 3497 { 0, { NULL }, }, 3498 }; 3499 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), 3505 }; 3506 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 3517 }; 3518 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); 3527 } 3528 } 3529 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); 3536 3537 struct SynReplyTests { 3538 const spdy::SpdyFrame* syn_reply; 3539 } test_cases[] = { 3540 { syn_reply_wrong_length.get(), }, 3541 }; 3542 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 3549 }; 3550 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 3556 }; 3557 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); 3566 } 3567 } 3568 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), 3577 }; 3578 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(); 3588 } 3589 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)); 3596 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 3603 }; 3604 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); 3615 } 3616 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); 3622 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), 3630 }; 3631 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) 3638 }; 3639 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(); 3649 3650 EnableCompression(false); 3651 } 3652 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", 3657 }; 3658 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(kExtraHeaders, 1, false, 1, 3659 LOWEST)); 3660 MockWrite writes[] = { CreateMockWrite(*req) }; 3661 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 3668 }; 3669 3670 net::CapturingBoundNetLog log(net::CapturingNetLog::kUnbounded); 3671 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); 3682 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); 3689 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); 3710 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(); 3721 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]); 3735 } 3736 } 3737 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; 3744 3745 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST)); 3746 MockWrite writes[] = { CreateMockWrite(*req) }; 3747 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(), 3756 }; 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)); 3763 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 3772 }; 3773 3774 scoped_refptr<DelayedSocketData> data( 3775 new DelayedSocketData(1, reads, arraysize(reads), 3776 writes, arraysize(writes))); 3777 3778 3779 TestCompletionCallback callback; 3780 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); 3788 3789 TransactionHelperResult out = helper.output(); 3790 out.rv = callback.WaitForResult(); 3791 EXPECT_EQ(out.rv, OK); 3792 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. 3798 3799 // Read Data 3800 TestCompletionCallback read_callback; 3801 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(); 3811 } 3812 if (rv > 0) { 3813 content.append(buf->data(), rv); 3814 } else if (rv < 0) { 3815 NOTREACHED(); 3816 } 3817 } while (rv > 0); 3818 3819 out.response_data.swap(content); 3820 3821 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the 3822 // MockClientSocketFactory) are still alive. 3823 MessageLoop::current()->RunAllPending(); 3824 3825 // Verify that we consumed all test data. 3826 helper.VerifyDataConsumed(); 3827 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); 3831 } 3832 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; 3838 3839 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST)); 3840 MockWrite writes[] = { CreateMockWrite(*req) }; 3841 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() 3852 }; 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)); 3857 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 3864 }; 3865 3866 scoped_refptr<DelayedSocketData> data( 3867 new DelayedSocketData(1, reads, arraysize(reads), 3868 writes, arraysize(writes))); 3869 3870 NormalSpdyTransactionHelper helper(CreateGetRequest(), 3871 BoundNetLog(), GetParam()); 3872 helper.RunPreTestSetup(); 3873 helper.AddData(data.get()); 3874 HttpNetworkTransaction* trans = helper.trans(); 3875 3876 TestCompletionCallback callback; 3877 int rv = trans->Start(&CreateGetRequest(), &callback, BoundNetLog()); 3878 EXPECT_EQ(ERR_IO_PENDING, rv); 3879 3880 TransactionHelperResult out = helper.output(); 3881 out.rv = callback.WaitForResult(); 3882 EXPECT_EQ(out.rv, OK); 3883 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. 3889 3890 // Read Data 3891 TestCompletionCallback read_callback; 3892 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(); 3903 } 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; 3909 } 3910 reads_completed++; 3911 } while (rv > 0); 3912 3913 EXPECT_EQ(3, reads_completed); // Reads are: 14 bytes, 14 bytes, 0 bytes. 3914 3915 out.response_data.swap(content); 3916 3917 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the 3918 // MockClientSocketFactory) are still alive. 3919 MessageLoop::current()->RunAllPending(); 3920 3921 // Verify that we consumed all test data. 3922 helper.VerifyDataConsumed(); 3923 3924 EXPECT_EQ(OK, out.rv); 3925 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line); 3926 EXPECT_EQ("messagemessagemessagemessage", out.response_data); 3927 } 3928 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; 3932 3933 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST)); 3934 MockWrite writes[] = { CreateMockWrite(*req) }; 3935 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() 3950 }; 3951 char combined_frames[200]; 3952 int combined_frames_len = 3953 CombineFrames(frames, arraysize(frames), 3954 combined_frames, arraysize(combined_frames)); 3955 3956 MockRead reads[] = { 3957 MockRead(true, combined_frames, combined_frames_len), 3958 MockRead(true, 0, 0) // EOF 3959 }; 3960 3961 scoped_refptr<DelayedSocketData> data( 3962 new DelayedSocketData(1, reads, arraysize(reads), 3963 writes, arraysize(writes))); 3964 3965 NormalSpdyTransactionHelper helper(CreateGetRequest(), 3966 BoundNetLog(), GetParam()); 3967 helper.RunPreTestSetup(); 3968 helper.AddData(data.get()); 3969 HttpNetworkTransaction* trans = helper.trans(); 3970 3971 TestCompletionCallback callback; 3972 int rv = trans->Start(&CreateGetRequest(), &callback, BoundNetLog()); 3973 EXPECT_EQ(ERR_IO_PENDING, rv); 3974 3975 TransactionHelperResult out = helper.output(); 3976 out.rv = callback.WaitForResult(); 3977 EXPECT_EQ(out.rv, OK); 3978 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. 3984 3985 // Read Data 3986 TestCompletionCallback read_callback; 3987 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; 4000 } 4001 reads_completed++; 4002 } while (rv > 0); 4003 4004 EXPECT_EQ(3, reads_completed); 4005 4006 out.response_data.swap(content); 4007 4008 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the 4009 // MockClientSocketFactory) are still alive. 4010 MessageLoop::current()->RunAllPending(); 4011 4012 // Verify that we consumed all test data. 4013 helper.VerifyDataConsumed(); 4014 4015 EXPECT_EQ(OK, out.rv); 4016 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line); 4017 EXPECT_EQ("messagemessagemessagemessage", out.response_data); 4018 } 4019 4020 // Verify the case where we buffer data and close the connection. 4021 TEST_P(SpdyNetworkTransactionTest, BufferedClosed) { 4022 spdy::SpdyFramer framer; 4023 4024 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST)); 4025 MockWrite writes[] = { CreateMockWrite(*req) }; 4026 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() 4036 }; 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 4047 }; 4048 4049 scoped_refptr<DelayedSocketData> data( 4050 new DelayedSocketData(1, reads, arraysize(reads), 4051 writes, arraysize(writes))); 4052 4053 NormalSpdyTransactionHelper helper(CreateGetRequest(), 4054 BoundNetLog(), GetParam()); 4055 helper.RunPreTestSetup(); 4056 helper.AddData(data.get()); 4057 HttpNetworkTransaction* trans = helper.trans(); 4058 4059 TestCompletionCallback callback; 4060 4061 int rv = trans->Start(&CreateGetRequest(), &callback, BoundNetLog()); 4062 EXPECT_EQ(ERR_IO_PENDING, rv); 4063 4064 TransactionHelperResult out = helper.output(); 4065 out.rv = callback.WaitForResult(); 4066 EXPECT_EQ(out.rv, OK); 4067 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. 4073 4074 // Read Data 4075 TestCompletionCallback read_callback; 4076 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(); 4087 } 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; 4094 } 4095 reads_completed++; 4096 } while (rv > 0); 4097 4098 EXPECT_EQ(0, reads_completed); 4099 4100 out.response_data.swap(content); 4101 4102 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the 4103 // MockClientSocketFactory) are still alive. 4104 MessageLoop::current()->RunAllPending(); 4105 4106 // Verify that we consumed all test data. 4107 helper.VerifyDataConsumed(); 4108 } 4109 4110 // Verify the case where we buffer data and cancel the transaction. 4111 TEST_P(SpdyNetworkTransactionTest, BufferedCancelled) { 4112 spdy::SpdyFramer framer; 4113 4114 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST)); 4115 MockWrite writes[] = { CreateMockWrite(*req) }; 4116 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)); 4120 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 4127 }; 4128 4129 scoped_refptr<DelayedSocketData> data( 4130 new DelayedSocketData(1, reads, arraysize(reads), 4131 writes, arraysize(writes))); 4132 4133 NormalSpdyTransactionHelper helper(CreateGetRequest(), 4134 BoundNetLog(), GetParam()); 4135 helper.RunPreTestSetup(); 4136 helper.AddData(data.get()); 4137 HttpNetworkTransaction* trans = helper.trans(); 4138 TestCompletionCallback callback; 4139 4140 int rv = trans->Start(&CreateGetRequest(), &callback, BoundNetLog()); 4141 EXPECT_EQ(ERR_IO_PENDING, rv); 4142 4143 TransactionHelperResult out = helper.output(); 4144 out.rv = callback.WaitForResult(); 4145 EXPECT_EQ(out.rv, OK); 4146 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. 4152 4153 // Read Data 4154 TestCompletionCallback read_callback; 4155 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; 4167 } 4168 // We shouldn't get here in this test. 4169 FAIL() << "Unexpected read: " << rv; 4170 } while (rv > 0); 4171 4172 // Flush the MessageLoop; this will cause the buffered IO task 4173 // to run for the final time. 4174 MessageLoop::current()->RunAllPending(); 4175 4176 // Verify that we consumed all test data. 4177 helper.VerifyDataConsumed(); 4178 } 4179 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 4195 }; 4196 static const char* const kExtraHeaders[] = { 4197 "status", "200", 4198 "version", "HTTP/1.1" 4199 }; 4200 4201 NormalSpdyTransactionHelper helper(CreateGetRequest(), 4202 BoundNetLog(), GetParam()); 4203 helper.RunPreTestSetup(); 4204 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()); 4209 4210 // Construct the request. 4211 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST)); 4212 MockWrite writes[] = { CreateMockWrite(*req) }; 4213 4214 // Construct the reply. 4215 scoped_ptr<spdy::SpdyFrame> reply( 4216 ConstructSpdyPacket(kSynReplyInfo, 4217 kExtraHeaders, 4218 arraysize(kExtraHeaders) / 2, 4219 NULL, 4220 0)); 4221 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; 4229 { 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)); 4246 } 4247 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 4254 }; 4255 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); 4266 4267 { 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()); 4272 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); 4279 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); 4286 } 4287 } 4288 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 4304 }; 4305 static const char* kExtraHeaders[] = { 4306 "status", "200", 4307 "version", "HTTP/1.1" 4308 }; 4309 4310 NormalSpdyTransactionHelper helper(CreateGetRequest(), 4311 BoundNetLog(), GetParam()); 4312 helper.RunPreTestSetup(); 4313 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()); 4318 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. 4324 { 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)); 4335 4336 spdy_session_pool->mutable_spdy_settings()->Set(host_port_pair, settings); 4337 } 4338 4339 EXPECT_EQ(2u, spdy_session_pool->spdy_settings().Get(host_port_pair).size()); 4340 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)); 4345 4346 // Construct the request. 4347 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST)); 4348 4349 MockWrite writes[] = { 4350 CreateMockWrite(*settings_frame), 4351 CreateMockWrite(*req), 4352 }; 4353 4354 // Construct the reply. 4355 scoped_ptr<spdy::SpdyFrame> reply( 4356 ConstructSpdyPacket(kSynReplyInfo, 4357 kExtraHeaders, 4358 arraysize(kExtraHeaders) / 2, 4359 NULL, 4360 0)); 4361 4362 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true)); 4363 MockRead reads[] = { 4364 CreateMockRead(*reply), 4365 CreateMockRead(*body), 4366 MockRead(true, 0, 0) // EOF 4367 }; 4368 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); 4379 4380 { 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()); 4385 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); 4392 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); 4399 } 4400 } 4401 4402 TEST_P(SpdyNetworkTransactionTest, GoAwayWithActiveStream) { 4403 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST)); 4404 MockWrite writes[] = { CreateMockWrite(*req) }; 4405 4406 scoped_ptr<spdy::SpdyFrame> go_away(ConstructSpdyGoAway()); 4407 MockRead reads[] = { 4408 CreateMockRead(*go_away), 4409 MockRead(true, 0, 0), // EOF 4410 }; 4411 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); 4421 } 4422 4423 TEST_P(SpdyNetworkTransactionTest, CloseWithActiveStream) { 4424 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST)); 4425 MockWrite writes[] = { CreateMockWrite(*req) }; 4426 4427 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1)); 4428 MockRead reads[] = { 4429 CreateMockRead(*resp), 4430 MockRead(false, 0, 0) // EOF 4431 }; 4432 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(); 4442 4443 TestCompletionCallback callback; 4444 TransactionHelperResult out; 4445 out.rv = trans->Start(&CreateGetRequest(), &callback, log); 4446 4447 EXPECT_EQ(out.rv, ERR_IO_PENDING); 4448 out.rv = callback.WaitForResult(); 4449 EXPECT_EQ(out.rv, OK); 4450 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); 4456 4457 // Verify that we consumed all test data. 4458 helper.VerifyDataConsumed(); 4459 } 4460 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(); 4471 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)); 4482 4483 MockWrite writes_SPDYNPN[] = { 4484 MockWrite(false, kConnect443, arraysize(kConnect443) - 1, 0), 4485 CreateMockWrite(*req, 2), 4486 }; 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), 4492 }; 4493 4494 MockWrite writes_SPDYSSL[] = { 4495 MockWrite(false, kConnect80, arraysize(kConnect80) - 1, 0), 4496 CreateMockWrite(*req, 2), 4497 }; 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), 4503 }; 4504 4505 MockWrite writes_SPDYNOSSL[] = { 4506 CreateMockWrite(*req, 0), 4507 }; 4508 4509 MockRead reads_SPDYNOSSL[] = { 4510 CreateMockRead(*resp, 1), 4511 CreateMockRead(*body.get(), 2), 4512 MockRead(true, 0, 0, 3), 4513 }; 4514 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(); 4533 } 4534 4535 helper.AddData(data.get()); 4536 TestCompletionCallback callback; 4537 4538 int rv = trans->Start(&CreateGetRequest(), &callback, BoundNetLog()); 4539 EXPECT_EQ(ERR_IO_PENDING, rv); 4540 4541 rv = callback.WaitForResult(); 4542 EXPECT_EQ(0, rv); 4543 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()); 4548 4549 std::string response_data; 4550 ASSERT_EQ(OK, ReadTransaction(trans, &response_data)); 4551 EXPECT_EQ("hello!", response_data); 4552 helper.VerifyDataConsumed(); 4553 } 4554 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()); 4563 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()))); 4572 4573 SpdySessionPool* spdy_session_pool = helper.session()->spdy_session_pool(); 4574 helper.RunPreTestSetup(); 4575 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), 4580 }; 4581 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 4589 }; 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(); 4595 4596 TestCompletionCallback callback; 4597 TransactionHelperResult out; 4598 out.rv = trans->Start(&CreateGetRequest(), &callback, BoundNetLog()); 4599 4600 EXPECT_EQ(out.rv, ERR_IO_PENDING); 4601 out.rv = callback.WaitForResult(); 4602 EXPECT_EQ(out.rv, OK); 4603 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); 4612 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)); 4622 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)); 4635 4636 MockWrite writes_SPDYNPN[] = { 4637 MockWrite(false, kConnect443, arraysize(kConnect443) - 1, 0), 4638 CreateMockWrite(*req2, 2), 4639 }; 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 4645 }; 4646 4647 MockWrite writes_SPDYNOSSL[] = { 4648 CreateMockWrite(*req2, 0), 4649 }; 4650 MockRead reads_SPDYNOSSL[] = { 4651 CreateMockRead(*resp2, 1), 4652 CreateMockRead(*body2, 2), 4653 MockRead(true, 0, 3) // EOF 4654 }; 4655 4656 MockWrite writes_SPDYSSL[] = { 4657 MockWrite(false, kConnect80, arraysize(kConnect80) - 1, 0), 4658 CreateMockWrite(*req2, 2), 4659 }; 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), 4665 }; 4666 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(); 4689 } 4690 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 session_peer.SetProxyService( 4704 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70")); 4705 helper_proxy.session_deps().swap(ssd_proxy); 4706 helper_proxy.SetSession(session_proxy); 4707 helper_proxy.RunPreTestSetup(); 4708 helper_proxy.AddData(data_proxy.get()); 4709 4710 HttpNetworkTransaction* trans_proxy = helper_proxy.trans(); 4711 TestCompletionCallback callback_proxy; 4712 int rv = trans_proxy->Start(&request_proxy, &callback_proxy, BoundNetLog()); 4713 EXPECT_EQ(ERR_IO_PENDING, rv); 4714 rv = callback_proxy.WaitForResult(); 4715 EXPECT_EQ(0, rv); 4716 4717 HttpResponseInfo response_proxy = *trans_proxy->GetResponseInfo(); 4718 EXPECT_TRUE(response_proxy.headers != NULL); 4719 EXPECT_EQ("HTTP/1.1 200 OK", response_proxy.headers->GetStatusLine()); 4720 4721 std::string response_data; 4722 ASSERT_EQ(OK, ReadTransaction(trans_proxy, &response_data)); 4723 EXPECT_EQ("hello!", response_data); 4724 4725 data->CompleteRead(); 4726 helper_proxy.VerifyDataConsumed(); 4727 } 4728 4729 // When we get a TCP-level RST, we need to retry a HttpNetworkTransaction 4730 // on a new connection, if the connection was previously known to be good. 4731 // This can happen when a server reboots without saying goodbye, or when 4732 // we're behind a NAT that masked the RST. 4733 TEST_P(SpdyNetworkTransactionTest, VerifyRetryOnConnectionReset) { 4734 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1)); 4735 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true)); 4736 MockRead reads[] = { 4737 CreateMockRead(*resp), 4738 CreateMockRead(*body), 4739 MockRead(true, ERR_IO_PENDING), 4740 MockRead(true, ERR_CONNECTION_RESET), 4741 }; 4742 4743 MockRead reads2[] = { 4744 CreateMockRead(*resp), 4745 CreateMockRead(*body), 4746 MockRead(true, 0, 0) // EOF 4747 }; 4748 4749 // This test has a couple of variants. 4750 enum { 4751 // Induce the RST while waiting for our transaction to send. 4752 VARIANT_RST_DURING_SEND_COMPLETION, 4753 // Induce the RST while waiting for our transaction to read. 4754 // In this case, the send completed - everything copied into the SNDBUF. 4755 VARIANT_RST_DURING_READ_COMPLETION 4756 }; 4757 4758 for (int variant = VARIANT_RST_DURING_SEND_COMPLETION; 4759 variant <= VARIANT_RST_DURING_READ_COMPLETION; 4760 ++variant) { 4761 scoped_refptr<DelayedSocketData> data1( 4762 new DelayedSocketData(1, reads, arraysize(reads), 4763 NULL, 0)); 4764 4765 scoped_refptr<DelayedSocketData> data2( 4766 new DelayedSocketData(1, reads2, arraysize(reads2), 4767 NULL, 0)); 4768 4769 NormalSpdyTransactionHelper helper(CreateGetRequest(), 4770 BoundNetLog(), GetParam()); 4771 helper.AddData(data1.get()); 4772 helper.AddData(data2.get()); 4773 helper.RunPreTestSetup(); 4774 4775 for (int i = 0; i < 2; ++i) { 4776 scoped_ptr<HttpNetworkTransaction> trans( 4777 new HttpNetworkTransaction(helper.session())); 4778 4779 TestCompletionCallback callback; 4780 int rv = trans->Start(&helper.request(), &callback, BoundNetLog()); 4781 EXPECT_EQ(ERR_IO_PENDING, rv); 4782 // On the second transaction, we trigger the RST. 4783 if (i == 1) { 4784 if (variant == VARIANT_RST_DURING_READ_COMPLETION) { 4785 // Writes to the socket complete asynchronously on SPDY by running 4786 // through the message loop. Complete the write here. 4787 MessageLoop::current()->RunAllPending(); 4788 } 4789 4790 // Now schedule the ERR_CONNECTION_RESET. 4791 EXPECT_EQ(3u, data1->read_index()); 4792 data1->CompleteRead(); 4793 EXPECT_EQ(4u, data1->read_index()); 4794 } 4795 rv = callback.WaitForResult(); 4796 EXPECT_EQ(OK, rv); 4797 4798 const HttpResponseInfo* response = trans->GetResponseInfo(); 4799 ASSERT_TRUE(response != NULL); 4800 EXPECT_TRUE(response->headers != NULL); 4801 EXPECT_TRUE(response->was_fetched_via_spdy); 4802 std::string response_data; 4803 rv = ReadTransaction(trans.get(), &response_data); 4804 EXPECT_EQ(OK, rv); 4805 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); 4806 EXPECT_EQ("hello!", response_data); 4807 } 4808 4809 helper.VerifyDataConsumed(); 4810 } 4811 } 4812 4813 // Test that turning SPDY on and off works properly. 4814 TEST_P(SpdyNetworkTransactionTest, SpdyOnOffToggle) { 4815 net::HttpStreamFactory::set_spdy_enabled(true); 4816 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST)); 4817 MockWrite spdy_writes[] = { CreateMockWrite(*req) }; 4818 4819 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1)); 4820 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true)); 4821 MockRead spdy_reads[] = { 4822 CreateMockRead(*resp), 4823 CreateMockRead(*body), 4824 MockRead(true, 0, 0) // EOF 4825 }; 4826 4827 scoped_refptr<DelayedSocketData> data( 4828 new DelayedSocketData(1, 4829 spdy_reads, arraysize(spdy_reads), 4830 spdy_writes, arraysize(spdy_writes))); 4831 NormalSpdyTransactionHelper helper(CreateGetRequest(), 4832 BoundNetLog(), GetParam()); 4833 helper.RunToCompletion(data.get()); 4834 TransactionHelperResult out = helper.output(); 4835 EXPECT_EQ(OK, out.rv); 4836 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line); 4837 EXPECT_EQ("hello!", out.response_data); 4838 4839 net::HttpStreamFactory::set_spdy_enabled(false); 4840 MockRead http_reads[] = { 4841 MockRead("HTTP/1.1 200 OK\r\n\r\n"), 4842 MockRead("hello from http"), 4843 MockRead(false, OK), 4844 }; 4845 scoped_refptr<DelayedSocketData> data2( 4846 new DelayedSocketData(1, http_reads, arraysize(http_reads), 4847 NULL, 0)); 4848 NormalSpdyTransactionHelper helper2(CreateGetRequest(), 4849 BoundNetLog(), GetParam()); 4850 helper2.SetSpdyDisabled(); 4851 helper2.RunToCompletion(data2.get()); 4852 TransactionHelperResult out2 = helper2.output(); 4853 EXPECT_EQ(OK, out2.rv); 4854 EXPECT_EQ("HTTP/1.1 200 OK", out2.status_line); 4855 EXPECT_EQ("hello from http", out2.response_data); 4856 4857 net::HttpStreamFactory::set_spdy_enabled(true); 4858 } 4859 4860 // Tests that Basic authentication works over SPDY 4861 TEST_P(SpdyNetworkTransactionTest, SpdyBasicAuth) { 4862 net::HttpStreamFactory::set_spdy_enabled(true); 4863 4864 // The first request will be a bare GET, the second request will be a 4865 // GET with an Authorization header. 4866 scoped_ptr<spdy::SpdyFrame> req_get( 4867 ConstructSpdyGet(NULL, 0, false, 1, LOWEST)); 4868 const char* const kExtraAuthorizationHeaders[] = { 4869 "authorization", 4870 "Basic Zm9vOmJhcg==", 4871 }; 4872 scoped_ptr<spdy::SpdyFrame> req_get_authorization( 4873 ConstructSpdyGet( 4874 kExtraAuthorizationHeaders, 4875 arraysize(kExtraAuthorizationHeaders) / 2, 4876 false, 3, LOWEST)); 4877 MockWrite spdy_writes[] = { 4878 CreateMockWrite(*req_get, 1), 4879 CreateMockWrite(*req_get_authorization, 4), 4880 }; 4881 4882 // The first response is a 401 authentication challenge, and the second 4883 // response will be a 200 response since the second request includes a valid 4884 // Authorization header. 4885 const char* const kExtraAuthenticationHeaders[] = { 4886 "WWW-Authenticate", 4887 "Basic realm=\"MyRealm\"" 4888 }; 4889 scoped_ptr<spdy::SpdyFrame> resp_authentication( 4890 ConstructSpdySynReplyError( 4891 "401 Authentication Required", 4892 kExtraAuthenticationHeaders, 4893 arraysize(kExtraAuthenticationHeaders) / 2, 4894 1)); 4895 scoped_ptr<spdy::SpdyFrame> body_authentication( 4896 ConstructSpdyBodyFrame(1, true)); 4897 scoped_ptr<spdy::SpdyFrame> resp_data(ConstructSpdyGetSynReply(NULL, 0, 3)); 4898 scoped_ptr<spdy::SpdyFrame> body_data(ConstructSpdyBodyFrame(3, true)); 4899 MockRead spdy_reads[] = { 4900 CreateMockRead(*resp_authentication, 2), 4901 CreateMockRead(*body_authentication, 3), 4902 CreateMockRead(*resp_data, 5), 4903 CreateMockRead(*body_data, 6), 4904 MockRead(true, 0, 7), 4905 }; 4906 4907 scoped_refptr<OrderedSocketData> data( 4908 new OrderedSocketData(spdy_reads, arraysize(spdy_reads), 4909 spdy_writes, arraysize(spdy_writes))); 4910 HttpRequestInfo request(CreateGetRequest()); 4911 BoundNetLog net_log; 4912 NormalSpdyTransactionHelper helper(request, net_log, GetParam()); 4913 4914 helper.RunPreTestSetup(); 4915 helper.AddData(data.get()); 4916 HttpNetworkTransaction* trans = helper.trans(); 4917 TestCompletionCallback callback_start; 4918 const int rv_start = trans->Start(&request, &callback_start, net_log); 4919 EXPECT_EQ(ERR_IO_PENDING, rv_start); 4920 const int rv_start_complete = callback_start.WaitForResult(); 4921 EXPECT_EQ(OK, rv_start_complete); 4922 4923 // Make sure the response has an auth challenge. 4924 const HttpResponseInfo* const response_start = trans->GetResponseInfo(); 4925 ASSERT_TRUE(response_start != NULL); 4926 ASSERT_TRUE(response_start->headers != NULL); 4927 EXPECT_EQ(401, response_start->headers->response_code()); 4928 EXPECT_TRUE(response_start->was_fetched_via_spdy); 4929 ASSERT_TRUE(response_start->auth_challenge.get() != NULL); 4930 EXPECT_FALSE(response_start->auth_challenge->is_proxy); 4931 EXPECT_EQ(L"basic", response_start->auth_challenge->scheme); 4932 EXPECT_EQ(L"MyRealm", response_start->auth_challenge->realm); 4933 4934 // Restart with a username/password. 4935 const string16 kFoo(ASCIIToUTF16("foo")); 4936 const string16 kBar(ASCIIToUTF16("bar")); 4937 TestCompletionCallback callback_restart; 4938 const int rv_restart = trans->RestartWithAuth(kFoo, kBar, &callback_restart); 4939 EXPECT_EQ(ERR_IO_PENDING, rv_restart); 4940 const int rv_restart_complete = callback_restart.WaitForResult(); 4941 EXPECT_EQ(OK, rv_restart_complete); 4942 // TODO(cbentzel): This is actually the same response object as before, but 4943 // data has changed. 4944 const HttpResponseInfo* const response_restart = trans->GetResponseInfo(); 4945 ASSERT_TRUE(response_restart != NULL); 4946 ASSERT_TRUE(response_restart->headers != NULL); 4947 EXPECT_EQ(200, response_restart->headers->response_code()); 4948 EXPECT_TRUE(response_restart->auth_challenge.get() == NULL); 4949 } 4950 4951 TEST_P(SpdyNetworkTransactionTest, ServerPushWithHeaders) { 4952 static const unsigned char kPushBodyFrame[] = { 4953 0x00, 0x00, 0x00, 0x02, // header, ID 4954 0x01, 0x00, 0x00, 0x06, // FIN, length 4955 'p', 'u', 's', 'h', 'e', 'd' // "pushed" 4956 }; 4957 scoped_ptr<spdy::SpdyFrame> 4958 stream1_syn(ConstructSpdyGet(NULL, 0, false, 1, LOWEST)); 4959 scoped_ptr<spdy::SpdyFrame> 4960 stream1_body(ConstructSpdyBodyFrame(1, true)); 4961 MockWrite writes[] = { 4962 CreateMockWrite(*stream1_syn, 1), 4963 }; 4964 4965 static const char* const kInitialHeaders[] = { 4966 "url", 4967 "http://www.google.com/foo.dat", 4968 }; 4969 static const char* const kLateHeaders[] = { 4970 "hello", 4971 "bye", 4972 "status", 4973 "200", 4974 "version", 4975 "HTTP/1.1" 4976 }; 4977 scoped_ptr<spdy::SpdyFrame> 4978 stream2_syn(ConstructSpdyControlFrame(kInitialHeaders, 4979 arraysize(kInitialHeaders) / 2, 4980 false, 4981 2, 4982 LOWEST, 4983 spdy::SYN_STREAM, 4984 spdy::CONTROL_FLAG_NONE, 4985 NULL, 4986 0, 4987 1)); 4988 scoped_ptr<spdy::SpdyFrame> 4989 stream2_headers(ConstructSpdyControlFrame(kLateHeaders, 4990 arraysize(kLateHeaders) / 2, 4991 false, 4992 2, 4993 LOWEST, 4994 spdy::HEADERS, 4995 spdy::CONTROL_FLAG_NONE, 4996 NULL, 4997 0, 4998 0)); 4999 5000 scoped_ptr<spdy::SpdyFrame> 5001 stream1_reply(ConstructSpdyGetSynReply(NULL, 0, 1)); 5002 MockRead reads[] = { 5003 CreateMockRead(*stream1_reply, 2), 5004 CreateMockRead(*stream2_syn, 3), 5005 CreateMockRead(*stream2_headers, 4), 5006 CreateMockRead(*stream1_body, 5, false), 5007 MockRead(true, reinterpret_cast<const char*>(kPushBodyFrame), 5008 arraysize(kPushBodyFrame), 6), 5009 MockRead(true, ERR_IO_PENDING, 7), // Force a pause 5010 }; 5011 5012 HttpResponseInfo response; 5013 HttpResponseInfo response2; 5014 std::string expected_push_result("pushed"); 5015 scoped_refptr<OrderedSocketData> data(new OrderedSocketData( 5016 reads, 5017 arraysize(reads), 5018 writes, 5019 arraysize(writes))); 5020 RunServerPushTest(data.get(), 5021 &response, 5022 &response2, 5023 expected_push_result); 5024 5025 // Verify the SYN_REPLY. 5026 EXPECT_TRUE(response.headers != NULL); 5027 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine()); 5028 5029 // Verify the pushed stream. 5030 EXPECT_TRUE(response2.headers != NULL); 5031 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine()); 5032 } 5033 5034 TEST_P(SpdyNetworkTransactionTest, ServerPushClaimBeforeHeaders) { 5035 // We push a stream and attempt to claim it before the headers come down. 5036 static const unsigned char kPushBodyFrame[] = { 5037 0x00, 0x00, 0x00, 0x02, // header, ID 5038 0x01, 0x00, 0x00, 0x06, // FIN, length 5039 'p', 'u', 's', 'h', 'e', 'd' // "pushed" 5040 }; 5041 scoped_ptr<spdy::SpdyFrame> 5042 stream1_syn(ConstructSpdyGet(NULL, 0, false, 1, LOWEST)); 5043 scoped_ptr<spdy::SpdyFrame> 5044 stream1_body(ConstructSpdyBodyFrame(1, true)); 5045 MockWrite writes[] = { 5046 CreateMockWrite(*stream1_syn, 0, false), 5047 }; 5048 5049 static const char* const kInitialHeaders[] = { 5050 "url", 5051 "http://www.google.com/foo.dat", 5052 }; 5053 static const char* const kLateHeaders[] = { 5054 "hello", 5055 "bye", 5056 "status", 5057 "200", 5058 "version", 5059 "HTTP/1.1" 5060 }; 5061 scoped_ptr<spdy::SpdyFrame> 5062 stream2_syn(ConstructSpdyControlFrame(kInitialHeaders, 5063 arraysize(kInitialHeaders) / 2, 5064 false, 5065 2, 5066 LOWEST, 5067 spdy::SYN_STREAM, 5068 spdy::CONTROL_FLAG_NONE, 5069 NULL, 5070 0, 5071 1)); 5072 scoped_ptr<spdy::SpdyFrame> 5073 stream2_headers(ConstructSpdyControlFrame(kLateHeaders, 5074 arraysize(kLateHeaders) / 2, 5075 false, 5076 2, 5077 LOWEST, 5078 spdy::HEADERS, 5079 spdy::CONTROL_FLAG_NONE, 5080 NULL, 5081 0, 5082 0)); 5083 5084 scoped_ptr<spdy::SpdyFrame> 5085 stream1_reply(ConstructSpdyGetSynReply(NULL, 0, 1)); 5086 MockRead reads[] = { 5087 CreateMockRead(*stream1_reply, 1), 5088 CreateMockRead(*stream2_syn, 2), 5089 CreateMockRead(*stream1_body, 3), 5090 CreateMockRead(*stream2_headers, 4), 5091 MockRead(true, reinterpret_cast<const char*>(kPushBodyFrame), 5092 arraysize(kPushBodyFrame), 5), 5093 MockRead(true, 0, 5), // EOF 5094 }; 5095 5096 HttpResponseInfo response; 5097 HttpResponseInfo response2; 5098 std::string expected_push_result("pushed"); 5099 scoped_refptr<DeterministicSocketData> data(new DeterministicSocketData( 5100 reads, 5101 arraysize(reads), 5102 writes, 5103 arraysize(writes))); 5104 5105 NormalSpdyTransactionHelper helper(CreateGetRequest(), 5106 BoundNetLog(), GetParam()); 5107 helper.SetDeterministic(); 5108 helper.AddDeterministicData(static_cast<DeterministicSocketData*>(data)); 5109 helper.RunPreTestSetup(); 5110 5111 HttpNetworkTransaction* trans = helper.trans(); 5112 5113 // Run until we've received the primary SYN_STREAM, the pushed SYN_STREAM, 5114 // and the body of the primary stream, but before we've received the HEADERS 5115 // for the pushed stream. 5116 data->SetStop(3); 5117 5118 // Start the transaction. 5119 TestCompletionCallback callback; 5120 int rv = trans->Start(&CreateGetRequest(), &callback, BoundNetLog()); 5121 EXPECT_EQ(ERR_IO_PENDING, rv); 5122 data->Run(); 5123 rv = callback.WaitForResult(); 5124 EXPECT_EQ(0, rv); 5125 5126 // Request the pushed path. At this point, we've received the push, but the 5127 // headers are not yet complete. 5128 scoped_ptr<HttpNetworkTransaction> trans2( 5129 new HttpNetworkTransaction(helper.session())); 5130 rv = trans2->Start(&CreateGetPushRequest(), &callback, BoundNetLog()); 5131 EXPECT_EQ(ERR_IO_PENDING, rv); 5132 data->RunFor(3); 5133 MessageLoop::current()->RunAllPending(); 5134 5135 // Read the server push body. 5136 std::string result2; 5137 ReadResult(trans2.get(), data.get(), &result2); 5138 // Read the response body. 5139 std::string result; 5140 ReadResult(trans, data, &result); 5141 5142 // Verify that we consumed all test data. 5143 EXPECT_TRUE(data->at_read_eof()); 5144 EXPECT_TRUE(data->at_write_eof()); 5145 5146 // Verify that the received push data is same as the expected push data. 5147 EXPECT_EQ(result2.compare(expected_push_result), 0) 5148 << "Received data: " 5149 << result2 5150 << "||||| Expected data: " 5151 << expected_push_result; 5152 5153 // Verify the SYN_REPLY. 5154 // Copy the response info, because trans goes away. 5155 response = *trans->GetResponseInfo(); 5156 response2 = *trans2->GetResponseInfo(); 5157 5158 VerifyStreamsClosed(helper); 5159 5160 // Verify the SYN_REPLY. 5161 EXPECT_TRUE(response.headers != NULL); 5162 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine()); 5163 5164 // Verify the pushed stream. 5165 EXPECT_TRUE(response2.headers != NULL); 5166 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine()); 5167 } 5168 5169 TEST_P(SpdyNetworkTransactionTest, ServerPushWithTwoHeaderFrames) { 5170 // We push a stream and attempt to claim it before the headers come down. 5171 static const unsigned char kPushBodyFrame[] = { 5172 0x00, 0x00, 0x00, 0x02, // header, ID 5173 0x01, 0x00, 0x00, 0x06, // FIN, length 5174 'p', 'u', 's', 'h', 'e', 'd' // "pushed" 5175 }; 5176 scoped_ptr<spdy::SpdyFrame> 5177 stream1_syn(ConstructSpdyGet(NULL, 0, false, 1, LOWEST)); 5178 scoped_ptr<spdy::SpdyFrame> 5179 stream1_body(ConstructSpdyBodyFrame(1, true)); 5180 MockWrite writes[] = { 5181 CreateMockWrite(*stream1_syn, 0, false), 5182 }; 5183 5184 static const char* const kInitialHeaders[] = { 5185 "url", 5186 "http://www.google.com/foo.dat", 5187 }; 5188 static const char* const kMiddleHeaders[] = { 5189 "hello", 5190 "bye", 5191 }; 5192 static const char* const kLateHeaders[] = { 5193 "status", 5194 "200", 5195 "version", 5196 "HTTP/1.1" 5197 }; 5198 scoped_ptr<spdy::SpdyFrame> 5199 stream2_syn(ConstructSpdyControlFrame(kInitialHeaders, 5200 arraysize(kInitialHeaders) / 2, 5201 false, 5202 2, 5203 LOWEST, 5204 spdy::SYN_STREAM, 5205 spdy::CONTROL_FLAG_NONE, 5206 NULL, 5207 0, 5208 1)); 5209 scoped_ptr<spdy::SpdyFrame> 5210 stream2_headers1(ConstructSpdyControlFrame(kMiddleHeaders, 5211 arraysize(kMiddleHeaders) / 2, 5212 false, 5213 2, 5214 LOWEST, 5215 spdy::HEADERS, 5216 spdy::CONTROL_FLAG_NONE, 5217 NULL, 5218 0, 5219 0)); 5220 scoped_ptr<spdy::SpdyFrame> 5221 stream2_headers2(ConstructSpdyControlFrame(kLateHeaders, 5222 arraysize(kLateHeaders) / 2, 5223 false, 5224 2, 5225 LOWEST, 5226 spdy::HEADERS, 5227 spdy::CONTROL_FLAG_NONE, 5228 NULL, 5229 0, 5230 0)); 5231 5232 scoped_ptr<spdy::SpdyFrame> 5233 stream1_reply(ConstructSpdyGetSynReply(NULL, 0, 1)); 5234 MockRead reads[] = { 5235 CreateMockRead(*stream1_reply, 1), 5236 CreateMockRead(*stream2_syn, 2), 5237 CreateMockRead(*stream1_body, 3), 5238 CreateMockRead(*stream2_headers1, 4), 5239 CreateMockRead(*stream2_headers2, 5), 5240 MockRead(true, reinterpret_cast<const char*>(kPushBodyFrame), 5241 arraysize(kPushBodyFrame), 6), 5242 MockRead(true, 0, 6), // EOF 5243 }; 5244 5245 HttpResponseInfo response; 5246 HttpResponseInfo response2; 5247 std::string expected_push_result("pushed"); 5248 scoped_refptr<DeterministicSocketData> data(new DeterministicSocketData( 5249 reads, 5250 arraysize(reads), 5251 writes, 5252 arraysize(writes))); 5253 5254 NormalSpdyTransactionHelper helper(CreateGetRequest(), 5255 BoundNetLog(), GetParam()); 5256 helper.SetDeterministic(); 5257 helper.AddDeterministicData(static_cast<DeterministicSocketData*>(data)); 5258 helper.RunPreTestSetup(); 5259 5260 HttpNetworkTransaction* trans = helper.trans(); 5261 5262 // Run until we've received the primary SYN_STREAM, the pushed SYN_STREAM, 5263 // the first HEADERS frame, and the body of the primary stream, but before 5264 // we've received the final HEADERS for the pushed stream. 5265 data->SetStop(4); 5266 5267 // Start the transaction. 5268 TestCompletionCallback callback; 5269 int rv = trans->Start(&CreateGetRequest(), &callback, BoundNetLog()); 5270 EXPECT_EQ(ERR_IO_PENDING, rv); 5271 data->Run(); 5272 rv = callback.WaitForResult(); 5273 EXPECT_EQ(0, rv); 5274 5275 // Request the pushed path. At this point, we've received the push, but the 5276 // headers are not yet complete. 5277 scoped_ptr<HttpNetworkTransaction> trans2( 5278 new HttpNetworkTransaction(helper.session())); 5279 rv = trans2->Start(&CreateGetPushRequest(), &callback, BoundNetLog()); 5280 EXPECT_EQ(ERR_IO_PENDING, rv); 5281 data->RunFor(3); 5282 MessageLoop::current()->RunAllPending(); 5283 5284 // Read the server push body. 5285 std::string result2; 5286 ReadResult(trans2.get(), data, &result2); 5287 // Read the response body. 5288 std::string result; 5289 ReadResult(trans, data, &result); 5290 5291 // Verify that we consumed all test data. 5292 EXPECT_TRUE(data->at_read_eof()); 5293 EXPECT_TRUE(data->at_write_eof()); 5294 5295 // Verify that the received push data is same as the expected push data. 5296 EXPECT_EQ(result2.compare(expected_push_result), 0) 5297 << "Received data: " 5298 << result2 5299 << "||||| Expected data: " 5300 << expected_push_result; 5301 5302 // Verify the SYN_REPLY. 5303 // Copy the response info, because trans goes away. 5304 response = *trans->GetResponseInfo(); 5305 response2 = *trans2->GetResponseInfo(); 5306 5307 VerifyStreamsClosed(helper); 5308 5309 // Verify the SYN_REPLY. 5310 EXPECT_TRUE(response.headers != NULL); 5311 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine()); 5312 5313 // Verify the pushed stream. 5314 EXPECT_TRUE(response2.headers != NULL); 5315 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine()); 5316 5317 // Verify we got all the headers 5318 EXPECT_TRUE(response2.headers->HasHeaderValue( 5319 "url", 5320 "http://www.google.com/foo.dat")); 5321 EXPECT_TRUE(response2.headers->HasHeaderValue("hello", "bye")); 5322 EXPECT_TRUE(response2.headers->HasHeaderValue("status", "200")); 5323 EXPECT_TRUE(response2.headers->HasHeaderValue("version", "HTTP/1.1")); 5324 } 5325 5326 TEST_P(SpdyNetworkTransactionTest, SynReplyWithHeaders) { 5327 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST)); 5328 MockWrite writes[] = { CreateMockWrite(*req) }; 5329 5330 static const char* const kInitialHeaders[] = { 5331 "status", 5332 "200 OK", 5333 "version", 5334 "HTTP/1.1" 5335 }; 5336 static const char* const kLateHeaders[] = { 5337 "hello", 5338 "bye", 5339 }; 5340 scoped_ptr<spdy::SpdyFrame> 5341 stream1_reply(ConstructSpdyControlFrame(kInitialHeaders, 5342 arraysize(kInitialHeaders) / 2, 5343 false, 5344 1, 5345 LOWEST, 5346 spdy::SYN_REPLY, 5347 spdy::CONTROL_FLAG_NONE, 5348 NULL, 5349 0, 5350 0)); 5351 scoped_ptr<spdy::SpdyFrame> 5352 stream1_headers(ConstructSpdyControlFrame(kLateHeaders, 5353 arraysize(kLateHeaders) / 2, 5354 false, 5355 1, 5356 LOWEST, 5357 spdy::HEADERS, 5358 spdy::CONTROL_FLAG_NONE, 5359 NULL, 5360 0, 5361 0)); 5362 scoped_ptr<spdy::SpdyFrame> stream1_body(ConstructSpdyBodyFrame(1, true)); 5363 MockRead reads[] = { 5364 CreateMockRead(*stream1_reply), 5365 CreateMockRead(*stream1_headers), 5366 CreateMockRead(*stream1_body), 5367 MockRead(true, 0, 0) // EOF 5368 }; 5369 5370 scoped_refptr<DelayedSocketData> data( 5371 new DelayedSocketData(1, reads, arraysize(reads), 5372 writes, arraysize(writes))); 5373 NormalSpdyTransactionHelper helper(CreateGetRequest(), 5374 BoundNetLog(), GetParam()); 5375 helper.RunToCompletion(data.get()); 5376 TransactionHelperResult out = helper.output(); 5377 EXPECT_EQ(OK, out.rv); 5378 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line); 5379 EXPECT_EQ("hello!", out.response_data); 5380 } 5381 5382 TEST_P(SpdyNetworkTransactionTest, SynReplyWithLateHeaders) { 5383 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST)); 5384 MockWrite writes[] = { CreateMockWrite(*req) }; 5385 5386 static const char* const kInitialHeaders[] = { 5387 "status", 5388 "200 OK", 5389 "version", 5390 "HTTP/1.1" 5391 }; 5392 static const char* const kLateHeaders[] = { 5393 "hello", 5394 "bye", 5395 }; 5396 scoped_ptr<spdy::SpdyFrame> 5397 stream1_reply(ConstructSpdyControlFrame(kInitialHeaders, 5398 arraysize(kInitialHeaders) / 2, 5399 false, 5400 1, 5401 LOWEST, 5402 spdy::SYN_REPLY, 5403 spdy::CONTROL_FLAG_NONE, 5404 NULL, 5405 0, 5406 0)); 5407 scoped_ptr<spdy::SpdyFrame> 5408 stream1_headers(ConstructSpdyControlFrame(kLateHeaders, 5409 arraysize(kLateHeaders) / 2, 5410 false, 5411 1, 5412 LOWEST, 5413 spdy::HEADERS, 5414 spdy::CONTROL_FLAG_NONE, 5415 NULL, 5416 0, 5417 0)); 5418 scoped_ptr<spdy::SpdyFrame> stream1_body(ConstructSpdyBodyFrame(1, false)); 5419 scoped_ptr<spdy::SpdyFrame> stream1_body2(ConstructSpdyBodyFrame(1, true)); 5420 MockRead reads[] = { 5421 CreateMockRead(*stream1_reply), 5422 CreateMockRead(*stream1_body), 5423 CreateMockRead(*stream1_headers), 5424 CreateMockRead(*stream1_body2), 5425 MockRead(true, 0, 0) // EOF 5426 }; 5427 5428 scoped_refptr<DelayedSocketData> data( 5429 new DelayedSocketData(1, reads, arraysize(reads), 5430 writes, arraysize(writes))); 5431 NormalSpdyTransactionHelper helper(CreateGetRequest(), 5432 BoundNetLog(), GetParam()); 5433 helper.RunToCompletion(data.get()); 5434 TransactionHelperResult out = helper.output(); 5435 EXPECT_EQ(OK, out.rv); 5436 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line); 5437 EXPECT_EQ("hello!hello!", out.response_data); 5438 } 5439 5440 TEST_P(SpdyNetworkTransactionTest, SynReplyWithDuplicateLateHeaders) { 5441 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST)); 5442 MockWrite writes[] = { CreateMockWrite(*req) }; 5443 5444 static const char* const kInitialHeaders[] = { 5445 "status", 5446 "200 OK", 5447 "version", 5448 "HTTP/1.1" 5449 }; 5450 static const char* const kLateHeaders[] = { 5451 "status", 5452 "500 Server Error", 5453 }; 5454 scoped_ptr<spdy::SpdyFrame> 5455 stream1_reply(ConstructSpdyControlFrame(kInitialHeaders, 5456 arraysize(kInitialHeaders) / 2, 5457 false, 5458 1, 5459 LOWEST, 5460 spdy::SYN_REPLY, 5461 spdy::CONTROL_FLAG_NONE, 5462 NULL, 5463 0, 5464 0)); 5465 scoped_ptr<spdy::SpdyFrame> 5466 stream1_headers(ConstructSpdyControlFrame(kLateHeaders, 5467 arraysize(kLateHeaders) / 2, 5468 false, 5469 1, 5470 LOWEST, 5471 spdy::HEADERS, 5472 spdy::CONTROL_FLAG_NONE, 5473 NULL, 5474 0, 5475 0)); 5476 scoped_ptr<spdy::SpdyFrame> stream1_body(ConstructSpdyBodyFrame(1, false)); 5477 scoped_ptr<spdy::SpdyFrame> stream1_body2(ConstructSpdyBodyFrame(1, true)); 5478 MockRead reads[] = { 5479 CreateMockRead(*stream1_reply), 5480 CreateMockRead(*stream1_body), 5481 CreateMockRead(*stream1_headers), 5482 CreateMockRead(*stream1_body2), 5483 MockRead(true, 0, 0) // EOF 5484 }; 5485 5486 scoped_refptr<DelayedSocketData> data( 5487 new DelayedSocketData(1, reads, arraysize(reads), 5488 writes, arraysize(writes))); 5489 NormalSpdyTransactionHelper helper(CreateGetRequest(), 5490 BoundNetLog(), GetParam()); 5491 helper.RunToCompletion(data.get()); 5492 TransactionHelperResult out = helper.output(); 5493 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv); 5494 } 5495 5496 TEST_P(SpdyNetworkTransactionTest, ServerPushCrossOriginCorrectness) { 5497 // In this test we want to verify that we can't accidentally push content 5498 // which can't be pushed by this content server. 5499 // This test assumes that: 5500 // - if we're requesting http://www.foo.com/barbaz 5501 // - the browser has made a connection to "www.foo.com". 5502 5503 // A list of the URL to fetch, followed by the URL being pushed. 5504 static const char* const kTestCases[] = { 5505 "http://www.google.com/foo.html", 5506 "http://www.google.com:81/foo.js", // Bad port 5507 5508 "http://www.google.com/foo.html", 5509 "https://www.google.com/foo.js", // Bad protocol 5510 5511 "http://www.google.com/foo.html", 5512 "ftp://www.google.com/foo.js", // Invalid Protocol 5513 5514 "http://www.google.com/foo.html", 5515 "http://blat.www.google.com/foo.js", // Cross subdomain 5516 5517 "http://www.google.com/foo.html", 5518 "http://www.foo.com/foo.js", // Cross domain 5519 }; 5520 5521 5522 static const unsigned char kPushBodyFrame[] = { 5523 0x00, 0x00, 0x00, 0x02, // header, ID 5524 0x01, 0x00, 0x00, 0x06, // FIN, length 5525 'p', 'u', 's', 'h', 'e', 'd' // "pushed" 5526 }; 5527 5528 for (size_t index = 0; index < arraysize(kTestCases); index += 2) { 5529 const char* url_to_fetch = kTestCases[index]; 5530 const char* url_to_push = kTestCases[index + 1]; 5531 5532 scoped_ptr<spdy::SpdyFrame> 5533 stream1_syn(ConstructSpdyGet(url_to_fetch, false, 1, LOWEST)); 5534 scoped_ptr<spdy::SpdyFrame> 5535 stream1_body(ConstructSpdyBodyFrame(1, true)); 5536 scoped_ptr<spdy::SpdyFrame> push_rst( 5537 ConstructSpdyRstStream(2, spdy::REFUSED_STREAM)); 5538 MockWrite writes[] = { 5539 CreateMockWrite(*stream1_syn, 1), 5540 CreateMockWrite(*push_rst, 4), 5541 }; 5542 5543 scoped_ptr<spdy::SpdyFrame> 5544 stream1_reply(ConstructSpdyGetSynReply(NULL, 0, 1)); 5545 scoped_ptr<spdy::SpdyFrame> 5546 stream2_syn(ConstructSpdyPush(NULL, 5547 0, 5548 2, 5549 1, 5550 url_to_push)); 5551 scoped_ptr<spdy::SpdyFrame> rst( 5552 ConstructSpdyRstStream(2, spdy::CANCEL)); 5553 5554 MockRead reads[] = { 5555 CreateMockRead(*stream1_reply, 2), 5556 CreateMockRead(*stream2_syn, 3), 5557 CreateMockRead(*stream1_body, 5, false), 5558 MockRead(true, reinterpret_cast<const char*>(kPushBodyFrame), 5559 arraysize(kPushBodyFrame), 6), 5560 MockRead(true, ERR_IO_PENDING, 7), // Force a pause 5561 }; 5562 5563 HttpResponseInfo response; 5564 scoped_refptr<OrderedSocketData> data(new OrderedSocketData( 5565 reads, 5566 arraysize(reads), 5567 writes, 5568 arraysize(writes))); 5569 5570 HttpRequestInfo request; 5571 request.method = "GET"; 5572 request.url = GURL(url_to_fetch); 5573 request.load_flags = 0; 5574 NormalSpdyTransactionHelper helper(request, 5575 BoundNetLog(), GetParam()); 5576 helper.RunPreTestSetup(); 5577 helper.AddData(data); 5578 5579 HttpNetworkTransaction* trans = helper.trans(); 5580 5581 // Start the transaction with basic parameters. 5582 TestCompletionCallback callback; 5583 5584 int rv = trans->Start(&request, &callback, BoundNetLog()); 5585 EXPECT_EQ(ERR_IO_PENDING, rv); 5586 rv = callback.WaitForResult(); 5587 5588 // Read the response body. 5589 std::string result; 5590 ReadResult(trans, data, &result); 5591 5592 // Verify that we consumed all test data. 5593 EXPECT_TRUE(data->at_read_eof()); 5594 EXPECT_TRUE(data->at_write_eof()); 5595 5596 // Verify the SYN_REPLY. 5597 // Copy the response info, because trans goes away. 5598 response = *trans->GetResponseInfo(); 5599 5600 VerifyStreamsClosed(helper); 5601 5602 // Verify the SYN_REPLY. 5603 EXPECT_TRUE(response.headers != NULL); 5604 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine()); 5605 } 5606 } 5607 5608 } // namespace net 5609