1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include <string> 6 #include <vector> 7 8 #include "base/bind.h" 9 #include "base/bind_helpers.h" 10 #include "base/file_util.h" 11 #include "base/files/scoped_temp_dir.h" 12 #include "base/memory/scoped_vector.h" 13 #include "base/run_loop.h" 14 #include "base/stl_util.h" 15 #include "base/test/test_file_util.h" 16 #include "net/base/auth.h" 17 #include "net/base/net_log_unittest.h" 18 #include "net/base/request_priority.h" 19 #include "net/base/upload_bytes_element_reader.h" 20 #include "net/base/upload_data_stream.h" 21 #include "net/base/upload_file_element_reader.h" 22 #include "net/http/http_network_session_peer.h" 23 #include "net/http/http_network_transaction.h" 24 #include "net/http/http_server_properties.h" 25 #include "net/http/http_transaction_unittest.h" 26 #include "net/socket/client_socket_pool_base.h" 27 #include "net/socket/next_proto.h" 28 #include "net/spdy/buffered_spdy_framer.h" 29 #include "net/spdy/spdy_http_stream.h" 30 #include "net/spdy/spdy_http_utils.h" 31 #include "net/spdy/spdy_session.h" 32 #include "net/spdy/spdy_session_pool.h" 33 #include "net/spdy/spdy_test_util_common.h" 34 #include "net/spdy/spdy_test_utils.h" 35 #include "net/url_request/url_request_test_util.h" 36 #include "testing/platform_test.h" 37 38 //----------------------------------------------------------------------------- 39 40 namespace net { 41 42 namespace { 43 const char kRequestUrl[] = "http://www.google.com/"; 44 45 enum SpdyNetworkTransactionTestSSLType { 46 SPDYNPN, 47 SPDYNOSSL, 48 SPDYSSL, 49 }; 50 51 struct SpdyNetworkTransactionTestParams { 52 SpdyNetworkTransactionTestParams() 53 : protocol(kProtoSPDY3), 54 ssl_type(SPDYNPN) {} 55 56 SpdyNetworkTransactionTestParams( 57 NextProto protocol, 58 SpdyNetworkTransactionTestSSLType ssl_type) 59 : protocol(protocol), 60 ssl_type(ssl_type) {} 61 62 NextProto protocol; 63 SpdyNetworkTransactionTestSSLType ssl_type; 64 }; 65 66 SpdySessionDependencies* CreateSpdySessionDependencies( 67 SpdyNetworkTransactionTestParams test_params) { 68 return new SpdySessionDependencies(test_params.protocol); 69 } 70 71 SpdySessionDependencies* CreateSpdySessionDependencies( 72 SpdyNetworkTransactionTestParams test_params, 73 ProxyService* proxy_service) { 74 return new SpdySessionDependencies(test_params.protocol, proxy_service); 75 } 76 77 } // namespace 78 79 class SpdyNetworkTransactionTest 80 : public ::testing::TestWithParam<SpdyNetworkTransactionTestParams> { 81 protected: 82 SpdyNetworkTransactionTest() : spdy_util_(GetParam().protocol) { 83 } 84 85 virtual ~SpdyNetworkTransactionTest() { 86 // UploadDataStream posts deletion tasks back to the message loop on 87 // destruction. 88 upload_data_stream_.reset(); 89 base::RunLoop().RunUntilIdle(); 90 } 91 92 virtual void SetUp() { 93 google_get_request_initialized_ = false; 94 google_post_request_initialized_ = false; 95 google_chunked_post_request_initialized_ = false; 96 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); 97 } 98 99 struct TransactionHelperResult { 100 int rv; 101 std::string status_line; 102 std::string response_data; 103 HttpResponseInfo response_info; 104 }; 105 106 // A helper class that handles all the initial npn/ssl setup. 107 class NormalSpdyTransactionHelper { 108 public: 109 NormalSpdyTransactionHelper(const HttpRequestInfo& request, 110 RequestPriority priority, 111 const BoundNetLog& log, 112 SpdyNetworkTransactionTestParams test_params, 113 SpdySessionDependencies* session_deps) 114 : request_(request), 115 priority_(priority), 116 session_deps_(session_deps == NULL ? 117 CreateSpdySessionDependencies(test_params) : 118 session_deps), 119 session_(SpdySessionDependencies::SpdyCreateSession( 120 session_deps_.get())), 121 log_(log), 122 test_params_(test_params), 123 deterministic_(false), 124 spdy_enabled_(true) { 125 switch (test_params_.ssl_type) { 126 case SPDYNOSSL: 127 case SPDYSSL: 128 port_ = 80; 129 break; 130 case SPDYNPN: 131 port_ = 443; 132 break; 133 default: 134 NOTREACHED(); 135 } 136 } 137 138 ~NormalSpdyTransactionHelper() { 139 // Any test which doesn't close the socket by sending it an EOF will 140 // have a valid session left open, which leaks the entire session pool. 141 // This is just fine - in fact, some of our tests intentionally do this 142 // so that we can check consistency of the SpdySessionPool as the test 143 // finishes. If we had put an EOF on the socket, the SpdySession would 144 // have closed and we wouldn't be able to check the consistency. 145 146 // Forcefully close existing sessions here. 147 session()->spdy_session_pool()->CloseAllSessions(); 148 } 149 150 void SetDeterministic() { 151 session_ = SpdySessionDependencies::SpdyCreateSessionDeterministic( 152 session_deps_.get()); 153 deterministic_ = true; 154 } 155 156 void SetSpdyDisabled() { 157 spdy_enabled_ = false; 158 port_ = 80; 159 } 160 161 void RunPreTestSetup() { 162 if (!session_deps_.get()) 163 session_deps_.reset(CreateSpdySessionDependencies(test_params_)); 164 if (!session_.get()) 165 session_ = SpdySessionDependencies::SpdyCreateSession( 166 session_deps_.get()); 167 HttpStreamFactory::set_use_alternate_protocols(false); 168 HttpStreamFactory::set_force_spdy_over_ssl(false); 169 HttpStreamFactory::set_force_spdy_always(false); 170 171 std::vector<NextProto> next_protos = SpdyNextProtos(); 172 173 switch (test_params_.ssl_type) { 174 case SPDYNPN: 175 session_->http_server_properties()->SetAlternateProtocol( 176 HostPortPair("www.google.com", 80), 443, 177 AlternateProtocolFromNextProto(test_params_.protocol)); 178 HttpStreamFactory::set_use_alternate_protocols(true); 179 HttpStreamFactory::SetNextProtos(next_protos); 180 break; 181 case SPDYNOSSL: 182 HttpStreamFactory::set_force_spdy_over_ssl(false); 183 HttpStreamFactory::set_force_spdy_always(true); 184 break; 185 case SPDYSSL: 186 HttpStreamFactory::set_force_spdy_over_ssl(true); 187 HttpStreamFactory::set_force_spdy_always(true); 188 break; 189 default: 190 NOTREACHED(); 191 } 192 193 // We're now ready to use SSL-npn SPDY. 194 trans_.reset(new HttpNetworkTransaction(priority_, session_.get())); 195 } 196 197 // Start the transaction, read some data, finish. 198 void RunDefaultTest() { 199 if (!StartDefaultTest()) 200 return; 201 FinishDefaultTest(); 202 } 203 204 bool StartDefaultTest() { 205 output_.rv = trans_->Start(&request_, callback.callback(), log_); 206 207 // We expect an IO Pending or some sort of error. 208 EXPECT_LT(output_.rv, 0); 209 return output_.rv == ERR_IO_PENDING; 210 } 211 212 void FinishDefaultTest() { 213 output_.rv = callback.WaitForResult(); 214 if (output_.rv != OK) { 215 session_->spdy_session_pool()->CloseCurrentSessions(net::ERR_ABORTED); 216 return; 217 } 218 219 // Verify responses. 220 const HttpResponseInfo* response = trans_->GetResponseInfo(); 221 ASSERT_TRUE(response != NULL); 222 ASSERT_TRUE(response->headers.get() != NULL); 223 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); 224 EXPECT_EQ(spdy_enabled_, response->was_fetched_via_spdy); 225 if (HttpStreamFactory::spdy_enabled()) { 226 EXPECT_EQ( 227 HttpResponseInfo::ConnectionInfoFromNextProto( 228 test_params_.protocol), 229 response->connection_info); 230 } else { 231 EXPECT_EQ(HttpResponseInfo::CONNECTION_INFO_HTTP1, 232 response->connection_info); 233 } 234 if (test_params_.ssl_type == SPDYNPN && spdy_enabled_) { 235 EXPECT_TRUE(response->was_npn_negotiated); 236 } else { 237 EXPECT_TRUE(!response->was_npn_negotiated); 238 } 239 // If SPDY is not enabled, a HTTP request should not be diverted 240 // over a SSL session. 241 if (!spdy_enabled_) { 242 EXPECT_EQ(request_.url.SchemeIs("https"), 243 response->was_npn_negotiated); 244 } 245 EXPECT_EQ("127.0.0.1", response->socket_address.host()); 246 EXPECT_EQ(port_, response->socket_address.port()); 247 output_.status_line = response->headers->GetStatusLine(); 248 output_.response_info = *response; // Make a copy so we can verify. 249 output_.rv = ReadTransaction(trans_.get(), &output_.response_data); 250 } 251 252 // Most tests will want to call this function. In particular, the MockReads 253 // should end with an empty read, and that read needs to be processed to 254 // ensure proper deletion of the spdy_session_pool. 255 void VerifyDataConsumed() { 256 for (DataVector::iterator it = data_vector_.begin(); 257 it != data_vector_.end(); ++it) { 258 EXPECT_TRUE((*it)->at_read_eof()) << "Read count: " 259 << (*it)->read_count() 260 << " Read index: " 261 << (*it)->read_index(); 262 EXPECT_TRUE((*it)->at_write_eof()) << "Write count: " 263 << (*it)->write_count() 264 << " Write index: " 265 << (*it)->write_index(); 266 } 267 } 268 269 // Occasionally a test will expect to error out before certain reads are 270 // processed. In that case we want to explicitly ensure that the reads were 271 // not processed. 272 void VerifyDataNotConsumed() { 273 for (DataVector::iterator it = data_vector_.begin(); 274 it != data_vector_.end(); ++it) { 275 EXPECT_TRUE(!(*it)->at_read_eof()) << "Read count: " 276 << (*it)->read_count() 277 << " Read index: " 278 << (*it)->read_index(); 279 EXPECT_TRUE(!(*it)->at_write_eof()) << "Write count: " 280 << (*it)->write_count() 281 << " Write index: " 282 << (*it)->write_index(); 283 } 284 } 285 286 void RunToCompletion(StaticSocketDataProvider* data) { 287 RunPreTestSetup(); 288 AddData(data); 289 RunDefaultTest(); 290 VerifyDataConsumed(); 291 } 292 293 void AddData(StaticSocketDataProvider* data) { 294 DCHECK(!deterministic_); 295 data_vector_.push_back(data); 296 SSLSocketDataProvider* ssl_provider = 297 new SSLSocketDataProvider(ASYNC, OK); 298 if (test_params_.ssl_type == SPDYNPN) 299 ssl_provider->SetNextProto(test_params_.protocol); 300 301 ssl_vector_.push_back(ssl_provider); 302 if (test_params_.ssl_type == SPDYNPN || test_params_.ssl_type == SPDYSSL) 303 session_deps_->socket_factory->AddSSLSocketDataProvider(ssl_provider); 304 305 session_deps_->socket_factory->AddSocketDataProvider(data); 306 if (test_params_.ssl_type == SPDYNPN) { 307 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING); 308 StaticSocketDataProvider* hanging_non_alternate_protocol_socket = 309 new StaticSocketDataProvider(NULL, 0, NULL, 0); 310 hanging_non_alternate_protocol_socket->set_connect_data( 311 never_finishing_connect); 312 session_deps_->socket_factory->AddSocketDataProvider( 313 hanging_non_alternate_protocol_socket); 314 alternate_vector_.push_back(hanging_non_alternate_protocol_socket); 315 } 316 } 317 318 void AddDeterministicData(DeterministicSocketData* data) { 319 DCHECK(deterministic_); 320 data_vector_.push_back(data); 321 SSLSocketDataProvider* ssl_provider = 322 new SSLSocketDataProvider(ASYNC, OK); 323 if (test_params_.ssl_type == SPDYNPN) 324 ssl_provider->SetNextProto(test_params_.protocol); 325 326 ssl_vector_.push_back(ssl_provider); 327 if (test_params_.ssl_type == SPDYNPN || 328 test_params_.ssl_type == SPDYSSL) { 329 session_deps_->deterministic_socket_factory-> 330 AddSSLSocketDataProvider(ssl_provider); 331 } 332 session_deps_->deterministic_socket_factory->AddSocketDataProvider(data); 333 if (test_params_.ssl_type == SPDYNPN) { 334 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING); 335 DeterministicSocketData* hanging_non_alternate_protocol_socket = 336 new DeterministicSocketData(NULL, 0, NULL, 0); 337 hanging_non_alternate_protocol_socket->set_connect_data( 338 never_finishing_connect); 339 session_deps_->deterministic_socket_factory->AddSocketDataProvider( 340 hanging_non_alternate_protocol_socket); 341 alternate_deterministic_vector_.push_back( 342 hanging_non_alternate_protocol_socket); 343 } 344 } 345 346 void SetSession(const scoped_refptr<HttpNetworkSession>& session) { 347 session_ = session; 348 } 349 HttpNetworkTransaction* trans() { return trans_.get(); } 350 void ResetTrans() { trans_.reset(); } 351 TransactionHelperResult& output() { return output_; } 352 const HttpRequestInfo& request() const { return request_; } 353 const scoped_refptr<HttpNetworkSession>& session() const { 354 return session_; 355 } 356 scoped_ptr<SpdySessionDependencies>& session_deps() { 357 return session_deps_; 358 } 359 int port() const { return port_; } 360 SpdyNetworkTransactionTestParams test_params() const { 361 return test_params_; 362 } 363 364 private: 365 typedef std::vector<StaticSocketDataProvider*> DataVector; 366 typedef ScopedVector<SSLSocketDataProvider> SSLVector; 367 typedef ScopedVector<StaticSocketDataProvider> AlternateVector; 368 typedef ScopedVector<DeterministicSocketData> AlternateDeterministicVector; 369 HttpRequestInfo request_; 370 RequestPriority priority_; 371 scoped_ptr<SpdySessionDependencies> session_deps_; 372 scoped_refptr<HttpNetworkSession> session_; 373 TransactionHelperResult output_; 374 scoped_ptr<StaticSocketDataProvider> first_transaction_; 375 SSLVector ssl_vector_; 376 TestCompletionCallback callback; 377 scoped_ptr<HttpNetworkTransaction> trans_; 378 scoped_ptr<HttpNetworkTransaction> trans_http_; 379 DataVector data_vector_; 380 AlternateVector alternate_vector_; 381 AlternateDeterministicVector alternate_deterministic_vector_; 382 const BoundNetLog& log_; 383 SpdyNetworkTransactionTestParams test_params_; 384 int port_; 385 bool deterministic_; 386 bool spdy_enabled_; 387 }; 388 389 void ConnectStatusHelperWithExpectedStatus(const MockRead& status, 390 int expected_status); 391 392 void ConnectStatusHelper(const MockRead& status); 393 394 const HttpRequestInfo& CreateGetPushRequest() { 395 google_get_push_request_.method = "GET"; 396 google_get_push_request_.url = GURL("http://www.google.com/foo.dat"); 397 google_get_push_request_.load_flags = 0; 398 return google_get_push_request_; 399 } 400 401 const HttpRequestInfo& CreateGetRequest() { 402 if (!google_get_request_initialized_) { 403 google_get_request_.method = "GET"; 404 google_get_request_.url = GURL(kDefaultURL); 405 google_get_request_.load_flags = 0; 406 google_get_request_initialized_ = true; 407 } 408 return google_get_request_; 409 } 410 411 const HttpRequestInfo& CreateGetRequestWithUserAgent() { 412 if (!google_get_request_initialized_) { 413 google_get_request_.method = "GET"; 414 google_get_request_.url = GURL(kDefaultURL); 415 google_get_request_.load_flags = 0; 416 google_get_request_.extra_headers.SetHeader("User-Agent", "Chrome"); 417 google_get_request_initialized_ = true; 418 } 419 return google_get_request_; 420 } 421 422 const HttpRequestInfo& CreatePostRequest() { 423 if (!google_post_request_initialized_) { 424 ScopedVector<UploadElementReader> element_readers; 425 element_readers.push_back( 426 new UploadBytesElementReader(kUploadData, kUploadDataSize)); 427 upload_data_stream_.reset( 428 new UploadDataStream(element_readers.Pass(), 0)); 429 430 google_post_request_.method = "POST"; 431 google_post_request_.url = GURL(kDefaultURL); 432 google_post_request_.upload_data_stream = upload_data_stream_.get(); 433 google_post_request_initialized_ = true; 434 } 435 return google_post_request_; 436 } 437 438 const HttpRequestInfo& CreateFilePostRequest() { 439 if (!google_post_request_initialized_) { 440 base::FilePath file_path; 441 CHECK(base::CreateTemporaryFileInDir(temp_dir_.path(), &file_path)); 442 CHECK_EQ(static_cast<int>(kUploadDataSize), 443 file_util::WriteFile(file_path, kUploadData, kUploadDataSize)); 444 445 ScopedVector<UploadElementReader> element_readers; 446 element_readers.push_back( 447 new UploadFileElementReader(base::MessageLoopProxy::current().get(), 448 file_path, 449 0, 450 kUploadDataSize, 451 base::Time())); 452 upload_data_stream_.reset( 453 new UploadDataStream(element_readers.Pass(), 0)); 454 455 google_post_request_.method = "POST"; 456 google_post_request_.url = GURL(kDefaultURL); 457 google_post_request_.upload_data_stream = upload_data_stream_.get(); 458 google_post_request_initialized_ = true; 459 } 460 return google_post_request_; 461 } 462 463 const HttpRequestInfo& CreateUnreadableFilePostRequest() { 464 if (google_post_request_initialized_) 465 return google_post_request_; 466 467 base::FilePath file_path; 468 CHECK(base::CreateTemporaryFileInDir(temp_dir_.path(), &file_path)); 469 CHECK_EQ(static_cast<int>(kUploadDataSize), 470 file_util::WriteFile(file_path, kUploadData, kUploadDataSize)); 471 CHECK(file_util::MakeFileUnreadable(file_path)); 472 473 ScopedVector<UploadElementReader> element_readers; 474 element_readers.push_back( 475 new UploadFileElementReader(base::MessageLoopProxy::current().get(), 476 file_path, 477 0, 478 kUploadDataSize, 479 base::Time())); 480 upload_data_stream_.reset( 481 new UploadDataStream(element_readers.Pass(), 0)); 482 483 google_post_request_.method = "POST"; 484 google_post_request_.url = GURL(kDefaultURL); 485 google_post_request_.upload_data_stream = upload_data_stream_.get(); 486 google_post_request_initialized_ = true; 487 return google_post_request_; 488 } 489 490 const HttpRequestInfo& CreateComplexPostRequest() { 491 if (!google_post_request_initialized_) { 492 const int kFileRangeOffset = 1; 493 const int kFileRangeLength = 3; 494 CHECK_LT(kFileRangeOffset + kFileRangeLength, kUploadDataSize); 495 496 base::FilePath file_path; 497 CHECK(base::CreateTemporaryFileInDir(temp_dir_.path(), &file_path)); 498 CHECK_EQ(static_cast<int>(kUploadDataSize), 499 file_util::WriteFile(file_path, kUploadData, kUploadDataSize)); 500 501 ScopedVector<UploadElementReader> element_readers; 502 element_readers.push_back( 503 new UploadBytesElementReader(kUploadData, kFileRangeOffset)); 504 element_readers.push_back( 505 new UploadFileElementReader(base::MessageLoopProxy::current().get(), 506 file_path, 507 kFileRangeOffset, 508 kFileRangeLength, 509 base::Time())); 510 element_readers.push_back(new UploadBytesElementReader( 511 kUploadData + kFileRangeOffset + kFileRangeLength, 512 kUploadDataSize - (kFileRangeOffset + kFileRangeLength))); 513 upload_data_stream_.reset( 514 new UploadDataStream(element_readers.Pass(), 0)); 515 516 google_post_request_.method = "POST"; 517 google_post_request_.url = GURL(kDefaultURL); 518 google_post_request_.upload_data_stream = upload_data_stream_.get(); 519 google_post_request_initialized_ = true; 520 } 521 return google_post_request_; 522 } 523 524 const HttpRequestInfo& CreateChunkedPostRequest() { 525 if (!google_chunked_post_request_initialized_) { 526 upload_data_stream_.reset( 527 new UploadDataStream(UploadDataStream::CHUNKED, 0)); 528 google_chunked_post_request_.method = "POST"; 529 google_chunked_post_request_.url = GURL(kDefaultURL); 530 google_chunked_post_request_.upload_data_stream = 531 upload_data_stream_.get(); 532 google_chunked_post_request_initialized_ = true; 533 } 534 return google_chunked_post_request_; 535 } 536 537 // Read the result of a particular transaction, knowing that we've got 538 // multiple transactions in the read pipeline; so as we read, we may have 539 // to skip over data destined for other transactions while we consume 540 // the data for |trans|. 541 int ReadResult(HttpNetworkTransaction* trans, 542 StaticSocketDataProvider* data, 543 std::string* result) { 544 const int kSize = 3000; 545 546 int bytes_read = 0; 547 scoped_refptr<net::IOBufferWithSize> buf(new net::IOBufferWithSize(kSize)); 548 TestCompletionCallback callback; 549 while (true) { 550 int rv = trans->Read(buf.get(), kSize, callback.callback()); 551 if (rv == ERR_IO_PENDING) { 552 // Multiple transactions may be in the data set. Keep pulling off 553 // reads until we complete our callback. 554 while (!callback.have_result()) { 555 data->CompleteRead(); 556 base::RunLoop().RunUntilIdle(); 557 } 558 rv = callback.WaitForResult(); 559 } else if (rv <= 0) { 560 break; 561 } 562 result->append(buf->data(), rv); 563 bytes_read += rv; 564 } 565 return bytes_read; 566 } 567 568 void VerifyStreamsClosed(const NormalSpdyTransactionHelper& helper) { 569 // This lengthy block is reaching into the pool to dig out the active 570 // session. Once we have the session, we verify that the streams are 571 // all closed and not leaked at this point. 572 const GURL& url = helper.request().url; 573 int port = helper.test_params().ssl_type == SPDYNPN ? 443 : 80; 574 HostPortPair host_port_pair(url.host(), port); 575 SpdySessionKey key(host_port_pair, ProxyServer::Direct(), 576 kPrivacyModeDisabled); 577 BoundNetLog log; 578 const scoped_refptr<HttpNetworkSession>& session = helper.session(); 579 base::WeakPtr<SpdySession> spdy_session = 580 session->spdy_session_pool()->FindAvailableSession(key, log); 581 ASSERT_TRUE(spdy_session != NULL); 582 EXPECT_EQ(0u, spdy_session->num_active_streams()); 583 EXPECT_EQ(0u, spdy_session->num_unclaimed_pushed_streams()); 584 } 585 586 void RunServerPushTest(OrderedSocketData* data, 587 HttpResponseInfo* response, 588 HttpResponseInfo* push_response, 589 const std::string& expected) { 590 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY, 591 BoundNetLog(), GetParam(), NULL); 592 helper.RunPreTestSetup(); 593 helper.AddData(data); 594 595 HttpNetworkTransaction* trans = helper.trans(); 596 597 // Start the transaction with basic parameters. 598 TestCompletionCallback callback; 599 int rv = trans->Start( 600 &CreateGetRequest(), callback.callback(), BoundNetLog()); 601 EXPECT_EQ(ERR_IO_PENDING, rv); 602 rv = callback.WaitForResult(); 603 604 // Request the pushed path. 605 scoped_ptr<HttpNetworkTransaction> trans2( 606 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get())); 607 rv = trans2->Start( 608 &CreateGetPushRequest(), callback.callback(), BoundNetLog()); 609 EXPECT_EQ(ERR_IO_PENDING, rv); 610 base::RunLoop().RunUntilIdle(); 611 612 // The data for the pushed path may be coming in more than 1 frame. Compile 613 // the results into a single string. 614 615 // Read the server push body. 616 std::string result2; 617 ReadResult(trans2.get(), data, &result2); 618 // Read the response body. 619 std::string result; 620 ReadResult(trans, data, &result); 621 622 // Verify that we consumed all test data. 623 EXPECT_TRUE(data->at_read_eof()); 624 EXPECT_TRUE(data->at_write_eof()); 625 626 // Verify that the received push data is same as the expected push data. 627 EXPECT_EQ(result2.compare(expected), 0) << "Received data: " 628 << result2 629 << "||||| Expected data: " 630 << expected; 631 632 // Verify the SYN_REPLY. 633 // Copy the response info, because trans goes away. 634 *response = *trans->GetResponseInfo(); 635 *push_response = *trans2->GetResponseInfo(); 636 637 VerifyStreamsClosed(helper); 638 } 639 640 static void DeleteSessionCallback(NormalSpdyTransactionHelper* helper, 641 int result) { 642 helper->ResetTrans(); 643 } 644 645 static void StartTransactionCallback( 646 const scoped_refptr<HttpNetworkSession>& session, 647 int result) { 648 scoped_ptr<HttpNetworkTransaction> trans( 649 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 650 TestCompletionCallback callback; 651 HttpRequestInfo request; 652 request.method = "GET"; 653 request.url = GURL("http://www.google.com/"); 654 request.load_flags = 0; 655 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 656 EXPECT_EQ(ERR_IO_PENDING, rv); 657 callback.WaitForResult(); 658 } 659 660 SpdyTestUtil spdy_util_; 661 662 private: 663 scoped_ptr<UploadDataStream> upload_data_stream_; 664 bool google_get_request_initialized_; 665 bool google_post_request_initialized_; 666 bool google_chunked_post_request_initialized_; 667 HttpRequestInfo google_get_request_; 668 HttpRequestInfo google_post_request_; 669 HttpRequestInfo google_chunked_post_request_; 670 HttpRequestInfo google_get_push_request_; 671 base::ScopedTempDir temp_dir_; 672 }; 673 674 //----------------------------------------------------------------------------- 675 // All tests are run with three different connection types: SPDY after NPN 676 // negotiation, SPDY without SSL, and SPDY with SSL. 677 // 678 // TODO(akalin): Use ::testing::Combine() when we are able to use 679 // <tr1/tuple>. 680 INSTANTIATE_TEST_CASE_P( 681 Spdy, 682 SpdyNetworkTransactionTest, 683 ::testing::Values( 684 SpdyNetworkTransactionTestParams(kProtoDeprecatedSPDY2, SPDYNOSSL), 685 SpdyNetworkTransactionTestParams(kProtoDeprecatedSPDY2, SPDYSSL), 686 SpdyNetworkTransactionTestParams(kProtoDeprecatedSPDY2, SPDYNPN), 687 SpdyNetworkTransactionTestParams(kProtoSPDY3, SPDYNOSSL), 688 SpdyNetworkTransactionTestParams(kProtoSPDY3, SPDYSSL), 689 SpdyNetworkTransactionTestParams(kProtoSPDY3, SPDYNPN), 690 SpdyNetworkTransactionTestParams(kProtoSPDY31, SPDYNOSSL), 691 SpdyNetworkTransactionTestParams(kProtoSPDY31, SPDYSSL), 692 SpdyNetworkTransactionTestParams(kProtoSPDY31, SPDYNPN), 693 SpdyNetworkTransactionTestParams(kProtoSPDY4a2, SPDYNOSSL), 694 SpdyNetworkTransactionTestParams(kProtoSPDY4a2, SPDYSSL), 695 SpdyNetworkTransactionTestParams(kProtoSPDY4a2, SPDYNPN), 696 SpdyNetworkTransactionTestParams(kProtoHTTP2Draft04, SPDYNOSSL), 697 SpdyNetworkTransactionTestParams(kProtoHTTP2Draft04, SPDYSSL), 698 SpdyNetworkTransactionTestParams(kProtoHTTP2Draft04, SPDYNPN))); 699 700 // Verify HttpNetworkTransaction constructor. 701 TEST_P(SpdyNetworkTransactionTest, Constructor) { 702 scoped_ptr<SpdySessionDependencies> session_deps( 703 CreateSpdySessionDependencies(GetParam())); 704 scoped_refptr<HttpNetworkSession> session( 705 SpdySessionDependencies::SpdyCreateSession(session_deps.get())); 706 scoped_ptr<HttpTransaction> trans( 707 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 708 } 709 710 TEST_P(SpdyNetworkTransactionTest, Get) { 711 // Construct the request. 712 scoped_ptr<SpdyFrame> req( 713 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); 714 MockWrite writes[] = { CreateMockWrite(*req) }; 715 716 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 717 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true)); 718 MockRead reads[] = { 719 CreateMockRead(*resp), 720 CreateMockRead(*body), 721 MockRead(ASYNC, 0, 0) // EOF 722 }; 723 724 DelayedSocketData data(1, reads, arraysize(reads), 725 writes, arraysize(writes)); 726 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY, 727 BoundNetLog(), GetParam(), NULL); 728 helper.RunToCompletion(&data); 729 TransactionHelperResult out = helper.output(); 730 EXPECT_EQ(OK, out.rv); 731 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line); 732 EXPECT_EQ("hello!", out.response_data); 733 } 734 735 TEST_P(SpdyNetworkTransactionTest, GetAtEachPriority) { 736 for (RequestPriority p = MINIMUM_PRIORITY; p <= MAXIMUM_PRIORITY; 737 p = RequestPriority(p + 1)) { 738 // Construct the request. 739 scoped_ptr<SpdyFrame> req( 740 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, p, true)); 741 MockWrite writes[] = { CreateMockWrite(*req) }; 742 743 SpdyPriority spdy_prio = 0; 744 EXPECT_TRUE(GetSpdyPriority(spdy_util_.spdy_version(), *req, &spdy_prio)); 745 // this repeats the RequestPriority-->SpdyPriority mapping from 746 // SpdyFramer::ConvertRequestPriorityToSpdyPriority to make 747 // sure it's being done right. 748 if (spdy_util_.spdy_version() < SPDY3) { 749 switch(p) { 750 case HIGHEST: 751 EXPECT_EQ(0, spdy_prio); 752 break; 753 case MEDIUM: 754 EXPECT_EQ(1, spdy_prio); 755 break; 756 case LOW: 757 case LOWEST: 758 EXPECT_EQ(2, spdy_prio); 759 break; 760 case IDLE: 761 EXPECT_EQ(3, spdy_prio); 762 break; 763 default: 764 FAIL(); 765 } 766 } else { 767 switch(p) { 768 case HIGHEST: 769 EXPECT_EQ(0, spdy_prio); 770 break; 771 case MEDIUM: 772 EXPECT_EQ(1, spdy_prio); 773 break; 774 case LOW: 775 EXPECT_EQ(2, spdy_prio); 776 break; 777 case LOWEST: 778 EXPECT_EQ(3, spdy_prio); 779 break; 780 case IDLE: 781 EXPECT_EQ(4, spdy_prio); 782 break; 783 default: 784 FAIL(); 785 } 786 } 787 788 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 789 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true)); 790 MockRead reads[] = { 791 CreateMockRead(*resp), 792 CreateMockRead(*body), 793 MockRead(ASYNC, 0, 0) // EOF 794 }; 795 796 DelayedSocketData data(1, reads, arraysize(reads), 797 writes, arraysize(writes)); 798 HttpRequestInfo http_req = CreateGetRequest(); 799 800 NormalSpdyTransactionHelper helper(http_req, p, BoundNetLog(), 801 GetParam(), NULL); 802 helper.RunToCompletion(&data); 803 TransactionHelperResult out = helper.output(); 804 EXPECT_EQ(OK, out.rv); 805 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line); 806 EXPECT_EQ("hello!", out.response_data); 807 } 808 } 809 810 // Start three gets simultaniously; making sure that multiplexed 811 // streams work properly. 812 813 // This can't use the TransactionHelper method, since it only 814 // handles a single transaction, and finishes them as soon 815 // as it launches them. 816 817 // TODO(gavinp): create a working generalized TransactionHelper that 818 // can allow multiple streams in flight. 819 820 TEST_P(SpdyNetworkTransactionTest, ThreeGets) { 821 scoped_ptr<SpdyFrame> req( 822 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); 823 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 824 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, false)); 825 scoped_ptr<SpdyFrame> fbody(spdy_util_.ConstructSpdyBodyFrame(1, true)); 826 827 scoped_ptr<SpdyFrame> req2( 828 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true)); 829 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3)); 830 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, false)); 831 scoped_ptr<SpdyFrame> fbody2(spdy_util_.ConstructSpdyBodyFrame(3, true)); 832 833 scoped_ptr<SpdyFrame> req3( 834 spdy_util_.ConstructSpdyGet(NULL, 0, false, 5, LOWEST, true)); 835 scoped_ptr<SpdyFrame> resp3(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 5)); 836 scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(5, false)); 837 scoped_ptr<SpdyFrame> fbody3(spdy_util_.ConstructSpdyBodyFrame(5, true)); 838 839 MockWrite writes[] = { 840 CreateMockWrite(*req), 841 CreateMockWrite(*req2), 842 CreateMockWrite(*req3), 843 }; 844 MockRead reads[] = { 845 CreateMockRead(*resp, 1), 846 CreateMockRead(*body), 847 CreateMockRead(*resp2, 4), 848 CreateMockRead(*body2), 849 CreateMockRead(*resp3, 7), 850 CreateMockRead(*body3), 851 852 CreateMockRead(*fbody), 853 CreateMockRead(*fbody2), 854 CreateMockRead(*fbody3), 855 856 MockRead(ASYNC, 0, 0), // EOF 857 }; 858 OrderedSocketData data(reads, arraysize(reads), 859 writes, arraysize(writes)); 860 OrderedSocketData data_placeholder(NULL, 0, NULL, 0); 861 862 BoundNetLog log; 863 TransactionHelperResult out; 864 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY, 865 BoundNetLog(), GetParam(), NULL); 866 helper.RunPreTestSetup(); 867 helper.AddData(&data); 868 // We require placeholder data because three get requests are sent out, so 869 // there needs to be three sets of SSL connection data. 870 helper.AddData(&data_placeholder); 871 helper.AddData(&data_placeholder); 872 scoped_ptr<HttpNetworkTransaction> trans1( 873 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get())); 874 scoped_ptr<HttpNetworkTransaction> trans2( 875 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get())); 876 scoped_ptr<HttpNetworkTransaction> trans3( 877 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get())); 878 879 TestCompletionCallback callback1; 880 TestCompletionCallback callback2; 881 TestCompletionCallback callback3; 882 883 HttpRequestInfo httpreq1 = CreateGetRequest(); 884 HttpRequestInfo httpreq2 = CreateGetRequest(); 885 HttpRequestInfo httpreq3 = CreateGetRequest(); 886 887 out.rv = trans1->Start(&httpreq1, callback1.callback(), log); 888 ASSERT_EQ(ERR_IO_PENDING, out.rv); 889 out.rv = trans2->Start(&httpreq2, callback2.callback(), log); 890 ASSERT_EQ(ERR_IO_PENDING, out.rv); 891 out.rv = trans3->Start(&httpreq3, callback3.callback(), log); 892 ASSERT_EQ(ERR_IO_PENDING, out.rv); 893 894 out.rv = callback1.WaitForResult(); 895 ASSERT_EQ(OK, out.rv); 896 out.rv = callback3.WaitForResult(); 897 ASSERT_EQ(OK, out.rv); 898 899 const HttpResponseInfo* response1 = trans1->GetResponseInfo(); 900 EXPECT_TRUE(response1->headers.get() != NULL); 901 EXPECT_TRUE(response1->was_fetched_via_spdy); 902 out.status_line = response1->headers->GetStatusLine(); 903 out.response_info = *response1; 904 905 trans2->GetResponseInfo(); 906 907 out.rv = ReadTransaction(trans1.get(), &out.response_data); 908 helper.VerifyDataConsumed(); 909 EXPECT_EQ(OK, out.rv); 910 911 EXPECT_EQ(OK, out.rv); 912 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line); 913 EXPECT_EQ("hello!hello!", out.response_data); 914 } 915 916 TEST_P(SpdyNetworkTransactionTest, TwoGetsLateBinding) { 917 scoped_ptr<SpdyFrame> req( 918 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); 919 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 920 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, false)); 921 scoped_ptr<SpdyFrame> fbody(spdy_util_.ConstructSpdyBodyFrame(1, true)); 922 923 scoped_ptr<SpdyFrame> req2( 924 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true)); 925 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3)); 926 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, false)); 927 scoped_ptr<SpdyFrame> fbody2(spdy_util_.ConstructSpdyBodyFrame(3, true)); 928 929 MockWrite writes[] = { 930 CreateMockWrite(*req), 931 CreateMockWrite(*req2), 932 }; 933 MockRead reads[] = { 934 CreateMockRead(*resp, 1), 935 CreateMockRead(*body), 936 CreateMockRead(*resp2, 4), 937 CreateMockRead(*body2), 938 CreateMockRead(*fbody), 939 CreateMockRead(*fbody2), 940 MockRead(ASYNC, 0, 0), // EOF 941 }; 942 OrderedSocketData data(reads, arraysize(reads), 943 writes, arraysize(writes)); 944 945 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING); 946 947 OrderedSocketData data_placeholder(NULL, 0, NULL, 0); 948 data_placeholder.set_connect_data(never_finishing_connect); 949 950 BoundNetLog log; 951 TransactionHelperResult out; 952 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY, 953 BoundNetLog(), GetParam(), NULL); 954 helper.RunPreTestSetup(); 955 helper.AddData(&data); 956 // We require placeholder data because two get requests are sent out, so 957 // there needs to be two sets of SSL connection data. 958 helper.AddData(&data_placeholder); 959 scoped_ptr<HttpNetworkTransaction> trans1( 960 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get())); 961 scoped_ptr<HttpNetworkTransaction> trans2( 962 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get())); 963 964 TestCompletionCallback callback1; 965 TestCompletionCallback callback2; 966 967 HttpRequestInfo httpreq1 = CreateGetRequest(); 968 HttpRequestInfo httpreq2 = CreateGetRequest(); 969 970 out.rv = trans1->Start(&httpreq1, callback1.callback(), log); 971 ASSERT_EQ(ERR_IO_PENDING, out.rv); 972 out.rv = trans2->Start(&httpreq2, callback2.callback(), log); 973 ASSERT_EQ(ERR_IO_PENDING, out.rv); 974 975 out.rv = callback1.WaitForResult(); 976 ASSERT_EQ(OK, out.rv); 977 out.rv = callback2.WaitForResult(); 978 ASSERT_EQ(OK, out.rv); 979 980 const HttpResponseInfo* response1 = trans1->GetResponseInfo(); 981 EXPECT_TRUE(response1->headers.get() != NULL); 982 EXPECT_TRUE(response1->was_fetched_via_spdy); 983 out.status_line = response1->headers->GetStatusLine(); 984 out.response_info = *response1; 985 out.rv = ReadTransaction(trans1.get(), &out.response_data); 986 EXPECT_EQ(OK, out.rv); 987 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line); 988 EXPECT_EQ("hello!hello!", out.response_data); 989 990 const HttpResponseInfo* response2 = trans2->GetResponseInfo(); 991 EXPECT_TRUE(response2->headers.get() != NULL); 992 EXPECT_TRUE(response2->was_fetched_via_spdy); 993 out.status_line = response2->headers->GetStatusLine(); 994 out.response_info = *response2; 995 out.rv = ReadTransaction(trans2.get(), &out.response_data); 996 EXPECT_EQ(OK, out.rv); 997 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line); 998 EXPECT_EQ("hello!hello!", out.response_data); 999 1000 helper.VerifyDataConsumed(); 1001 } 1002 1003 TEST_P(SpdyNetworkTransactionTest, TwoGetsLateBindingFromPreconnect) { 1004 scoped_ptr<SpdyFrame> req( 1005 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); 1006 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 1007 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, false)); 1008 scoped_ptr<SpdyFrame> fbody(spdy_util_.ConstructSpdyBodyFrame(1, true)); 1009 1010 scoped_ptr<SpdyFrame> req2( 1011 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true)); 1012 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3)); 1013 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, false)); 1014 scoped_ptr<SpdyFrame> fbody2(spdy_util_.ConstructSpdyBodyFrame(3, true)); 1015 1016 MockWrite writes[] = { 1017 CreateMockWrite(*req), 1018 CreateMockWrite(*req2), 1019 }; 1020 MockRead reads[] = { 1021 CreateMockRead(*resp, 1), 1022 CreateMockRead(*body), 1023 CreateMockRead(*resp2, 4), 1024 CreateMockRead(*body2), 1025 CreateMockRead(*fbody), 1026 CreateMockRead(*fbody2), 1027 MockRead(ASYNC, 0, 0), // EOF 1028 }; 1029 OrderedSocketData preconnect_data(reads, arraysize(reads), 1030 writes, arraysize(writes)); 1031 1032 MockConnect never_finishing_connect(ASYNC, ERR_IO_PENDING); 1033 1034 OrderedSocketData data_placeholder(NULL, 0, NULL, 0); 1035 data_placeholder.set_connect_data(never_finishing_connect); 1036 1037 BoundNetLog log; 1038 TransactionHelperResult out; 1039 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY, 1040 BoundNetLog(), GetParam(), NULL); 1041 helper.RunPreTestSetup(); 1042 helper.AddData(&preconnect_data); 1043 // We require placeholder data because 3 connections are attempted (first is 1044 // the preconnect, 2nd and 3rd are the never finished connections. 1045 helper.AddData(&data_placeholder); 1046 helper.AddData(&data_placeholder); 1047 1048 scoped_ptr<HttpNetworkTransaction> trans1( 1049 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get())); 1050 scoped_ptr<HttpNetworkTransaction> trans2( 1051 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get())); 1052 1053 TestCompletionCallback callback1; 1054 TestCompletionCallback callback2; 1055 1056 HttpRequestInfo httpreq = CreateGetRequest(); 1057 1058 // Preconnect the first. 1059 SSLConfig preconnect_ssl_config; 1060 helper.session()->ssl_config_service()->GetSSLConfig(&preconnect_ssl_config); 1061 HttpStreamFactory* http_stream_factory = 1062 helper.session()->http_stream_factory(); 1063 if (http_stream_factory->has_next_protos()) { 1064 preconnect_ssl_config.next_protos = http_stream_factory->next_protos(); 1065 } 1066 1067 http_stream_factory->PreconnectStreams( 1068 1, httpreq, DEFAULT_PRIORITY, 1069 preconnect_ssl_config, preconnect_ssl_config); 1070 1071 out.rv = trans1->Start(&httpreq, callback1.callback(), log); 1072 ASSERT_EQ(ERR_IO_PENDING, out.rv); 1073 out.rv = trans2->Start(&httpreq, callback2.callback(), log); 1074 ASSERT_EQ(ERR_IO_PENDING, out.rv); 1075 1076 out.rv = callback1.WaitForResult(); 1077 ASSERT_EQ(OK, out.rv); 1078 out.rv = callback2.WaitForResult(); 1079 ASSERT_EQ(OK, out.rv); 1080 1081 const HttpResponseInfo* response1 = trans1->GetResponseInfo(); 1082 EXPECT_TRUE(response1->headers.get() != NULL); 1083 EXPECT_TRUE(response1->was_fetched_via_spdy); 1084 out.status_line = response1->headers->GetStatusLine(); 1085 out.response_info = *response1; 1086 out.rv = ReadTransaction(trans1.get(), &out.response_data); 1087 EXPECT_EQ(OK, out.rv); 1088 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line); 1089 EXPECT_EQ("hello!hello!", out.response_data); 1090 1091 const HttpResponseInfo* response2 = trans2->GetResponseInfo(); 1092 EXPECT_TRUE(response2->headers.get() != NULL); 1093 EXPECT_TRUE(response2->was_fetched_via_spdy); 1094 out.status_line = response2->headers->GetStatusLine(); 1095 out.response_info = *response2; 1096 out.rv = ReadTransaction(trans2.get(), &out.response_data); 1097 EXPECT_EQ(OK, out.rv); 1098 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line); 1099 EXPECT_EQ("hello!hello!", out.response_data); 1100 1101 helper.VerifyDataConsumed(); 1102 } 1103 1104 // Similar to ThreeGets above, however this test adds a SETTINGS 1105 // frame. The SETTINGS frame is read during the IO loop waiting on 1106 // the first transaction completion, and sets a maximum concurrent 1107 // stream limit of 1. This means that our IO loop exists after the 1108 // second transaction completes, so we can assert on read_index(). 1109 TEST_P(SpdyNetworkTransactionTest, ThreeGetsWithMaxConcurrent) { 1110 // Construct the request. 1111 scoped_ptr<SpdyFrame> req( 1112 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); 1113 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 1114 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, false)); 1115 scoped_ptr<SpdyFrame> fbody(spdy_util_.ConstructSpdyBodyFrame(1, true)); 1116 1117 scoped_ptr<SpdyFrame> req2( 1118 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true)); 1119 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3)); 1120 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, false)); 1121 scoped_ptr<SpdyFrame> fbody2(spdy_util_.ConstructSpdyBodyFrame(3, true)); 1122 1123 scoped_ptr<SpdyFrame> req3( 1124 spdy_util_.ConstructSpdyGet(NULL, 0, false, 5, LOWEST, true)); 1125 scoped_ptr<SpdyFrame> resp3(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 5)); 1126 scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(5, false)); 1127 scoped_ptr<SpdyFrame> fbody3(spdy_util_.ConstructSpdyBodyFrame(5, true)); 1128 1129 SettingsMap settings; 1130 const uint32 max_concurrent_streams = 1; 1131 settings[SETTINGS_MAX_CONCURRENT_STREAMS] = 1132 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams); 1133 scoped_ptr<SpdyFrame> settings_frame( 1134 spdy_util_.ConstructSpdySettings(settings)); 1135 1136 MockWrite writes[] = { 1137 CreateMockWrite(*req), 1138 CreateMockWrite(*req2), 1139 CreateMockWrite(*req3), 1140 }; 1141 1142 MockRead reads[] = { 1143 CreateMockRead(*settings_frame, 1), 1144 CreateMockRead(*resp), 1145 CreateMockRead(*body), 1146 CreateMockRead(*fbody), 1147 CreateMockRead(*resp2, 7), 1148 CreateMockRead(*body2), 1149 CreateMockRead(*fbody2), 1150 CreateMockRead(*resp3, 12), 1151 CreateMockRead(*body3), 1152 CreateMockRead(*fbody3), 1153 1154 MockRead(ASYNC, 0, 0), // EOF 1155 }; 1156 1157 OrderedSocketData data(reads, arraysize(reads), 1158 writes, arraysize(writes)); 1159 OrderedSocketData data_placeholder(NULL, 0, NULL, 0); 1160 1161 BoundNetLog log; 1162 TransactionHelperResult out; 1163 { 1164 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY, 1165 BoundNetLog(), GetParam(), NULL); 1166 helper.RunPreTestSetup(); 1167 helper.AddData(&data); 1168 // We require placeholder data because three get requests are sent out, so 1169 // there needs to be three sets of SSL connection data. 1170 helper.AddData(&data_placeholder); 1171 helper.AddData(&data_placeholder); 1172 scoped_ptr<HttpNetworkTransaction> trans1( 1173 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get())); 1174 scoped_ptr<HttpNetworkTransaction> trans2( 1175 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get())); 1176 scoped_ptr<HttpNetworkTransaction> trans3( 1177 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get())); 1178 1179 TestCompletionCallback callback1; 1180 TestCompletionCallback callback2; 1181 TestCompletionCallback callback3; 1182 1183 HttpRequestInfo httpreq1 = CreateGetRequest(); 1184 HttpRequestInfo httpreq2 = CreateGetRequest(); 1185 HttpRequestInfo httpreq3 = CreateGetRequest(); 1186 1187 out.rv = trans1->Start(&httpreq1, callback1.callback(), log); 1188 ASSERT_EQ(out.rv, ERR_IO_PENDING); 1189 // Run transaction 1 through quickly to force a read of our SETTINGS 1190 // frame. 1191 out.rv = callback1.WaitForResult(); 1192 ASSERT_EQ(OK, out.rv); 1193 1194 out.rv = trans2->Start(&httpreq2, callback2.callback(), log); 1195 ASSERT_EQ(out.rv, ERR_IO_PENDING); 1196 out.rv = trans3->Start(&httpreq3, callback3.callback(), log); 1197 ASSERT_EQ(out.rv, ERR_IO_PENDING); 1198 out.rv = callback2.WaitForResult(); 1199 ASSERT_EQ(OK, out.rv); 1200 EXPECT_EQ(7U, data.read_index()); // i.e. the third trans was queued 1201 1202 out.rv = callback3.WaitForResult(); 1203 ASSERT_EQ(OK, out.rv); 1204 1205 const HttpResponseInfo* response1 = trans1->GetResponseInfo(); 1206 ASSERT_TRUE(response1 != NULL); 1207 EXPECT_TRUE(response1->headers.get() != NULL); 1208 EXPECT_TRUE(response1->was_fetched_via_spdy); 1209 out.status_line = response1->headers->GetStatusLine(); 1210 out.response_info = *response1; 1211 out.rv = ReadTransaction(trans1.get(), &out.response_data); 1212 EXPECT_EQ(OK, out.rv); 1213 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line); 1214 EXPECT_EQ("hello!hello!", out.response_data); 1215 1216 const HttpResponseInfo* response2 = trans2->GetResponseInfo(); 1217 out.status_line = response2->headers->GetStatusLine(); 1218 out.response_info = *response2; 1219 out.rv = ReadTransaction(trans2.get(), &out.response_data); 1220 EXPECT_EQ(OK, out.rv); 1221 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line); 1222 EXPECT_EQ("hello!hello!", out.response_data); 1223 1224 const HttpResponseInfo* response3 = trans3->GetResponseInfo(); 1225 out.status_line = response3->headers->GetStatusLine(); 1226 out.response_info = *response3; 1227 out.rv = ReadTransaction(trans3.get(), &out.response_data); 1228 EXPECT_EQ(OK, out.rv); 1229 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line); 1230 EXPECT_EQ("hello!hello!", out.response_data); 1231 1232 helper.VerifyDataConsumed(); 1233 } 1234 EXPECT_EQ(OK, out.rv); 1235 } 1236 1237 // Similar to ThreeGetsWithMaxConcurrent above, however this test adds 1238 // a fourth transaction. The third and fourth transactions have 1239 // different data ("hello!" vs "hello!hello!") and because of the 1240 // user specified priority, we expect to see them inverted in 1241 // the response from the server. 1242 TEST_P(SpdyNetworkTransactionTest, FourGetsWithMaxConcurrentPriority) { 1243 // Construct the request. 1244 scoped_ptr<SpdyFrame> req( 1245 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); 1246 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 1247 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, false)); 1248 scoped_ptr<SpdyFrame> fbody(spdy_util_.ConstructSpdyBodyFrame(1, true)); 1249 1250 scoped_ptr<SpdyFrame> req2( 1251 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true)); 1252 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3)); 1253 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, false)); 1254 scoped_ptr<SpdyFrame> fbody2(spdy_util_.ConstructSpdyBodyFrame(3, true)); 1255 1256 scoped_ptr<SpdyFrame> req4( 1257 spdy_util_.ConstructSpdyGet(NULL, 0, false, 5, HIGHEST, true)); 1258 scoped_ptr<SpdyFrame> resp4(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 5)); 1259 scoped_ptr<SpdyFrame> fbody4(spdy_util_.ConstructSpdyBodyFrame(5, true)); 1260 1261 scoped_ptr<SpdyFrame> req3( 1262 spdy_util_.ConstructSpdyGet(NULL, 0, false, 7, LOWEST, true)); 1263 scoped_ptr<SpdyFrame> resp3(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 7)); 1264 scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(7, false)); 1265 scoped_ptr<SpdyFrame> fbody3(spdy_util_.ConstructSpdyBodyFrame(7, true)); 1266 1267 SettingsMap settings; 1268 const uint32 max_concurrent_streams = 1; 1269 settings[SETTINGS_MAX_CONCURRENT_STREAMS] = 1270 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams); 1271 scoped_ptr<SpdyFrame> settings_frame( 1272 spdy_util_.ConstructSpdySettings(settings)); 1273 1274 MockWrite writes[] = { CreateMockWrite(*req), 1275 CreateMockWrite(*req2), 1276 CreateMockWrite(*req4), 1277 CreateMockWrite(*req3), 1278 }; 1279 MockRead reads[] = { 1280 CreateMockRead(*settings_frame, 1), 1281 CreateMockRead(*resp), 1282 CreateMockRead(*body), 1283 CreateMockRead(*fbody), 1284 CreateMockRead(*resp2, 7), 1285 CreateMockRead(*body2), 1286 CreateMockRead(*fbody2), 1287 CreateMockRead(*resp4, 13), 1288 CreateMockRead(*fbody4), 1289 CreateMockRead(*resp3, 16), 1290 CreateMockRead(*body3), 1291 CreateMockRead(*fbody3), 1292 1293 MockRead(ASYNC, 0, 0), // EOF 1294 }; 1295 1296 OrderedSocketData data(reads, arraysize(reads), 1297 writes, arraysize(writes)); 1298 OrderedSocketData data_placeholder(NULL, 0, NULL, 0); 1299 1300 BoundNetLog log; 1301 TransactionHelperResult out; 1302 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY, 1303 BoundNetLog(), GetParam(), NULL); 1304 helper.RunPreTestSetup(); 1305 helper.AddData(&data); 1306 // We require placeholder data because four get requests are sent out, so 1307 // there needs to be four sets of SSL connection data. 1308 helper.AddData(&data_placeholder); 1309 helper.AddData(&data_placeholder); 1310 helper.AddData(&data_placeholder); 1311 scoped_ptr<HttpNetworkTransaction> trans1( 1312 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get())); 1313 scoped_ptr<HttpNetworkTransaction> trans2( 1314 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get())); 1315 scoped_ptr<HttpNetworkTransaction> trans3( 1316 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get())); 1317 scoped_ptr<HttpNetworkTransaction> trans4( 1318 new HttpNetworkTransaction(HIGHEST, helper.session().get())); 1319 1320 TestCompletionCallback callback1; 1321 TestCompletionCallback callback2; 1322 TestCompletionCallback callback3; 1323 TestCompletionCallback callback4; 1324 1325 HttpRequestInfo httpreq1 = CreateGetRequest(); 1326 HttpRequestInfo httpreq2 = CreateGetRequest(); 1327 HttpRequestInfo httpreq3 = CreateGetRequest(); 1328 HttpRequestInfo httpreq4 = CreateGetRequest(); 1329 1330 out.rv = trans1->Start(&httpreq1, callback1.callback(), log); 1331 ASSERT_EQ(ERR_IO_PENDING, out.rv); 1332 // Run transaction 1 through quickly to force a read of our SETTINGS frame. 1333 out.rv = callback1.WaitForResult(); 1334 ASSERT_EQ(OK, out.rv); 1335 1336 out.rv = trans2->Start(&httpreq2, callback2.callback(), log); 1337 ASSERT_EQ(ERR_IO_PENDING, out.rv); 1338 out.rv = trans3->Start(&httpreq3, callback3.callback(), log); 1339 ASSERT_EQ(ERR_IO_PENDING, out.rv); 1340 out.rv = trans4->Start(&httpreq4, callback4.callback(), log); 1341 ASSERT_EQ(ERR_IO_PENDING, out.rv); 1342 1343 out.rv = callback2.WaitForResult(); 1344 ASSERT_EQ(OK, out.rv); 1345 EXPECT_EQ(data.read_index(), 7U); // i.e. the third & fourth trans queued 1346 1347 out.rv = callback3.WaitForResult(); 1348 ASSERT_EQ(OK, out.rv); 1349 1350 const HttpResponseInfo* response1 = trans1->GetResponseInfo(); 1351 EXPECT_TRUE(response1->headers.get() != NULL); 1352 EXPECT_TRUE(response1->was_fetched_via_spdy); 1353 out.status_line = response1->headers->GetStatusLine(); 1354 out.response_info = *response1; 1355 out.rv = ReadTransaction(trans1.get(), &out.response_data); 1356 EXPECT_EQ(OK, out.rv); 1357 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line); 1358 EXPECT_EQ("hello!hello!", out.response_data); 1359 1360 const HttpResponseInfo* response2 = trans2->GetResponseInfo(); 1361 out.status_line = response2->headers->GetStatusLine(); 1362 out.response_info = *response2; 1363 out.rv = ReadTransaction(trans2.get(), &out.response_data); 1364 EXPECT_EQ(OK, out.rv); 1365 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line); 1366 EXPECT_EQ("hello!hello!", out.response_data); 1367 1368 // notice: response3 gets two hellos, response4 gets one 1369 // hello, so we know dequeuing priority was respected. 1370 const HttpResponseInfo* response3 = trans3->GetResponseInfo(); 1371 out.status_line = response3->headers->GetStatusLine(); 1372 out.response_info = *response3; 1373 out.rv = ReadTransaction(trans3.get(), &out.response_data); 1374 EXPECT_EQ(OK, out.rv); 1375 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line); 1376 EXPECT_EQ("hello!hello!", out.response_data); 1377 1378 out.rv = callback4.WaitForResult(); 1379 EXPECT_EQ(OK, out.rv); 1380 const HttpResponseInfo* response4 = trans4->GetResponseInfo(); 1381 out.status_line = response4->headers->GetStatusLine(); 1382 out.response_info = *response4; 1383 out.rv = ReadTransaction(trans4.get(), &out.response_data); 1384 EXPECT_EQ(OK, out.rv); 1385 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line); 1386 EXPECT_EQ("hello!", out.response_data); 1387 helper.VerifyDataConsumed(); 1388 EXPECT_EQ(OK, out.rv); 1389 } 1390 1391 // Similar to ThreeGetsMaxConcurrrent above, however, this test 1392 // deletes a session in the middle of the transaction to insure 1393 // that we properly remove pendingcreatestream objects from 1394 // the spdy_session 1395 TEST_P(SpdyNetworkTransactionTest, ThreeGetsWithMaxConcurrentDelete) { 1396 // Construct the request. 1397 scoped_ptr<SpdyFrame> req( 1398 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); 1399 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 1400 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, false)); 1401 scoped_ptr<SpdyFrame> fbody(spdy_util_.ConstructSpdyBodyFrame(1, true)); 1402 1403 scoped_ptr<SpdyFrame> req2( 1404 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true)); 1405 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3)); 1406 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, false)); 1407 scoped_ptr<SpdyFrame> fbody2(spdy_util_.ConstructSpdyBodyFrame(3, true)); 1408 1409 SettingsMap settings; 1410 const uint32 max_concurrent_streams = 1; 1411 settings[SETTINGS_MAX_CONCURRENT_STREAMS] = 1412 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams); 1413 scoped_ptr<SpdyFrame> settings_frame( 1414 spdy_util_.ConstructSpdySettings(settings)); 1415 1416 MockWrite writes[] = { CreateMockWrite(*req), 1417 CreateMockWrite(*req2), 1418 }; 1419 MockRead reads[] = { 1420 CreateMockRead(*settings_frame, 1), 1421 CreateMockRead(*resp), 1422 CreateMockRead(*body), 1423 CreateMockRead(*fbody), 1424 CreateMockRead(*resp2, 7), 1425 CreateMockRead(*body2), 1426 CreateMockRead(*fbody2), 1427 MockRead(ASYNC, 0, 0), // EOF 1428 }; 1429 1430 OrderedSocketData data(reads, arraysize(reads), 1431 writes, arraysize(writes)); 1432 OrderedSocketData data_placeholder(NULL, 0, NULL, 0); 1433 1434 BoundNetLog log; 1435 TransactionHelperResult out; 1436 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY, 1437 BoundNetLog(), GetParam(), NULL); 1438 helper.RunPreTestSetup(); 1439 helper.AddData(&data); 1440 // We require placeholder data because three get requests are sent out, so 1441 // there needs to be three sets of SSL connection data. 1442 helper.AddData(&data_placeholder); 1443 helper.AddData(&data_placeholder); 1444 scoped_ptr<HttpNetworkTransaction> trans1( 1445 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get())); 1446 scoped_ptr<HttpNetworkTransaction> trans2( 1447 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get())); 1448 scoped_ptr<HttpNetworkTransaction> trans3( 1449 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get())); 1450 1451 TestCompletionCallback callback1; 1452 TestCompletionCallback callback2; 1453 TestCompletionCallback callback3; 1454 1455 HttpRequestInfo httpreq1 = CreateGetRequest(); 1456 HttpRequestInfo httpreq2 = CreateGetRequest(); 1457 HttpRequestInfo httpreq3 = CreateGetRequest(); 1458 1459 out.rv = trans1->Start(&httpreq1, callback1.callback(), log); 1460 ASSERT_EQ(out.rv, ERR_IO_PENDING); 1461 // Run transaction 1 through quickly to force a read of our SETTINGS frame. 1462 out.rv = callback1.WaitForResult(); 1463 ASSERT_EQ(OK, out.rv); 1464 1465 out.rv = trans2->Start(&httpreq2, callback2.callback(), log); 1466 ASSERT_EQ(out.rv, ERR_IO_PENDING); 1467 out.rv = trans3->Start(&httpreq3, callback3.callback(), log); 1468 delete trans3.release(); 1469 ASSERT_EQ(out.rv, ERR_IO_PENDING); 1470 out.rv = callback2.WaitForResult(); 1471 ASSERT_EQ(OK, out.rv); 1472 1473 EXPECT_EQ(8U, data.read_index()); 1474 1475 const HttpResponseInfo* response1 = trans1->GetResponseInfo(); 1476 ASSERT_TRUE(response1 != NULL); 1477 EXPECT_TRUE(response1->headers.get() != NULL); 1478 EXPECT_TRUE(response1->was_fetched_via_spdy); 1479 out.status_line = response1->headers->GetStatusLine(); 1480 out.response_info = *response1; 1481 out.rv = ReadTransaction(trans1.get(), &out.response_data); 1482 EXPECT_EQ(OK, out.rv); 1483 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line); 1484 EXPECT_EQ("hello!hello!", out.response_data); 1485 1486 const HttpResponseInfo* response2 = trans2->GetResponseInfo(); 1487 ASSERT_TRUE(response2 != NULL); 1488 out.status_line = response2->headers->GetStatusLine(); 1489 out.response_info = *response2; 1490 out.rv = ReadTransaction(trans2.get(), &out.response_data); 1491 EXPECT_EQ(OK, out.rv); 1492 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line); 1493 EXPECT_EQ("hello!hello!", out.response_data); 1494 helper.VerifyDataConsumed(); 1495 EXPECT_EQ(OK, out.rv); 1496 } 1497 1498 namespace { 1499 1500 // The KillerCallback will delete the transaction on error as part of the 1501 // callback. 1502 class KillerCallback : public TestCompletionCallbackBase { 1503 public: 1504 explicit KillerCallback(HttpNetworkTransaction* transaction) 1505 : transaction_(transaction), 1506 callback_(base::Bind(&KillerCallback::OnComplete, 1507 base::Unretained(this))) { 1508 } 1509 1510 virtual ~KillerCallback() {} 1511 1512 const CompletionCallback& callback() const { return callback_; } 1513 1514 private: 1515 void OnComplete(int result) { 1516 if (result < 0) 1517 delete transaction_; 1518 1519 SetResult(result); 1520 } 1521 1522 HttpNetworkTransaction* transaction_; 1523 CompletionCallback callback_; 1524 }; 1525 1526 } // namespace 1527 1528 // Similar to ThreeGetsMaxConcurrrentDelete above, however, this test 1529 // closes the socket while we have a pending transaction waiting for 1530 // a pending stream creation. http://crbug.com/52901 1531 TEST_P(SpdyNetworkTransactionTest, ThreeGetsWithMaxConcurrentSocketClose) { 1532 // Construct the request. 1533 scoped_ptr<SpdyFrame> req( 1534 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); 1535 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 1536 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, false)); 1537 scoped_ptr<SpdyFrame> fin_body(spdy_util_.ConstructSpdyBodyFrame(1, true)); 1538 1539 scoped_ptr<SpdyFrame> req2( 1540 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true)); 1541 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3)); 1542 1543 SettingsMap settings; 1544 const uint32 max_concurrent_streams = 1; 1545 settings[SETTINGS_MAX_CONCURRENT_STREAMS] = 1546 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams); 1547 scoped_ptr<SpdyFrame> settings_frame( 1548 spdy_util_.ConstructSpdySettings(settings)); 1549 1550 MockWrite writes[] = { CreateMockWrite(*req), 1551 CreateMockWrite(*req2), 1552 }; 1553 MockRead reads[] = { 1554 CreateMockRead(*settings_frame, 1), 1555 CreateMockRead(*resp), 1556 CreateMockRead(*body), 1557 CreateMockRead(*fin_body), 1558 CreateMockRead(*resp2, 7), 1559 MockRead(ASYNC, ERR_CONNECTION_RESET, 0), // Abort! 1560 }; 1561 1562 OrderedSocketData data(reads, arraysize(reads), 1563 writes, arraysize(writes)); 1564 OrderedSocketData data_placeholder(NULL, 0, NULL, 0); 1565 1566 BoundNetLog log; 1567 TransactionHelperResult out; 1568 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY, 1569 BoundNetLog(), GetParam(), NULL); 1570 helper.RunPreTestSetup(); 1571 helper.AddData(&data); 1572 // We require placeholder data because three get requests are sent out, so 1573 // there needs to be three sets of SSL connection data. 1574 helper.AddData(&data_placeholder); 1575 helper.AddData(&data_placeholder); 1576 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, helper.session().get()); 1577 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, helper.session().get()); 1578 HttpNetworkTransaction* trans3( 1579 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get())); 1580 1581 TestCompletionCallback callback1; 1582 TestCompletionCallback callback2; 1583 KillerCallback callback3(trans3); 1584 1585 HttpRequestInfo httpreq1 = CreateGetRequest(); 1586 HttpRequestInfo httpreq2 = CreateGetRequest(); 1587 HttpRequestInfo httpreq3 = CreateGetRequest(); 1588 1589 out.rv = trans1.Start(&httpreq1, callback1.callback(), log); 1590 ASSERT_EQ(out.rv, ERR_IO_PENDING); 1591 // Run transaction 1 through quickly to force a read of our SETTINGS frame. 1592 out.rv = callback1.WaitForResult(); 1593 ASSERT_EQ(OK, out.rv); 1594 1595 out.rv = trans2.Start(&httpreq2, callback2.callback(), log); 1596 ASSERT_EQ(out.rv, ERR_IO_PENDING); 1597 out.rv = trans3->Start(&httpreq3, callback3.callback(), log); 1598 ASSERT_EQ(out.rv, ERR_IO_PENDING); 1599 out.rv = callback3.WaitForResult(); 1600 ASSERT_EQ(ERR_ABORTED, out.rv); 1601 1602 EXPECT_EQ(6U, data.read_index()); 1603 1604 const HttpResponseInfo* response1 = trans1.GetResponseInfo(); 1605 ASSERT_TRUE(response1 != NULL); 1606 EXPECT_TRUE(response1->headers.get() != NULL); 1607 EXPECT_TRUE(response1->was_fetched_via_spdy); 1608 out.status_line = response1->headers->GetStatusLine(); 1609 out.response_info = *response1; 1610 out.rv = ReadTransaction(&trans1, &out.response_data); 1611 EXPECT_EQ(OK, out.rv); 1612 1613 const HttpResponseInfo* response2 = trans2.GetResponseInfo(); 1614 ASSERT_TRUE(response2 != NULL); 1615 out.status_line = response2->headers->GetStatusLine(); 1616 out.response_info = *response2; 1617 out.rv = ReadTransaction(&trans2, &out.response_data); 1618 EXPECT_EQ(ERR_CONNECTION_RESET, out.rv); 1619 1620 helper.VerifyDataConsumed(); 1621 } 1622 1623 // Test that a simple PUT request works. 1624 TEST_P(SpdyNetworkTransactionTest, Put) { 1625 // Setup the request 1626 HttpRequestInfo request; 1627 request.method = "PUT"; 1628 request.url = GURL("http://www.google.com/"); 1629 1630 const SpdyHeaderInfo kSynStartHeader = { 1631 SYN_STREAM, // Kind = Syn 1632 1, // Stream ID 1633 0, // Associated stream ID 1634 ConvertRequestPriorityToSpdyPriority( 1635 LOWEST, spdy_util_.spdy_version()), 1636 kSpdyCredentialSlotUnused, 1637 CONTROL_FLAG_FIN, // Control Flags 1638 false, // Compressed 1639 RST_STREAM_INVALID, // Status 1640 NULL, // Data 1641 0, // Length 1642 DATA_FLAG_NONE // Data Flags 1643 }; 1644 scoped_ptr<SpdyHeaderBlock> put_headers( 1645 spdy_util_.ConstructPutHeaderBlock("http://www.google.com", 0)); 1646 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyFrame( 1647 kSynStartHeader, put_headers.Pass())); 1648 MockWrite writes[] = { 1649 CreateMockWrite(*req), 1650 }; 1651 1652 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true)); 1653 const SpdyHeaderInfo kSynReplyHeader = { 1654 SYN_REPLY, // Kind = SynReply 1655 1, // Stream ID 1656 0, // Associated stream ID 1657 ConvertRequestPriorityToSpdyPriority( 1658 LOWEST, spdy_util_.spdy_version()), 1659 kSpdyCredentialSlotUnused, 1660 CONTROL_FLAG_NONE, // Control Flags 1661 false, // Compressed 1662 RST_STREAM_INVALID, // Status 1663 NULL, // Data 1664 0, // Length 1665 DATA_FLAG_NONE // Data Flags 1666 }; 1667 scoped_ptr<SpdyHeaderBlock> reply_headers(new SpdyHeaderBlock()); 1668 (*reply_headers)[spdy_util_.GetStatusKey()] = "200"; 1669 (*reply_headers)[spdy_util_.GetVersionKey()] = "HTTP/1.1"; 1670 (*reply_headers)["content-length"] = "1234"; 1671 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyFrame( 1672 kSynReplyHeader, reply_headers.Pass())); 1673 MockRead reads[] = { 1674 CreateMockRead(*resp), 1675 CreateMockRead(*body), 1676 MockRead(ASYNC, 0, 0) // EOF 1677 }; 1678 1679 DelayedSocketData data(1, reads, arraysize(reads), 1680 writes, arraysize(writes)); 1681 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY, 1682 BoundNetLog(), GetParam(), NULL); 1683 helper.RunToCompletion(&data); 1684 TransactionHelperResult out = helper.output(); 1685 1686 EXPECT_EQ(OK, out.rv); 1687 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line); 1688 } 1689 1690 // Test that a simple HEAD request works. 1691 TEST_P(SpdyNetworkTransactionTest, Head) { 1692 // Setup the request 1693 HttpRequestInfo request; 1694 request.method = "HEAD"; 1695 request.url = GURL("http://www.google.com/"); 1696 1697 const SpdyHeaderInfo kSynStartHeader = { 1698 SYN_STREAM, // Kind = Syn 1699 1, // Stream ID 1700 0, // Associated stream ID 1701 ConvertRequestPriorityToSpdyPriority( 1702 LOWEST, spdy_util_.spdy_version()), 1703 kSpdyCredentialSlotUnused, 1704 CONTROL_FLAG_FIN, // Control Flags 1705 false, // Compressed 1706 RST_STREAM_INVALID, // Status 1707 NULL, // Data 1708 0, // Length 1709 DATA_FLAG_NONE // Data Flags 1710 }; 1711 scoped_ptr<SpdyHeaderBlock> head_headers( 1712 spdy_util_.ConstructHeadHeaderBlock("http://www.google.com", 0)); 1713 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyFrame( 1714 kSynStartHeader, head_headers.Pass())); 1715 MockWrite writes[] = { 1716 CreateMockWrite(*req), 1717 }; 1718 1719 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true)); 1720 const SpdyHeaderInfo kSynReplyHeader = { 1721 SYN_REPLY, // Kind = SynReply 1722 1, // Stream ID 1723 0, // Associated stream ID 1724 ConvertRequestPriorityToSpdyPriority( 1725 LOWEST, spdy_util_.spdy_version()), 1726 kSpdyCredentialSlotUnused, 1727 CONTROL_FLAG_NONE, // Control Flags 1728 false, // Compressed 1729 RST_STREAM_INVALID, // Status 1730 NULL, // Data 1731 0, // Length 1732 DATA_FLAG_NONE // Data Flags 1733 }; 1734 scoped_ptr<SpdyHeaderBlock> reply_headers(new SpdyHeaderBlock()); 1735 (*reply_headers)[spdy_util_.GetStatusKey()] = "200"; 1736 (*reply_headers)[spdy_util_.GetVersionKey()] = "HTTP/1.1"; 1737 (*reply_headers)["content-length"] = "1234"; 1738 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyFrame( 1739 kSynReplyHeader, 1740 reply_headers.Pass())); 1741 MockRead reads[] = { 1742 CreateMockRead(*resp), 1743 CreateMockRead(*body), 1744 MockRead(ASYNC, 0, 0) // EOF 1745 }; 1746 1747 DelayedSocketData data(1, reads, arraysize(reads), 1748 writes, arraysize(writes)); 1749 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY, 1750 BoundNetLog(), GetParam(), NULL); 1751 helper.RunToCompletion(&data); 1752 TransactionHelperResult out = helper.output(); 1753 1754 EXPECT_EQ(OK, out.rv); 1755 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line); 1756 } 1757 1758 // Test that a simple POST works. 1759 TEST_P(SpdyNetworkTransactionTest, Post) { 1760 scoped_ptr<SpdyFrame> req( 1761 spdy_util_.ConstructSpdyPost( 1762 kRequestUrl, 1, kUploadDataSize, LOWEST, NULL, 0)); 1763 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true)); 1764 MockWrite writes[] = { 1765 CreateMockWrite(*req), 1766 CreateMockWrite(*body), // POST upload frame 1767 }; 1768 1769 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0)); 1770 MockRead reads[] = { 1771 CreateMockRead(*resp), 1772 CreateMockRead(*body), 1773 MockRead(ASYNC, 0, 0) // EOF 1774 }; 1775 1776 DelayedSocketData data(2, reads, arraysize(reads), 1777 writes, arraysize(writes)); 1778 NormalSpdyTransactionHelper helper(CreatePostRequest(), DEFAULT_PRIORITY, 1779 BoundNetLog(), GetParam(), NULL); 1780 helper.RunToCompletion(&data); 1781 TransactionHelperResult out = helper.output(); 1782 EXPECT_EQ(OK, out.rv); 1783 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line); 1784 EXPECT_EQ("hello!", out.response_data); 1785 } 1786 1787 // Test that a POST with a file works. 1788 TEST_P(SpdyNetworkTransactionTest, FilePost) { 1789 scoped_ptr<SpdyFrame> req( 1790 spdy_util_.ConstructSpdyPost( 1791 kRequestUrl, 1, kUploadDataSize, LOWEST, NULL, 0)); 1792 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true)); 1793 MockWrite writes[] = { 1794 CreateMockWrite(*req), 1795 CreateMockWrite(*body), // POST upload frame 1796 }; 1797 1798 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0)); 1799 MockRead reads[] = { 1800 CreateMockRead(*resp), 1801 CreateMockRead(*body), 1802 MockRead(ASYNC, 0, 0) // EOF 1803 }; 1804 1805 DelayedSocketData data(2, reads, arraysize(reads), 1806 writes, arraysize(writes)); 1807 NormalSpdyTransactionHelper helper(CreateFilePostRequest(), DEFAULT_PRIORITY, 1808 BoundNetLog(), GetParam(), NULL); 1809 helper.RunToCompletion(&data); 1810 TransactionHelperResult out = helper.output(); 1811 EXPECT_EQ(OK, out.rv); 1812 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line); 1813 EXPECT_EQ("hello!", out.response_data); 1814 } 1815 1816 // Test that a POST with a unreadable file fails. 1817 TEST_P(SpdyNetworkTransactionTest, UnreadableFilePost) { 1818 MockWrite writes[] = { 1819 MockWrite(ASYNC, 0, 0) // EOF 1820 }; 1821 MockRead reads[] = { 1822 MockRead(ASYNC, 0, 0) // EOF 1823 }; 1824 1825 DelayedSocketData data(1, reads, arraysize(reads), writes, arraysize(writes)); 1826 NormalSpdyTransactionHelper helper(CreateUnreadableFilePostRequest(), 1827 DEFAULT_PRIORITY, 1828 BoundNetLog(), GetParam(), NULL); 1829 helper.RunPreTestSetup(); 1830 helper.AddData(&data); 1831 helper.RunDefaultTest(); 1832 1833 base::RunLoop().RunUntilIdle(); 1834 helper.VerifyDataNotConsumed(); 1835 EXPECT_EQ(ERR_ACCESS_DENIED, helper.output().rv); 1836 } 1837 1838 // Test that a complex POST works. 1839 TEST_P(SpdyNetworkTransactionTest, ComplexPost) { 1840 scoped_ptr<SpdyFrame> req( 1841 spdy_util_.ConstructSpdyPost( 1842 kRequestUrl, 1, kUploadDataSize, LOWEST, NULL, 0)); 1843 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true)); 1844 MockWrite writes[] = { 1845 CreateMockWrite(*req), 1846 CreateMockWrite(*body), // POST upload frame 1847 }; 1848 1849 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0)); 1850 MockRead reads[] = { 1851 CreateMockRead(*resp), 1852 CreateMockRead(*body), 1853 MockRead(ASYNC, 0, 0) // EOF 1854 }; 1855 1856 DelayedSocketData data(2, reads, arraysize(reads), 1857 writes, arraysize(writes)); 1858 NormalSpdyTransactionHelper helper(CreateComplexPostRequest(), 1859 DEFAULT_PRIORITY, 1860 BoundNetLog(), GetParam(), NULL); 1861 helper.RunToCompletion(&data); 1862 TransactionHelperResult out = helper.output(); 1863 EXPECT_EQ(OK, out.rv); 1864 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line); 1865 EXPECT_EQ("hello!", out.response_data); 1866 } 1867 1868 // Test that a chunked POST works. 1869 TEST_P(SpdyNetworkTransactionTest, ChunkedPost) { 1870 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructChunkedSpdyPost(NULL, 0)); 1871 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true)); 1872 MockWrite writes[] = { 1873 CreateMockWrite(*req), 1874 CreateMockWrite(*body), 1875 }; 1876 1877 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0)); 1878 MockRead reads[] = { 1879 CreateMockRead(*resp), 1880 CreateMockRead(*body), 1881 MockRead(ASYNC, 0, 0) // EOF 1882 }; 1883 1884 DelayedSocketData data(2, reads, arraysize(reads), 1885 writes, arraysize(writes)); 1886 NormalSpdyTransactionHelper helper(CreateChunkedPostRequest(), 1887 DEFAULT_PRIORITY, 1888 BoundNetLog(), GetParam(), NULL); 1889 1890 // These chunks get merged into a single frame when being sent. 1891 const int kFirstChunkSize = kUploadDataSize/2; 1892 helper.request().upload_data_stream->AppendChunk( 1893 kUploadData, kFirstChunkSize, false); 1894 helper.request().upload_data_stream->AppendChunk( 1895 kUploadData + kFirstChunkSize, kUploadDataSize - kFirstChunkSize, true); 1896 1897 helper.RunToCompletion(&data); 1898 TransactionHelperResult out = helper.output(); 1899 EXPECT_EQ(OK, out.rv); 1900 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line); 1901 EXPECT_EQ(kUploadData, out.response_data); 1902 } 1903 1904 // Test that a chunked POST works with chunks appended after transaction starts. 1905 TEST_P(SpdyNetworkTransactionTest, DelayedChunkedPost) { 1906 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructChunkedSpdyPost(NULL, 0)); 1907 scoped_ptr<SpdyFrame> chunk1(spdy_util_.ConstructSpdyBodyFrame(1, false)); 1908 scoped_ptr<SpdyFrame> chunk2(spdy_util_.ConstructSpdyBodyFrame(1, false)); 1909 scoped_ptr<SpdyFrame> chunk3(spdy_util_.ConstructSpdyBodyFrame(1, true)); 1910 MockWrite writes[] = { 1911 CreateMockWrite(*req), 1912 CreateMockWrite(*chunk1), 1913 CreateMockWrite(*chunk2), 1914 CreateMockWrite(*chunk3), 1915 }; 1916 1917 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0)); 1918 MockRead reads[] = { 1919 CreateMockRead(*resp), 1920 CreateMockRead(*chunk1), 1921 CreateMockRead(*chunk2), 1922 CreateMockRead(*chunk3), 1923 MockRead(ASYNC, 0, 0) // EOF 1924 }; 1925 1926 DelayedSocketData data(4, reads, arraysize(reads), 1927 writes, arraysize(writes)); 1928 NormalSpdyTransactionHelper helper(CreateChunkedPostRequest(), 1929 DEFAULT_PRIORITY, 1930 BoundNetLog(), GetParam(), NULL); 1931 1932 helper.request().upload_data_stream->AppendChunk( 1933 kUploadData, kUploadDataSize, false); 1934 1935 helper.RunPreTestSetup(); 1936 helper.AddData(&data); 1937 ASSERT_TRUE(helper.StartDefaultTest()); 1938 1939 base::RunLoop().RunUntilIdle(); 1940 helper.request().upload_data_stream->AppendChunk( 1941 kUploadData, kUploadDataSize, false); 1942 base::RunLoop().RunUntilIdle(); 1943 helper.request().upload_data_stream->AppendChunk( 1944 kUploadData, kUploadDataSize, true); 1945 1946 helper.FinishDefaultTest(); 1947 helper.VerifyDataConsumed(); 1948 1949 std::string expected_response; 1950 expected_response += kUploadData; 1951 expected_response += kUploadData; 1952 expected_response += kUploadData; 1953 1954 TransactionHelperResult out = helper.output(); 1955 EXPECT_EQ(OK, out.rv); 1956 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line); 1957 EXPECT_EQ(expected_response, out.response_data); 1958 } 1959 1960 // Test that a POST without any post data works. 1961 TEST_P(SpdyNetworkTransactionTest, NullPost) { 1962 // Setup the request 1963 HttpRequestInfo request; 1964 request.method = "POST"; 1965 request.url = GURL(kRequestUrl); 1966 // Create an empty UploadData. 1967 request.upload_data_stream = NULL; 1968 1969 // When request.upload_data_stream is NULL for post, content-length is 1970 // expected to be 0. 1971 scoped_ptr<SpdyFrame> req( 1972 spdy_util_.ConstructSpdyPost(kRequestUrl, 1, 0, LOWEST, NULL, 0)); 1973 // Set the FIN bit since there will be no body. 1974 test::SetFrameFlags(req.get(), CONTROL_FLAG_FIN, spdy_util_.spdy_version()); 1975 MockWrite writes[] = { 1976 CreateMockWrite(*req), 1977 }; 1978 1979 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0)); 1980 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true)); 1981 MockRead reads[] = { 1982 CreateMockRead(*resp), 1983 CreateMockRead(*body), 1984 MockRead(ASYNC, 0, 0) // EOF 1985 }; 1986 1987 DelayedSocketData data(1, reads, arraysize(reads), 1988 writes, arraysize(writes)); 1989 1990 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY, 1991 BoundNetLog(), GetParam(), NULL); 1992 helper.RunToCompletion(&data); 1993 TransactionHelperResult out = helper.output(); 1994 EXPECT_EQ(OK, out.rv); 1995 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line); 1996 EXPECT_EQ("hello!", out.response_data); 1997 } 1998 1999 // Test that a simple POST works. 2000 TEST_P(SpdyNetworkTransactionTest, EmptyPost) { 2001 // Create an empty UploadDataStream. 2002 ScopedVector<UploadElementReader> element_readers; 2003 UploadDataStream stream(element_readers.Pass(), 0); 2004 2005 // Setup the request 2006 HttpRequestInfo request; 2007 request.method = "POST"; 2008 request.url = GURL(kRequestUrl); 2009 request.upload_data_stream = &stream; 2010 2011 const uint64 kContentLength = 0; 2012 scoped_ptr<SpdyFrame> req( 2013 spdy_util_.ConstructSpdyPost( 2014 kRequestUrl, 1, kContentLength, LOWEST, NULL, 0)); 2015 // Set the FIN bit since there will be no body. 2016 test::SetFrameFlags(req.get(), CONTROL_FLAG_FIN, spdy_util_.spdy_version()); 2017 MockWrite writes[] = { 2018 CreateMockWrite(*req), 2019 }; 2020 2021 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0)); 2022 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true)); 2023 MockRead reads[] = { 2024 CreateMockRead(*resp), 2025 CreateMockRead(*body), 2026 MockRead(ASYNC, 0, 0) // EOF 2027 }; 2028 2029 DelayedSocketData data(1, reads, arraysize(reads), writes, arraysize(writes)); 2030 2031 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY, 2032 BoundNetLog(), GetParam(), NULL); 2033 helper.RunToCompletion(&data); 2034 TransactionHelperResult out = helper.output(); 2035 EXPECT_EQ(OK, out.rv); 2036 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line); 2037 EXPECT_EQ("hello!", out.response_data); 2038 } 2039 2040 // While we're doing a post, the server sends back a SYN_REPLY. 2041 TEST_P(SpdyNetworkTransactionTest, PostWithEarlySynReply) { 2042 static const char upload[] = { "hello!" }; 2043 ScopedVector<UploadElementReader> element_readers; 2044 element_readers.push_back( 2045 new UploadBytesElementReader(upload, sizeof(upload))); 2046 UploadDataStream stream(element_readers.Pass(), 0); 2047 2048 // Setup the request 2049 HttpRequestInfo request; 2050 request.method = "POST"; 2051 request.url = GURL(kRequestUrl); 2052 request.upload_data_stream = &stream; 2053 2054 scoped_ptr<SpdyFrame> stream_reply( 2055 spdy_util_.ConstructSpdyPostSynReply(NULL, 0)); 2056 MockRead reads[] = { 2057 CreateMockRead(*stream_reply, 1), 2058 MockRead(ASYNC, 0, 4) // EOF 2059 }; 2060 2061 scoped_ptr<SpdyFrame> req( 2062 spdy_util_.ConstructSpdyPost( 2063 kRequestUrl, 1, kUploadDataSize, LOWEST, NULL, 0)); 2064 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true)); 2065 scoped_ptr<SpdyFrame> rst( 2066 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR)); 2067 MockWrite writes[] = { 2068 CreateMockWrite(*req, 0), 2069 CreateMockWrite(*body, 2), 2070 CreateMockWrite(*rst, 3) 2071 }; 2072 2073 DeterministicSocketData data(reads, arraysize(reads), 2074 writes, arraysize(writes)); 2075 NormalSpdyTransactionHelper helper(CreatePostRequest(), DEFAULT_PRIORITY, 2076 BoundNetLog(), GetParam(), NULL); 2077 helper.SetDeterministic(); 2078 helper.RunPreTestSetup(); 2079 helper.AddDeterministicData(&data); 2080 HttpNetworkTransaction* trans = helper.trans(); 2081 2082 TestCompletionCallback callback; 2083 int rv = trans->Start( 2084 &CreatePostRequest(), callback.callback(), BoundNetLog()); 2085 EXPECT_EQ(ERR_IO_PENDING, rv); 2086 2087 data.RunFor(4); 2088 rv = callback.WaitForResult(); 2089 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, rv); 2090 data.RunFor(1); 2091 } 2092 2093 // The client upon cancellation tries to send a RST_STREAM frame. The mock 2094 // socket causes the TCP write to return zero. This test checks that the client 2095 // tries to queue up the RST_STREAM frame again. 2096 TEST_P(SpdyNetworkTransactionTest, SocketWriteReturnsZero) { 2097 scoped_ptr<SpdyFrame> req( 2098 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); 2099 scoped_ptr<SpdyFrame> rst( 2100 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL)); 2101 MockWrite writes[] = { 2102 CreateMockWrite(*req.get(), 0, SYNCHRONOUS), 2103 MockWrite(SYNCHRONOUS, 0, 0, 2), 2104 CreateMockWrite(*rst.get(), 3, SYNCHRONOUS), 2105 }; 2106 2107 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 2108 MockRead reads[] = { 2109 CreateMockRead(*resp.get(), 1, ASYNC), 2110 MockRead(ASYNC, 0, 0, 4) // EOF 2111 }; 2112 2113 DeterministicSocketData data(reads, arraysize(reads), 2114 writes, arraysize(writes)); 2115 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY, 2116 BoundNetLog(), GetParam(), NULL); 2117 helper.SetDeterministic(); 2118 helper.RunPreTestSetup(); 2119 helper.AddDeterministicData(&data); 2120 HttpNetworkTransaction* trans = helper.trans(); 2121 2122 TestCompletionCallback callback; 2123 int rv = trans->Start( 2124 &CreateGetRequest(), callback.callback(), BoundNetLog()); 2125 EXPECT_EQ(ERR_IO_PENDING, rv); 2126 2127 data.SetStop(2); 2128 data.Run(); 2129 helper.ResetTrans(); 2130 data.SetStop(20); 2131 data.Run(); 2132 2133 helper.VerifyDataConsumed(); 2134 } 2135 2136 // Test that the transaction doesn't crash when we don't have a reply. 2137 TEST_P(SpdyNetworkTransactionTest, ResponseWithoutSynReply) { 2138 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true)); 2139 MockRead reads[] = { 2140 CreateMockRead(*body), 2141 MockRead(ASYNC, 0, 0) // EOF 2142 }; 2143 2144 DelayedSocketData data(1, reads, arraysize(reads), NULL, 0); 2145 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY, 2146 BoundNetLog(), GetParam(), NULL); 2147 helper.RunToCompletion(&data); 2148 TransactionHelperResult out = helper.output(); 2149 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv); 2150 } 2151 2152 // Test that the transaction doesn't crash when we get two replies on the same 2153 // stream ID. See http://crbug.com/45639. 2154 TEST_P(SpdyNetworkTransactionTest, ResponseWithTwoSynReplies) { 2155 scoped_ptr<SpdyFrame> req( 2156 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); 2157 scoped_ptr<SpdyFrame> rst( 2158 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_STREAM_IN_USE)); 2159 MockWrite writes[] = { 2160 CreateMockWrite(*req), 2161 CreateMockWrite(*rst), 2162 }; 2163 2164 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 2165 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true)); 2166 MockRead reads[] = { 2167 CreateMockRead(*resp), 2168 CreateMockRead(*resp), 2169 CreateMockRead(*body), 2170 MockRead(ASYNC, 0, 0) // EOF 2171 }; 2172 2173 DelayedSocketData data(1, reads, arraysize(reads), 2174 writes, arraysize(writes)); 2175 2176 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY, 2177 BoundNetLog(), GetParam(), NULL); 2178 helper.RunPreTestSetup(); 2179 helper.AddData(&data); 2180 2181 HttpNetworkTransaction* trans = helper.trans(); 2182 2183 TestCompletionCallback callback; 2184 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog()); 2185 EXPECT_EQ(ERR_IO_PENDING, rv); 2186 rv = callback.WaitForResult(); 2187 EXPECT_EQ(OK, rv); 2188 2189 const HttpResponseInfo* response = trans->GetResponseInfo(); 2190 ASSERT_TRUE(response != NULL); 2191 EXPECT_TRUE(response->headers.get() != NULL); 2192 EXPECT_TRUE(response->was_fetched_via_spdy); 2193 std::string response_data; 2194 rv = ReadTransaction(trans, &response_data); 2195 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, rv); 2196 2197 helper.VerifyDataConsumed(); 2198 } 2199 2200 TEST_P(SpdyNetworkTransactionTest, ResetReplyWithTransferEncoding) { 2201 // Construct the request. 2202 scoped_ptr<SpdyFrame> req( 2203 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); 2204 scoped_ptr<SpdyFrame> rst( 2205 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR)); 2206 MockWrite writes[] = { 2207 CreateMockWrite(*req), 2208 CreateMockWrite(*rst), 2209 }; 2210 2211 const char* const headers[] = { 2212 "transfer-encoding", "chunked" 2213 }; 2214 scoped_ptr<SpdyFrame> resp( 2215 spdy_util_.ConstructSpdyGetSynReply(headers, 1, 1)); 2216 scoped_ptr<SpdyFrame> body( 2217 spdy_util_.ConstructSpdyBodyFrame(1, true)); 2218 MockRead reads[] = { 2219 CreateMockRead(*resp), 2220 CreateMockRead(*body), 2221 MockRead(ASYNC, 0, 0) // EOF 2222 }; 2223 2224 DelayedSocketData data(1, reads, arraysize(reads), 2225 writes, arraysize(writes)); 2226 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY, 2227 BoundNetLog(), GetParam(), NULL); 2228 helper.RunToCompletion(&data); 2229 TransactionHelperResult out = helper.output(); 2230 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv); 2231 2232 helper.session()->spdy_session_pool()->CloseAllSessions(); 2233 helper.VerifyDataConsumed(); 2234 } 2235 2236 TEST_P(SpdyNetworkTransactionTest, ResetPushWithTransferEncoding) { 2237 // Construct the request. 2238 scoped_ptr<SpdyFrame> req( 2239 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); 2240 scoped_ptr<SpdyFrame> rst( 2241 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_PROTOCOL_ERROR)); 2242 MockWrite writes[] = { 2243 CreateMockWrite(*req), 2244 CreateMockWrite(*rst), 2245 }; 2246 2247 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 2248 const char* const headers[] = { 2249 "transfer-encoding", "chunked" 2250 }; 2251 scoped_ptr<SpdyFrame> push( 2252 spdy_util_.ConstructSpdyPush(headers, arraysize(headers) / 2, 2253 2, 1, "http://www.google.com/1")); 2254 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true)); 2255 MockRead reads[] = { 2256 CreateMockRead(*resp), 2257 CreateMockRead(*push), 2258 CreateMockRead(*body), 2259 MockRead(ASYNC, 0, 0) // EOF 2260 }; 2261 2262 DelayedSocketData data(1, reads, arraysize(reads), 2263 writes, arraysize(writes)); 2264 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY, 2265 BoundNetLog(), GetParam(), NULL); 2266 helper.RunToCompletion(&data); 2267 TransactionHelperResult out = helper.output(); 2268 EXPECT_EQ(OK, out.rv); 2269 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line); 2270 EXPECT_EQ("hello!", out.response_data); 2271 2272 helper.session()->spdy_session_pool()->CloseAllSessions(); 2273 helper.VerifyDataConsumed(); 2274 } 2275 2276 TEST_P(SpdyNetworkTransactionTest, CancelledTransaction) { 2277 // Construct the request. 2278 scoped_ptr<SpdyFrame> req( 2279 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); 2280 MockWrite writes[] = { 2281 CreateMockWrite(*req), 2282 }; 2283 2284 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 2285 MockRead reads[] = { 2286 CreateMockRead(*resp), 2287 // This following read isn't used by the test, except during the 2288 // RunUntilIdle() call at the end since the SpdySession survives the 2289 // HttpNetworkTransaction and still tries to continue Read()'ing. Any 2290 // MockRead will do here. 2291 MockRead(ASYNC, 0, 0) // EOF 2292 }; 2293 2294 StaticSocketDataProvider data(reads, arraysize(reads), 2295 writes, arraysize(writes)); 2296 2297 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY, 2298 BoundNetLog(), GetParam(), NULL); 2299 helper.RunPreTestSetup(); 2300 helper.AddData(&data); 2301 HttpNetworkTransaction* trans = helper.trans(); 2302 2303 TestCompletionCallback callback; 2304 int rv = trans->Start( 2305 &CreateGetRequest(), callback.callback(), BoundNetLog()); 2306 EXPECT_EQ(ERR_IO_PENDING, rv); 2307 helper.ResetTrans(); // Cancel the transaction. 2308 2309 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the 2310 // MockClientSocketFactory) are still alive. 2311 base::RunLoop().RunUntilIdle(); 2312 helper.VerifyDataNotConsumed(); 2313 } 2314 2315 // Verify that the client sends a Rst Frame upon cancelling the stream. 2316 TEST_P(SpdyNetworkTransactionTest, CancelledTransactionSendRst) { 2317 scoped_ptr<SpdyFrame> req( 2318 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); 2319 scoped_ptr<SpdyFrame> rst( 2320 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL)); 2321 MockWrite writes[] = { 2322 CreateMockWrite(*req, 0, SYNCHRONOUS), 2323 CreateMockWrite(*rst, 2, SYNCHRONOUS), 2324 }; 2325 2326 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 2327 MockRead reads[] = { 2328 CreateMockRead(*resp, 1, ASYNC), 2329 MockRead(ASYNC, 0, 0, 3) // EOF 2330 }; 2331 2332 DeterministicSocketData data(reads, arraysize(reads), 2333 writes, arraysize(writes)); 2334 2335 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY, 2336 BoundNetLog(), 2337 GetParam(), NULL); 2338 helper.SetDeterministic(); 2339 helper.RunPreTestSetup(); 2340 helper.AddDeterministicData(&data); 2341 HttpNetworkTransaction* trans = helper.trans(); 2342 2343 TestCompletionCallback callback; 2344 2345 int rv = trans->Start( 2346 &CreateGetRequest(), callback.callback(), BoundNetLog()); 2347 EXPECT_EQ(ERR_IO_PENDING, rv); 2348 2349 data.SetStop(2); 2350 data.Run(); 2351 helper.ResetTrans(); 2352 data.SetStop(20); 2353 data.Run(); 2354 2355 helper.VerifyDataConsumed(); 2356 } 2357 2358 // Verify that the client can correctly deal with the user callback attempting 2359 // to start another transaction on a session that is closing down. See 2360 // http://crbug.com/47455 2361 TEST_P(SpdyNetworkTransactionTest, StartTransactionOnReadCallback) { 2362 scoped_ptr<SpdyFrame> req( 2363 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); 2364 MockWrite writes[] = { CreateMockWrite(*req) }; 2365 MockWrite writes2[] = { CreateMockWrite(*req) }; 2366 2367 // The indicated length of this frame is longer than its actual length. When 2368 // the session receives an empty frame after this one, it shuts down the 2369 // session, and calls the read callback with the incomplete data. 2370 const uint8 kGetBodyFrame2[] = { 2371 0x00, 0x00, 0x00, 0x01, 2372 0x01, 0x00, 0x00, 0x07, 2373 'h', 'e', 'l', 'l', 'o', '!', 2374 }; 2375 2376 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 2377 MockRead reads[] = { 2378 CreateMockRead(*resp, 2), 2379 MockRead(ASYNC, ERR_IO_PENDING, 3), // Force a pause 2380 MockRead(ASYNC, reinterpret_cast<const char*>(kGetBodyFrame2), 2381 arraysize(kGetBodyFrame2), 4), 2382 MockRead(ASYNC, ERR_IO_PENDING, 5), // Force a pause 2383 MockRead(ASYNC, 0, 0, 6), // EOF 2384 }; 2385 MockRead reads2[] = { 2386 CreateMockRead(*resp, 2), 2387 MockRead(ASYNC, 0, 0, 3), // EOF 2388 }; 2389 2390 OrderedSocketData data(reads, arraysize(reads), 2391 writes, arraysize(writes)); 2392 DelayedSocketData data2(1, reads2, arraysize(reads2), 2393 writes2, arraysize(writes2)); 2394 2395 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY, 2396 BoundNetLog(), GetParam(), NULL); 2397 helper.RunPreTestSetup(); 2398 helper.AddData(&data); 2399 helper.AddData(&data2); 2400 HttpNetworkTransaction* trans = helper.trans(); 2401 2402 // Start the transaction with basic parameters. 2403 TestCompletionCallback callback; 2404 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog()); 2405 EXPECT_EQ(ERR_IO_PENDING, rv); 2406 rv = callback.WaitForResult(); 2407 2408 const int kSize = 3000; 2409 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kSize)); 2410 rv = trans->Read( 2411 buf.get(), 2412 kSize, 2413 base::Bind(&SpdyNetworkTransactionTest::StartTransactionCallback, 2414 helper.session())); 2415 // This forces an err_IO_pending, which sets the callback. 2416 data.CompleteRead(); 2417 // This finishes the read. 2418 data.CompleteRead(); 2419 helper.VerifyDataConsumed(); 2420 } 2421 2422 // Verify that the client can correctly deal with the user callback deleting the 2423 // transaction. Failures will usually be valgrind errors. See 2424 // http://crbug.com/46925 2425 TEST_P(SpdyNetworkTransactionTest, DeleteSessionOnReadCallback) { 2426 scoped_ptr<SpdyFrame> req( 2427 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); 2428 MockWrite writes[] = { CreateMockWrite(*req) }; 2429 2430 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 2431 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true)); 2432 MockRead reads[] = { 2433 CreateMockRead(*resp.get(), 2), 2434 MockRead(ASYNC, ERR_IO_PENDING, 3), // Force a pause 2435 CreateMockRead(*body.get(), 4), 2436 MockRead(ASYNC, 0, 0, 5), // EOF 2437 }; 2438 2439 OrderedSocketData data(reads, arraysize(reads), 2440 writes, arraysize(writes)); 2441 2442 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY, 2443 BoundNetLog(), GetParam(), NULL); 2444 helper.RunPreTestSetup(); 2445 helper.AddData(&data); 2446 HttpNetworkTransaction* trans = helper.trans(); 2447 2448 // Start the transaction with basic parameters. 2449 TestCompletionCallback callback; 2450 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog()); 2451 EXPECT_EQ(ERR_IO_PENDING, rv); 2452 rv = callback.WaitForResult(); 2453 2454 // Setup a user callback which will delete the session, and clear out the 2455 // memory holding the stream object. Note that the callback deletes trans. 2456 const int kSize = 3000; 2457 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kSize)); 2458 rv = trans->Read( 2459 buf.get(), 2460 kSize, 2461 base::Bind(&SpdyNetworkTransactionTest::DeleteSessionCallback, 2462 base::Unretained(&helper))); 2463 ASSERT_EQ(ERR_IO_PENDING, rv); 2464 data.CompleteRead(); 2465 2466 // Finish running rest of tasks. 2467 base::RunLoop().RunUntilIdle(); 2468 helper.VerifyDataConsumed(); 2469 } 2470 2471 // Send a spdy request to www.google.com that gets redirected to www.foo.com. 2472 TEST_P(SpdyNetworkTransactionTest, RedirectGetRequest) { 2473 const SpdyHeaderInfo kSynStartHeader = spdy_util_.MakeSpdyHeader(SYN_STREAM); 2474 scoped_ptr<SpdyHeaderBlock> headers( 2475 spdy_util_.ConstructGetHeaderBlock("http://www.google.com/")); 2476 (*headers)["user-agent"] = ""; 2477 (*headers)["accept-encoding"] = "gzip,deflate"; 2478 scoped_ptr<SpdyHeaderBlock> headers2( 2479 spdy_util_.ConstructGetHeaderBlock("http://www.foo.com/index.php")); 2480 (*headers2)["user-agent"] = ""; 2481 (*headers2)["accept-encoding"] = "gzip,deflate"; 2482 2483 // Setup writes/reads to www.google.com 2484 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyFrame( 2485 kSynStartHeader, headers.Pass())); 2486 scoped_ptr<SpdyFrame> req2(spdy_util_.ConstructSpdyFrame( 2487 kSynStartHeader, headers2.Pass())); 2488 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReplyRedirect(1)); 2489 MockWrite writes[] = { 2490 CreateMockWrite(*req, 1), 2491 }; 2492 MockRead reads[] = { 2493 CreateMockRead(*resp, 2), 2494 MockRead(ASYNC, 0, 0, 3) // EOF 2495 }; 2496 2497 // Setup writes/reads to www.foo.com 2498 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 2499 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(1, true)); 2500 MockWrite writes2[] = { 2501 CreateMockWrite(*req2, 1), 2502 }; 2503 MockRead reads2[] = { 2504 CreateMockRead(*resp2, 2), 2505 CreateMockRead(*body2, 3), 2506 MockRead(ASYNC, 0, 0, 4) // EOF 2507 }; 2508 OrderedSocketData data(reads, arraysize(reads), 2509 writes, arraysize(writes)); 2510 OrderedSocketData data2(reads2, arraysize(reads2), 2511 writes2, arraysize(writes2)); 2512 2513 // TODO(erikchen): Make test support SPDYSSL, SPDYNPN 2514 HttpStreamFactory::set_force_spdy_over_ssl(false); 2515 HttpStreamFactory::set_force_spdy_always(true); 2516 TestDelegate d; 2517 { 2518 SpdyURLRequestContext spdy_url_request_context(GetParam().protocol); 2519 net::URLRequest r(GURL("http://www.google.com/"), 2520 DEFAULT_PRIORITY, 2521 &d, 2522 &spdy_url_request_context); 2523 spdy_url_request_context.socket_factory(). 2524 AddSocketDataProvider(&data); 2525 spdy_url_request_context.socket_factory(). 2526 AddSocketDataProvider(&data2); 2527 2528 d.set_quit_on_redirect(true); 2529 r.Start(); 2530 base::RunLoop().Run(); 2531 2532 EXPECT_EQ(1, d.received_redirect_count()); 2533 2534 r.FollowDeferredRedirect(); 2535 base::RunLoop().Run(); 2536 EXPECT_EQ(1, d.response_started_count()); 2537 EXPECT_FALSE(d.received_data_before_response()); 2538 EXPECT_EQ(net::URLRequestStatus::SUCCESS, r.status().status()); 2539 std::string contents("hello!"); 2540 EXPECT_EQ(contents, d.data_received()); 2541 } 2542 EXPECT_TRUE(data.at_read_eof()); 2543 EXPECT_TRUE(data.at_write_eof()); 2544 EXPECT_TRUE(data2.at_read_eof()); 2545 EXPECT_TRUE(data2.at_write_eof()); 2546 } 2547 2548 // Send a spdy request to www.google.com. Get a pushed stream that redirects to 2549 // www.foo.com. 2550 TEST_P(SpdyNetworkTransactionTest, RedirectServerPush) { 2551 const SpdyHeaderInfo kSynStartHeader = spdy_util_.MakeSpdyHeader(SYN_STREAM); 2552 2553 scoped_ptr<SpdyHeaderBlock> headers( 2554 spdy_util_.ConstructGetHeaderBlock("http://www.google.com/")); 2555 (*headers)["user-agent"] = ""; 2556 (*headers)["accept-encoding"] = "gzip,deflate"; 2557 2558 // Setup writes/reads to www.google.com 2559 scoped_ptr<SpdyFrame> req( 2560 spdy_util_.ConstructSpdyFrame(kSynStartHeader, headers.Pass())); 2561 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 2562 scoped_ptr<SpdyFrame> rep( 2563 spdy_util_.ConstructSpdyPush(NULL, 2564 0, 2565 2, 2566 1, 2567 "http://www.google.com/foo.dat", 2568 "301 Moved Permanently", 2569 "http://www.foo.com/index.php")); 2570 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true)); 2571 scoped_ptr<SpdyFrame> rst( 2572 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_CANCEL)); 2573 MockWrite writes[] = { 2574 CreateMockWrite(*req, 1), 2575 CreateMockWrite(*rst, 6), 2576 }; 2577 MockRead reads[] = { 2578 CreateMockRead(*resp, 2), 2579 CreateMockRead(*rep, 3), 2580 CreateMockRead(*body, 4), 2581 MockRead(ASYNC, ERR_IO_PENDING, 5), // Force a pause 2582 MockRead(ASYNC, 0, 0, 7) // EOF 2583 }; 2584 2585 // Setup writes/reads to www.foo.com 2586 scoped_ptr<SpdyHeaderBlock> headers2( 2587 spdy_util_.ConstructGetHeaderBlock("http://www.foo.com/index.php")); 2588 (*headers2)["user-agent"] = ""; 2589 (*headers2)["accept-encoding"] = "gzip,deflate"; 2590 scoped_ptr<SpdyFrame> req2( 2591 spdy_util_.ConstructSpdyFrame(kSynStartHeader, headers2.Pass())); 2592 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 2593 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(1, true)); 2594 MockWrite writes2[] = { 2595 CreateMockWrite(*req2, 1), 2596 }; 2597 MockRead reads2[] = { 2598 CreateMockRead(*resp2, 2), 2599 CreateMockRead(*body2, 3), 2600 MockRead(ASYNC, 0, 0, 5) // EOF 2601 }; 2602 OrderedSocketData data(reads, arraysize(reads), 2603 writes, arraysize(writes)); 2604 OrderedSocketData data2(reads2, arraysize(reads2), 2605 writes2, arraysize(writes2)); 2606 2607 // TODO(erikchen): Make test support SPDYSSL, SPDYNPN 2608 HttpStreamFactory::set_force_spdy_over_ssl(false); 2609 HttpStreamFactory::set_force_spdy_always(true); 2610 TestDelegate d; 2611 TestDelegate d2; 2612 SpdyURLRequestContext spdy_url_request_context(GetParam().protocol); 2613 { 2614 net::URLRequest r(GURL("http://www.google.com/"), 2615 DEFAULT_PRIORITY, 2616 &d, 2617 &spdy_url_request_context); 2618 spdy_url_request_context.socket_factory(). 2619 AddSocketDataProvider(&data); 2620 2621 r.Start(); 2622 base::RunLoop().Run(); 2623 2624 EXPECT_EQ(0, d.received_redirect_count()); 2625 std::string contents("hello!"); 2626 EXPECT_EQ(contents, d.data_received()); 2627 2628 net::URLRequest r2(GURL("http://www.google.com/foo.dat"), 2629 DEFAULT_PRIORITY, 2630 &d2, 2631 &spdy_url_request_context); 2632 spdy_url_request_context.socket_factory(). 2633 AddSocketDataProvider(&data2); 2634 2635 d2.set_quit_on_redirect(true); 2636 r2.Start(); 2637 base::RunLoop().Run(); 2638 EXPECT_EQ(1, d2.received_redirect_count()); 2639 2640 r2.FollowDeferredRedirect(); 2641 base::RunLoop().Run(); 2642 EXPECT_EQ(1, d2.response_started_count()); 2643 EXPECT_FALSE(d2.received_data_before_response()); 2644 EXPECT_EQ(net::URLRequestStatus::SUCCESS, r2.status().status()); 2645 std::string contents2("hello!"); 2646 EXPECT_EQ(contents2, d2.data_received()); 2647 } 2648 data.CompleteRead(); 2649 data2.CompleteRead(); 2650 EXPECT_TRUE(data.at_read_eof()); 2651 EXPECT_TRUE(data.at_write_eof()); 2652 EXPECT_TRUE(data2.at_read_eof()); 2653 EXPECT_TRUE(data2.at_write_eof()); 2654 } 2655 2656 TEST_P(SpdyNetworkTransactionTest, ServerPushSingleDataFrame) { 2657 scoped_ptr<SpdyFrame> stream1_syn( 2658 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); 2659 scoped_ptr<SpdyFrame> stream1_body( 2660 spdy_util_.ConstructSpdyBodyFrame(1, true)); 2661 MockWrite writes[] = { 2662 CreateMockWrite(*stream1_syn, 1), 2663 }; 2664 2665 scoped_ptr<SpdyFrame> 2666 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 2667 scoped_ptr<SpdyFrame> 2668 stream2_syn(spdy_util_.ConstructSpdyPush(NULL, 2669 0, 2670 2, 2671 1, 2672 "http://www.google.com/foo.dat")); 2673 const char kPushedData[] = "pushed"; 2674 scoped_ptr<SpdyFrame> stream2_body( 2675 spdy_util_.ConstructSpdyBodyFrame( 2676 2, kPushedData, strlen(kPushedData), true)); 2677 MockRead reads[] = { 2678 CreateMockRead(*stream1_reply, 2), 2679 CreateMockRead(*stream2_syn, 3), 2680 CreateMockRead(*stream1_body, 4, SYNCHRONOUS), 2681 CreateMockRead(*stream2_body, 5), 2682 MockRead(ASYNC, ERR_IO_PENDING, 6), // Force a pause 2683 }; 2684 2685 HttpResponseInfo response; 2686 HttpResponseInfo response2; 2687 std::string expected_push_result("pushed"); 2688 OrderedSocketData data(reads, arraysize(reads), 2689 writes, arraysize(writes)); 2690 RunServerPushTest(&data, 2691 &response, 2692 &response2, 2693 expected_push_result); 2694 2695 // Verify the SYN_REPLY. 2696 EXPECT_TRUE(response.headers.get() != NULL); 2697 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine()); 2698 2699 // Verify the pushed stream. 2700 EXPECT_TRUE(response2.headers.get() != NULL); 2701 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine()); 2702 } 2703 2704 TEST_P(SpdyNetworkTransactionTest, ServerPushBeforeSynReply) { 2705 scoped_ptr<SpdyFrame> stream1_syn( 2706 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); 2707 scoped_ptr<SpdyFrame> stream1_body( 2708 spdy_util_.ConstructSpdyBodyFrame(1, true)); 2709 MockWrite writes[] = { 2710 CreateMockWrite(*stream1_syn, 1), 2711 }; 2712 2713 scoped_ptr<SpdyFrame> 2714 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 2715 scoped_ptr<SpdyFrame> 2716 stream2_syn(spdy_util_.ConstructSpdyPush(NULL, 2717 0, 2718 2, 2719 1, 2720 "http://www.google.com/foo.dat")); 2721 const char kPushedData[] = "pushed"; 2722 scoped_ptr<SpdyFrame> stream2_body( 2723 spdy_util_.ConstructSpdyBodyFrame( 2724 2, kPushedData, strlen(kPushedData), true)); 2725 MockRead reads[] = { 2726 CreateMockRead(*stream2_syn, 2), 2727 CreateMockRead(*stream1_reply, 3), 2728 CreateMockRead(*stream1_body, 4, SYNCHRONOUS), 2729 CreateMockRead(*stream2_body, 5), 2730 MockRead(ASYNC, ERR_IO_PENDING, 6), // Force a pause 2731 }; 2732 2733 HttpResponseInfo response; 2734 HttpResponseInfo response2; 2735 std::string expected_push_result("pushed"); 2736 OrderedSocketData data(reads, arraysize(reads), 2737 writes, arraysize(writes)); 2738 RunServerPushTest(&data, 2739 &response, 2740 &response2, 2741 expected_push_result); 2742 2743 // Verify the SYN_REPLY. 2744 EXPECT_TRUE(response.headers.get() != NULL); 2745 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine()); 2746 2747 // Verify the pushed stream. 2748 EXPECT_TRUE(response2.headers.get() != NULL); 2749 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine()); 2750 } 2751 2752 TEST_P(SpdyNetworkTransactionTest, ServerPushSingleDataFrame2) { 2753 scoped_ptr<SpdyFrame> stream1_syn( 2754 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); 2755 MockWrite writes[] = { CreateMockWrite(*stream1_syn, 1), }; 2756 2757 scoped_ptr<SpdyFrame> 2758 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 2759 scoped_ptr<SpdyFrame> 2760 stream2_syn(spdy_util_.ConstructSpdyPush(NULL, 2761 0, 2762 2, 2763 1, 2764 "http://www.google.com/foo.dat")); 2765 const char kPushedData[] = "pushed"; 2766 scoped_ptr<SpdyFrame> stream2_body( 2767 spdy_util_.ConstructSpdyBodyFrame( 2768 2, kPushedData, strlen(kPushedData), true)); 2769 scoped_ptr<SpdyFrame> 2770 stream1_body(spdy_util_.ConstructSpdyBodyFrame(1, true)); 2771 MockRead reads[] = { 2772 CreateMockRead(*stream1_reply, 2), 2773 CreateMockRead(*stream2_syn, 3), 2774 CreateMockRead(*stream2_body, 4), 2775 CreateMockRead(*stream1_body, 5, SYNCHRONOUS), 2776 MockRead(ASYNC, ERR_IO_PENDING, 6), // Force a pause 2777 }; 2778 2779 HttpResponseInfo response; 2780 HttpResponseInfo response2; 2781 std::string expected_push_result("pushed"); 2782 OrderedSocketData data(reads, arraysize(reads), 2783 writes, arraysize(writes)); 2784 RunServerPushTest(&data, 2785 &response, 2786 &response2, 2787 expected_push_result); 2788 2789 // Verify the SYN_REPLY. 2790 EXPECT_TRUE(response.headers.get() != NULL); 2791 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine()); 2792 2793 // Verify the pushed stream. 2794 EXPECT_TRUE(response2.headers.get() != NULL); 2795 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine()); 2796 } 2797 2798 TEST_P(SpdyNetworkTransactionTest, ServerPushServerAborted) { 2799 scoped_ptr<SpdyFrame> stream1_syn( 2800 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); 2801 scoped_ptr<SpdyFrame> stream1_body( 2802 spdy_util_.ConstructSpdyBodyFrame(1, true)); 2803 MockWrite writes[] = { 2804 CreateMockWrite(*stream1_syn, 1), 2805 }; 2806 2807 scoped_ptr<SpdyFrame> 2808 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 2809 scoped_ptr<SpdyFrame> 2810 stream2_syn(spdy_util_.ConstructSpdyPush(NULL, 2811 0, 2812 2, 2813 1, 2814 "http://www.google.com/foo.dat")); 2815 scoped_ptr<SpdyFrame> stream2_rst( 2816 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_PROTOCOL_ERROR)); 2817 MockRead reads[] = { 2818 CreateMockRead(*stream1_reply, 2), 2819 CreateMockRead(*stream2_syn, 3), 2820 CreateMockRead(*stream2_rst, 4), 2821 CreateMockRead(*stream1_body, 5, SYNCHRONOUS), 2822 MockRead(ASYNC, ERR_IO_PENDING, 6), // Force a pause 2823 }; 2824 2825 OrderedSocketData data(reads, arraysize(reads), 2826 writes, arraysize(writes)); 2827 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY, 2828 BoundNetLog(), GetParam(), NULL); 2829 2830 helper.RunPreTestSetup(); 2831 helper.AddData(&data); 2832 2833 HttpNetworkTransaction* trans = helper.trans(); 2834 2835 // Start the transaction with basic parameters. 2836 TestCompletionCallback callback; 2837 int rv = trans->Start( 2838 &CreateGetRequest(), callback.callback(), BoundNetLog()); 2839 EXPECT_EQ(ERR_IO_PENDING, rv); 2840 rv = callback.WaitForResult(); 2841 EXPECT_EQ(OK, rv); 2842 2843 // Verify that we consumed all test data. 2844 EXPECT_TRUE(data.at_read_eof()) << "Read count: " 2845 << data.read_count() 2846 << " Read index: " 2847 << data.read_index(); 2848 EXPECT_TRUE(data.at_write_eof()) << "Write count: " 2849 << data.write_count() 2850 << " Write index: " 2851 << data.write_index(); 2852 2853 // Verify the SYN_REPLY. 2854 HttpResponseInfo response = *trans->GetResponseInfo(); 2855 EXPECT_TRUE(response.headers.get() != NULL); 2856 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine()); 2857 } 2858 2859 // Verify that we don't leak streams and that we properly send a reset 2860 // if the server pushes the same stream twice. 2861 TEST_P(SpdyNetworkTransactionTest, ServerPushDuplicate) { 2862 scoped_ptr<SpdyFrame> stream1_syn( 2863 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); 2864 scoped_ptr<SpdyFrame> stream1_body( 2865 spdy_util_.ConstructSpdyBodyFrame(1, true)); 2866 scoped_ptr<SpdyFrame> stream3_rst( 2867 spdy_util_.ConstructSpdyRstStream(4, RST_STREAM_PROTOCOL_ERROR)); 2868 MockWrite writes[] = { 2869 CreateMockWrite(*stream1_syn, 1), 2870 CreateMockWrite(*stream3_rst, 5), 2871 }; 2872 2873 scoped_ptr<SpdyFrame> 2874 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 2875 scoped_ptr<SpdyFrame> 2876 stream2_syn(spdy_util_.ConstructSpdyPush(NULL, 2877 0, 2878 2, 2879 1, 2880 "http://www.google.com/foo.dat")); 2881 const char kPushedData[] = "pushed"; 2882 scoped_ptr<SpdyFrame> stream2_body( 2883 spdy_util_.ConstructSpdyBodyFrame( 2884 2, kPushedData, strlen(kPushedData), true)); 2885 scoped_ptr<SpdyFrame> 2886 stream3_syn(spdy_util_.ConstructSpdyPush(NULL, 2887 0, 2888 4, 2889 1, 2890 "http://www.google.com/foo.dat")); 2891 MockRead reads[] = { 2892 CreateMockRead(*stream1_reply, 2), 2893 CreateMockRead(*stream2_syn, 3), 2894 CreateMockRead(*stream3_syn, 4), 2895 CreateMockRead(*stream1_body, 6, SYNCHRONOUS), 2896 CreateMockRead(*stream2_body, 7), 2897 MockRead(ASYNC, ERR_IO_PENDING, 8), // Force a pause 2898 }; 2899 2900 HttpResponseInfo response; 2901 HttpResponseInfo response2; 2902 std::string expected_push_result("pushed"); 2903 OrderedSocketData data(reads, arraysize(reads), 2904 writes, arraysize(writes)); 2905 RunServerPushTest(&data, 2906 &response, 2907 &response2, 2908 expected_push_result); 2909 2910 // Verify the SYN_REPLY. 2911 EXPECT_TRUE(response.headers.get() != NULL); 2912 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine()); 2913 2914 // Verify the pushed stream. 2915 EXPECT_TRUE(response2.headers.get() != NULL); 2916 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine()); 2917 } 2918 2919 TEST_P(SpdyNetworkTransactionTest, ServerPushMultipleDataFrame) { 2920 scoped_ptr<SpdyFrame> stream1_syn( 2921 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); 2922 scoped_ptr<SpdyFrame> stream1_body( 2923 spdy_util_.ConstructSpdyBodyFrame(1, true)); 2924 MockWrite writes[] = { 2925 CreateMockWrite(*stream1_syn, 1), 2926 }; 2927 2928 scoped_ptr<SpdyFrame> 2929 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 2930 scoped_ptr<SpdyFrame> 2931 stream2_syn(spdy_util_.ConstructSpdyPush(NULL, 2932 0, 2933 2, 2934 1, 2935 "http://www.google.com/foo.dat")); 2936 static const char kPushedData[] = "pushed my darling hello my baby"; 2937 scoped_ptr<SpdyFrame> stream2_body_base( 2938 spdy_util_.ConstructSpdyBodyFrame( 2939 2, kPushedData, strlen(kPushedData), true)); 2940 const size_t kChunkSize = strlen(kPushedData) / 4; 2941 scoped_ptr<SpdyFrame> stream2_body1( 2942 new SpdyFrame(stream2_body_base->data(), kChunkSize, false)); 2943 scoped_ptr<SpdyFrame> stream2_body2( 2944 new SpdyFrame(stream2_body_base->data() + kChunkSize, kChunkSize, false)); 2945 scoped_ptr<SpdyFrame> stream2_body3( 2946 new SpdyFrame(stream2_body_base->data() + 2 * kChunkSize, 2947 kChunkSize, false)); 2948 scoped_ptr<SpdyFrame> stream2_body4( 2949 new SpdyFrame(stream2_body_base->data() + 3 * kChunkSize, 2950 stream2_body_base->size() - 3 * kChunkSize, false)); 2951 MockRead reads[] = { 2952 CreateMockRead(*stream1_reply, 2), 2953 CreateMockRead(*stream2_syn, 3), 2954 CreateMockRead(*stream2_body1, 4), 2955 CreateMockRead(*stream2_body2, 5), 2956 CreateMockRead(*stream2_body3, 6), 2957 CreateMockRead(*stream2_body4, 7), 2958 CreateMockRead(*stream1_body, 8, SYNCHRONOUS), 2959 MockRead(ASYNC, ERR_IO_PENDING, 9), // Force a pause 2960 }; 2961 2962 HttpResponseInfo response; 2963 HttpResponseInfo response2; 2964 std::string expected_push_result("pushed my darling hello my baby"); 2965 OrderedSocketData data(reads, arraysize(reads), 2966 writes, arraysize(writes)); 2967 RunServerPushTest(&data, &response, &response2, kPushedData); 2968 2969 // Verify the SYN_REPLY. 2970 EXPECT_TRUE(response.headers.get() != NULL); 2971 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine()); 2972 2973 // Verify the pushed stream. 2974 EXPECT_TRUE(response2.headers.get() != NULL); 2975 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine()); 2976 } 2977 2978 TEST_P(SpdyNetworkTransactionTest, ServerPushMultipleDataFrameInterrupted) { 2979 scoped_ptr<SpdyFrame> stream1_syn( 2980 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); 2981 scoped_ptr<SpdyFrame> stream1_body( 2982 spdy_util_.ConstructSpdyBodyFrame(1, true)); 2983 MockWrite writes[] = { 2984 CreateMockWrite(*stream1_syn, 1), 2985 }; 2986 2987 scoped_ptr<SpdyFrame> 2988 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 2989 scoped_ptr<SpdyFrame> 2990 stream2_syn(spdy_util_.ConstructSpdyPush(NULL, 2991 0, 2992 2, 2993 1, 2994 "http://www.google.com/foo.dat")); 2995 static const char kPushedData[] = "pushed my darling hello my baby"; 2996 scoped_ptr<SpdyFrame> stream2_body_base( 2997 spdy_util_.ConstructSpdyBodyFrame( 2998 2, kPushedData, strlen(kPushedData), true)); 2999 const size_t kChunkSize = strlen(kPushedData) / 4; 3000 scoped_ptr<SpdyFrame> stream2_body1( 3001 new SpdyFrame(stream2_body_base->data(), kChunkSize, false)); 3002 scoped_ptr<SpdyFrame> stream2_body2( 3003 new SpdyFrame(stream2_body_base->data() + kChunkSize, kChunkSize, false)); 3004 scoped_ptr<SpdyFrame> stream2_body3( 3005 new SpdyFrame(stream2_body_base->data() + 2 * kChunkSize, 3006 kChunkSize, false)); 3007 scoped_ptr<SpdyFrame> stream2_body4( 3008 new SpdyFrame(stream2_body_base->data() + 3 * kChunkSize, 3009 stream2_body_base->size() - 3 * kChunkSize, false)); 3010 MockRead reads[] = { 3011 CreateMockRead(*stream1_reply, 2), 3012 CreateMockRead(*stream2_syn, 3), 3013 CreateMockRead(*stream2_body1, 4), 3014 CreateMockRead(*stream2_body2, 5), 3015 MockRead(ASYNC, ERR_IO_PENDING, 6), // Force a pause 3016 CreateMockRead(*stream2_body3, 7), 3017 CreateMockRead(*stream2_body4, 8), 3018 CreateMockRead(*stream1_body.get(), 9, SYNCHRONOUS), 3019 MockRead(ASYNC, ERR_IO_PENDING, 10) // Force a pause. 3020 }; 3021 3022 HttpResponseInfo response; 3023 HttpResponseInfo response2; 3024 OrderedSocketData data(reads, arraysize(reads), 3025 writes, arraysize(writes)); 3026 RunServerPushTest(&data, &response, &response2, kPushedData); 3027 3028 // Verify the SYN_REPLY. 3029 EXPECT_TRUE(response.headers.get() != NULL); 3030 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine()); 3031 3032 // Verify the pushed stream. 3033 EXPECT_TRUE(response2.headers.get() != NULL); 3034 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine()); 3035 } 3036 3037 TEST_P(SpdyNetworkTransactionTest, ServerPushInvalidAssociatedStreamID0) { 3038 scoped_ptr<SpdyFrame> stream1_syn( 3039 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); 3040 scoped_ptr<SpdyFrame> stream1_body( 3041 spdy_util_.ConstructSpdyBodyFrame(1, true)); 3042 scoped_ptr<SpdyFrame> stream2_rst( 3043 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM)); 3044 MockWrite writes[] = { 3045 CreateMockWrite(*stream1_syn, 1), 3046 CreateMockWrite(*stream2_rst, 4), 3047 }; 3048 3049 scoped_ptr<SpdyFrame> 3050 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 3051 scoped_ptr<SpdyFrame> 3052 stream2_syn(spdy_util_.ConstructSpdyPush(NULL, 3053 0, 3054 2, 3055 0, 3056 "http://www.google.com/foo.dat")); 3057 MockRead reads[] = { 3058 CreateMockRead(*stream1_reply, 2), 3059 CreateMockRead(*stream2_syn, 3), 3060 CreateMockRead(*stream1_body, 4), 3061 MockRead(ASYNC, ERR_IO_PENDING, 5) // Force a pause 3062 }; 3063 3064 OrderedSocketData data(reads, arraysize(reads), 3065 writes, arraysize(writes)); 3066 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY, 3067 BoundNetLog(), GetParam(), NULL); 3068 3069 helper.RunPreTestSetup(); 3070 helper.AddData(&data); 3071 3072 HttpNetworkTransaction* trans = helper.trans(); 3073 3074 // Start the transaction with basic parameters. 3075 TestCompletionCallback callback; 3076 int rv = trans->Start( 3077 &CreateGetRequest(), callback.callback(), BoundNetLog()); 3078 EXPECT_EQ(ERR_IO_PENDING, rv); 3079 rv = callback.WaitForResult(); 3080 EXPECT_EQ(OK, rv); 3081 3082 // Verify that we consumed all test data. 3083 EXPECT_TRUE(data.at_read_eof()) << "Read count: " 3084 << data.read_count() 3085 << " Read index: " 3086 << data.read_index(); 3087 EXPECT_TRUE(data.at_write_eof()) << "Write count: " 3088 << data.write_count() 3089 << " Write index: " 3090 << data.write_index(); 3091 3092 // Verify the SYN_REPLY. 3093 HttpResponseInfo response = *trans->GetResponseInfo(); 3094 EXPECT_TRUE(response.headers.get() != NULL); 3095 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine()); 3096 } 3097 3098 TEST_P(SpdyNetworkTransactionTest, ServerPushInvalidAssociatedStreamID9) { 3099 scoped_ptr<SpdyFrame> stream1_syn( 3100 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); 3101 scoped_ptr<SpdyFrame> stream1_body( 3102 spdy_util_.ConstructSpdyBodyFrame(1, true)); 3103 scoped_ptr<SpdyFrame> stream2_rst( 3104 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_INVALID_STREAM)); 3105 MockWrite writes[] = { 3106 CreateMockWrite(*stream1_syn, 1), 3107 CreateMockWrite(*stream2_rst, 4), 3108 }; 3109 3110 scoped_ptr<SpdyFrame> 3111 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 3112 scoped_ptr<SpdyFrame> 3113 stream2_syn(spdy_util_.ConstructSpdyPush(NULL, 3114 0, 3115 2, 3116 9, 3117 "http://www.google.com/foo.dat")); 3118 MockRead reads[] = { 3119 CreateMockRead(*stream1_reply, 2), 3120 CreateMockRead(*stream2_syn, 3), 3121 CreateMockRead(*stream1_body, 4), 3122 MockRead(ASYNC, ERR_IO_PENDING, 5), // Force a pause 3123 }; 3124 3125 OrderedSocketData data(reads, arraysize(reads), 3126 writes, arraysize(writes)); 3127 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY, 3128 BoundNetLog(), GetParam(), NULL); 3129 3130 helper.RunPreTestSetup(); 3131 helper.AddData(&data); 3132 3133 HttpNetworkTransaction* trans = helper.trans(); 3134 3135 // Start the transaction with basic parameters. 3136 TestCompletionCallback callback; 3137 int rv = trans->Start( 3138 &CreateGetRequest(), callback.callback(), BoundNetLog()); 3139 EXPECT_EQ(ERR_IO_PENDING, rv); 3140 rv = callback.WaitForResult(); 3141 EXPECT_EQ(OK, rv); 3142 3143 // Verify that we consumed all test data. 3144 EXPECT_TRUE(data.at_read_eof()) << "Read count: " 3145 << data.read_count() 3146 << " Read index: " 3147 << data.read_index(); 3148 EXPECT_TRUE(data.at_write_eof()) << "Write count: " 3149 << data.write_count() 3150 << " Write index: " 3151 << data.write_index(); 3152 3153 // Verify the SYN_REPLY. 3154 HttpResponseInfo response = *trans->GetResponseInfo(); 3155 EXPECT_TRUE(response.headers.get() != NULL); 3156 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine()); 3157 } 3158 3159 TEST_P(SpdyNetworkTransactionTest, ServerPushNoURL) { 3160 scoped_ptr<SpdyFrame> stream1_syn( 3161 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); 3162 scoped_ptr<SpdyFrame> stream1_body( 3163 spdy_util_.ConstructSpdyBodyFrame(1, true)); 3164 scoped_ptr<SpdyFrame> stream2_rst( 3165 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_PROTOCOL_ERROR)); 3166 MockWrite writes[] = { 3167 CreateMockWrite(*stream1_syn, 1), 3168 CreateMockWrite(*stream2_rst, 4), 3169 }; 3170 3171 scoped_ptr<SpdyFrame> 3172 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 3173 scoped_ptr<SpdyHeaderBlock> incomplete_headers(new SpdyHeaderBlock()); 3174 (*incomplete_headers)["hello"] = "bye"; 3175 (*incomplete_headers)[spdy_util_.GetStatusKey()] = "200 OK"; 3176 (*incomplete_headers)[spdy_util_.GetVersionKey()] = "HTTP/1.1"; 3177 scoped_ptr<SpdyFrame> stream2_syn( 3178 spdy_util_.ConstructSpdyControlFrame(incomplete_headers.Pass(), 3179 false, 3180 2, // Stream ID 3181 LOWEST, 3182 SYN_STREAM, 3183 CONTROL_FLAG_NONE, 3184 // Associated stream ID 3185 1)); 3186 MockRead reads[] = { 3187 CreateMockRead(*stream1_reply, 2), 3188 CreateMockRead(*stream2_syn, 3), 3189 CreateMockRead(*stream1_body, 4), 3190 MockRead(ASYNC, ERR_IO_PENDING, 5) // Force a pause 3191 }; 3192 3193 OrderedSocketData data(reads, arraysize(reads), 3194 writes, arraysize(writes)); 3195 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY, 3196 BoundNetLog(), GetParam(), NULL); 3197 3198 helper.RunPreTestSetup(); 3199 helper.AddData(&data); 3200 3201 HttpNetworkTransaction* trans = helper.trans(); 3202 3203 // Start the transaction with basic parameters. 3204 TestCompletionCallback callback; 3205 int rv = trans->Start( 3206 &CreateGetRequest(), callback.callback(), BoundNetLog()); 3207 EXPECT_EQ(ERR_IO_PENDING, rv); 3208 rv = callback.WaitForResult(); 3209 EXPECT_EQ(OK, rv); 3210 // Verify that we consumed all test data. 3211 EXPECT_TRUE(data.at_read_eof()) << "Read count: " 3212 << data.read_count() 3213 << " Read index: " 3214 << data.read_index(); 3215 EXPECT_TRUE(data.at_write_eof()) << "Write count: " 3216 << data.write_count() 3217 << " Write index: " 3218 << data.write_index(); 3219 3220 // Verify the SYN_REPLY. 3221 HttpResponseInfo response = *trans->GetResponseInfo(); 3222 EXPECT_TRUE(response.headers.get() != NULL); 3223 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine()); 3224 } 3225 3226 // Verify that various SynReply headers parse correctly through the 3227 // HTTP layer. 3228 TEST_P(SpdyNetworkTransactionTest, SynReplyHeaders) { 3229 struct SynReplyHeadersTests { 3230 int num_headers; 3231 const char* extra_headers[5]; 3232 SpdyHeaderBlock expected_headers; 3233 } test_cases[] = { 3234 // This uses a multi-valued cookie header. 3235 { 2, 3236 { "cookie", "val1", 3237 "cookie", "val2", // will get appended separated by NULL 3238 NULL 3239 }, 3240 }, 3241 // This is the minimalist set of headers. 3242 { 0, 3243 { NULL }, 3244 }, 3245 // Headers with a comma separated list. 3246 { 1, 3247 { "cookie", "val1,val2", 3248 NULL 3249 }, 3250 } 3251 }; 3252 3253 test_cases[0].expected_headers["cookie"] = "val1"; 3254 test_cases[0].expected_headers["cookie"] += '\0'; 3255 test_cases[0].expected_headers["cookie"] += "val2"; 3256 test_cases[0].expected_headers["hello"] = "bye"; 3257 test_cases[0].expected_headers["status"] = "200"; 3258 test_cases[0].expected_headers["version"] = "HTTP/1.1"; 3259 3260 test_cases[1].expected_headers["hello"] = "bye"; 3261 test_cases[1].expected_headers["status"] = "200"; 3262 test_cases[1].expected_headers["version"] = "HTTP/1.1"; 3263 3264 test_cases[2].expected_headers["cookie"] = "val1,val2"; 3265 test_cases[2].expected_headers["hello"] = "bye"; 3266 test_cases[2].expected_headers["status"] = "200"; 3267 test_cases[2].expected_headers["version"] = "HTTP/1.1"; 3268 3269 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) { 3270 scoped_ptr<SpdyFrame> req( 3271 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); 3272 MockWrite writes[] = { CreateMockWrite(*req) }; 3273 3274 scoped_ptr<SpdyFrame> resp( 3275 spdy_util_.ConstructSpdyGetSynReply(test_cases[i].extra_headers, 3276 test_cases[i].num_headers, 3277 1)); 3278 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true)); 3279 MockRead reads[] = { 3280 CreateMockRead(*resp), 3281 CreateMockRead(*body), 3282 MockRead(ASYNC, 0, 0) // EOF 3283 }; 3284 3285 DelayedSocketData data(1, reads, arraysize(reads), 3286 writes, arraysize(writes)); 3287 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY, 3288 BoundNetLog(), GetParam(), NULL); 3289 helper.RunToCompletion(&data); 3290 TransactionHelperResult out = helper.output(); 3291 3292 EXPECT_EQ(OK, out.rv); 3293 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line); 3294 EXPECT_EQ("hello!", out.response_data); 3295 3296 scoped_refptr<HttpResponseHeaders> headers = out.response_info.headers; 3297 EXPECT_TRUE(headers.get() != NULL); 3298 void* iter = NULL; 3299 std::string name, value; 3300 SpdyHeaderBlock header_block; 3301 while (headers->EnumerateHeaderLines(&iter, &name, &value)) { 3302 if (header_block[name].empty()) { 3303 header_block[name] = value; 3304 } else { 3305 header_block[name] += '\0'; 3306 header_block[name] += value; 3307 } 3308 } 3309 EXPECT_EQ(test_cases[i].expected_headers, header_block); 3310 } 3311 } 3312 3313 // Verify that various SynReply headers parse vary fields correctly 3314 // through the HTTP layer, and the response matches the request. 3315 TEST_P(SpdyNetworkTransactionTest, SynReplyHeadersVary) { 3316 static const SpdyHeaderInfo syn_reply_info = { 3317 SYN_REPLY, // Syn Reply 3318 1, // Stream ID 3319 0, // Associated Stream ID 3320 ConvertRequestPriorityToSpdyPriority( 3321 LOWEST, spdy_util_.spdy_version()), 3322 kSpdyCredentialSlotUnused, 3323 CONTROL_FLAG_NONE, // Control Flags 3324 false, // Compressed 3325 RST_STREAM_INVALID, // Status 3326 NULL, // Data 3327 0, // Data Length 3328 DATA_FLAG_NONE // Data Flags 3329 }; 3330 // Modify the following data to change/add test cases: 3331 struct SynReplyTests { 3332 const SpdyHeaderInfo* syn_reply; 3333 bool vary_matches; 3334 int num_headers[2]; 3335 const char* extra_headers[2][16]; 3336 } test_cases[] = { 3337 // Test the case of a multi-valued cookie. When the value is delimited 3338 // with NUL characters, it needs to be unfolded into multiple headers. 3339 { 3340 &syn_reply_info, 3341 true, 3342 { 1, 4 }, 3343 { { "cookie", "val1,val2", 3344 NULL 3345 }, 3346 { "vary", "cookie", 3347 spdy_util_.GetStatusKey(), "200", 3348 spdy_util_.GetPathKey(), "/index.php", 3349 spdy_util_.GetVersionKey(), "HTTP/1.1", 3350 NULL 3351 } 3352 } 3353 }, { // Multiple vary fields. 3354 &syn_reply_info, 3355 true, 3356 { 2, 5 }, 3357 { { "friend", "barney", 3358 "enemy", "snaggletooth", 3359 NULL 3360 }, 3361 { "vary", "friend", 3362 "vary", "enemy", 3363 spdy_util_.GetStatusKey(), "200", 3364 spdy_util_.GetPathKey(), "/index.php", 3365 spdy_util_.GetVersionKey(), "HTTP/1.1", 3366 NULL 3367 } 3368 } 3369 }, { // Test a '*' vary field. 3370 &syn_reply_info, 3371 false, 3372 { 1, 4 }, 3373 { { "cookie", "val1,val2", 3374 NULL 3375 }, 3376 { "vary", "*", 3377 spdy_util_.GetStatusKey(), "200", 3378 spdy_util_.GetPathKey(), "/index.php", 3379 spdy_util_.GetVersionKey(), "HTTP/1.1", 3380 NULL 3381 } 3382 } 3383 }, { // Multiple comma-separated vary fields. 3384 &syn_reply_info, 3385 true, 3386 { 2, 4 }, 3387 { { "friend", "barney", 3388 "enemy", "snaggletooth", 3389 NULL 3390 }, 3391 { "vary", "friend,enemy", 3392 spdy_util_.GetStatusKey(), "200", 3393 spdy_util_.GetPathKey(), "/index.php", 3394 spdy_util_.GetVersionKey(), "HTTP/1.1", 3395 NULL 3396 } 3397 } 3398 } 3399 }; 3400 3401 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) { 3402 // Construct the request. 3403 scoped_ptr<SpdyFrame> frame_req( 3404 spdy_util_.ConstructSpdyGet(test_cases[i].extra_headers[0], 3405 test_cases[i].num_headers[0], 3406 false, 1, LOWEST, true)); 3407 3408 MockWrite writes[] = { 3409 CreateMockWrite(*frame_req), 3410 }; 3411 3412 // Construct the reply. 3413 scoped_ptr<SpdyFrame> frame_reply( 3414 spdy_util_.ConstructSpdyFrame(*test_cases[i].syn_reply, 3415 test_cases[i].extra_headers[1], 3416 test_cases[i].num_headers[1], 3417 NULL, 3418 0)); 3419 3420 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true)); 3421 MockRead reads[] = { 3422 CreateMockRead(*frame_reply), 3423 CreateMockRead(*body), 3424 MockRead(ASYNC, 0, 0) // EOF 3425 }; 3426 3427 // Attach the headers to the request. 3428 int header_count = test_cases[i].num_headers[0]; 3429 3430 HttpRequestInfo request = CreateGetRequest(); 3431 for (int ct = 0; ct < header_count; ct++) { 3432 const char* header_key = test_cases[i].extra_headers[0][ct * 2]; 3433 const char* header_value = test_cases[i].extra_headers[0][ct * 2 + 1]; 3434 request.extra_headers.SetHeader(header_key, header_value); 3435 } 3436 3437 DelayedSocketData data(1, reads, arraysize(reads), 3438 writes, arraysize(writes)); 3439 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY, 3440 BoundNetLog(), GetParam(), NULL); 3441 helper.RunToCompletion(&data); 3442 TransactionHelperResult out = helper.output(); 3443 3444 EXPECT_EQ(OK, out.rv) << i; 3445 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line) << i; 3446 EXPECT_EQ("hello!", out.response_data) << i; 3447 3448 // Test the response information. 3449 EXPECT_TRUE(out.response_info.response_time > 3450 out.response_info.request_time) << i; 3451 base::TimeDelta test_delay = out.response_info.response_time - 3452 out.response_info.request_time; 3453 base::TimeDelta min_expected_delay; 3454 min_expected_delay.FromMilliseconds(10); 3455 EXPECT_GT(test_delay.InMillisecondsF(), 3456 min_expected_delay.InMillisecondsF()) << i; 3457 EXPECT_EQ(out.response_info.vary_data.is_valid(), 3458 test_cases[i].vary_matches) << i; 3459 3460 // Check the headers. 3461 scoped_refptr<HttpResponseHeaders> headers = out.response_info.headers; 3462 ASSERT_TRUE(headers.get() != NULL) << i; 3463 void* iter = NULL; 3464 std::string name, value, lines; 3465 while (headers->EnumerateHeaderLines(&iter, &name, &value)) { 3466 lines.append(name); 3467 lines.append(": "); 3468 lines.append(value); 3469 lines.append("\n"); 3470 } 3471 3472 // Construct the expected header reply string. 3473 SpdyHeaderBlock reply_headers; 3474 AppendToHeaderBlock(test_cases[i].extra_headers[1], 3475 test_cases[i].num_headers[1], 3476 &reply_headers); 3477 std::string expected_reply = 3478 spdy_util_.ConstructSpdyReplyString(reply_headers); 3479 EXPECT_EQ(expected_reply, lines) << i; 3480 } 3481 } 3482 3483 // Verify that we don't crash on invalid SynReply responses. 3484 TEST_P(SpdyNetworkTransactionTest, InvalidSynReply) { 3485 const SpdyHeaderInfo kSynStartHeader = { 3486 SYN_REPLY, // Kind = SynReply 3487 1, // Stream ID 3488 0, // Associated stream ID 3489 ConvertRequestPriorityToSpdyPriority( 3490 LOWEST, spdy_util_.spdy_version()), 3491 kSpdyCredentialSlotUnused, 3492 CONTROL_FLAG_NONE, // Control Flags 3493 false, // Compressed 3494 RST_STREAM_INVALID, // Status 3495 NULL, // Data 3496 0, // Length 3497 DATA_FLAG_NONE // Data Flags 3498 }; 3499 3500 struct InvalidSynReplyTests { 3501 int num_headers; 3502 const char* headers[10]; 3503 } test_cases[] = { 3504 // SYN_REPLY missing status header 3505 { 4, 3506 { "cookie", "val1", 3507 "cookie", "val2", 3508 spdy_util_.GetPathKey(), "/index.php", 3509 spdy_util_.GetVersionKey(), "HTTP/1.1", 3510 NULL 3511 }, 3512 }, 3513 // SYN_REPLY missing version header 3514 { 2, 3515 { "status", "200", 3516 spdy_util_.GetPathKey(), "/index.php", 3517 NULL 3518 }, 3519 }, 3520 // SYN_REPLY with no headers 3521 { 0, { NULL }, }, 3522 }; 3523 3524 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) { 3525 scoped_ptr<SpdyFrame> req( 3526 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); 3527 scoped_ptr<SpdyFrame> rst( 3528 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR)); 3529 MockWrite writes[] = { 3530 CreateMockWrite(*req), 3531 CreateMockWrite(*rst), 3532 }; 3533 3534 scoped_ptr<SpdyFrame> resp( 3535 spdy_util_.ConstructSpdyFrame(kSynStartHeader, 3536 NULL, 0, 3537 test_cases[i].headers, 3538 test_cases[i].num_headers)); 3539 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true)); 3540 MockRead reads[] = { 3541 CreateMockRead(*resp), 3542 MockRead(ASYNC, 0, 0) // EOF 3543 }; 3544 3545 DelayedSocketData data(1, reads, arraysize(reads), 3546 writes, arraysize(writes)); 3547 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY, 3548 BoundNetLog(), GetParam(), NULL); 3549 helper.RunToCompletion(&data); 3550 TransactionHelperResult out = helper.output(); 3551 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv); 3552 } 3553 } 3554 3555 // Verify that we don't crash on some corrupt frames. 3556 TEST_P(SpdyNetworkTransactionTest, CorruptFrameSessionError) { 3557 // This is the length field that's too short. 3558 scoped_ptr<SpdyFrame> syn_reply_wrong_length( 3559 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 3560 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false); 3561 size_t right_size = 3562 (spdy_util_.spdy_version() < SPDY4) ? 3563 syn_reply_wrong_length->size() - framer.GetControlFrameHeaderSize() : 3564 syn_reply_wrong_length->size(); 3565 size_t wrong_size = right_size - 4; 3566 test::SetFrameLength(syn_reply_wrong_length.get(), 3567 wrong_size, 3568 spdy_util_.spdy_version()); 3569 3570 struct SynReplyTests { 3571 const SpdyFrame* syn_reply; 3572 } test_cases[] = { 3573 { syn_reply_wrong_length.get(), }, 3574 }; 3575 3576 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) { 3577 scoped_ptr<SpdyFrame> req( 3578 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); 3579 scoped_ptr<SpdyFrame> rst( 3580 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR)); 3581 MockWrite writes[] = { 3582 CreateMockWrite(*req), 3583 CreateMockWrite(*rst), 3584 }; 3585 3586 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true)); 3587 MockRead reads[] = { 3588 MockRead(ASYNC, test_cases[i].syn_reply->data(), wrong_size), 3589 CreateMockRead(*body), 3590 MockRead(ASYNC, 0, 0) // EOF 3591 }; 3592 3593 DelayedSocketData data(1, reads, arraysize(reads), 3594 writes, arraysize(writes)); 3595 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY, 3596 BoundNetLog(), GetParam(), NULL); 3597 helper.RunToCompletion(&data); 3598 TransactionHelperResult out = helper.output(); 3599 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv); 3600 } 3601 } 3602 3603 // Test that we shutdown correctly on write errors. 3604 TEST_P(SpdyNetworkTransactionTest, WriteError) { 3605 scoped_ptr<SpdyFrame> req( 3606 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); 3607 MockWrite writes[] = { 3608 // We'll write 10 bytes successfully 3609 MockWrite(ASYNC, req->data(), 10, 0), 3610 // Followed by ERROR! 3611 MockWrite(ASYNC, ERR_FAILED, 1), 3612 }; 3613 3614 MockRead reads[] = { 3615 MockRead(ASYNC, 0, 2) // EOF 3616 }; 3617 3618 DeterministicSocketData data(reads, arraysize(reads), 3619 writes, arraysize(writes)); 3620 3621 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY, 3622 BoundNetLog(), GetParam(), NULL); 3623 helper.SetDeterministic(); 3624 helper.RunPreTestSetup(); 3625 helper.AddDeterministicData(&data); 3626 EXPECT_TRUE(helper.StartDefaultTest()); 3627 data.RunFor(2); 3628 helper.FinishDefaultTest(); 3629 EXPECT_TRUE(data.at_write_eof()); 3630 EXPECT_TRUE(!data.at_read_eof()); 3631 TransactionHelperResult out = helper.output(); 3632 EXPECT_EQ(ERR_FAILED, out.rv); 3633 } 3634 3635 // Test that partial writes work. 3636 TEST_P(SpdyNetworkTransactionTest, PartialWrite) { 3637 // Chop the SYN_STREAM frame into 5 chunks. 3638 scoped_ptr<SpdyFrame> req( 3639 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); 3640 const int kChunks = 5; 3641 scoped_ptr<MockWrite[]> writes(ChopWriteFrame(*req.get(), kChunks)); 3642 3643 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 3644 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true)); 3645 MockRead reads[] = { 3646 CreateMockRead(*resp), 3647 CreateMockRead(*body), 3648 MockRead(ASYNC, 0, 0) // EOF 3649 }; 3650 3651 DelayedSocketData data(kChunks, reads, arraysize(reads), 3652 writes.get(), kChunks); 3653 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY, 3654 BoundNetLog(), GetParam(), NULL); 3655 helper.RunToCompletion(&data); 3656 TransactionHelperResult out = helper.output(); 3657 EXPECT_EQ(OK, out.rv); 3658 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line); 3659 EXPECT_EQ("hello!", out.response_data); 3660 } 3661 3662 // In this test, we enable compression, but get a uncompressed SynReply from 3663 // the server. Verify that teardown is all clean. 3664 TEST_P(SpdyNetworkTransactionTest, DecompressFailureOnSynReply) { 3665 scoped_ptr<SpdyFrame> compressed( 3666 spdy_util_.ConstructSpdyGet(NULL, 0, true, 1, LOWEST, true)); 3667 scoped_ptr<SpdyFrame> rst( 3668 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR)); 3669 MockWrite writes[] = { 3670 CreateMockWrite(*compressed), 3671 }; 3672 3673 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 3674 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true)); 3675 MockRead reads[] = { 3676 CreateMockRead(*resp), 3677 }; 3678 3679 DelayedSocketData data(1, reads, arraysize(reads), 3680 writes, arraysize(writes)); 3681 SpdySessionDependencies* session_deps = 3682 CreateSpdySessionDependencies(GetParam()); 3683 session_deps->enable_compression = true; 3684 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY, 3685 BoundNetLog(), GetParam(), session_deps); 3686 helper.RunToCompletion(&data); 3687 TransactionHelperResult out = helper.output(); 3688 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv); 3689 data.Reset(); 3690 } 3691 3692 // Test that the NetLog contains good data for a simple GET request. 3693 TEST_P(SpdyNetworkTransactionTest, NetLog) { 3694 static const char* const kExtraHeaders[] = { 3695 "user-agent", "Chrome", 3696 }; 3697 scoped_ptr<SpdyFrame> req( 3698 spdy_util_.ConstructSpdyGet(kExtraHeaders, 1, false, 1, LOWEST, true)); 3699 MockWrite writes[] = { CreateMockWrite(*req) }; 3700 3701 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 3702 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true)); 3703 MockRead reads[] = { 3704 CreateMockRead(*resp), 3705 CreateMockRead(*body), 3706 MockRead(ASYNC, 0, 0) // EOF 3707 }; 3708 3709 CapturingBoundNetLog log; 3710 3711 DelayedSocketData data(1, reads, arraysize(reads), 3712 writes, arraysize(writes)); 3713 NormalSpdyTransactionHelper helper(CreateGetRequestWithUserAgent(), 3714 DEFAULT_PRIORITY, 3715 log.bound(), GetParam(), NULL); 3716 helper.RunToCompletion(&data); 3717 TransactionHelperResult out = helper.output(); 3718 EXPECT_EQ(OK, out.rv); 3719 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line); 3720 EXPECT_EQ("hello!", out.response_data); 3721 3722 // Check that the NetLog was filled reasonably. 3723 // This test is intentionally non-specific about the exact ordering of the 3724 // log; instead we just check to make sure that certain events exist, and that 3725 // they are in the right order. 3726 net::CapturingNetLog::CapturedEntryList entries; 3727 log.GetEntries(&entries); 3728 3729 EXPECT_LT(0u, entries.size()); 3730 int pos = 0; 3731 pos = net::ExpectLogContainsSomewhere(entries, 0, 3732 net::NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST, 3733 net::NetLog::PHASE_BEGIN); 3734 pos = net::ExpectLogContainsSomewhere(entries, pos + 1, 3735 net::NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST, 3736 net::NetLog::PHASE_END); 3737 pos = net::ExpectLogContainsSomewhere(entries, pos + 1, 3738 net::NetLog::TYPE_HTTP_TRANSACTION_READ_HEADERS, 3739 net::NetLog::PHASE_BEGIN); 3740 pos = net::ExpectLogContainsSomewhere(entries, pos + 1, 3741 net::NetLog::TYPE_HTTP_TRANSACTION_READ_HEADERS, 3742 net::NetLog::PHASE_END); 3743 pos = net::ExpectLogContainsSomewhere(entries, pos + 1, 3744 net::NetLog::TYPE_HTTP_TRANSACTION_READ_BODY, 3745 net::NetLog::PHASE_BEGIN); 3746 pos = net::ExpectLogContainsSomewhere(entries, pos + 1, 3747 net::NetLog::TYPE_HTTP_TRANSACTION_READ_BODY, 3748 net::NetLog::PHASE_END); 3749 3750 // Check that we logged all the headers correctly 3751 pos = net::ExpectLogContainsSomewhere( 3752 entries, 0, 3753 net::NetLog::TYPE_SPDY_SESSION_SYN_STREAM, 3754 net::NetLog::PHASE_NONE); 3755 3756 base::ListValue* header_list; 3757 ASSERT_TRUE(entries[pos].params.get()); 3758 ASSERT_TRUE(entries[pos].params->GetList("headers", &header_list)); 3759 3760 std::vector<std::string> expected; 3761 expected.push_back(std::string(spdy_util_.GetHostKey()) + ": www.google.com"); 3762 expected.push_back(std::string(spdy_util_.GetPathKey()) + ": /"); 3763 expected.push_back(std::string(spdy_util_.GetSchemeKey()) + ": http"); 3764 expected.push_back(std::string(spdy_util_.GetVersionKey()) + ": HTTP/1.1"); 3765 expected.push_back(std::string(spdy_util_.GetMethodKey()) + ": GET"); 3766 expected.push_back("user-agent: Chrome"); 3767 EXPECT_EQ(expected.size(), header_list->GetSize()); 3768 for (std::vector<std::string>::const_iterator it = expected.begin(); 3769 it != expected.end(); 3770 ++it) { 3771 base::StringValue header(*it); 3772 EXPECT_NE(header_list->end(), header_list->Find(header)) << 3773 "Header not found: " << *it; 3774 } 3775 } 3776 3777 // Since we buffer the IO from the stream to the renderer, this test verifies 3778 // that when we read out the maximum amount of data (e.g. we received 50 bytes 3779 // on the network, but issued a Read for only 5 of those bytes) that the data 3780 // flow still works correctly. 3781 TEST_P(SpdyNetworkTransactionTest, BufferFull) { 3782 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false); 3783 3784 scoped_ptr<SpdyFrame> req( 3785 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); 3786 MockWrite writes[] = { CreateMockWrite(*req) }; 3787 3788 // 2 data frames in a single read. 3789 scoped_ptr<SpdyFrame> data_frame_1( 3790 framer.CreateDataFrame(1, "goodby", 6, DATA_FLAG_NONE)); 3791 scoped_ptr<SpdyFrame> data_frame_2( 3792 framer.CreateDataFrame(1, "e worl", 6, DATA_FLAG_NONE)); 3793 const SpdyFrame* data_frames[2] = { 3794 data_frame_1.get(), 3795 data_frame_2.get(), 3796 }; 3797 char combined_data_frames[100]; 3798 int combined_data_frames_len = 3799 CombineFrames(data_frames, arraysize(data_frames), 3800 combined_data_frames, arraysize(combined_data_frames)); 3801 scoped_ptr<SpdyFrame> last_frame( 3802 framer.CreateDataFrame(1, "d", 1, DATA_FLAG_FIN)); 3803 3804 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 3805 MockRead reads[] = { 3806 CreateMockRead(*resp), 3807 MockRead(ASYNC, ERR_IO_PENDING), // Force a pause 3808 MockRead(ASYNC, combined_data_frames, combined_data_frames_len), 3809 MockRead(ASYNC, ERR_IO_PENDING), // Force a pause 3810 CreateMockRead(*last_frame), 3811 MockRead(ASYNC, 0, 0) // EOF 3812 }; 3813 3814 DelayedSocketData data(1, reads, arraysize(reads), 3815 writes, arraysize(writes)); 3816 3817 TestCompletionCallback callback; 3818 3819 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY, 3820 BoundNetLog(), GetParam(), NULL); 3821 helper.RunPreTestSetup(); 3822 helper.AddData(&data); 3823 HttpNetworkTransaction* trans = helper.trans(); 3824 int rv = trans->Start( 3825 &CreateGetRequest(), callback.callback(), BoundNetLog()); 3826 EXPECT_EQ(ERR_IO_PENDING, rv); 3827 3828 TransactionHelperResult out = helper.output(); 3829 out.rv = callback.WaitForResult(); 3830 EXPECT_EQ(out.rv, OK); 3831 3832 const HttpResponseInfo* response = trans->GetResponseInfo(); 3833 EXPECT_TRUE(response->headers.get() != NULL); 3834 EXPECT_TRUE(response->was_fetched_via_spdy); 3835 out.status_line = response->headers->GetStatusLine(); 3836 out.response_info = *response; // Make a copy so we can verify. 3837 3838 // Read Data 3839 TestCompletionCallback read_callback; 3840 3841 std::string content; 3842 do { 3843 // Read small chunks at a time. 3844 const int kSmallReadSize = 3; 3845 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kSmallReadSize)); 3846 rv = trans->Read(buf.get(), kSmallReadSize, read_callback.callback()); 3847 if (rv == net::ERR_IO_PENDING) { 3848 data.CompleteRead(); 3849 rv = read_callback.WaitForResult(); 3850 } 3851 if (rv > 0) { 3852 content.append(buf->data(), rv); 3853 } else if (rv < 0) { 3854 NOTREACHED(); 3855 } 3856 } while (rv > 0); 3857 3858 out.response_data.swap(content); 3859 3860 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the 3861 // MockClientSocketFactory) are still alive. 3862 base::RunLoop().RunUntilIdle(); 3863 3864 // Verify that we consumed all test data. 3865 helper.VerifyDataConsumed(); 3866 3867 EXPECT_EQ(OK, out.rv); 3868 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line); 3869 EXPECT_EQ("goodbye world", out.response_data); 3870 } 3871 3872 // Verify that basic buffering works; when multiple data frames arrive 3873 // at the same time, ensure that we don't notify a read completion for 3874 // each data frame individually. 3875 TEST_P(SpdyNetworkTransactionTest, Buffering) { 3876 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false); 3877 3878 scoped_ptr<SpdyFrame> req( 3879 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); 3880 MockWrite writes[] = { CreateMockWrite(*req) }; 3881 3882 // 4 data frames in a single read. 3883 scoped_ptr<SpdyFrame> data_frame( 3884 framer.CreateDataFrame(1, "message", 7, DATA_FLAG_NONE)); 3885 scoped_ptr<SpdyFrame> data_frame_fin( 3886 framer.CreateDataFrame(1, "message", 7, DATA_FLAG_FIN)); 3887 const SpdyFrame* data_frames[4] = { 3888 data_frame.get(), 3889 data_frame.get(), 3890 data_frame.get(), 3891 data_frame_fin.get() 3892 }; 3893 char combined_data_frames[100]; 3894 int combined_data_frames_len = 3895 CombineFrames(data_frames, arraysize(data_frames), 3896 combined_data_frames, arraysize(combined_data_frames)); 3897 3898 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 3899 MockRead reads[] = { 3900 CreateMockRead(*resp), 3901 MockRead(ASYNC, ERR_IO_PENDING), // Force a pause 3902 MockRead(ASYNC, combined_data_frames, combined_data_frames_len), 3903 MockRead(ASYNC, 0, 0) // EOF 3904 }; 3905 3906 DelayedSocketData data(1, reads, arraysize(reads), 3907 writes, arraysize(writes)); 3908 3909 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY, 3910 BoundNetLog(), GetParam(), NULL); 3911 helper.RunPreTestSetup(); 3912 helper.AddData(&data); 3913 HttpNetworkTransaction* trans = helper.trans(); 3914 3915 TestCompletionCallback callback; 3916 int rv = trans->Start( 3917 &CreateGetRequest(), callback.callback(), BoundNetLog()); 3918 EXPECT_EQ(ERR_IO_PENDING, rv); 3919 3920 TransactionHelperResult out = helper.output(); 3921 out.rv = callback.WaitForResult(); 3922 EXPECT_EQ(out.rv, OK); 3923 3924 const HttpResponseInfo* response = trans->GetResponseInfo(); 3925 EXPECT_TRUE(response->headers.get() != NULL); 3926 EXPECT_TRUE(response->was_fetched_via_spdy); 3927 out.status_line = response->headers->GetStatusLine(); 3928 out.response_info = *response; // Make a copy so we can verify. 3929 3930 // Read Data 3931 TestCompletionCallback read_callback; 3932 3933 std::string content; 3934 int reads_completed = 0; 3935 do { 3936 // Read small chunks at a time. 3937 const int kSmallReadSize = 14; 3938 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kSmallReadSize)); 3939 rv = trans->Read(buf.get(), kSmallReadSize, read_callback.callback()); 3940 if (rv == net::ERR_IO_PENDING) { 3941 data.CompleteRead(); 3942 rv = read_callback.WaitForResult(); 3943 } 3944 if (rv > 0) { 3945 EXPECT_EQ(kSmallReadSize, rv); 3946 content.append(buf->data(), rv); 3947 } else if (rv < 0) { 3948 FAIL() << "Unexpected read error: " << rv; 3949 } 3950 reads_completed++; 3951 } while (rv > 0); 3952 3953 EXPECT_EQ(3, reads_completed); // Reads are: 14 bytes, 14 bytes, 0 bytes. 3954 3955 out.response_data.swap(content); 3956 3957 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the 3958 // MockClientSocketFactory) are still alive. 3959 base::RunLoop().RunUntilIdle(); 3960 3961 // Verify that we consumed all test data. 3962 helper.VerifyDataConsumed(); 3963 3964 EXPECT_EQ(OK, out.rv); 3965 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line); 3966 EXPECT_EQ("messagemessagemessagemessage", out.response_data); 3967 } 3968 3969 // Verify the case where we buffer data but read it after it has been buffered. 3970 TEST_P(SpdyNetworkTransactionTest, BufferedAll) { 3971 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false); 3972 3973 scoped_ptr<SpdyFrame> req( 3974 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); 3975 MockWrite writes[] = { CreateMockWrite(*req) }; 3976 3977 // 5 data frames in a single read. 3978 scoped_ptr<SpdyFrame> syn_reply( 3979 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 3980 // turn off FIN bit 3981 test::SetFrameFlags( 3982 syn_reply.get(), CONTROL_FLAG_NONE, spdy_util_.spdy_version()); 3983 scoped_ptr<SpdyFrame> data_frame( 3984 framer.CreateDataFrame(1, "message", 7, DATA_FLAG_NONE)); 3985 scoped_ptr<SpdyFrame> data_frame_fin( 3986 framer.CreateDataFrame(1, "message", 7, DATA_FLAG_FIN)); 3987 const SpdyFrame* frames[5] = { 3988 syn_reply.get(), 3989 data_frame.get(), 3990 data_frame.get(), 3991 data_frame.get(), 3992 data_frame_fin.get() 3993 }; 3994 char combined_frames[200]; 3995 int combined_frames_len = 3996 CombineFrames(frames, arraysize(frames), 3997 combined_frames, arraysize(combined_frames)); 3998 3999 MockRead reads[] = { 4000 MockRead(ASYNC, combined_frames, combined_frames_len), 4001 MockRead(ASYNC, 0, 0) // EOF 4002 }; 4003 4004 DelayedSocketData data(1, reads, arraysize(reads), 4005 writes, arraysize(writes)); 4006 4007 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY, 4008 BoundNetLog(), GetParam(), NULL); 4009 helper.RunPreTestSetup(); 4010 helper.AddData(&data); 4011 HttpNetworkTransaction* trans = helper.trans(); 4012 4013 TestCompletionCallback callback; 4014 int rv = trans->Start( 4015 &CreateGetRequest(), callback.callback(), BoundNetLog()); 4016 EXPECT_EQ(ERR_IO_PENDING, rv); 4017 4018 TransactionHelperResult out = helper.output(); 4019 out.rv = callback.WaitForResult(); 4020 EXPECT_EQ(out.rv, OK); 4021 4022 const HttpResponseInfo* response = trans->GetResponseInfo(); 4023 EXPECT_TRUE(response->headers.get() != NULL); 4024 EXPECT_TRUE(response->was_fetched_via_spdy); 4025 out.status_line = response->headers->GetStatusLine(); 4026 out.response_info = *response; // Make a copy so we can verify. 4027 4028 // Read Data 4029 TestCompletionCallback read_callback; 4030 4031 std::string content; 4032 int reads_completed = 0; 4033 do { 4034 // Read small chunks at a time. 4035 const int kSmallReadSize = 14; 4036 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kSmallReadSize)); 4037 rv = trans->Read(buf.get(), kSmallReadSize, read_callback.callback()); 4038 if (rv > 0) { 4039 EXPECT_EQ(kSmallReadSize, rv); 4040 content.append(buf->data(), rv); 4041 } else if (rv < 0) { 4042 FAIL() << "Unexpected read error: " << rv; 4043 } 4044 reads_completed++; 4045 } while (rv > 0); 4046 4047 EXPECT_EQ(3, reads_completed); 4048 4049 out.response_data.swap(content); 4050 4051 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the 4052 // MockClientSocketFactory) are still alive. 4053 base::RunLoop().RunUntilIdle(); 4054 4055 // Verify that we consumed all test data. 4056 helper.VerifyDataConsumed(); 4057 4058 EXPECT_EQ(OK, out.rv); 4059 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line); 4060 EXPECT_EQ("messagemessagemessagemessage", out.response_data); 4061 } 4062 4063 // Verify the case where we buffer data and close the connection. 4064 TEST_P(SpdyNetworkTransactionTest, BufferedClosed) { 4065 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false); 4066 4067 scoped_ptr<SpdyFrame> req( 4068 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); 4069 MockWrite writes[] = { CreateMockWrite(*req) }; 4070 4071 // All data frames in a single read. 4072 // NOTE: We don't FIN the stream. 4073 scoped_ptr<SpdyFrame> data_frame( 4074 framer.CreateDataFrame(1, "message", 7, DATA_FLAG_NONE)); 4075 const SpdyFrame* data_frames[4] = { 4076 data_frame.get(), 4077 data_frame.get(), 4078 data_frame.get(), 4079 data_frame.get() 4080 }; 4081 char combined_data_frames[100]; 4082 int combined_data_frames_len = 4083 CombineFrames(data_frames, arraysize(data_frames), 4084 combined_data_frames, arraysize(combined_data_frames)); 4085 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 4086 MockRead reads[] = { 4087 CreateMockRead(*resp), 4088 MockRead(ASYNC, ERR_IO_PENDING), // Force a wait 4089 MockRead(ASYNC, combined_data_frames, combined_data_frames_len), 4090 MockRead(ASYNC, 0, 0) // EOF 4091 }; 4092 4093 DelayedSocketData data(1, reads, arraysize(reads), 4094 writes, arraysize(writes)); 4095 4096 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY, 4097 BoundNetLog(), GetParam(), NULL); 4098 helper.RunPreTestSetup(); 4099 helper.AddData(&data); 4100 HttpNetworkTransaction* trans = helper.trans(); 4101 4102 TestCompletionCallback callback; 4103 4104 int rv = trans->Start( 4105 &CreateGetRequest(), callback.callback(), BoundNetLog()); 4106 EXPECT_EQ(ERR_IO_PENDING, rv); 4107 4108 TransactionHelperResult out = helper.output(); 4109 out.rv = callback.WaitForResult(); 4110 EXPECT_EQ(out.rv, OK); 4111 4112 const HttpResponseInfo* response = trans->GetResponseInfo(); 4113 EXPECT_TRUE(response->headers.get() != NULL); 4114 EXPECT_TRUE(response->was_fetched_via_spdy); 4115 out.status_line = response->headers->GetStatusLine(); 4116 out.response_info = *response; // Make a copy so we can verify. 4117 4118 // Read Data 4119 TestCompletionCallback read_callback; 4120 4121 std::string content; 4122 int reads_completed = 0; 4123 do { 4124 // Read small chunks at a time. 4125 const int kSmallReadSize = 14; 4126 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kSmallReadSize)); 4127 rv = trans->Read(buf.get(), kSmallReadSize, read_callback.callback()); 4128 if (rv == net::ERR_IO_PENDING) { 4129 data.CompleteRead(); 4130 rv = read_callback.WaitForResult(); 4131 } 4132 if (rv > 0) { 4133 content.append(buf->data(), rv); 4134 } else if (rv < 0) { 4135 // This test intentionally closes the connection, and will get an error. 4136 EXPECT_EQ(ERR_CONNECTION_CLOSED, rv); 4137 break; 4138 } 4139 reads_completed++; 4140 } while (rv > 0); 4141 4142 EXPECT_EQ(0, reads_completed); 4143 4144 out.response_data.swap(content); 4145 4146 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the 4147 // MockClientSocketFactory) are still alive. 4148 base::RunLoop().RunUntilIdle(); 4149 4150 // Verify that we consumed all test data. 4151 helper.VerifyDataConsumed(); 4152 } 4153 4154 // Verify the case where we buffer data and cancel the transaction. 4155 TEST_P(SpdyNetworkTransactionTest, BufferedCancelled) { 4156 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false); 4157 4158 scoped_ptr<SpdyFrame> req( 4159 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); 4160 MockWrite writes[] = { CreateMockWrite(*req) }; 4161 4162 // NOTE: We don't FIN the stream. 4163 scoped_ptr<SpdyFrame> data_frame( 4164 framer.CreateDataFrame(1, "message", 7, DATA_FLAG_NONE)); 4165 4166 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 4167 MockRead reads[] = { 4168 CreateMockRead(*resp), 4169 MockRead(ASYNC, ERR_IO_PENDING), // Force a wait 4170 CreateMockRead(*data_frame), 4171 MockRead(ASYNC, 0, 0) // EOF 4172 }; 4173 4174 DelayedSocketData data(1, reads, arraysize(reads), 4175 writes, arraysize(writes)); 4176 4177 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY, 4178 BoundNetLog(), GetParam(), NULL); 4179 helper.RunPreTestSetup(); 4180 helper.AddData(&data); 4181 HttpNetworkTransaction* trans = helper.trans(); 4182 TestCompletionCallback callback; 4183 4184 int rv = trans->Start( 4185 &CreateGetRequest(), callback.callback(), BoundNetLog()); 4186 EXPECT_EQ(ERR_IO_PENDING, rv); 4187 4188 TransactionHelperResult out = helper.output(); 4189 out.rv = callback.WaitForResult(); 4190 EXPECT_EQ(out.rv, OK); 4191 4192 const HttpResponseInfo* response = trans->GetResponseInfo(); 4193 EXPECT_TRUE(response->headers.get() != NULL); 4194 EXPECT_TRUE(response->was_fetched_via_spdy); 4195 out.status_line = response->headers->GetStatusLine(); 4196 out.response_info = *response; // Make a copy so we can verify. 4197 4198 // Read Data 4199 TestCompletionCallback read_callback; 4200 4201 do { 4202 const int kReadSize = 256; 4203 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kReadSize)); 4204 rv = trans->Read(buf.get(), kReadSize, read_callback.callback()); 4205 if (rv == net::ERR_IO_PENDING) { 4206 // Complete the read now, which causes buffering to start. 4207 data.CompleteRead(); 4208 // Destroy the transaction, causing the stream to get cancelled 4209 // and orphaning the buffered IO task. 4210 helper.ResetTrans(); 4211 break; 4212 } 4213 // We shouldn't get here in this test. 4214 FAIL() << "Unexpected read: " << rv; 4215 } while (rv > 0); 4216 4217 // Flush the MessageLoop; this will cause the buffered IO task 4218 // to run for the final time. 4219 base::RunLoop().RunUntilIdle(); 4220 4221 // Verify that we consumed all test data. 4222 helper.VerifyDataConsumed(); 4223 } 4224 4225 // Test that if the server requests persistence of settings, that we save 4226 // the settings in the HttpServerProperties. 4227 TEST_P(SpdyNetworkTransactionTest, SettingsSaved) { 4228 static const SpdyHeaderInfo kSynReplyInfo = { 4229 SYN_REPLY, // Syn Reply 4230 1, // Stream ID 4231 0, // Associated Stream ID 4232 ConvertRequestPriorityToSpdyPriority( 4233 LOWEST, spdy_util_.spdy_version()), 4234 kSpdyCredentialSlotUnused, 4235 CONTROL_FLAG_NONE, // Control Flags 4236 false, // Compressed 4237 RST_STREAM_INVALID, // Status 4238 NULL, // Data 4239 0, // Data Length 4240 DATA_FLAG_NONE // Data Flags 4241 }; 4242 4243 BoundNetLog net_log; 4244 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY, 4245 net_log, GetParam(), NULL); 4246 helper.RunPreTestSetup(); 4247 4248 // Verify that no settings exist initially. 4249 HostPortPair host_port_pair("www.google.com", helper.port()); 4250 SpdySessionPool* spdy_session_pool = helper.session()->spdy_session_pool(); 4251 EXPECT_TRUE(spdy_session_pool->http_server_properties()->GetSpdySettings( 4252 host_port_pair).empty()); 4253 4254 // Construct the request. 4255 scoped_ptr<SpdyFrame> req( 4256 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); 4257 MockWrite writes[] = { CreateMockWrite(*req) }; 4258 4259 // Construct the reply. 4260 scoped_ptr<SpdyHeaderBlock> reply_headers(new SpdyHeaderBlock()); 4261 (*reply_headers)[spdy_util_.GetStatusKey()] = "200"; 4262 (*reply_headers)[spdy_util_.GetVersionKey()] = "HTTP/1.1"; 4263 scoped_ptr<SpdyFrame> reply( 4264 spdy_util_.ConstructSpdyFrame(kSynReplyInfo, reply_headers.Pass())); 4265 4266 const SpdySettingsIds kSampleId1 = SETTINGS_UPLOAD_BANDWIDTH; 4267 unsigned int kSampleValue1 = 0x0a0a0a0a; 4268 const SpdySettingsIds kSampleId2 = SETTINGS_DOWNLOAD_BANDWIDTH; 4269 unsigned int kSampleValue2 = 0x0b0b0b0b; 4270 const SpdySettingsIds kSampleId3 = SETTINGS_ROUND_TRIP_TIME; 4271 unsigned int kSampleValue3 = 0x0c0c0c0c; 4272 scoped_ptr<SpdyFrame> settings_frame; 4273 { 4274 // Construct the SETTINGS frame. 4275 SettingsMap settings; 4276 // First add a persisted setting. 4277 settings[kSampleId1] = 4278 SettingsFlagsAndValue(SETTINGS_FLAG_PLEASE_PERSIST, kSampleValue1); 4279 // Next add a non-persisted setting. 4280 settings[kSampleId2] = 4281 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, kSampleValue2); 4282 // Next add another persisted setting. 4283 settings[kSampleId3] = 4284 SettingsFlagsAndValue(SETTINGS_FLAG_PLEASE_PERSIST, kSampleValue3); 4285 settings_frame.reset(spdy_util_.ConstructSpdySettings(settings)); 4286 } 4287 4288 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true)); 4289 MockRead reads[] = { 4290 CreateMockRead(*reply), 4291 CreateMockRead(*body), 4292 CreateMockRead(*settings_frame), 4293 MockRead(ASYNC, 0, 0) // EOF 4294 }; 4295 4296 DelayedSocketData data(1, reads, arraysize(reads), 4297 writes, arraysize(writes)); 4298 helper.AddData(&data); 4299 helper.RunDefaultTest(); 4300 helper.VerifyDataConsumed(); 4301 TransactionHelperResult out = helper.output(); 4302 EXPECT_EQ(OK, out.rv); 4303 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line); 4304 EXPECT_EQ("hello!", out.response_data); 4305 4306 { 4307 // Verify we had two persisted settings. 4308 const SettingsMap& settings_map = 4309 spdy_session_pool->http_server_properties()->GetSpdySettings( 4310 host_port_pair); 4311 ASSERT_EQ(2u, settings_map.size()); 4312 4313 // Verify the first persisted setting. 4314 SettingsMap::const_iterator it1 = settings_map.find(kSampleId1); 4315 EXPECT_TRUE(it1 != settings_map.end()); 4316 SettingsFlagsAndValue flags_and_value1 = it1->second; 4317 EXPECT_EQ(SETTINGS_FLAG_PERSISTED, flags_and_value1.first); 4318 EXPECT_EQ(kSampleValue1, flags_and_value1.second); 4319 4320 // Verify the second persisted setting. 4321 SettingsMap::const_iterator it3 = settings_map.find(kSampleId3); 4322 EXPECT_TRUE(it3 != settings_map.end()); 4323 SettingsFlagsAndValue flags_and_value3 = it3->second; 4324 EXPECT_EQ(SETTINGS_FLAG_PERSISTED, flags_and_value3.first); 4325 EXPECT_EQ(kSampleValue3, flags_and_value3.second); 4326 } 4327 } 4328 4329 // Test that when there are settings saved that they are sent back to the 4330 // server upon session establishment. 4331 TEST_P(SpdyNetworkTransactionTest, SettingsPlayback) { 4332 static const SpdyHeaderInfo kSynReplyInfo = { 4333 SYN_REPLY, // Syn Reply 4334 1, // Stream ID 4335 0, // Associated Stream ID 4336 ConvertRequestPriorityToSpdyPriority( 4337 LOWEST, spdy_util_.spdy_version()), 4338 kSpdyCredentialSlotUnused, 4339 CONTROL_FLAG_NONE, // Control Flags 4340 false, // Compressed 4341 RST_STREAM_INVALID, // Status 4342 NULL, // Data 4343 0, // Data Length 4344 DATA_FLAG_NONE // Data Flags 4345 }; 4346 4347 BoundNetLog net_log; 4348 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY, 4349 net_log, GetParam(), NULL); 4350 helper.RunPreTestSetup(); 4351 4352 SpdySessionPool* spdy_session_pool = helper.session()->spdy_session_pool(); 4353 4354 SpdySessionPoolPeer pool_peer(spdy_session_pool); 4355 pool_peer.SetEnableSendingInitialData(true); 4356 4357 // Verify that no settings exist initially. 4358 HostPortPair host_port_pair("www.google.com", helper.port()); 4359 EXPECT_TRUE(spdy_session_pool->http_server_properties()->GetSpdySettings( 4360 host_port_pair).empty()); 4361 4362 const SpdySettingsIds kSampleId1 = SETTINGS_UPLOAD_BANDWIDTH; 4363 unsigned int kSampleValue1 = 0x0a0a0a0a; 4364 const SpdySettingsIds kSampleId2 = SETTINGS_ROUND_TRIP_TIME; 4365 unsigned int kSampleValue2 = 0x0c0c0c0c; 4366 4367 // First add a persisted setting. 4368 spdy_session_pool->http_server_properties()->SetSpdySetting( 4369 host_port_pair, 4370 kSampleId1, 4371 SETTINGS_FLAG_PLEASE_PERSIST, 4372 kSampleValue1); 4373 4374 // Next add another persisted setting. 4375 spdy_session_pool->http_server_properties()->SetSpdySetting( 4376 host_port_pair, 4377 kSampleId2, 4378 SETTINGS_FLAG_PLEASE_PERSIST, 4379 kSampleValue2); 4380 4381 EXPECT_EQ(2u, spdy_session_pool->http_server_properties()->GetSpdySettings( 4382 host_port_pair).size()); 4383 4384 // Construct the initial SETTINGS frame. 4385 SettingsMap initial_settings; 4386 initial_settings[SETTINGS_MAX_CONCURRENT_STREAMS] = 4387 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, kMaxConcurrentPushedStreams); 4388 scoped_ptr<SpdyFrame> initial_settings_frame( 4389 spdy_util_.ConstructSpdySettings(initial_settings)); 4390 4391 // Construct the initial window update. 4392 scoped_ptr<SpdyFrame> initial_window_update( 4393 spdy_util_.ConstructSpdyWindowUpdate( 4394 kSessionFlowControlStreamId, 4395 kDefaultInitialRecvWindowSize - kSpdySessionInitialWindowSize)); 4396 4397 // Construct the persisted SETTINGS frame. 4398 const SettingsMap& settings = 4399 spdy_session_pool->http_server_properties()->GetSpdySettings( 4400 host_port_pair); 4401 scoped_ptr<SpdyFrame> settings_frame( 4402 spdy_util_.ConstructSpdySettings(settings)); 4403 4404 // Construct the request. 4405 scoped_ptr<SpdyFrame> req( 4406 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); 4407 4408 std::vector<MockWrite> writes; 4409 if (GetParam().protocol == kProtoHTTP2Draft04) { 4410 writes.push_back( 4411 MockWrite(ASYNC, 4412 kHttp2ConnectionHeaderPrefix, 4413 kHttp2ConnectionHeaderPrefixSize)); 4414 } 4415 writes.push_back(CreateMockWrite(*initial_settings_frame)); 4416 if (GetParam().protocol >= kProtoSPDY31) { 4417 writes.push_back(CreateMockWrite(*initial_window_update)); 4418 }; 4419 writes.push_back(CreateMockWrite(*settings_frame)); 4420 writes.push_back(CreateMockWrite(*req)); 4421 4422 // Construct the reply. 4423 scoped_ptr<SpdyHeaderBlock> reply_headers(new SpdyHeaderBlock()); 4424 (*reply_headers)[spdy_util_.GetStatusKey()] = "200"; 4425 (*reply_headers)[spdy_util_.GetVersionKey()] = "HTTP/1.1"; 4426 scoped_ptr<SpdyFrame> reply( 4427 spdy_util_.ConstructSpdyFrame(kSynReplyInfo, reply_headers.Pass())); 4428 4429 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true)); 4430 MockRead reads[] = { 4431 CreateMockRead(*reply), 4432 CreateMockRead(*body), 4433 MockRead(ASYNC, 0, 0) // EOF 4434 }; 4435 4436 DelayedSocketData data(2, reads, arraysize(reads), 4437 vector_as_array(&writes), writes.size()); 4438 helper.AddData(&data); 4439 helper.RunDefaultTest(); 4440 helper.VerifyDataConsumed(); 4441 TransactionHelperResult out = helper.output(); 4442 EXPECT_EQ(OK, out.rv); 4443 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line); 4444 EXPECT_EQ("hello!", out.response_data); 4445 4446 { 4447 // Verify we had two persisted settings. 4448 const SettingsMap& settings_map = 4449 spdy_session_pool->http_server_properties()->GetSpdySettings( 4450 host_port_pair); 4451 ASSERT_EQ(2u, settings_map.size()); 4452 4453 // Verify the first persisted setting. 4454 SettingsMap::const_iterator it1 = settings_map.find(kSampleId1); 4455 EXPECT_TRUE(it1 != settings_map.end()); 4456 SettingsFlagsAndValue flags_and_value1 = it1->second; 4457 EXPECT_EQ(SETTINGS_FLAG_PERSISTED, flags_and_value1.first); 4458 EXPECT_EQ(kSampleValue1, flags_and_value1.second); 4459 4460 // Verify the second persisted setting. 4461 SettingsMap::const_iterator it2 = settings_map.find(kSampleId2); 4462 EXPECT_TRUE(it2 != settings_map.end()); 4463 SettingsFlagsAndValue flags_and_value2 = it2->second; 4464 EXPECT_EQ(SETTINGS_FLAG_PERSISTED, flags_and_value2.first); 4465 EXPECT_EQ(kSampleValue2, flags_and_value2.second); 4466 } 4467 } 4468 4469 TEST_P(SpdyNetworkTransactionTest, GoAwayWithActiveStream) { 4470 scoped_ptr<SpdyFrame> req( 4471 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); 4472 MockWrite writes[] = { CreateMockWrite(*req) }; 4473 4474 scoped_ptr<SpdyFrame> go_away(spdy_util_.ConstructSpdyGoAway()); 4475 MockRead reads[] = { 4476 CreateMockRead(*go_away), 4477 }; 4478 4479 DelayedSocketData data(1, reads, arraysize(reads), 4480 writes, arraysize(writes)); 4481 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY, 4482 BoundNetLog(), GetParam(), NULL); 4483 helper.AddData(&data); 4484 helper.RunToCompletion(&data); 4485 TransactionHelperResult out = helper.output(); 4486 EXPECT_EQ(ERR_ABORTED, out.rv); 4487 } 4488 4489 TEST_P(SpdyNetworkTransactionTest, CloseWithActiveStream) { 4490 scoped_ptr<SpdyFrame> req( 4491 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); 4492 MockWrite writes[] = { CreateMockWrite(*req) }; 4493 4494 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 4495 MockRead reads[] = { 4496 CreateMockRead(*resp), 4497 MockRead(SYNCHRONOUS, 0, 0) // EOF 4498 }; 4499 4500 DelayedSocketData data(1, reads, arraysize(reads), 4501 writes, arraysize(writes)); 4502 BoundNetLog log; 4503 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY, 4504 log, GetParam(), NULL); 4505 helper.RunPreTestSetup(); 4506 helper.AddData(&data); 4507 HttpNetworkTransaction* trans = helper.trans(); 4508 4509 TestCompletionCallback callback; 4510 TransactionHelperResult out; 4511 out.rv = trans->Start(&CreateGetRequest(), callback.callback(), log); 4512 4513 EXPECT_EQ(out.rv, ERR_IO_PENDING); 4514 out.rv = callback.WaitForResult(); 4515 EXPECT_EQ(out.rv, OK); 4516 4517 const HttpResponseInfo* response = trans->GetResponseInfo(); 4518 EXPECT_TRUE(response->headers.get() != NULL); 4519 EXPECT_TRUE(response->was_fetched_via_spdy); 4520 out.rv = ReadTransaction(trans, &out.response_data); 4521 EXPECT_EQ(ERR_CONNECTION_CLOSED, out.rv); 4522 4523 // Verify that we consumed all test data. 4524 helper.VerifyDataConsumed(); 4525 } 4526 4527 // Test to make sure we can correctly connect through a proxy. 4528 TEST_P(SpdyNetworkTransactionTest, ProxyConnect) { 4529 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY, 4530 BoundNetLog(), GetParam(), NULL); 4531 helper.session_deps().reset(CreateSpdySessionDependencies( 4532 GetParam(), 4533 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"))); 4534 helper.SetSession(make_scoped_refptr( 4535 SpdySessionDependencies::SpdyCreateSession(helper.session_deps().get()))); 4536 helper.RunPreTestSetup(); 4537 HttpNetworkTransaction* trans = helper.trans(); 4538 4539 const char kConnect443[] = {"CONNECT www.google.com:443 HTTP/1.1\r\n" 4540 "Host: www.google.com\r\n" 4541 "Proxy-Connection: keep-alive\r\n\r\n"}; 4542 const char kConnect80[] = {"CONNECT www.google.com:80 HTTP/1.1\r\n" 4543 "Host: www.google.com\r\n" 4544 "Proxy-Connection: keep-alive\r\n\r\n"}; 4545 const char kHTTP200[] = {"HTTP/1.1 200 OK\r\n\r\n"}; 4546 scoped_ptr<SpdyFrame> req( 4547 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); 4548 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 4549 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true)); 4550 4551 MockWrite writes_SPDYNPN[] = { 4552 MockWrite(SYNCHRONOUS, kConnect443, arraysize(kConnect443) - 1, 0), 4553 CreateMockWrite(*req, 2), 4554 }; 4555 MockRead reads_SPDYNPN[] = { 4556 MockRead(SYNCHRONOUS, kHTTP200, arraysize(kHTTP200) - 1, 1), 4557 CreateMockRead(*resp, 3), 4558 CreateMockRead(*body.get(), 4), 4559 MockRead(ASYNC, 0, 0, 5), 4560 }; 4561 4562 MockWrite writes_SPDYSSL[] = { 4563 MockWrite(SYNCHRONOUS, kConnect80, arraysize(kConnect80) - 1, 0), 4564 CreateMockWrite(*req, 2), 4565 }; 4566 MockRead reads_SPDYSSL[] = { 4567 MockRead(SYNCHRONOUS, kHTTP200, arraysize(kHTTP200) - 1, 1), 4568 CreateMockRead(*resp, 3), 4569 CreateMockRead(*body.get(), 4), 4570 MockRead(ASYNC, 0, 0, 5), 4571 }; 4572 4573 MockWrite writes_SPDYNOSSL[] = { 4574 CreateMockWrite(*req, 0), 4575 }; 4576 4577 MockRead reads_SPDYNOSSL[] = { 4578 CreateMockRead(*resp, 1), 4579 CreateMockRead(*body.get(), 2), 4580 MockRead(ASYNC, 0, 0, 3), 4581 }; 4582 4583 scoped_ptr<OrderedSocketData> data; 4584 switch(GetParam().ssl_type) { 4585 case SPDYNOSSL: 4586 data.reset(new OrderedSocketData(reads_SPDYNOSSL, 4587 arraysize(reads_SPDYNOSSL), 4588 writes_SPDYNOSSL, 4589 arraysize(writes_SPDYNOSSL))); 4590 break; 4591 case SPDYSSL: 4592 data.reset(new OrderedSocketData(reads_SPDYSSL, 4593 arraysize(reads_SPDYSSL), 4594 writes_SPDYSSL, 4595 arraysize(writes_SPDYSSL))); 4596 break; 4597 case SPDYNPN: 4598 data.reset(new OrderedSocketData(reads_SPDYNPN, 4599 arraysize(reads_SPDYNPN), 4600 writes_SPDYNPN, 4601 arraysize(writes_SPDYNPN))); 4602 break; 4603 default: 4604 NOTREACHED(); 4605 } 4606 4607 helper.AddData(data.get()); 4608 TestCompletionCallback callback; 4609 4610 int rv = trans->Start( 4611 &CreateGetRequest(), callback.callback(), BoundNetLog()); 4612 EXPECT_EQ(ERR_IO_PENDING, rv); 4613 4614 rv = callback.WaitForResult(); 4615 EXPECT_EQ(0, rv); 4616 4617 // Verify the SYN_REPLY. 4618 HttpResponseInfo response = *trans->GetResponseInfo(); 4619 EXPECT_TRUE(response.headers.get() != NULL); 4620 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine()); 4621 4622 std::string response_data; 4623 ASSERT_EQ(OK, ReadTransaction(trans, &response_data)); 4624 EXPECT_EQ("hello!", response_data); 4625 helper.VerifyDataConsumed(); 4626 } 4627 4628 // Test to make sure we can correctly connect through a proxy to www.google.com, 4629 // if there already exists a direct spdy connection to www.google.com. See 4630 // http://crbug.com/49874 4631 TEST_P(SpdyNetworkTransactionTest, DirectConnectProxyReconnect) { 4632 // When setting up the first transaction, we store the SpdySessionPool so that 4633 // we can use the same pool in the second transaction. 4634 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY, 4635 BoundNetLog(), GetParam(), NULL); 4636 4637 // Use a proxy service which returns a proxy fallback list from DIRECT to 4638 // myproxy:70. For this test there will be no fallback, so it is equivalent 4639 // to simply DIRECT. The reason for appending the second proxy is to verify 4640 // that the session pool key used does is just "DIRECT". 4641 helper.session_deps().reset(CreateSpdySessionDependencies( 4642 GetParam(), 4643 ProxyService::CreateFixedFromPacResult("DIRECT; PROXY myproxy:70"))); 4644 helper.SetSession(make_scoped_refptr( 4645 SpdySessionDependencies::SpdyCreateSession(helper.session_deps().get()))); 4646 4647 SpdySessionPool* spdy_session_pool = helper.session()->spdy_session_pool(); 4648 helper.RunPreTestSetup(); 4649 4650 // Construct and send a simple GET request. 4651 scoped_ptr<SpdyFrame> req( 4652 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); 4653 MockWrite writes[] = { 4654 CreateMockWrite(*req, 1), 4655 }; 4656 4657 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 4658 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true)); 4659 MockRead reads[] = { 4660 CreateMockRead(*resp, 2), 4661 CreateMockRead(*body, 3), 4662 MockRead(ASYNC, ERR_IO_PENDING, 4), // Force a pause 4663 MockRead(ASYNC, 0, 5) // EOF 4664 }; 4665 OrderedSocketData data(reads, arraysize(reads), 4666 writes, arraysize(writes)); 4667 helper.AddData(&data); 4668 HttpNetworkTransaction* trans = helper.trans(); 4669 4670 TestCompletionCallback callback; 4671 TransactionHelperResult out; 4672 out.rv = trans->Start( 4673 &CreateGetRequest(), callback.callback(), BoundNetLog()); 4674 4675 EXPECT_EQ(out.rv, ERR_IO_PENDING); 4676 out.rv = callback.WaitForResult(); 4677 EXPECT_EQ(out.rv, OK); 4678 4679 const HttpResponseInfo* response = trans->GetResponseInfo(); 4680 EXPECT_TRUE(response->headers.get() != NULL); 4681 EXPECT_TRUE(response->was_fetched_via_spdy); 4682 out.rv = ReadTransaction(trans, &out.response_data); 4683 EXPECT_EQ(OK, out.rv); 4684 out.status_line = response->headers->GetStatusLine(); 4685 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line); 4686 EXPECT_EQ("hello!", out.response_data); 4687 4688 // Check that the SpdySession is still in the SpdySessionPool. 4689 HostPortPair host_port_pair("www.google.com", helper.port()); 4690 SpdySessionKey session_pool_key_direct( 4691 host_port_pair, ProxyServer::Direct(), kPrivacyModeDisabled); 4692 EXPECT_TRUE(HasSpdySession(spdy_session_pool, session_pool_key_direct)); 4693 SpdySessionKey session_pool_key_proxy( 4694 host_port_pair, 4695 ProxyServer::FromURI("www.foo.com", ProxyServer::SCHEME_HTTP), 4696 kPrivacyModeDisabled); 4697 EXPECT_FALSE(HasSpdySession(spdy_session_pool, session_pool_key_proxy)); 4698 4699 // Set up data for the proxy connection. 4700 const char kConnect443[] = {"CONNECT www.google.com:443 HTTP/1.1\r\n" 4701 "Host: www.google.com\r\n" 4702 "Proxy-Connection: keep-alive\r\n\r\n"}; 4703 const char kConnect80[] = {"CONNECT www.google.com:80 HTTP/1.1\r\n" 4704 "Host: www.google.com\r\n" 4705 "Proxy-Connection: keep-alive\r\n\r\n"}; 4706 const char kHTTP200[] = {"HTTP/1.1 200 OK\r\n\r\n"}; 4707 scoped_ptr<SpdyFrame> req2(spdy_util_.ConstructSpdyGet( 4708 "http://www.google.com/foo.dat", false, 1, LOWEST)); 4709 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 4710 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(1, true)); 4711 4712 MockWrite writes_SPDYNPN[] = { 4713 MockWrite(SYNCHRONOUS, kConnect443, arraysize(kConnect443) - 1, 0), 4714 CreateMockWrite(*req2, 2), 4715 }; 4716 MockRead reads_SPDYNPN[] = { 4717 MockRead(SYNCHRONOUS, kHTTP200, arraysize(kHTTP200) - 1, 1), 4718 CreateMockRead(*resp2, 3), 4719 CreateMockRead(*body2, 4), 4720 MockRead(ASYNC, 0, 5) // EOF 4721 }; 4722 4723 MockWrite writes_SPDYNOSSL[] = { 4724 CreateMockWrite(*req2, 0), 4725 }; 4726 MockRead reads_SPDYNOSSL[] = { 4727 CreateMockRead(*resp2, 1), 4728 CreateMockRead(*body2, 2), 4729 MockRead(ASYNC, 0, 3) // EOF 4730 }; 4731 4732 MockWrite writes_SPDYSSL[] = { 4733 MockWrite(SYNCHRONOUS, kConnect80, arraysize(kConnect80) - 1, 0), 4734 CreateMockWrite(*req2, 2), 4735 }; 4736 MockRead reads_SPDYSSL[] = { 4737 MockRead(SYNCHRONOUS, kHTTP200, arraysize(kHTTP200) - 1, 1), 4738 CreateMockRead(*resp2, 3), 4739 CreateMockRead(*body2, 4), 4740 MockRead(ASYNC, 0, 0, 5), 4741 }; 4742 4743 scoped_ptr<OrderedSocketData> data_proxy; 4744 switch(GetParam().ssl_type) { 4745 case SPDYNPN: 4746 data_proxy.reset(new OrderedSocketData(reads_SPDYNPN, 4747 arraysize(reads_SPDYNPN), 4748 writes_SPDYNPN, 4749 arraysize(writes_SPDYNPN))); 4750 break; 4751 case SPDYNOSSL: 4752 data_proxy.reset(new OrderedSocketData(reads_SPDYNOSSL, 4753 arraysize(reads_SPDYNOSSL), 4754 writes_SPDYNOSSL, 4755 arraysize(writes_SPDYNOSSL))); 4756 break; 4757 case SPDYSSL: 4758 data_proxy.reset(new OrderedSocketData(reads_SPDYSSL, 4759 arraysize(reads_SPDYSSL), 4760 writes_SPDYSSL, 4761 arraysize(writes_SPDYSSL))); 4762 break; 4763 default: 4764 NOTREACHED(); 4765 } 4766 4767 // Create another request to www.google.com, but this time through a proxy. 4768 HttpRequestInfo request_proxy; 4769 request_proxy.method = "GET"; 4770 request_proxy.url = GURL("http://www.google.com/foo.dat"); 4771 request_proxy.load_flags = 0; 4772 scoped_ptr<SpdySessionDependencies> ssd_proxy( 4773 CreateSpdySessionDependencies(GetParam())); 4774 // Ensure that this transaction uses the same SpdySessionPool. 4775 scoped_refptr<HttpNetworkSession> session_proxy( 4776 SpdySessionDependencies::SpdyCreateSession(ssd_proxy.get())); 4777 NormalSpdyTransactionHelper helper_proxy(request_proxy, DEFAULT_PRIORITY, 4778 BoundNetLog(), GetParam(), NULL); 4779 HttpNetworkSessionPeer session_peer(session_proxy); 4780 scoped_ptr<net::ProxyService> proxy_service( 4781 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70")); 4782 session_peer.SetProxyService(proxy_service.get()); 4783 helper_proxy.session_deps().swap(ssd_proxy); 4784 helper_proxy.SetSession(session_proxy); 4785 helper_proxy.RunPreTestSetup(); 4786 helper_proxy.AddData(data_proxy.get()); 4787 4788 HttpNetworkTransaction* trans_proxy = helper_proxy.trans(); 4789 TestCompletionCallback callback_proxy; 4790 int rv = trans_proxy->Start( 4791 &request_proxy, callback_proxy.callback(), BoundNetLog()); 4792 EXPECT_EQ(ERR_IO_PENDING, rv); 4793 rv = callback_proxy.WaitForResult(); 4794 EXPECT_EQ(0, rv); 4795 4796 HttpResponseInfo response_proxy = *trans_proxy->GetResponseInfo(); 4797 EXPECT_TRUE(response_proxy.headers.get() != NULL); 4798 EXPECT_EQ("HTTP/1.1 200 OK", response_proxy.headers->GetStatusLine()); 4799 4800 std::string response_data; 4801 ASSERT_EQ(OK, ReadTransaction(trans_proxy, &response_data)); 4802 EXPECT_EQ("hello!", response_data); 4803 4804 data.CompleteRead(); 4805 helper_proxy.VerifyDataConsumed(); 4806 } 4807 4808 // When we get a TCP-level RST, we need to retry a HttpNetworkTransaction 4809 // on a new connection, if the connection was previously known to be good. 4810 // This can happen when a server reboots without saying goodbye, or when 4811 // we're behind a NAT that masked the RST. 4812 TEST_P(SpdyNetworkTransactionTest, VerifyRetryOnConnectionReset) { 4813 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 4814 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true)); 4815 MockRead reads[] = { 4816 CreateMockRead(*resp), 4817 CreateMockRead(*body), 4818 MockRead(ASYNC, ERR_IO_PENDING), 4819 MockRead(ASYNC, ERR_CONNECTION_RESET), 4820 }; 4821 4822 MockRead reads2[] = { 4823 CreateMockRead(*resp), 4824 CreateMockRead(*body), 4825 MockRead(ASYNC, 0, 0) // EOF 4826 }; 4827 4828 // This test has a couple of variants. 4829 enum { 4830 // Induce the RST while waiting for our transaction to send. 4831 VARIANT_RST_DURING_SEND_COMPLETION, 4832 // Induce the RST while waiting for our transaction to read. 4833 // In this case, the send completed - everything copied into the SNDBUF. 4834 VARIANT_RST_DURING_READ_COMPLETION 4835 }; 4836 4837 for (int variant = VARIANT_RST_DURING_SEND_COMPLETION; 4838 variant <= VARIANT_RST_DURING_READ_COMPLETION; 4839 ++variant) { 4840 DelayedSocketData data1(1, reads, arraysize(reads), NULL, 0); 4841 4842 DelayedSocketData data2(1, reads2, arraysize(reads2), NULL, 0); 4843 4844 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY, 4845 BoundNetLog(), GetParam(), NULL); 4846 helper.AddData(&data1); 4847 helper.AddData(&data2); 4848 helper.RunPreTestSetup(); 4849 4850 for (int i = 0; i < 2; ++i) { 4851 scoped_ptr<HttpNetworkTransaction> trans( 4852 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get())); 4853 4854 TestCompletionCallback callback; 4855 int rv = trans->Start( 4856 &helper.request(), callback.callback(), BoundNetLog()); 4857 EXPECT_EQ(ERR_IO_PENDING, rv); 4858 // On the second transaction, we trigger the RST. 4859 if (i == 1) { 4860 if (variant == VARIANT_RST_DURING_READ_COMPLETION) { 4861 // Writes to the socket complete asynchronously on SPDY by running 4862 // through the message loop. Complete the write here. 4863 base::RunLoop().RunUntilIdle(); 4864 } 4865 4866 // Now schedule the ERR_CONNECTION_RESET. 4867 EXPECT_EQ(3u, data1.read_index()); 4868 data1.CompleteRead(); 4869 EXPECT_EQ(4u, data1.read_index()); 4870 } 4871 rv = callback.WaitForResult(); 4872 EXPECT_EQ(OK, rv); 4873 4874 const HttpResponseInfo* response = trans->GetResponseInfo(); 4875 ASSERT_TRUE(response != NULL); 4876 EXPECT_TRUE(response->headers.get() != NULL); 4877 EXPECT_TRUE(response->was_fetched_via_spdy); 4878 std::string response_data; 4879 rv = ReadTransaction(trans.get(), &response_data); 4880 EXPECT_EQ(OK, rv); 4881 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); 4882 EXPECT_EQ("hello!", response_data); 4883 } 4884 4885 helper.VerifyDataConsumed(); 4886 } 4887 } 4888 4889 // Test that turning SPDY on and off works properly. 4890 TEST_P(SpdyNetworkTransactionTest, SpdyOnOffToggle) { 4891 net::HttpStreamFactory::set_spdy_enabled(true); 4892 scoped_ptr<SpdyFrame> req( 4893 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); 4894 MockWrite spdy_writes[] = { CreateMockWrite(*req) }; 4895 4896 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 4897 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true)); 4898 MockRead spdy_reads[] = { 4899 CreateMockRead(*resp), 4900 CreateMockRead(*body), 4901 MockRead(ASYNC, 0, 0) // EOF 4902 }; 4903 4904 DelayedSocketData data(1, spdy_reads, arraysize(spdy_reads), 4905 spdy_writes, arraysize(spdy_writes)); 4906 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY, 4907 BoundNetLog(), GetParam(), NULL); 4908 helper.RunToCompletion(&data); 4909 TransactionHelperResult out = helper.output(); 4910 EXPECT_EQ(OK, out.rv); 4911 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line); 4912 EXPECT_EQ("hello!", out.response_data); 4913 4914 net::HttpStreamFactory::set_spdy_enabled(false); 4915 MockRead http_reads[] = { 4916 MockRead("HTTP/1.1 200 OK\r\n\r\n"), 4917 MockRead("hello from http"), 4918 MockRead(SYNCHRONOUS, OK), 4919 }; 4920 DelayedSocketData data2(1, http_reads, arraysize(http_reads), NULL, 0); 4921 NormalSpdyTransactionHelper helper2(CreateGetRequest(), DEFAULT_PRIORITY, 4922 BoundNetLog(), GetParam(), NULL); 4923 helper2.SetSpdyDisabled(); 4924 helper2.RunToCompletion(&data2); 4925 TransactionHelperResult out2 = helper2.output(); 4926 EXPECT_EQ(OK, out2.rv); 4927 EXPECT_EQ("HTTP/1.1 200 OK", out2.status_line); 4928 EXPECT_EQ("hello from http", out2.response_data); 4929 4930 net::HttpStreamFactory::set_spdy_enabled(true); 4931 } 4932 4933 // Tests that Basic authentication works over SPDY 4934 TEST_P(SpdyNetworkTransactionTest, SpdyBasicAuth) { 4935 net::HttpStreamFactory::set_spdy_enabled(true); 4936 4937 // The first request will be a bare GET, the second request will be a 4938 // GET with an Authorization header. 4939 scoped_ptr<SpdyFrame> req_get( 4940 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); 4941 const char* const kExtraAuthorizationHeaders[] = { 4942 "authorization", "Basic Zm9vOmJhcg==" 4943 }; 4944 scoped_ptr<SpdyFrame> req_get_authorization( 4945 spdy_util_.ConstructSpdyGet(kExtraAuthorizationHeaders, 4946 arraysize(kExtraAuthorizationHeaders) / 2, 4947 false, 3, LOWEST, true)); 4948 MockWrite spdy_writes[] = { 4949 CreateMockWrite(*req_get, 1), 4950 CreateMockWrite(*req_get_authorization, 4), 4951 }; 4952 4953 // The first response is a 401 authentication challenge, and the second 4954 // response will be a 200 response since the second request includes a valid 4955 // Authorization header. 4956 const char* const kExtraAuthenticationHeaders[] = { 4957 "www-authenticate", 4958 "Basic realm=\"MyRealm\"" 4959 }; 4960 scoped_ptr<SpdyFrame> resp_authentication( 4961 spdy_util_.ConstructSpdySynReplyError( 4962 "401 Authentication Required", 4963 kExtraAuthenticationHeaders, 4964 arraysize(kExtraAuthenticationHeaders) / 2, 4965 1)); 4966 scoped_ptr<SpdyFrame> body_authentication( 4967 spdy_util_.ConstructSpdyBodyFrame(1, true)); 4968 scoped_ptr<SpdyFrame> resp_data( 4969 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3)); 4970 scoped_ptr<SpdyFrame> body_data(spdy_util_.ConstructSpdyBodyFrame(3, true)); 4971 MockRead spdy_reads[] = { 4972 CreateMockRead(*resp_authentication, 2), 4973 CreateMockRead(*body_authentication, 3), 4974 CreateMockRead(*resp_data, 5), 4975 CreateMockRead(*body_data, 6), 4976 MockRead(ASYNC, 0, 7), 4977 }; 4978 4979 OrderedSocketData data(spdy_reads, arraysize(spdy_reads), 4980 spdy_writes, arraysize(spdy_writes)); 4981 HttpRequestInfo request(CreateGetRequest()); 4982 BoundNetLog net_log; 4983 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY, 4984 net_log, GetParam(), NULL); 4985 4986 helper.RunPreTestSetup(); 4987 helper.AddData(&data); 4988 HttpNetworkTransaction* trans = helper.trans(); 4989 TestCompletionCallback callback; 4990 const int rv_start = trans->Start(&request, callback.callback(), net_log); 4991 EXPECT_EQ(ERR_IO_PENDING, rv_start); 4992 const int rv_start_complete = callback.WaitForResult(); 4993 EXPECT_EQ(OK, rv_start_complete); 4994 4995 // Make sure the response has an auth challenge. 4996 const HttpResponseInfo* const response_start = trans->GetResponseInfo(); 4997 ASSERT_TRUE(response_start != NULL); 4998 ASSERT_TRUE(response_start->headers.get() != NULL); 4999 EXPECT_EQ(401, response_start->headers->response_code()); 5000 EXPECT_TRUE(response_start->was_fetched_via_spdy); 5001 AuthChallengeInfo* auth_challenge = response_start->auth_challenge.get(); 5002 ASSERT_TRUE(auth_challenge != NULL); 5003 EXPECT_FALSE(auth_challenge->is_proxy); 5004 EXPECT_EQ("basic", auth_challenge->scheme); 5005 EXPECT_EQ("MyRealm", auth_challenge->realm); 5006 5007 // Restart with a username/password. 5008 AuthCredentials credentials(ASCIIToUTF16("foo"), ASCIIToUTF16("bar")); 5009 TestCompletionCallback callback_restart; 5010 const int rv_restart = trans->RestartWithAuth( 5011 credentials, callback_restart.callback()); 5012 EXPECT_EQ(ERR_IO_PENDING, rv_restart); 5013 const int rv_restart_complete = callback_restart.WaitForResult(); 5014 EXPECT_EQ(OK, rv_restart_complete); 5015 // TODO(cbentzel): This is actually the same response object as before, but 5016 // data has changed. 5017 const HttpResponseInfo* const response_restart = trans->GetResponseInfo(); 5018 ASSERT_TRUE(response_restart != NULL); 5019 ASSERT_TRUE(response_restart->headers.get() != NULL); 5020 EXPECT_EQ(200, response_restart->headers->response_code()); 5021 EXPECT_TRUE(response_restart->auth_challenge.get() == NULL); 5022 } 5023 5024 TEST_P(SpdyNetworkTransactionTest, ServerPushWithHeaders) { 5025 scoped_ptr<SpdyFrame> stream1_syn( 5026 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); 5027 scoped_ptr<SpdyFrame> stream1_body( 5028 spdy_util_.ConstructSpdyBodyFrame(1, true)); 5029 MockWrite writes[] = { 5030 CreateMockWrite(*stream1_syn, 1), 5031 }; 5032 5033 scoped_ptr<SpdyHeaderBlock> initial_headers(new SpdyHeaderBlock()); 5034 spdy_util_.AddUrlToHeaderBlock( 5035 "http://www.google.com/foo.dat", initial_headers.get()); 5036 scoped_ptr<SpdyFrame> stream2_syn( 5037 spdy_util_.ConstructSpdyControlFrame(initial_headers.Pass(), 5038 false, 5039 2, 5040 LOWEST, 5041 SYN_STREAM, 5042 CONTROL_FLAG_NONE, 5043 1)); 5044 5045 scoped_ptr<SpdyHeaderBlock> late_headers(new SpdyHeaderBlock()); 5046 (*late_headers)["hello"] = "bye"; 5047 (*late_headers)[spdy_util_.GetStatusKey()] = "200"; 5048 (*late_headers)[spdy_util_.GetVersionKey()] = "HTTP/1.1"; 5049 scoped_ptr<SpdyFrame> stream2_headers( 5050 spdy_util_.ConstructSpdyControlFrame(late_headers.Pass(), 5051 false, 5052 2, 5053 LOWEST, 5054 HEADERS, 5055 CONTROL_FLAG_NONE, 5056 0)); 5057 5058 scoped_ptr<SpdyFrame> 5059 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 5060 const char kPushedData[] = "pushed"; 5061 scoped_ptr<SpdyFrame> stream2_body( 5062 spdy_util_.ConstructSpdyBodyFrame( 5063 2, kPushedData, strlen(kPushedData), true)); 5064 MockRead reads[] = { 5065 CreateMockRead(*stream1_reply, 2), 5066 CreateMockRead(*stream2_syn, 3), 5067 CreateMockRead(*stream2_headers, 4), 5068 CreateMockRead(*stream1_body, 5, SYNCHRONOUS), 5069 CreateMockRead(*stream2_body, 5), 5070 MockRead(ASYNC, ERR_IO_PENDING, 7), // Force a pause 5071 }; 5072 5073 HttpResponseInfo response; 5074 HttpResponseInfo response2; 5075 std::string expected_push_result("pushed"); 5076 OrderedSocketData data(reads, arraysize(reads), 5077 writes, arraysize(writes)); 5078 RunServerPushTest(&data, 5079 &response, 5080 &response2, 5081 expected_push_result); 5082 5083 // Verify the SYN_REPLY. 5084 EXPECT_TRUE(response.headers.get() != NULL); 5085 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine()); 5086 5087 // Verify the pushed stream. 5088 EXPECT_TRUE(response2.headers.get() != NULL); 5089 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine()); 5090 } 5091 5092 TEST_P(SpdyNetworkTransactionTest, ServerPushClaimBeforeHeaders) { 5093 // We push a stream and attempt to claim it before the headers come down. 5094 scoped_ptr<SpdyFrame> stream1_syn( 5095 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); 5096 scoped_ptr<SpdyFrame> stream1_body( 5097 spdy_util_.ConstructSpdyBodyFrame(1, true)); 5098 MockWrite writes[] = { 5099 CreateMockWrite(*stream1_syn, 0, SYNCHRONOUS), 5100 }; 5101 5102 scoped_ptr<SpdyHeaderBlock> initial_headers(new SpdyHeaderBlock()); 5103 spdy_util_.AddUrlToHeaderBlock( 5104 "http://www.google.com/foo.dat", initial_headers.get()); 5105 scoped_ptr<SpdyFrame> stream2_syn( 5106 spdy_util_.ConstructSpdyControlFrame(initial_headers.Pass(), 5107 false, 5108 2, 5109 LOWEST, 5110 SYN_STREAM, 5111 CONTROL_FLAG_NONE, 5112 1)); 5113 5114 scoped_ptr<SpdyHeaderBlock> late_headers(new SpdyHeaderBlock()); 5115 (*late_headers)["hello"] = "bye"; 5116 (*late_headers)[spdy_util_.GetStatusKey()] = "200"; 5117 (*late_headers)[spdy_util_.GetVersionKey()] = "HTTP/1.1"; 5118 scoped_ptr<SpdyFrame> stream2_headers( 5119 spdy_util_.ConstructSpdyControlFrame(late_headers.Pass(), 5120 false, 5121 2, 5122 LOWEST, 5123 HEADERS, 5124 CONTROL_FLAG_NONE, 5125 0)); 5126 5127 scoped_ptr<SpdyFrame> 5128 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 5129 const char kPushedData[] = "pushed"; 5130 scoped_ptr<SpdyFrame> stream2_body( 5131 spdy_util_.ConstructSpdyBodyFrame( 5132 2, kPushedData, strlen(kPushedData), true)); 5133 MockRead reads[] = { 5134 CreateMockRead(*stream1_reply, 1), 5135 CreateMockRead(*stream2_syn, 2), 5136 CreateMockRead(*stream1_body, 3), 5137 CreateMockRead(*stream2_headers, 4), 5138 CreateMockRead(*stream2_body, 5), 5139 MockRead(ASYNC, 0, 6), // EOF 5140 }; 5141 5142 HttpResponseInfo response; 5143 HttpResponseInfo response2; 5144 std::string expected_push_result("pushed"); 5145 DeterministicSocketData data(reads, arraysize(reads), 5146 writes, arraysize(writes)); 5147 5148 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY, 5149 BoundNetLog(), GetParam(), NULL); 5150 helper.SetDeterministic(); 5151 helper.AddDeterministicData(&data); 5152 helper.RunPreTestSetup(); 5153 5154 HttpNetworkTransaction* trans = helper.trans(); 5155 5156 // Run until we've received the primary SYN_STREAM, the pushed SYN_STREAM, 5157 // and the body of the primary stream, but before we've received the HEADERS 5158 // for the pushed stream. 5159 data.SetStop(3); 5160 5161 // Start the transaction. 5162 TestCompletionCallback callback; 5163 int rv = trans->Start( 5164 &CreateGetRequest(), callback.callback(), BoundNetLog()); 5165 EXPECT_EQ(ERR_IO_PENDING, rv); 5166 data.Run(); 5167 rv = callback.WaitForResult(); 5168 EXPECT_EQ(0, rv); 5169 5170 // Request the pushed path. At this point, we've received the push, but the 5171 // headers are not yet complete. 5172 scoped_ptr<HttpNetworkTransaction> trans2( 5173 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get())); 5174 rv = trans2->Start( 5175 &CreateGetPushRequest(), callback.callback(), BoundNetLog()); 5176 EXPECT_EQ(ERR_IO_PENDING, rv); 5177 data.RunFor(3); 5178 base::RunLoop().RunUntilIdle(); 5179 5180 // Read the server push body. 5181 std::string result2; 5182 ReadResult(trans2.get(), &data, &result2); 5183 // Read the response body. 5184 std::string result; 5185 ReadResult(trans, &data, &result); 5186 5187 // Verify that the received push data is same as the expected push data. 5188 EXPECT_EQ(result2.compare(expected_push_result), 0) 5189 << "Received data: " 5190 << result2 5191 << "||||| Expected data: " 5192 << expected_push_result; 5193 5194 // Verify the SYN_REPLY. 5195 // Copy the response info, because trans goes away. 5196 response = *trans->GetResponseInfo(); 5197 response2 = *trans2->GetResponseInfo(); 5198 5199 VerifyStreamsClosed(helper); 5200 5201 // Verify the SYN_REPLY. 5202 EXPECT_TRUE(response.headers.get() != NULL); 5203 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine()); 5204 5205 // Verify the pushed stream. 5206 EXPECT_TRUE(response2.headers.get() != NULL); 5207 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine()); 5208 5209 // Read the final EOF (which will close the session) 5210 data.RunFor(1); 5211 5212 // Verify that we consumed all test data. 5213 EXPECT_TRUE(data.at_read_eof()); 5214 EXPECT_TRUE(data.at_write_eof()); 5215 } 5216 5217 TEST_P(SpdyNetworkTransactionTest, ServerPushWithTwoHeaderFrames) { 5218 // We push a stream and attempt to claim it before the headers come down. 5219 scoped_ptr<SpdyFrame> stream1_syn( 5220 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); 5221 scoped_ptr<SpdyFrame> stream1_body( 5222 spdy_util_.ConstructSpdyBodyFrame(1, true)); 5223 MockWrite writes[] = { 5224 CreateMockWrite(*stream1_syn, 0, SYNCHRONOUS), 5225 }; 5226 5227 scoped_ptr<SpdyHeaderBlock> initial_headers(new SpdyHeaderBlock()); 5228 spdy_util_.AddUrlToHeaderBlock( 5229 "http://www.google.com/foo.dat", initial_headers.get()); 5230 scoped_ptr<SpdyFrame> stream2_syn( 5231 spdy_util_.ConstructSpdyControlFrame(initial_headers.Pass(), 5232 false, 5233 2, 5234 LOWEST, 5235 SYN_STREAM, 5236 CONTROL_FLAG_NONE, 5237 1)); 5238 5239 scoped_ptr<SpdyHeaderBlock> middle_headers(new SpdyHeaderBlock()); 5240 (*middle_headers)["hello"] = "bye"; 5241 scoped_ptr<SpdyFrame> stream2_headers1( 5242 spdy_util_.ConstructSpdyControlFrame(middle_headers.Pass(), 5243 false, 5244 2, 5245 LOWEST, 5246 HEADERS, 5247 CONTROL_FLAG_NONE, 5248 0)); 5249 5250 scoped_ptr<SpdyHeaderBlock> late_headers(new SpdyHeaderBlock()); 5251 (*late_headers)[spdy_util_.GetStatusKey()] = "200"; 5252 (*late_headers)[spdy_util_.GetVersionKey()] = "HTTP/1.1"; 5253 scoped_ptr<SpdyFrame> stream2_headers2( 5254 spdy_util_.ConstructSpdyControlFrame(late_headers.Pass(), 5255 false, 5256 2, 5257 LOWEST, 5258 HEADERS, 5259 CONTROL_FLAG_NONE, 5260 0)); 5261 5262 scoped_ptr<SpdyFrame> 5263 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 5264 const char kPushedData[] = "pushed"; 5265 scoped_ptr<SpdyFrame> stream2_body( 5266 spdy_util_.ConstructSpdyBodyFrame( 5267 2, kPushedData, strlen(kPushedData), true)); 5268 MockRead reads[] = { 5269 CreateMockRead(*stream1_reply, 1), 5270 CreateMockRead(*stream2_syn, 2), 5271 CreateMockRead(*stream1_body, 3), 5272 CreateMockRead(*stream2_headers1, 4), 5273 CreateMockRead(*stream2_headers2, 5), 5274 CreateMockRead(*stream2_body, 6), 5275 MockRead(ASYNC, 0, 7), // EOF 5276 }; 5277 5278 HttpResponseInfo response; 5279 HttpResponseInfo response2; 5280 std::string expected_push_result("pushed"); 5281 DeterministicSocketData data(reads, arraysize(reads), 5282 writes, arraysize(writes)); 5283 5284 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY, 5285 BoundNetLog(), GetParam(), NULL); 5286 helper.SetDeterministic(); 5287 helper.AddDeterministicData(&data); 5288 helper.RunPreTestSetup(); 5289 5290 HttpNetworkTransaction* trans = helper.trans(); 5291 5292 // Run until we've received the primary SYN_STREAM, the pushed SYN_STREAM, 5293 // the first HEADERS frame, and the body of the primary stream, but before 5294 // we've received the final HEADERS for the pushed stream. 5295 data.SetStop(4); 5296 5297 // Start the transaction. 5298 TestCompletionCallback callback; 5299 int rv = trans->Start( 5300 &CreateGetRequest(), callback.callback(), BoundNetLog()); 5301 EXPECT_EQ(ERR_IO_PENDING, rv); 5302 data.Run(); 5303 rv = callback.WaitForResult(); 5304 EXPECT_EQ(0, rv); 5305 5306 // Request the pushed path. At this point, we've received the push, but the 5307 // headers are not yet complete. 5308 scoped_ptr<HttpNetworkTransaction> trans2( 5309 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get())); 5310 rv = trans2->Start( 5311 &CreateGetPushRequest(), callback.callback(), BoundNetLog()); 5312 EXPECT_EQ(ERR_IO_PENDING, rv); 5313 data.RunFor(3); 5314 base::RunLoop().RunUntilIdle(); 5315 5316 // Read the server push body. 5317 std::string result2; 5318 ReadResult(trans2.get(), &data, &result2); 5319 // Read the response body. 5320 std::string result; 5321 ReadResult(trans, &data, &result); 5322 5323 // Verify that the received push data is same as the expected push data. 5324 EXPECT_EQ(expected_push_result, result2); 5325 5326 // Verify the SYN_REPLY. 5327 // Copy the response info, because trans goes away. 5328 response = *trans->GetResponseInfo(); 5329 response2 = *trans2->GetResponseInfo(); 5330 5331 VerifyStreamsClosed(helper); 5332 5333 // Verify the SYN_REPLY. 5334 EXPECT_TRUE(response.headers.get() != NULL); 5335 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine()); 5336 5337 // Verify the pushed stream. 5338 EXPECT_TRUE(response2.headers.get() != NULL); 5339 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine()); 5340 5341 // Verify we got all the headers 5342 if (spdy_util_.spdy_version() < SPDY3) { 5343 EXPECT_TRUE(response2.headers->HasHeaderValue( 5344 "url", 5345 "http://www.google.com/foo.dat")); 5346 } else { 5347 EXPECT_TRUE(response2.headers->HasHeaderValue( 5348 "scheme", "http")); 5349 EXPECT_TRUE(response2.headers->HasHeaderValue( 5350 "host", "www.google.com")); 5351 EXPECT_TRUE(response2.headers->HasHeaderValue( 5352 "path", "/foo.dat")); 5353 } 5354 EXPECT_TRUE(response2.headers->HasHeaderValue("hello", "bye")); 5355 EXPECT_TRUE(response2.headers->HasHeaderValue("status", "200")); 5356 EXPECT_TRUE(response2.headers->HasHeaderValue("version", "HTTP/1.1")); 5357 5358 // Read the final EOF (which will close the session) 5359 data.RunFor(1); 5360 5361 // Verify that we consumed all test data. 5362 EXPECT_TRUE(data.at_read_eof()); 5363 EXPECT_TRUE(data.at_write_eof()); 5364 } 5365 5366 TEST_P(SpdyNetworkTransactionTest, ServerPushWithNoStatusHeaderFrames) { 5367 // We push a stream and attempt to claim it before the headers come down. 5368 scoped_ptr<SpdyFrame> stream1_syn( 5369 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); 5370 scoped_ptr<SpdyFrame> stream1_body( 5371 spdy_util_.ConstructSpdyBodyFrame(1, true)); 5372 MockWrite writes[] = { 5373 CreateMockWrite(*stream1_syn, 0, SYNCHRONOUS), 5374 }; 5375 5376 scoped_ptr<SpdyHeaderBlock> initial_headers(new SpdyHeaderBlock()); 5377 spdy_util_.AddUrlToHeaderBlock( 5378 "http://www.google.com/foo.dat", initial_headers.get()); 5379 scoped_ptr<SpdyFrame> stream2_syn( 5380 spdy_util_.ConstructSpdyControlFrame(initial_headers.Pass(), 5381 false, 5382 2, 5383 LOWEST, 5384 SYN_STREAM, 5385 CONTROL_FLAG_NONE, 5386 1)); 5387 5388 scoped_ptr<SpdyHeaderBlock> middle_headers(new SpdyHeaderBlock()); 5389 (*middle_headers)["hello"] = "bye"; 5390 scoped_ptr<SpdyFrame> stream2_headers1( 5391 spdy_util_.ConstructSpdyControlFrame(middle_headers.Pass(), 5392 false, 5393 2, 5394 LOWEST, 5395 HEADERS, 5396 CONTROL_FLAG_NONE, 5397 0)); 5398 5399 scoped_ptr<SpdyFrame> 5400 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 5401 const char kPushedData[] = "pushed"; 5402 scoped_ptr<SpdyFrame> stream2_body( 5403 spdy_util_.ConstructSpdyBodyFrame( 5404 2, kPushedData, strlen(kPushedData), true)); 5405 MockRead reads[] = { 5406 CreateMockRead(*stream1_reply, 1), 5407 CreateMockRead(*stream2_syn, 2), 5408 CreateMockRead(*stream1_body, 3), 5409 CreateMockRead(*stream2_headers1, 4), 5410 CreateMockRead(*stream2_body, 5), 5411 MockRead(ASYNC, 0, 6), // EOF 5412 }; 5413 5414 DeterministicSocketData data(reads, arraysize(reads), 5415 writes, arraysize(writes)); 5416 5417 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY, 5418 BoundNetLog(), GetParam(), NULL); 5419 helper.SetDeterministic(); 5420 helper.AddDeterministicData(&data); 5421 helper.RunPreTestSetup(); 5422 5423 HttpNetworkTransaction* trans = helper.trans(); 5424 5425 // Run until we've received the primary SYN_STREAM, the pushed SYN_STREAM, 5426 // the first HEADERS frame, and the body of the primary stream, but before 5427 // we've received the final HEADERS for the pushed stream. 5428 data.SetStop(4); 5429 5430 // Start the transaction. 5431 TestCompletionCallback callback; 5432 int rv = trans->Start( 5433 &CreateGetRequest(), callback.callback(), BoundNetLog()); 5434 EXPECT_EQ(ERR_IO_PENDING, rv); 5435 data.Run(); 5436 rv = callback.WaitForResult(); 5437 EXPECT_EQ(0, rv); 5438 5439 // Request the pushed path. At this point, we've received the push, but the 5440 // headers are not yet complete. 5441 scoped_ptr<HttpNetworkTransaction> trans2( 5442 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get())); 5443 rv = trans2->Start( 5444 &CreateGetPushRequest(), callback.callback(), BoundNetLog()); 5445 EXPECT_EQ(ERR_IO_PENDING, rv); 5446 data.RunFor(2); 5447 base::RunLoop().RunUntilIdle(); 5448 5449 // Read the server push body. 5450 std::string result2; 5451 ReadResult(trans2.get(), &data, &result2); 5452 // Read the response body. 5453 std::string result; 5454 ReadResult(trans, &data, &result); 5455 EXPECT_EQ("hello!", result); 5456 5457 // Verify that we haven't received any push data. 5458 EXPECT_EQ("", result2); 5459 5460 // Verify the SYN_REPLY. 5461 // Copy the response info, because trans goes away. 5462 HttpResponseInfo response = *trans->GetResponseInfo(); 5463 ASSERT_TRUE(trans2->GetResponseInfo() == NULL); 5464 5465 VerifyStreamsClosed(helper); 5466 5467 // Verify the SYN_REPLY. 5468 EXPECT_TRUE(response.headers.get() != NULL); 5469 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine()); 5470 5471 // Read the final EOF (which will close the session). 5472 data.RunFor(1); 5473 5474 // Verify that we consumed all test data. 5475 EXPECT_TRUE(data.at_read_eof()); 5476 EXPECT_TRUE(data.at_write_eof()); 5477 } 5478 5479 TEST_P(SpdyNetworkTransactionTest, SynReplyWithHeaders) { 5480 scoped_ptr<SpdyFrame> req( 5481 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); 5482 scoped_ptr<SpdyFrame> rst( 5483 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR)); 5484 MockWrite writes[] = { 5485 CreateMockWrite(*req), 5486 CreateMockWrite(*rst), 5487 }; 5488 5489 scoped_ptr<SpdyHeaderBlock> initial_headers(new SpdyHeaderBlock()); 5490 (*initial_headers)[spdy_util_.GetStatusKey()] = "200 OK"; 5491 (*initial_headers)[spdy_util_.GetVersionKey()] = "HTTP/1.1"; 5492 scoped_ptr<SpdyFrame> stream1_reply( 5493 spdy_util_.ConstructSpdyControlFrame(initial_headers.Pass(), 5494 false, 5495 1, 5496 LOWEST, 5497 SYN_REPLY, 5498 CONTROL_FLAG_NONE, 5499 0)); 5500 5501 scoped_ptr<SpdyHeaderBlock> late_headers(new SpdyHeaderBlock()); 5502 (*late_headers)["hello"] = "bye"; 5503 scoped_ptr<SpdyFrame> stream1_headers( 5504 spdy_util_.ConstructSpdyControlFrame(late_headers.Pass(), 5505 false, 5506 1, 5507 LOWEST, 5508 HEADERS, 5509 CONTROL_FLAG_NONE, 5510 0)); 5511 scoped_ptr<SpdyFrame> stream1_body( 5512 spdy_util_.ConstructSpdyBodyFrame(1, true)); 5513 MockRead reads[] = { 5514 CreateMockRead(*stream1_reply), 5515 CreateMockRead(*stream1_headers), 5516 CreateMockRead(*stream1_body), 5517 MockRead(ASYNC, 0, 0) // EOF 5518 }; 5519 5520 DelayedSocketData data(1, reads, arraysize(reads), 5521 writes, arraysize(writes)); 5522 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY, 5523 BoundNetLog(), GetParam(), NULL); 5524 helper.RunToCompletion(&data); 5525 TransactionHelperResult out = helper.output(); 5526 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv); 5527 } 5528 5529 TEST_P(SpdyNetworkTransactionTest, SynReplyWithLateHeaders) { 5530 scoped_ptr<SpdyFrame> req( 5531 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); 5532 scoped_ptr<SpdyFrame> rst( 5533 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR)); 5534 MockWrite writes[] = { 5535 CreateMockWrite(*req), 5536 CreateMockWrite(*rst), 5537 }; 5538 5539 scoped_ptr<SpdyHeaderBlock> initial_headers(new SpdyHeaderBlock()); 5540 (*initial_headers)[spdy_util_.GetStatusKey()] = "200 OK"; 5541 (*initial_headers)[spdy_util_.GetVersionKey()] = "HTTP/1.1"; 5542 scoped_ptr<SpdyFrame> stream1_reply( 5543 spdy_util_.ConstructSpdyControlFrame(initial_headers.Pass(), 5544 false, 5545 1, 5546 LOWEST, 5547 SYN_REPLY, 5548 CONTROL_FLAG_NONE, 5549 0)); 5550 5551 scoped_ptr<SpdyHeaderBlock> late_headers(new SpdyHeaderBlock()); 5552 (*late_headers)["hello"] = "bye"; 5553 scoped_ptr<SpdyFrame> stream1_headers( 5554 spdy_util_.ConstructSpdyControlFrame(late_headers.Pass(), 5555 false, 5556 1, 5557 LOWEST, 5558 HEADERS, 5559 CONTROL_FLAG_NONE, 5560 0)); 5561 scoped_ptr<SpdyFrame> stream1_body( 5562 spdy_util_.ConstructSpdyBodyFrame(1, false)); 5563 scoped_ptr<SpdyFrame> stream1_body2( 5564 spdy_util_.ConstructSpdyBodyFrame(1, true)); 5565 MockRead reads[] = { 5566 CreateMockRead(*stream1_reply), 5567 CreateMockRead(*stream1_body), 5568 CreateMockRead(*stream1_headers), 5569 CreateMockRead(*stream1_body2), 5570 MockRead(ASYNC, 0, 0) // EOF 5571 }; 5572 5573 DelayedSocketData data(1, reads, arraysize(reads), 5574 writes, arraysize(writes)); 5575 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY, 5576 BoundNetLog(), GetParam(), NULL); 5577 helper.RunToCompletion(&data); 5578 TransactionHelperResult out = helper.output(); 5579 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv); 5580 } 5581 5582 TEST_P(SpdyNetworkTransactionTest, ServerPushCrossOriginCorrectness) { 5583 // In this test we want to verify that we can't accidentally push content 5584 // which can't be pushed by this content server. 5585 // This test assumes that: 5586 // - if we're requesting http://www.foo.com/barbaz 5587 // - the browser has made a connection to "www.foo.com". 5588 5589 // A list of the URL to fetch, followed by the URL being pushed. 5590 static const char* const kTestCases[] = { 5591 "http://www.google.com/foo.html", 5592 "http://www.google.com:81/foo.js", // Bad port 5593 5594 "http://www.google.com/foo.html", 5595 "https://www.google.com/foo.js", // Bad protocol 5596 5597 "http://www.google.com/foo.html", 5598 "ftp://www.google.com/foo.js", // Invalid Protocol 5599 5600 "http://www.google.com/foo.html", 5601 "http://blat.www.google.com/foo.js", // Cross subdomain 5602 5603 "http://www.google.com/foo.html", 5604 "http://www.foo.com/foo.js", // Cross domain 5605 }; 5606 5607 for (size_t index = 0; index < arraysize(kTestCases); index += 2) { 5608 const char* url_to_fetch = kTestCases[index]; 5609 const char* url_to_push = kTestCases[index + 1]; 5610 5611 scoped_ptr<SpdyFrame> stream1_syn( 5612 spdy_util_.ConstructSpdyGet(url_to_fetch, false, 1, LOWEST)); 5613 scoped_ptr<SpdyFrame> stream1_body( 5614 spdy_util_.ConstructSpdyBodyFrame(1, true)); 5615 scoped_ptr<SpdyFrame> push_rst( 5616 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM)); 5617 MockWrite writes[] = { 5618 CreateMockWrite(*stream1_syn, 1), 5619 CreateMockWrite(*push_rst, 4), 5620 }; 5621 5622 scoped_ptr<SpdyFrame> 5623 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 5624 scoped_ptr<SpdyFrame> 5625 stream2_syn(spdy_util_.ConstructSpdyPush(NULL, 5626 0, 5627 2, 5628 1, 5629 url_to_push)); 5630 const char kPushedData[] = "pushed"; 5631 scoped_ptr<SpdyFrame> stream2_body( 5632 spdy_util_.ConstructSpdyBodyFrame( 5633 2, kPushedData, strlen(kPushedData), true)); 5634 scoped_ptr<SpdyFrame> rst( 5635 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_CANCEL)); 5636 5637 MockRead reads[] = { 5638 CreateMockRead(*stream1_reply, 2), 5639 CreateMockRead(*stream2_syn, 3), 5640 CreateMockRead(*stream1_body, 5, SYNCHRONOUS), 5641 CreateMockRead(*stream2_body, 6), 5642 MockRead(ASYNC, ERR_IO_PENDING, 7), // Force a pause 5643 }; 5644 5645 HttpResponseInfo response; 5646 OrderedSocketData data(reads, arraysize(reads), 5647 writes, arraysize(writes)); 5648 5649 HttpRequestInfo request; 5650 request.method = "GET"; 5651 request.url = GURL(url_to_fetch); 5652 request.load_flags = 0; 5653 5654 // Enable cross-origin push. Since we are not using a proxy, this should 5655 // not actually enable cross-origin SPDY push. 5656 scoped_ptr<SpdySessionDependencies> session_deps( 5657 CreateSpdySessionDependencies(GetParam())); 5658 session_deps->trusted_spdy_proxy = "123.45.67.89:8080"; 5659 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY, 5660 BoundNetLog(), GetParam(), 5661 session_deps.release()); 5662 helper.RunPreTestSetup(); 5663 helper.AddData(&data); 5664 5665 HttpNetworkTransaction* trans = helper.trans(); 5666 5667 // Start the transaction with basic parameters. 5668 TestCompletionCallback callback; 5669 5670 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 5671 EXPECT_EQ(ERR_IO_PENDING, rv); 5672 rv = callback.WaitForResult(); 5673 5674 // Read the response body. 5675 std::string result; 5676 ReadResult(trans, &data, &result); 5677 5678 // Verify that we consumed all test data. 5679 EXPECT_TRUE(data.at_read_eof()); 5680 EXPECT_TRUE(data.at_write_eof()); 5681 5682 // Verify the SYN_REPLY. 5683 // Copy the response info, because trans goes away. 5684 response = *trans->GetResponseInfo(); 5685 5686 VerifyStreamsClosed(helper); 5687 5688 // Verify the SYN_REPLY. 5689 EXPECT_TRUE(response.headers.get() != NULL); 5690 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine()); 5691 } 5692 } 5693 5694 TEST_P(SpdyNetworkTransactionTest, RetryAfterRefused) { 5695 // Construct the request. 5696 scoped_ptr<SpdyFrame> req( 5697 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); 5698 scoped_ptr<SpdyFrame> req2( 5699 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true)); 5700 MockWrite writes[] = { 5701 CreateMockWrite(*req, 1), 5702 CreateMockWrite(*req2, 3), 5703 }; 5704 5705 scoped_ptr<SpdyFrame> refused( 5706 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_REFUSED_STREAM)); 5707 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3)); 5708 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(3, true)); 5709 MockRead reads[] = { 5710 CreateMockRead(*refused, 2), 5711 CreateMockRead(*resp, 4), 5712 CreateMockRead(*body, 5), 5713 MockRead(ASYNC, 0, 6) // EOF 5714 }; 5715 5716 OrderedSocketData data(reads, arraysize(reads), 5717 writes, arraysize(writes)); 5718 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY, 5719 BoundNetLog(), GetParam(), NULL); 5720 5721 helper.RunPreTestSetup(); 5722 helper.AddData(&data); 5723 5724 HttpNetworkTransaction* trans = helper.trans(); 5725 5726 // Start the transaction with basic parameters. 5727 TestCompletionCallback callback; 5728 int rv = trans->Start( 5729 &CreateGetRequest(), callback.callback(), BoundNetLog()); 5730 EXPECT_EQ(ERR_IO_PENDING, rv); 5731 rv = callback.WaitForResult(); 5732 EXPECT_EQ(OK, rv); 5733 5734 // Verify that we consumed all test data. 5735 EXPECT_TRUE(data.at_read_eof()) << "Read count: " 5736 << data.read_count() 5737 << " Read index: " 5738 << data.read_index(); 5739 EXPECT_TRUE(data.at_write_eof()) << "Write count: " 5740 << data.write_count() 5741 << " Write index: " 5742 << data.write_index(); 5743 5744 // Verify the SYN_REPLY. 5745 HttpResponseInfo response = *trans->GetResponseInfo(); 5746 EXPECT_TRUE(response.headers.get() != NULL); 5747 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine()); 5748 } 5749 5750 TEST_P(SpdyNetworkTransactionTest, OutOfOrderSynStream) { 5751 // This first request will start to establish the SpdySession. 5752 // Then we will start the second (MEDIUM priority) and then third 5753 // (HIGHEST priority) request in such a way that the third will actually 5754 // start before the second, causing the second to be numbered differently 5755 // than the order they were created. 5756 scoped_ptr<SpdyFrame> req1( 5757 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); 5758 scoped_ptr<SpdyFrame> req2( 5759 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, HIGHEST, true)); 5760 scoped_ptr<SpdyFrame> req3( 5761 spdy_util_.ConstructSpdyGet(NULL, 0, false, 5, MEDIUM, true)); 5762 MockWrite writes[] = { 5763 CreateMockWrite(*req1, 0), 5764 CreateMockWrite(*req2, 3), 5765 CreateMockWrite(*req3, 4), 5766 }; 5767 5768 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 5769 scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true)); 5770 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3)); 5771 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, true)); 5772 scoped_ptr<SpdyFrame> resp3(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 5)); 5773 scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(5, true)); 5774 MockRead reads[] = { 5775 CreateMockRead(*resp1, 1), 5776 CreateMockRead(*body1, 2), 5777 CreateMockRead(*resp2, 5), 5778 CreateMockRead(*body2, 6), 5779 CreateMockRead(*resp3, 7), 5780 CreateMockRead(*body3, 8), 5781 MockRead(ASYNC, 0, 9) // EOF 5782 }; 5783 5784 DeterministicSocketData data(reads, arraysize(reads), 5785 writes, arraysize(writes)); 5786 NormalSpdyTransactionHelper helper(CreateGetRequest(), LOWEST, 5787 BoundNetLog(), GetParam(), NULL); 5788 helper.SetDeterministic(); 5789 helper.RunPreTestSetup(); 5790 helper.AddDeterministicData(&data); 5791 5792 // Start the first transaction to set up the SpdySession 5793 HttpNetworkTransaction* trans = helper.trans(); 5794 TestCompletionCallback callback; 5795 HttpRequestInfo info1 = CreateGetRequest(); 5796 int rv = trans->Start(&info1, callback.callback(), BoundNetLog()); 5797 EXPECT_EQ(ERR_IO_PENDING, rv); 5798 5799 // Run the message loop, but do not allow the write to complete. 5800 // This leaves the SpdySession with a write pending, which prevents 5801 // SpdySession from attempting subsequent writes until this write completes. 5802 base::RunLoop().RunUntilIdle(); 5803 5804 // Now, start both new transactions 5805 HttpRequestInfo info2 = CreateGetRequest(); 5806 TestCompletionCallback callback2; 5807 scoped_ptr<HttpNetworkTransaction> trans2( 5808 new HttpNetworkTransaction(MEDIUM, helper.session().get())); 5809 rv = trans2->Start(&info2, callback2.callback(), BoundNetLog()); 5810 EXPECT_EQ(ERR_IO_PENDING, rv); 5811 base::RunLoop().RunUntilIdle(); 5812 5813 HttpRequestInfo info3 = CreateGetRequest(); 5814 TestCompletionCallback callback3; 5815 scoped_ptr<HttpNetworkTransaction> trans3( 5816 new HttpNetworkTransaction(HIGHEST, helper.session().get())); 5817 rv = trans3->Start(&info3, callback3.callback(), BoundNetLog()); 5818 EXPECT_EQ(ERR_IO_PENDING, rv); 5819 base::RunLoop().RunUntilIdle(); 5820 5821 // We now have two SYN_STREAM frames queued up which will be 5822 // dequeued only once the first write completes, which we 5823 // now allow to happen. 5824 data.RunFor(2); 5825 EXPECT_EQ(OK, callback.WaitForResult()); 5826 5827 // And now we can allow everything else to run to completion. 5828 data.SetStop(10); 5829 data.Run(); 5830 EXPECT_EQ(OK, callback2.WaitForResult()); 5831 EXPECT_EQ(OK, callback3.WaitForResult()); 5832 5833 helper.VerifyDataConsumed(); 5834 } 5835 5836 // The tests below are only for SPDY/3 and above. 5837 5838 // Test that sent data frames and received WINDOW_UPDATE frames change 5839 // the send_window_size_ correctly. 5840 5841 // WINDOW_UPDATE is different than most other frames in that it can arrive 5842 // while the client is still sending the request body. In order to enforce 5843 // this scenario, we feed a couple of dummy frames and give a delay of 0 to 5844 // socket data provider, so that initial read that is done as soon as the 5845 // stream is created, succeeds and schedules another read. This way reads 5846 // and writes are interleaved; after doing a full frame write, SpdyStream 5847 // will break out of DoLoop and will read and process a WINDOW_UPDATE. 5848 // Once our WINDOW_UPDATE is read, we cannot send SYN_REPLY right away 5849 // since request has not been completely written, therefore we feed 5850 // enough number of WINDOW_UPDATEs to finish the first read and cause a 5851 // write, leading to a complete write of request body; after that we send 5852 // a reply with a body, to cause a graceful shutdown. 5853 5854 // TODO(agayev): develop a socket data provider where both, reads and 5855 // writes are ordered so that writing tests like these are easy and rewrite 5856 // all these tests using it. Right now we are working around the 5857 // limitations as described above and it's not deterministic, tests may 5858 // fail under specific circumstances. 5859 TEST_P(SpdyNetworkTransactionTest, WindowUpdateReceived) { 5860 if (GetParam().protocol < kProtoSPDY3) 5861 return; 5862 5863 static int kFrameCount = 2; 5864 scoped_ptr<std::string> content( 5865 new std::string(kMaxSpdyFrameChunkSize, 'a')); 5866 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost( 5867 kRequestUrl, 1, kMaxSpdyFrameChunkSize * kFrameCount, LOWEST, NULL, 0)); 5868 scoped_ptr<SpdyFrame> body( 5869 spdy_util_.ConstructSpdyBodyFrame( 5870 1, content->c_str(), content->size(), false)); 5871 scoped_ptr<SpdyFrame> body_end( 5872 spdy_util_.ConstructSpdyBodyFrame( 5873 1, content->c_str(), content->size(), true)); 5874 5875 MockWrite writes[] = { 5876 CreateMockWrite(*req, 0), 5877 CreateMockWrite(*body, 1), 5878 CreateMockWrite(*body_end, 2), 5879 }; 5880 5881 static const int32 kDeltaWindowSize = 0xff; 5882 static const int kDeltaCount = 4; 5883 scoped_ptr<SpdyFrame> window_update( 5884 spdy_util_.ConstructSpdyWindowUpdate(1, kDeltaWindowSize)); 5885 scoped_ptr<SpdyFrame> window_update_dummy( 5886 spdy_util_.ConstructSpdyWindowUpdate(2, kDeltaWindowSize)); 5887 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0)); 5888 MockRead reads[] = { 5889 CreateMockRead(*window_update_dummy, 3), 5890 CreateMockRead(*window_update_dummy, 4), 5891 CreateMockRead(*window_update_dummy, 5), 5892 CreateMockRead(*window_update, 6), // Four updates, therefore window 5893 CreateMockRead(*window_update, 7), // size should increase by 5894 CreateMockRead(*window_update, 8), // kDeltaWindowSize * 4 5895 CreateMockRead(*window_update, 9), 5896 CreateMockRead(*resp, 10), 5897 CreateMockRead(*body_end, 11), 5898 MockRead(ASYNC, 0, 0, 12) // EOF 5899 }; 5900 5901 DeterministicSocketData data(reads, arraysize(reads), 5902 writes, arraysize(writes)); 5903 5904 ScopedVector<UploadElementReader> element_readers; 5905 for (int i = 0; i < kFrameCount; ++i) { 5906 element_readers.push_back( 5907 new UploadBytesElementReader(content->c_str(), content->size())); 5908 } 5909 UploadDataStream upload_data_stream(element_readers.Pass(), 0); 5910 5911 // Setup the request 5912 HttpRequestInfo request; 5913 request.method = "POST"; 5914 request.url = GURL(kDefaultURL); 5915 request.upload_data_stream = &upload_data_stream; 5916 5917 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY, 5918 BoundNetLog(), GetParam(), NULL); 5919 helper.SetDeterministic(); 5920 helper.AddDeterministicData(&data); 5921 helper.RunPreTestSetup(); 5922 5923 HttpNetworkTransaction* trans = helper.trans(); 5924 5925 TestCompletionCallback callback; 5926 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog()); 5927 5928 EXPECT_EQ(ERR_IO_PENDING, rv); 5929 5930 data.RunFor(11); 5931 5932 SpdyHttpStream* stream = static_cast<SpdyHttpStream*>(trans->stream_.get()); 5933 ASSERT_TRUE(stream != NULL); 5934 ASSERT_TRUE(stream->stream() != NULL); 5935 EXPECT_EQ(static_cast<int>(kSpdyStreamInitialWindowSize) + 5936 kDeltaWindowSize * kDeltaCount - 5937 kMaxSpdyFrameChunkSize * kFrameCount, 5938 stream->stream()->send_window_size()); 5939 5940 data.RunFor(1); 5941 5942 rv = callback.WaitForResult(); 5943 EXPECT_EQ(OK, rv); 5944 5945 helper.VerifyDataConsumed(); 5946 } 5947 5948 // Test that received data frames and sent WINDOW_UPDATE frames change 5949 // the recv_window_size_ correctly. 5950 TEST_P(SpdyNetworkTransactionTest, WindowUpdateSent) { 5951 if (GetParam().protocol < kProtoSPDY3) 5952 return; 5953 5954 // Set the data in the body frame large enough to trigger sending a 5955 // WINDOW_UPDATE by the stream. 5956 const std::string body_data(kSpdyStreamInitialWindowSize / 2 + 1, 'x'); 5957 5958 scoped_ptr<SpdyFrame> req( 5959 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); 5960 scoped_ptr<SpdyFrame> session_window_update( 5961 spdy_util_.ConstructSpdyWindowUpdate(0, body_data.size())); 5962 scoped_ptr<SpdyFrame> window_update( 5963 spdy_util_.ConstructSpdyWindowUpdate(1, body_data.size())); 5964 5965 std::vector<MockWrite> writes; 5966 writes.push_back(CreateMockWrite(*req)); 5967 if (GetParam().protocol >= kProtoSPDY31) 5968 writes.push_back(CreateMockWrite(*session_window_update)); 5969 writes.push_back(CreateMockWrite(*window_update)); 5970 5971 scoped_ptr<SpdyFrame> resp( 5972 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 5973 scoped_ptr<SpdyFrame> body_no_fin( 5974 spdy_util_.ConstructSpdyBodyFrame( 5975 1, body_data.data(), body_data.size(), false)); 5976 scoped_ptr<SpdyFrame> body_fin( 5977 spdy_util_.ConstructSpdyBodyFrame(1, NULL, 0, true)); 5978 MockRead reads[] = { 5979 CreateMockRead(*resp), 5980 CreateMockRead(*body_no_fin), 5981 MockRead(ASYNC, ERR_IO_PENDING, 0), // Force a pause 5982 CreateMockRead(*body_fin), 5983 MockRead(ASYNC, ERR_IO_PENDING, 0), // Force a pause 5984 MockRead(ASYNC, 0, 0) // EOF 5985 }; 5986 5987 DelayedSocketData data(1, reads, arraysize(reads), 5988 vector_as_array(&writes), writes.size()); 5989 5990 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY, 5991 BoundNetLog(), GetParam(), NULL); 5992 helper.AddData(&data); 5993 helper.RunPreTestSetup(); 5994 HttpNetworkTransaction* trans = helper.trans(); 5995 5996 TestCompletionCallback callback; 5997 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog()); 5998 5999 EXPECT_EQ(ERR_IO_PENDING, rv); 6000 rv = callback.WaitForResult(); 6001 EXPECT_EQ(OK, rv); 6002 6003 SpdyHttpStream* stream = 6004 static_cast<SpdyHttpStream*>(trans->stream_.get()); 6005 ASSERT_TRUE(stream != NULL); 6006 ASSERT_TRUE(stream->stream() != NULL); 6007 6008 EXPECT_EQ( 6009 static_cast<int>(kSpdyStreamInitialWindowSize - body_data.size()), 6010 stream->stream()->recv_window_size()); 6011 6012 const HttpResponseInfo* response = trans->GetResponseInfo(); 6013 ASSERT_TRUE(response != NULL); 6014 ASSERT_TRUE(response->headers.get() != NULL); 6015 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); 6016 EXPECT_TRUE(response->was_fetched_via_spdy); 6017 6018 // Issue a read which will cause a WINDOW_UPDATE to be sent and window 6019 // size increased to default. 6020 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(body_data.size())); 6021 rv = trans->Read(buf.get(), body_data.size(), CompletionCallback()); 6022 EXPECT_EQ(static_cast<int>(body_data.size()), rv); 6023 std::string content(buf->data(), buf->data() + body_data.size()); 6024 EXPECT_EQ(body_data, content); 6025 6026 // Schedule the reading of empty data frame with FIN 6027 data.CompleteRead(); 6028 6029 // Force write of WINDOW_UPDATE which was scheduled during the above 6030 // read. 6031 base::RunLoop().RunUntilIdle(); 6032 6033 // Read EOF. 6034 data.CompleteRead(); 6035 6036 helper.VerifyDataConsumed(); 6037 } 6038 6039 // Test that WINDOW_UPDATE frame causing overflow is handled correctly. 6040 TEST_P(SpdyNetworkTransactionTest, WindowUpdateOverflow) { 6041 if (GetParam().protocol < kProtoSPDY3) 6042 return; 6043 6044 // Number of full frames we hope to write (but will not, used to 6045 // set content-length header correctly) 6046 static int kFrameCount = 3; 6047 6048 scoped_ptr<std::string> content( 6049 new std::string(kMaxSpdyFrameChunkSize, 'a')); 6050 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost( 6051 kRequestUrl, 1, kMaxSpdyFrameChunkSize * kFrameCount, LOWEST, NULL, 0)); 6052 scoped_ptr<SpdyFrame> body( 6053 spdy_util_.ConstructSpdyBodyFrame( 6054 1, content->c_str(), content->size(), false)); 6055 scoped_ptr<SpdyFrame> rst( 6056 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_FLOW_CONTROL_ERROR)); 6057 6058 // We're not going to write a data frame with FIN, we'll receive a bad 6059 // WINDOW_UPDATE while sending a request and will send a RST_STREAM frame. 6060 MockWrite writes[] = { 6061 CreateMockWrite(*req, 0), 6062 CreateMockWrite(*body, 2), 6063 CreateMockWrite(*rst, 3), 6064 }; 6065 6066 static const int32 kDeltaWindowSize = 0x7fffffff; // cause an overflow 6067 scoped_ptr<SpdyFrame> window_update( 6068 spdy_util_.ConstructSpdyWindowUpdate(1, kDeltaWindowSize)); 6069 MockRead reads[] = { 6070 CreateMockRead(*window_update, 1), 6071 MockRead(ASYNC, 0, 4) // EOF 6072 }; 6073 6074 DeterministicSocketData data(reads, arraysize(reads), 6075 writes, arraysize(writes)); 6076 6077 ScopedVector<UploadElementReader> element_readers; 6078 for (int i = 0; i < kFrameCount; ++i) { 6079 element_readers.push_back( 6080 new UploadBytesElementReader(content->c_str(), content->size())); 6081 } 6082 UploadDataStream upload_data_stream(element_readers.Pass(), 0); 6083 6084 // Setup the request 6085 HttpRequestInfo request; 6086 request.method = "POST"; 6087 request.url = GURL("http://www.google.com/"); 6088 request.upload_data_stream = &upload_data_stream; 6089 6090 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY, 6091 BoundNetLog(), GetParam(), NULL); 6092 helper.SetDeterministic(); 6093 helper.RunPreTestSetup(); 6094 helper.AddDeterministicData(&data); 6095 HttpNetworkTransaction* trans = helper.trans(); 6096 6097 TestCompletionCallback callback; 6098 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog()); 6099 ASSERT_EQ(ERR_IO_PENDING, rv); 6100 6101 data.RunFor(5); 6102 ASSERT_TRUE(callback.have_result()); 6103 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, callback.WaitForResult()); 6104 helper.VerifyDataConsumed(); 6105 } 6106 6107 // Test that after hitting a send window size of 0, the write process 6108 // stalls and upon receiving WINDOW_UPDATE frame write resumes. 6109 6110 // This test constructs a POST request followed by enough data frames 6111 // containing 'a' that would make the window size 0, followed by another 6112 // data frame containing default content (which is "hello!") and this frame 6113 // also contains a FIN flag. DelayedSocketData is used to enforce all 6114 // writes go through before a read could happen. However, the last frame 6115 // ("hello!") is not supposed to go through since by the time its turn 6116 // arrives, window size is 0. At this point MessageLoop::Run() called via 6117 // callback would block. Therefore we call MessageLoop::RunUntilIdle() 6118 // which returns after performing all possible writes. We use DCHECKS to 6119 // ensure that last data frame is still there and stream has stalled. 6120 // After that, next read is artifically enforced, which causes a 6121 // WINDOW_UPDATE to be read and I/O process resumes. 6122 TEST_P(SpdyNetworkTransactionTest, FlowControlStallResume) { 6123 if (GetParam().protocol < kProtoSPDY3) 6124 return; 6125 6126 // Number of frames we need to send to zero out the window size: data 6127 // frames plus SYN_STREAM plus the last data frame; also we need another 6128 // data frame that we will send once the WINDOW_UPDATE is received, 6129 // therefore +3. 6130 size_t num_writes = kSpdyStreamInitialWindowSize / kMaxSpdyFrameChunkSize + 3; 6131 6132 // Calculate last frame's size; 0 size data frame is legal. 6133 size_t last_frame_size = 6134 kSpdyStreamInitialWindowSize % kMaxSpdyFrameChunkSize; 6135 6136 // Construct content for a data frame of maximum size. 6137 std::string content(kMaxSpdyFrameChunkSize, 'a'); 6138 6139 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost( 6140 kRequestUrl, 1, kSpdyStreamInitialWindowSize + kUploadDataSize, 6141 LOWEST, NULL, 0)); 6142 6143 // Full frames. 6144 scoped_ptr<SpdyFrame> body1( 6145 spdy_util_.ConstructSpdyBodyFrame( 6146 1, content.c_str(), content.size(), false)); 6147 6148 // Last frame to zero out the window size. 6149 scoped_ptr<SpdyFrame> body2( 6150 spdy_util_.ConstructSpdyBodyFrame( 6151 1, content.c_str(), last_frame_size, false)); 6152 6153 // Data frame to be sent once WINDOW_UPDATE frame is received. 6154 scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(1, true)); 6155 6156 // Fill in mock writes. 6157 scoped_ptr<MockWrite[]> writes(new MockWrite[num_writes]); 6158 size_t i = 0; 6159 writes[i] = CreateMockWrite(*req); 6160 for (i = 1; i < num_writes - 2; i++) 6161 writes[i] = CreateMockWrite(*body1); 6162 writes[i++] = CreateMockWrite(*body2); 6163 writes[i] = CreateMockWrite(*body3); 6164 6165 // Construct read frame, give enough space to upload the rest of the 6166 // data. 6167 scoped_ptr<SpdyFrame> session_window_update( 6168 spdy_util_.ConstructSpdyWindowUpdate(0, kUploadDataSize)); 6169 scoped_ptr<SpdyFrame> window_update( 6170 spdy_util_.ConstructSpdyWindowUpdate(1, kUploadDataSize)); 6171 scoped_ptr<SpdyFrame> reply(spdy_util_.ConstructSpdyPostSynReply(NULL, 0)); 6172 MockRead reads[] = { 6173 CreateMockRead(*session_window_update), 6174 CreateMockRead(*session_window_update), 6175 CreateMockRead(*window_update), 6176 CreateMockRead(*window_update), 6177 CreateMockRead(*reply), 6178 CreateMockRead(*body2), 6179 CreateMockRead(*body3), 6180 MockRead(ASYNC, 0, 0) // EOF 6181 }; 6182 6183 // Skip the session window updates unless we're using SPDY/3.1 and 6184 // above. 6185 size_t read_offset = (GetParam().protocol >= kProtoSPDY31) ? 0 : 2; 6186 size_t num_reads = arraysize(reads) - read_offset; 6187 6188 // Force all writes to happen before any read, last write will not 6189 // actually queue a frame, due to window size being 0. 6190 DelayedSocketData data(num_writes, reads + read_offset, num_reads, 6191 writes.get(), num_writes); 6192 6193 ScopedVector<UploadElementReader> element_readers; 6194 std::string upload_data_string(kSpdyStreamInitialWindowSize, 'a'); 6195 upload_data_string.append(kUploadData, kUploadDataSize); 6196 element_readers.push_back(new UploadBytesElementReader( 6197 upload_data_string.c_str(), upload_data_string.size())); 6198 UploadDataStream upload_data_stream(element_readers.Pass(), 0); 6199 6200 HttpRequestInfo request; 6201 request.method = "POST"; 6202 request.url = GURL("http://www.google.com/"); 6203 request.upload_data_stream = &upload_data_stream; 6204 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY, 6205 BoundNetLog(), GetParam(), NULL); 6206 helper.AddData(&data); 6207 helper.RunPreTestSetup(); 6208 6209 HttpNetworkTransaction* trans = helper.trans(); 6210 6211 TestCompletionCallback callback; 6212 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog()); 6213 EXPECT_EQ(ERR_IO_PENDING, rv); 6214 6215 base::RunLoop().RunUntilIdle(); // Write as much as we can. 6216 6217 SpdyHttpStream* stream = static_cast<SpdyHttpStream*>(trans->stream_.get()); 6218 ASSERT_TRUE(stream != NULL); 6219 ASSERT_TRUE(stream->stream() != NULL); 6220 EXPECT_EQ(0, stream->stream()->send_window_size()); 6221 // All the body data should have been read. 6222 // TODO(satorux): This is because of the weirdness in reading the request 6223 // body in OnSendBodyComplete(). See crbug.com/113107. 6224 EXPECT_TRUE(upload_data_stream.IsEOF()); 6225 // But the body is not yet fully sent (kUploadData is not yet sent) 6226 // since we're send-stalled. 6227 EXPECT_TRUE(stream->stream()->send_stalled_by_flow_control()); 6228 6229 data.ForceNextRead(); // Read in WINDOW_UPDATE frame. 6230 rv = callback.WaitForResult(); 6231 helper.VerifyDataConsumed(); 6232 } 6233 6234 // Test we correctly handle the case where the SETTINGS frame results in 6235 // unstalling the send window. 6236 TEST_P(SpdyNetworkTransactionTest, FlowControlStallResumeAfterSettings) { 6237 if (GetParam().protocol < kProtoSPDY3) 6238 return; 6239 6240 // Number of frames we need to send to zero out the window size: data 6241 // frames plus SYN_STREAM plus the last data frame; also we need another 6242 // data frame that we will send once the SETTING is received, therefore +3. 6243 size_t num_writes = kSpdyStreamInitialWindowSize / kMaxSpdyFrameChunkSize + 3; 6244 6245 // Calculate last frame's size; 0 size data frame is legal. 6246 size_t last_frame_size = 6247 kSpdyStreamInitialWindowSize % kMaxSpdyFrameChunkSize; 6248 6249 // Construct content for a data frame of maximum size. 6250 std::string content(kMaxSpdyFrameChunkSize, 'a'); 6251 6252 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost( 6253 kRequestUrl, 1, kSpdyStreamInitialWindowSize + kUploadDataSize, 6254 LOWEST, NULL, 0)); 6255 6256 // Full frames. 6257 scoped_ptr<SpdyFrame> body1( 6258 spdy_util_.ConstructSpdyBodyFrame( 6259 1, content.c_str(), content.size(), false)); 6260 6261 // Last frame to zero out the window size. 6262 scoped_ptr<SpdyFrame> body2( 6263 spdy_util_.ConstructSpdyBodyFrame( 6264 1, content.c_str(), last_frame_size, false)); 6265 6266 // Data frame to be sent once SETTINGS frame is received. 6267 scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(1, true)); 6268 6269 // Fill in mock reads/writes. 6270 std::vector<MockRead> reads; 6271 std::vector<MockWrite> writes; 6272 size_t i = 0; 6273 writes.push_back(CreateMockWrite(*req, i++)); 6274 while (i < num_writes - 2) 6275 writes.push_back(CreateMockWrite(*body1, i++)); 6276 writes.push_back(CreateMockWrite(*body2, i++)); 6277 6278 // Construct read frame for SETTINGS that gives enough space to upload the 6279 // rest of the data. 6280 SettingsMap settings; 6281 settings[SETTINGS_INITIAL_WINDOW_SIZE] = 6282 SettingsFlagsAndValue( 6283 SETTINGS_FLAG_NONE, kSpdyStreamInitialWindowSize * 2); 6284 scoped_ptr<SpdyFrame> settings_frame_large( 6285 spdy_util_.ConstructSpdySettings(settings)); 6286 6287 reads.push_back(CreateMockRead(*settings_frame_large, i++)); 6288 6289 scoped_ptr<SpdyFrame> session_window_update( 6290 spdy_util_.ConstructSpdyWindowUpdate(0, kUploadDataSize)); 6291 if (GetParam().protocol >= kProtoSPDY31) 6292 reads.push_back(CreateMockRead(*session_window_update, i++)); 6293 6294 writes.push_back(CreateMockWrite(*body3, i++)); 6295 6296 scoped_ptr<SpdyFrame> reply(spdy_util_.ConstructSpdyPostSynReply(NULL, 0)); 6297 reads.push_back(CreateMockRead(*reply, i++)); 6298 reads.push_back(CreateMockRead(*body2, i++)); 6299 reads.push_back(CreateMockRead(*body3, i++)); 6300 reads.push_back(MockRead(ASYNC, 0, i++)); // EOF 6301 6302 // Force all writes to happen before any read, last write will not 6303 // actually queue a frame, due to window size being 0. 6304 DeterministicSocketData data(vector_as_array(&reads), reads.size(), 6305 vector_as_array(&writes), writes.size()); 6306 6307 ScopedVector<UploadElementReader> element_readers; 6308 std::string upload_data_string(kSpdyStreamInitialWindowSize, 'a'); 6309 upload_data_string.append(kUploadData, kUploadDataSize); 6310 element_readers.push_back(new UploadBytesElementReader( 6311 upload_data_string.c_str(), upload_data_string.size())); 6312 UploadDataStream upload_data_stream(element_readers.Pass(), 0); 6313 6314 HttpRequestInfo request; 6315 request.method = "POST"; 6316 request.url = GURL("http://www.google.com/"); 6317 request.upload_data_stream = &upload_data_stream; 6318 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY, 6319 BoundNetLog(), GetParam(), NULL); 6320 helper.SetDeterministic(); 6321 helper.RunPreTestSetup(); 6322 helper.AddDeterministicData(&data); 6323 6324 HttpNetworkTransaction* trans = helper.trans(); 6325 6326 TestCompletionCallback callback; 6327 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog()); 6328 EXPECT_EQ(ERR_IO_PENDING, rv); 6329 6330 data.RunFor(num_writes - 1); // Write as much as we can. 6331 6332 SpdyHttpStream* stream = static_cast<SpdyHttpStream*>(trans->stream_.get()); 6333 ASSERT_TRUE(stream != NULL); 6334 ASSERT_TRUE(stream->stream() != NULL); 6335 EXPECT_EQ(0, stream->stream()->send_window_size()); 6336 6337 // All the body data should have been read. 6338 // TODO(satorux): This is because of the weirdness in reading the request 6339 // body in OnSendBodyComplete(). See crbug.com/113107. 6340 EXPECT_TRUE(upload_data_stream.IsEOF()); 6341 // But the body is not yet fully sent (kUploadData is not yet sent) 6342 // since we're send-stalled. 6343 EXPECT_TRUE(stream->stream()->send_stalled_by_flow_control()); 6344 6345 data.RunFor(6); // Read in SETTINGS frame to unstall. 6346 rv = callback.WaitForResult(); 6347 helper.VerifyDataConsumed(); 6348 // If stream is NULL, that means it was unstalled and closed. 6349 EXPECT_TRUE(stream->stream() == NULL); 6350 } 6351 6352 // Test we correctly handle the case where the SETTINGS frame results in a 6353 // negative send window size. 6354 TEST_P(SpdyNetworkTransactionTest, FlowControlNegativeSendWindowSize) { 6355 if (GetParam().protocol < kProtoSPDY3) 6356 return; 6357 6358 // Number of frames we need to send to zero out the window size: data 6359 // frames plus SYN_STREAM plus the last data frame; also we need another 6360 // data frame that we will send once the SETTING is received, therefore +3. 6361 size_t num_writes = kSpdyStreamInitialWindowSize / kMaxSpdyFrameChunkSize + 3; 6362 6363 // Calculate last frame's size; 0 size data frame is legal. 6364 size_t last_frame_size = 6365 kSpdyStreamInitialWindowSize % kMaxSpdyFrameChunkSize; 6366 6367 // Construct content for a data frame of maximum size. 6368 std::string content(kMaxSpdyFrameChunkSize, 'a'); 6369 6370 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost( 6371 kRequestUrl, 1, kSpdyStreamInitialWindowSize + kUploadDataSize, 6372 LOWEST, NULL, 0)); 6373 6374 // Full frames. 6375 scoped_ptr<SpdyFrame> body1( 6376 spdy_util_.ConstructSpdyBodyFrame( 6377 1, content.c_str(), content.size(), false)); 6378 6379 // Last frame to zero out the window size. 6380 scoped_ptr<SpdyFrame> body2( 6381 spdy_util_.ConstructSpdyBodyFrame( 6382 1, content.c_str(), last_frame_size, false)); 6383 6384 // Data frame to be sent once SETTINGS frame is received. 6385 scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(1, true)); 6386 6387 // Fill in mock reads/writes. 6388 std::vector<MockRead> reads; 6389 std::vector<MockWrite> writes; 6390 size_t i = 0; 6391 writes.push_back(CreateMockWrite(*req, i++)); 6392 while (i < num_writes - 2) 6393 writes.push_back(CreateMockWrite(*body1, i++)); 6394 writes.push_back(CreateMockWrite(*body2, i++)); 6395 6396 // Construct read frame for SETTINGS that makes the send_window_size 6397 // negative. 6398 SettingsMap new_settings; 6399 new_settings[SETTINGS_INITIAL_WINDOW_SIZE] = 6400 SettingsFlagsAndValue( 6401 SETTINGS_FLAG_NONE, kSpdyStreamInitialWindowSize / 2); 6402 scoped_ptr<SpdyFrame> settings_frame_small( 6403 spdy_util_.ConstructSpdySettings(new_settings)); 6404 // Construct read frames for WINDOW_UPDATE that makes the send_window_size 6405 // positive. 6406 scoped_ptr<SpdyFrame> session_window_update_init_size( 6407 spdy_util_.ConstructSpdyWindowUpdate(0, kSpdyStreamInitialWindowSize)); 6408 scoped_ptr<SpdyFrame> window_update_init_size( 6409 spdy_util_.ConstructSpdyWindowUpdate(1, kSpdyStreamInitialWindowSize)); 6410 6411 reads.push_back(CreateMockRead(*settings_frame_small, i++)); 6412 6413 if (GetParam().protocol >= kProtoSPDY3) 6414 reads.push_back(CreateMockRead(*session_window_update_init_size, i++)); 6415 6416 reads.push_back(CreateMockRead(*window_update_init_size, i++)); 6417 6418 writes.push_back(CreateMockWrite(*body3, i++)); 6419 6420 scoped_ptr<SpdyFrame> reply(spdy_util_.ConstructSpdyPostSynReply(NULL, 0)); 6421 reads.push_back(CreateMockRead(*reply, i++)); 6422 reads.push_back(CreateMockRead(*body2, i++)); 6423 reads.push_back(CreateMockRead(*body3, i++)); 6424 reads.push_back(MockRead(ASYNC, 0, i++)); // EOF 6425 6426 // Force all writes to happen before any read, last write will not 6427 // actually queue a frame, due to window size being 0. 6428 DeterministicSocketData data(vector_as_array(&reads), reads.size(), 6429 vector_as_array(&writes), writes.size()); 6430 6431 ScopedVector<UploadElementReader> element_readers; 6432 std::string upload_data_string(kSpdyStreamInitialWindowSize, 'a'); 6433 upload_data_string.append(kUploadData, kUploadDataSize); 6434 element_readers.push_back(new UploadBytesElementReader( 6435 upload_data_string.c_str(), upload_data_string.size())); 6436 UploadDataStream upload_data_stream(element_readers.Pass(), 0); 6437 6438 HttpRequestInfo request; 6439 request.method = "POST"; 6440 request.url = GURL("http://www.google.com/"); 6441 request.upload_data_stream = &upload_data_stream; 6442 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY, 6443 BoundNetLog(), GetParam(), NULL); 6444 helper.SetDeterministic(); 6445 helper.RunPreTestSetup(); 6446 helper.AddDeterministicData(&data); 6447 6448 HttpNetworkTransaction* trans = helper.trans(); 6449 6450 TestCompletionCallback callback; 6451 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog()); 6452 EXPECT_EQ(ERR_IO_PENDING, rv); 6453 6454 data.RunFor(num_writes - 1); // Write as much as we can. 6455 6456 SpdyHttpStream* stream = static_cast<SpdyHttpStream*>(trans->stream_.get()); 6457 ASSERT_TRUE(stream != NULL); 6458 ASSERT_TRUE(stream->stream() != NULL); 6459 EXPECT_EQ(0, stream->stream()->send_window_size()); 6460 6461 // All the body data should have been read. 6462 // TODO(satorux): This is because of the weirdness in reading the request 6463 // body in OnSendBodyComplete(). See crbug.com/113107. 6464 EXPECT_TRUE(upload_data_stream.IsEOF()); 6465 // But the body is not yet fully sent (kUploadData is not yet sent) 6466 // since we're send-stalled. 6467 EXPECT_TRUE(stream->stream()->send_stalled_by_flow_control()); 6468 6469 // Read in WINDOW_UPDATE or SETTINGS frame. 6470 data.RunFor((GetParam().protocol >= kProtoSPDY31) ? 8 : 7); 6471 rv = callback.WaitForResult(); 6472 helper.VerifyDataConsumed(); 6473 } 6474 6475 } // namespace net 6476