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