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