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