quic_http_stream_test.cc revision 5d1f7b1de12d16ceb2c938c56701a3e8bfa558f7
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 "net/quic/quic_http_stream.h" 6 7#include <vector> 8 9#include "net/base/net_errors.h" 10#include "net/base/test_completion_callback.h" 11#include "net/base/upload_bytes_element_reader.h" 12#include "net/base/upload_data_stream.h" 13#include "net/http/http_response_headers.h" 14#include "net/quic/congestion_control/receive_algorithm_interface.h" 15#include "net/quic/congestion_control/send_algorithm_interface.h" 16#include "net/quic/crypto/crypto_protocol.h" 17#include "net/quic/crypto/quic_decrypter.h" 18#include "net/quic/crypto/quic_encrypter.h" 19#include "net/quic/quic_client_session.h" 20#include "net/quic/quic_connection.h" 21#include "net/quic/quic_connection_helper.h" 22#include "net/quic/quic_default_packet_writer.h" 23#include "net/quic/quic_http_utils.h" 24#include "net/quic/quic_reliable_client_stream.h" 25#include "net/quic/quic_write_blocked_list.h" 26#include "net/quic/spdy_utils.h" 27#include "net/quic/test_tools/mock_clock.h" 28#include "net/quic/test_tools/mock_crypto_client_stream_factory.h" 29#include "net/quic/test_tools/mock_random.h" 30#include "net/quic/test_tools/quic_connection_peer.h" 31#include "net/quic/test_tools/quic_test_packet_maker.h" 32#include "net/quic/test_tools/quic_test_utils.h" 33#include "net/quic/test_tools/test_task_runner.h" 34#include "net/socket/socket_test_util.h" 35#include "net/spdy/spdy_frame_builder.h" 36#include "net/spdy/spdy_framer.h" 37#include "net/spdy/spdy_http_utils.h" 38#include "net/spdy/spdy_protocol.h" 39#include "testing/gmock/include/gmock/gmock.h" 40#include "testing/gtest/include/gtest/gtest.h" 41 42using testing::_; 43using testing::AnyNumber; 44using testing::Return; 45 46namespace net { 47namespace test { 48namespace { 49 50const char kUploadData[] = "hello world!"; 51 52class TestQuicConnection : public QuicConnection { 53 public: 54 TestQuicConnection(const QuicVersionVector& versions, 55 QuicGuid guid, 56 IPEndPoint address, 57 QuicConnectionHelper* helper, 58 QuicPacketWriter* writer) 59 : QuicConnection(guid, address, helper, writer, false, versions) { 60 } 61 62 void SetSendAlgorithm(SendAlgorithmInterface* send_algorithm) { 63 QuicConnectionPeer::SetSendAlgorithm(this, send_algorithm); 64 } 65 66 void SetReceiveAlgorithm(ReceiveAlgorithmInterface* receive_algorithm) { 67 QuicConnectionPeer::SetReceiveAlgorithm(this, receive_algorithm); 68 } 69}; 70 71class TestReceiveAlgorithm : public ReceiveAlgorithmInterface { 72 public: 73 virtual bool GenerateCongestionFeedback( 74 QuicCongestionFeedbackFrame* /*congestion_feedback*/) { 75 return false; 76 } 77 78 MOCK_METHOD3(RecordIncomingPacket, 79 void(QuicByteCount, QuicPacketSequenceNumber, QuicTime)); 80}; 81 82// Subclass of QuicHttpStream that closes itself when the first piece of data 83// is received. 84class AutoClosingStream : public QuicHttpStream { 85 public: 86 explicit AutoClosingStream(const base::WeakPtr<QuicClientSession>& session) 87 : QuicHttpStream(session) { 88 } 89 90 virtual int OnDataReceived(const char* data, int length) OVERRIDE { 91 Close(false); 92 return OK; 93 } 94}; 95 96} // namespace 97 98class QuicHttpStreamPeer { 99 public: 100 static QuicReliableClientStream* GetQuicReliableClientStream( 101 QuicHttpStream* stream) { 102 return stream->stream_; 103 } 104}; 105 106class QuicHttpStreamTest : public ::testing::TestWithParam<QuicVersion> { 107 protected: 108 static const bool kFin = true; 109 static const bool kIncludeVersion = true; 110 static const bool kIncludeCongestionFeedback = true; 111 112 // Holds a packet to be written to the wire, and the IO mode that should 113 // be used by the mock socket when performing the write. 114 struct PacketToWrite { 115 PacketToWrite(IoMode mode, QuicEncryptedPacket* packet) 116 : mode(mode), 117 packet(packet) { 118 } 119 IoMode mode; 120 QuicEncryptedPacket* packet; 121 }; 122 123 QuicHttpStreamTest() 124 : net_log_(BoundNetLog()), 125 use_closing_stream_(false), 126 read_buffer_(new IOBufferWithSize(4096)), 127 guid_(2), 128 stream_id_(GetParam() > QUIC_VERSION_12 ? 5 : 3), 129 maker_(GetParam(), guid_), 130 random_generator_(0) { 131 IPAddressNumber ip; 132 CHECK(ParseIPLiteralToNumber("192.0.2.33", &ip)); 133 peer_addr_ = IPEndPoint(ip, 443); 134 self_addr_ = IPEndPoint(ip, 8435); 135 } 136 137 ~QuicHttpStreamTest() { 138 session_->CloseSessionOnError(ERR_ABORTED); 139 for (size_t i = 0; i < writes_.size(); i++) { 140 delete writes_[i].packet; 141 } 142 } 143 144 // Adds a packet to the list of expected writes. 145 void AddWrite(scoped_ptr<QuicEncryptedPacket> packet) { 146 writes_.push_back(PacketToWrite(SYNCHRONOUS, packet.release())); 147 } 148 149 // Returns the packet to be written at position |pos|. 150 QuicEncryptedPacket* GetWrite(size_t pos) { 151 return writes_[pos].packet; 152 } 153 154 bool AtEof() { 155 return socket_data_->at_read_eof() && socket_data_->at_write_eof(); 156 } 157 158 void ProcessPacket(scoped_ptr<QuicEncryptedPacket> packet) { 159 connection_->ProcessUdpPacket(self_addr_, peer_addr_, *packet); 160 } 161 162 // Configures the test fixture to use the list of expected writes. 163 void Initialize() { 164 mock_writes_.reset(new MockWrite[writes_.size()]); 165 for (size_t i = 0; i < writes_.size(); i++) { 166 mock_writes_[i] = MockWrite(writes_[i].mode, 167 writes_[i].packet->data(), 168 writes_[i].packet->length()); 169 }; 170 171 socket_data_.reset(new StaticSocketDataProvider(NULL, 0, mock_writes_.get(), 172 writes_.size())); 173 174 MockUDPClientSocket* socket = new MockUDPClientSocket(socket_data_.get(), 175 net_log_.net_log()); 176 socket->Connect(peer_addr_); 177 runner_ = new TestTaskRunner(&clock_); 178 send_algorithm_ = new MockSendAlgorithm(); 179 receive_algorithm_ = new TestReceiveAlgorithm(); 180 EXPECT_CALL(*receive_algorithm_, RecordIncomingPacket(_, _, _)). 181 Times(AnyNumber()); 182 EXPECT_CALL(*send_algorithm_, 183 OnPacketSent(_, _, _, _, _)).WillRepeatedly(Return(true)); 184 EXPECT_CALL(*send_algorithm_, RetransmissionDelay()).WillRepeatedly( 185 Return(QuicTime::Delta::Zero())); 186 EXPECT_CALL(*send_algorithm_, TimeUntilSend(_, _, _, _)). 187 WillRepeatedly(Return(QuicTime::Delta::Zero())); 188 EXPECT_CALL(*send_algorithm_, SmoothedRtt()).WillRepeatedly( 189 Return(QuicTime::Delta::Zero())); 190 EXPECT_CALL(*send_algorithm_, BandwidthEstimate()).WillRepeatedly( 191 Return(QuicBandwidth::Zero())); 192 EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _)).Times(AnyNumber()); 193 helper_.reset(new QuicConnectionHelper(runner_.get(), &clock_, 194 &random_generator_)); 195 writer_.reset(new QuicDefaultPacketWriter(socket)); 196 connection_ = new TestQuicConnection(SupportedVersions(GetParam()), guid_, 197 peer_addr_, helper_.get(), 198 writer_.get()); 199 connection_->set_visitor(&visitor_); 200 connection_->SetSendAlgorithm(send_algorithm_); 201 connection_->SetReceiveAlgorithm(receive_algorithm_); 202 crypto_config_.SetDefaults(); 203 session_.reset( 204 new QuicClientSession(connection_, 205 scoped_ptr<DatagramClientSocket>(socket), 206 writer_.Pass(), NULL, 207 &crypto_client_stream_factory_, 208 "www.google.com", DefaultQuicConfig(), 209 &crypto_config_, NULL)); 210 session_->GetCryptoStream()->CryptoConnect(); 211 EXPECT_TRUE(session_->IsCryptoHandshakeConfirmed()); 212 stream_.reset(use_closing_stream_ ? 213 new AutoClosingStream(session_->GetWeakPtr()) : 214 new QuicHttpStream(session_->GetWeakPtr())); 215 } 216 217 void SetRequest(const std::string& method, 218 const std::string& path, 219 RequestPriority priority) { 220 request_headers_ = maker_.GetRequestHeaders(method, "http", path); 221 request_data_ = GetParam() > QUIC_VERSION_12 ? "" : 222 SerializeHeaderBlock(request_headers_, true, priority); 223 } 224 225 void SetResponse(const std::string& status, const std::string& body) { 226 response_headers_ = maker_.GetResponseHeaders(status); 227 if (GetParam() > QUIC_VERSION_12) { 228 response_data_ = body; 229 } else { 230 response_data_ = 231 SerializeHeaderBlock(response_headers_, false, DEFAULT_PRIORITY) + 232 body; 233 } 234 } 235 236 scoped_ptr<QuicEncryptedPacket> ConstructDataPacket( 237 QuicPacketSequenceNumber sequence_number, 238 bool should_include_version, 239 bool fin, 240 QuicStreamOffset offset, 241 base::StringPiece data) { 242 return maker_.MakeDataPacket( 243 sequence_number, stream_id_, should_include_version, fin, offset, data); 244 } 245 246 scoped_ptr<QuicEncryptedPacket> ConstructRequestHeadersPacket( 247 QuicPacketSequenceNumber sequence_number, 248 bool fin) { 249 return maker_.MakeRequestHeadersPacket( 250 sequence_number, stream_id_, kIncludeVersion, fin, request_headers_); 251 } 252 253 scoped_ptr<QuicEncryptedPacket> ConstructResponseHeadersPacket( 254 QuicPacketSequenceNumber sequence_number, 255 bool fin) { 256 return maker_.MakeResponseHeadersPacket( 257 sequence_number, stream_id_, !kIncludeVersion, fin, response_headers_); 258 } 259 260 scoped_ptr<QuicEncryptedPacket> ConstructRstStreamPacket( 261 QuicPacketSequenceNumber sequence_number) { 262 return maker_.MakeRstPacket( 263 sequence_number, true, stream_id_, QUIC_STREAM_NO_ERROR); 264 } 265 266 scoped_ptr<QuicEncryptedPacket> ConstructAckAndRstStreamPacket( 267 QuicPacketSequenceNumber sequence_number) { 268 return maker_.MakeAckAndRstPacket( 269 sequence_number, !kIncludeVersion, stream_id_, QUIC_STREAM_CANCELLED, 270 1, 1, !kIncludeCongestionFeedback); 271 } 272 273 scoped_ptr<QuicEncryptedPacket> ConstructAckPacket( 274 QuicPacketSequenceNumber sequence_number, 275 QuicPacketSequenceNumber largest_received, 276 QuicPacketSequenceNumber least_unacked) { 277 return maker_.MakeAckPacket(sequence_number, largest_received, 278 least_unacked, !kIncludeCongestionFeedback); 279 } 280 281 BoundNetLog net_log_; 282 bool use_closing_stream_; 283 MockSendAlgorithm* send_algorithm_; 284 TestReceiveAlgorithm* receive_algorithm_; 285 scoped_refptr<TestTaskRunner> runner_; 286 scoped_ptr<MockWrite[]> mock_writes_; 287 MockClock clock_; 288 TestQuicConnection* connection_; 289 scoped_ptr<QuicConnectionHelper> helper_; 290 testing::StrictMock<MockConnectionVisitor> visitor_; 291 scoped_ptr<QuicHttpStream> stream_; 292 scoped_ptr<QuicDefaultPacketWriter> writer_; 293 scoped_ptr<QuicClientSession> session_; 294 QuicCryptoClientConfig crypto_config_; 295 TestCompletionCallback callback_; 296 HttpRequestInfo request_; 297 HttpRequestHeaders headers_; 298 HttpResponseInfo response_; 299 scoped_refptr<IOBufferWithSize> read_buffer_; 300 SpdyHeaderBlock request_headers_; 301 SpdyHeaderBlock response_headers_; 302 std::string request_data_; 303 std::string response_data_; 304 305 private: 306 std::string SerializeHeaderBlock(const SpdyHeaderBlock& headers, 307 bool write_priority, 308 RequestPriority priority) { 309 QuicSpdyCompressor compressor; 310 if (write_priority) { 311 return compressor.CompressHeadersWithPriority( 312 ConvertRequestPriorityToQuicPriority(priority), headers); 313 } 314 return compressor.CompressHeaders(headers); 315 } 316 317 const QuicGuid guid_; 318 const QuicStreamId stream_id_; 319 QuicTestPacketMaker maker_; 320 IPEndPoint self_addr_; 321 IPEndPoint peer_addr_; 322 MockRandom random_generator_; 323 MockCryptoClientStreamFactory crypto_client_stream_factory_; 324 scoped_ptr<StaticSocketDataProvider> socket_data_; 325 std::vector<PacketToWrite> writes_; 326}; 327 328INSTANTIATE_TEST_CASE_P(Version, QuicHttpStreamTest, 329 ::testing::ValuesIn(QuicSupportedVersions())); 330 331TEST_P(QuicHttpStreamTest, RenewStreamForAuth) { 332 Initialize(); 333 EXPECT_EQ(NULL, stream_->RenewStreamForAuth()); 334} 335 336TEST_P(QuicHttpStreamTest, CanFindEndOfResponse) { 337 Initialize(); 338 EXPECT_TRUE(stream_->CanFindEndOfResponse()); 339} 340 341TEST_P(QuicHttpStreamTest, IsConnectionReusable) { 342 Initialize(); 343 EXPECT_FALSE(stream_->IsConnectionReusable()); 344} 345 346TEST_P(QuicHttpStreamTest, GetRequest) { 347 SetRequest("GET", "/", DEFAULT_PRIORITY); 348 if (GetParam() > QUIC_VERSION_12) { 349 AddWrite(ConstructRequestHeadersPacket(1, kFin)); 350 } else { 351 AddWrite(ConstructDataPacket(1, kIncludeVersion, kFin, 0, request_data_)); 352 } 353 Initialize(); 354 355 request_.method = "GET"; 356 request_.url = GURL("http://www.google.com/"); 357 358 EXPECT_EQ(OK, stream_->InitializeStream(&request_, DEFAULT_PRIORITY, 359 net_log_, callback_.callback())); 360 EXPECT_EQ(OK, stream_->SendRequest(headers_, &response_, 361 callback_.callback())); 362 EXPECT_EQ(&response_, stream_->GetResponseInfo()); 363 364 // Ack the request. 365 ProcessPacket(ConstructAckPacket(1, 0, 0)); 366 367 EXPECT_EQ(ERR_IO_PENDING, 368 stream_->ReadResponseHeaders(callback_.callback())); 369 370 SetResponse("404 Not Found", std::string()); 371 if (GetParam() > QUIC_VERSION_12) { 372 ProcessPacket(ConstructResponseHeadersPacket(2, kFin)); 373 } else { 374 ProcessPacket(ConstructDataPacket(2, false, kFin, 0, response_data_)); 375 } 376 377 // Now that the headers have been processed, the callback will return. 378 EXPECT_EQ(OK, callback_.WaitForResult()); 379 ASSERT_TRUE(response_.headers.get()); 380 EXPECT_EQ(404, response_.headers->response_code()); 381 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain")); 382 383 // There is no body, so this should return immediately. 384 EXPECT_EQ(0, stream_->ReadResponseBody(read_buffer_.get(), 385 read_buffer_->size(), 386 callback_.callback())); 387 EXPECT_TRUE(stream_->IsResponseBodyComplete()); 388 EXPECT_TRUE(AtEof()); 389} 390 391// Regression test for http://crbug.com/288128 392TEST_P(QuicHttpStreamTest, GetRequestLargeResponse) { 393 SetRequest("GET", "/", DEFAULT_PRIORITY); 394 if (GetParam() > QUIC_VERSION_12) { 395 AddWrite(ConstructRequestHeadersPacket(1, kFin)); 396 } else { 397 AddWrite(ConstructDataPacket(1, kIncludeVersion, kFin, 0, request_data_)); 398 } 399 Initialize(); 400 401 request_.method = "GET"; 402 request_.url = GURL("http://www.google.com/"); 403 404 EXPECT_EQ(OK, stream_->InitializeStream(&request_, DEFAULT_PRIORITY, 405 net_log_, callback_.callback())); 406 EXPECT_EQ(OK, stream_->SendRequest(headers_, &response_, 407 callback_.callback())); 408 EXPECT_EQ(&response_, stream_->GetResponseInfo()); 409 410 // Ack the request. 411 ProcessPacket(ConstructAckPacket(1, 0, 0)); 412 413 EXPECT_EQ(ERR_IO_PENDING, 414 stream_->ReadResponseHeaders(callback_.callback())); 415 416 SpdyHeaderBlock headers; 417 headers[":status"] = "200 OK"; 418 headers[":version"] = "HTTP/1.1"; 419 headers["content-type"] = "text/plain"; 420 headers["big6"] = std::string(10000, 'x'); // Lots of x's. 421 422 std::string response = SpdyUtils::SerializeUncompressedHeaders(headers); 423 EXPECT_LT(4096u, response.length()); 424 stream_->OnDataReceived(response.data(), response.length()); 425 stream_->OnClose(QUIC_NO_ERROR); 426 427 // Now that the headers have been processed, the callback will return. 428 EXPECT_EQ(OK, callback_.WaitForResult()); 429 ASSERT_TRUE(response_.headers.get()); 430 EXPECT_EQ(200, response_.headers->response_code()); 431 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain")); 432 433 // There is no body, so this should return immediately. 434 EXPECT_EQ(0, stream_->ReadResponseBody(read_buffer_.get(), 435 read_buffer_->size(), 436 callback_.callback())); 437 EXPECT_TRUE(stream_->IsResponseBodyComplete()); 438 EXPECT_TRUE(AtEof()); 439} 440 441TEST_P(QuicHttpStreamTest, GetRequestFullResponseInSinglePacket) { 442 SetRequest("GET", "/", DEFAULT_PRIORITY); 443 AddWrite(ConstructDataPacket(1, kIncludeVersion, kFin, 0, request_data_)); 444 Initialize(); 445 446 if (GetParam() > QUIC_VERSION_12) { 447 // we can't put the request and response into a single frame. 448 return; 449 } 450 451 request_.method = "GET"; 452 request_.url = GURL("http://www.google.com/"); 453 454 EXPECT_EQ(OK, stream_->InitializeStream(&request_, DEFAULT_PRIORITY, 455 net_log_, callback_.callback())); 456 EXPECT_EQ(OK, stream_->SendRequest(headers_, &response_, 457 callback_.callback())); 458 EXPECT_EQ(&response_, stream_->GetResponseInfo()); 459 460 // Ack the request. 461 ProcessPacket(ConstructAckPacket(1, 0, 0)); 462 463 EXPECT_EQ(ERR_IO_PENDING, 464 stream_->ReadResponseHeaders(callback_.callback())); 465 466 // Send the response with a body. 467 SetResponse("200 OK", "hello world!"); 468 ProcessPacket(ConstructDataPacket(2, false, kFin, 0, response_data_)); 469 470 // Now that the headers have been processed, the callback will return. 471 EXPECT_EQ(OK, callback_.WaitForResult()); 472 ASSERT_TRUE(response_.headers.get()); 473 EXPECT_EQ(200, response_.headers->response_code()); 474 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain")); 475 476 // There is no body, so this should return immediately. 477 // Since the body has already arrived, this should return immediately. 478 EXPECT_EQ(12, stream_->ReadResponseBody(read_buffer_.get(), 479 read_buffer_->size(), 480 callback_.callback())); 481 EXPECT_TRUE(stream_->IsResponseBodyComplete()); 482 EXPECT_TRUE(AtEof()); 483} 484 485TEST_P(QuicHttpStreamTest, SendPostRequest) { 486 SetRequest("POST", "/", DEFAULT_PRIORITY); 487 if (GetParam() > QUIC_VERSION_12) { 488 AddWrite(ConstructRequestHeadersPacket(1, !kFin)); 489 AddWrite(ConstructDataPacket(2, kIncludeVersion, kFin, 0, kUploadData)); 490 } else { 491 AddWrite(ConstructDataPacket(1, kIncludeVersion, !kFin, 0, request_data_)); 492 AddWrite(ConstructDataPacket(2, kIncludeVersion, kFin, 493 request_data_.length(), kUploadData)); 494 } 495 AddWrite(ConstructAckPacket(3, 3, 1)); 496 497 Initialize(); 498 499 ScopedVector<UploadElementReader> element_readers; 500 element_readers.push_back( 501 new UploadBytesElementReader(kUploadData, strlen(kUploadData))); 502 UploadDataStream upload_data_stream(element_readers.Pass(), 0); 503 request_.method = "POST"; 504 request_.url = GURL("http://www.google.com/"); 505 request_.upload_data_stream = &upload_data_stream; 506 ASSERT_EQ(OK, request_.upload_data_stream->Init(CompletionCallback())); 507 508 EXPECT_EQ(OK, stream_->InitializeStream(&request_, DEFAULT_PRIORITY, 509 net_log_, callback_.callback())); 510 EXPECT_EQ(OK, stream_->SendRequest(headers_, &response_, 511 callback_.callback())); 512 EXPECT_EQ(&response_, stream_->GetResponseInfo()); 513 514 // Ack both packets in the request. 515 ProcessPacket(ConstructAckPacket(1, 0, 0)); 516 517 // Send the response headers (but not the body). 518 SetResponse("200 OK", std::string()); 519 if (GetParam() > QUIC_VERSION_12) { 520 ProcessPacket(ConstructResponseHeadersPacket(2, !kFin)); 521 } else { 522 ProcessPacket(ConstructDataPacket(2, false, !kFin, 0, response_data_)); 523 } 524 525 // Since the headers have already arrived, this should return immediately. 526 EXPECT_EQ(OK, stream_->ReadResponseHeaders(callback_.callback())); 527 ASSERT_TRUE(response_.headers.get()); 528 EXPECT_EQ(200, response_.headers->response_code()); 529 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain")); 530 531 // Send the response body. 532 const char kResponseBody[] = "Hello world!"; 533 if (GetParam() > QUIC_VERSION_12) { 534 ProcessPacket(ConstructDataPacket(3, false, kFin, 0, kResponseBody)); 535 } else { 536 ProcessPacket(ConstructDataPacket(3, false, kFin, response_data_.length(), 537 kResponseBody)); 538 } 539 // Since the body has already arrived, this should return immediately. 540 EXPECT_EQ(static_cast<int>(strlen(kResponseBody)), 541 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(), 542 callback_.callback())); 543 544 EXPECT_TRUE(stream_->IsResponseBodyComplete()); 545 EXPECT_TRUE(AtEof()); 546} 547 548TEST_P(QuicHttpStreamTest, SendChunkedPostRequest) { 549 SetRequest("POST", "/", DEFAULT_PRIORITY); 550 size_t chunk_size = strlen(kUploadData); 551 if (GetParam() > QUIC_VERSION_12) { 552 AddWrite(ConstructRequestHeadersPacket(1, !kFin)); 553 AddWrite(ConstructDataPacket(2, kIncludeVersion, !kFin, 0, kUploadData)); 554 AddWrite(ConstructDataPacket(3, kIncludeVersion, kFin, chunk_size, 555 kUploadData)); 556 } else { 557 AddWrite(ConstructDataPacket(1, kIncludeVersion, !kFin, 0, request_data_)); 558 AddWrite(ConstructDataPacket(2, kIncludeVersion, !kFin, 559 request_data_.length(), kUploadData)); 560 AddWrite(ConstructDataPacket(3, kIncludeVersion, kFin, 561 request_data_.length() + chunk_size, 562 kUploadData)); 563 } 564 AddWrite(ConstructAckPacket(4, 3, 1)); 565 Initialize(); 566 567 UploadDataStream upload_data_stream(UploadDataStream::CHUNKED, 0); 568 upload_data_stream.AppendChunk(kUploadData, chunk_size, false); 569 570 request_.method = "POST"; 571 request_.url = GURL("http://www.google.com/"); 572 request_.upload_data_stream = &upload_data_stream; 573 ASSERT_EQ(OK, request_.upload_data_stream->Init(CompletionCallback())); 574 575 ASSERT_EQ(OK, stream_->InitializeStream(&request_, DEFAULT_PRIORITY, 576 net_log_, callback_.callback())); 577 ASSERT_EQ(ERR_IO_PENDING, stream_->SendRequest(headers_, &response_, 578 callback_.callback())); 579 EXPECT_EQ(&response_, stream_->GetResponseInfo()); 580 581 upload_data_stream.AppendChunk(kUploadData, chunk_size, true); 582 583 // Ack both packets in the request. 584 ProcessPacket(ConstructAckPacket(1, 0, 0)); 585 586 // Send the response headers (but not the body). 587 SetResponse("200 OK", std::string()); 588 if (GetParam() > QUIC_VERSION_12) { 589 ProcessPacket(ConstructResponseHeadersPacket(2, !kFin)); 590 } else { 591 ProcessPacket(ConstructDataPacket(2, false, !kFin, 0, response_data_)); 592 } 593 594 // Since the headers have already arrived, this should return immediately. 595 ASSERT_EQ(OK, stream_->ReadResponseHeaders(callback_.callback())); 596 ASSERT_TRUE(response_.headers.get()); 597 EXPECT_EQ(200, response_.headers->response_code()); 598 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain")); 599 600 // Send the response body. 601 const char kResponseBody[] = "Hello world!"; 602 ProcessPacket(ConstructDataPacket(3, false, kFin, response_data_.length(), 603 kResponseBody)); 604 605 // Since the body has already arrived, this should return immediately. 606 ASSERT_EQ(static_cast<int>(strlen(kResponseBody)), 607 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(), 608 callback_.callback())); 609 610 EXPECT_TRUE(stream_->IsResponseBodyComplete()); 611 EXPECT_TRUE(AtEof()); 612} 613 614TEST_P(QuicHttpStreamTest, DestroyedEarly) { 615 SetRequest("GET", "/", DEFAULT_PRIORITY); 616 if (GetParam() > QUIC_VERSION_12) { 617 AddWrite(ConstructRequestHeadersPacket(1, kFin)); 618 } else { 619 AddWrite(ConstructDataPacket(1, kIncludeVersion, kFin, 0, request_data_)); 620 } 621 AddWrite(ConstructAckAndRstStreamPacket(2)); 622 use_closing_stream_ = true; 623 Initialize(); 624 625 request_.method = "GET"; 626 request_.url = GURL("http://www.google.com/"); 627 628 EXPECT_EQ(OK, stream_->InitializeStream(&request_, DEFAULT_PRIORITY, 629 net_log_, callback_.callback())); 630 EXPECT_EQ(OK, stream_->SendRequest(headers_, &response_, 631 callback_.callback())); 632 EXPECT_EQ(&response_, stream_->GetResponseInfo()); 633 634 // Ack the request. 635 ProcessPacket(ConstructAckPacket(1, 0, 0)); 636 EXPECT_EQ(ERR_IO_PENDING, 637 stream_->ReadResponseHeaders(callback_.callback())); 638 639 // Send the response with a body. 640 SetResponse("404 OK", "hello world!"); 641 // In the course of processing this packet, the QuicHttpStream close itself. 642 if (GetParam() > QUIC_VERSION_12) { 643 ProcessPacket(ConstructResponseHeadersPacket(2, kFin)); 644 } else { 645 ProcessPacket(ConstructDataPacket(2, false, kFin, 0, response_data_)); 646 } 647 648 EXPECT_TRUE(AtEof()); 649} 650 651TEST_P(QuicHttpStreamTest, Priority) { 652 SetRequest("GET", "/", MEDIUM); 653 if (GetParam() > QUIC_VERSION_12) { 654 AddWrite(ConstructRequestHeadersPacket(1, kFin)); 655 } else { 656 AddWrite(ConstructDataPacket(1, kIncludeVersion, kFin, 0, request_data_)); 657 } 658 AddWrite(ConstructAckAndRstStreamPacket(2)); 659 use_closing_stream_ = true; 660 Initialize(); 661 662 request_.method = "GET"; 663 request_.url = GURL("http://www.google.com/"); 664 665 EXPECT_EQ(OK, stream_->InitializeStream(&request_, MEDIUM, 666 net_log_, callback_.callback())); 667 668 // Check that priority is highest. 669 QuicReliableClientStream* reliable_stream = 670 QuicHttpStreamPeer::GetQuicReliableClientStream(stream_.get()); 671 DCHECK(reliable_stream); 672 DCHECK_EQ(QuicWriteBlockedList::kHighestPriority, 673 reliable_stream->EffectivePriority()); 674 675 EXPECT_EQ(OK, stream_->SendRequest(headers_, &response_, 676 callback_.callback())); 677 EXPECT_EQ(&response_, stream_->GetResponseInfo()); 678 679 // Check that priority has now dropped back to MEDIUM. 680 DCHECK_EQ(MEDIUM, ConvertQuicPriorityToRequestPriority( 681 reliable_stream->EffectivePriority())); 682 683 // Ack the request. 684 ProcessPacket(ConstructAckPacket(1, 0, 0)); 685 EXPECT_EQ(ERR_IO_PENDING, 686 stream_->ReadResponseHeaders(callback_.callback())); 687 688 // Send the response with a body. 689 SetResponse("404 OK", "hello world!"); 690 // In the course of processing this packet, the QuicHttpStream close itself. 691 if (GetParam() > QUIC_VERSION_12) { 692 ProcessPacket(ConstructResponseHeadersPacket(2, kFin)); 693 } else { 694 ProcessPacket(ConstructDataPacket(2, !kIncludeVersion, kFin, 0, 695 response_data_)); 696 } 697 698 EXPECT_TRUE(AtEof()); 699} 700 701// Regression test for http://crbug.com/294870 702TEST_P(QuicHttpStreamTest, CheckPriorityWithNoDelegate) { 703 SetRequest("GET", "/", MEDIUM); 704 use_closing_stream_ = true; 705 706 if (GetParam() > QUIC_VERSION_13) { 707 AddWrite(ConstructRstStreamPacket(1)); 708 } 709 710 Initialize(); 711 712 request_.method = "GET"; 713 request_.url = GURL("http://www.google.com/"); 714 715 EXPECT_EQ(OK, stream_->InitializeStream(&request_, MEDIUM, 716 net_log_, callback_.callback())); 717 718 // Check that priority is highest. 719 QuicReliableClientStream* reliable_stream = 720 QuicHttpStreamPeer::GetQuicReliableClientStream(stream_.get()); 721 DCHECK(reliable_stream); 722 QuicReliableClientStream::Delegate* delegate = reliable_stream->GetDelegate(); 723 DCHECK(delegate); 724 DCHECK_EQ(QuicWriteBlockedList::kHighestPriority, 725 reliable_stream->EffectivePriority()); 726 727 // Set Delegate to NULL and make sure EffectivePriority returns highest 728 // priority. 729 reliable_stream->SetDelegate(NULL); 730 DCHECK_EQ(QuicWriteBlockedList::kHighestPriority, 731 reliable_stream->EffectivePriority()); 732 reliable_stream->SetDelegate(delegate); 733} 734 735TEST_P(QuicHttpStreamTest, DontCompressHeadersWhenNotWritable) { 736 SetRequest("GET", "/", MEDIUM); 737 AddWrite(ConstructDataPacket(1, kIncludeVersion, kFin, 0, request_data_)); 738 Initialize(); 739 740 if (GetParam() > QUIC_VERSION_12) { 741 // The behavior tested here is obsolete. 742 return; 743 } 744 request_.method = "GET"; 745 request_.url = GURL("http://www.google.com/"); 746 747 EXPECT_CALL(*send_algorithm_, TimeUntilSend(_, _, _, _)). 748 WillRepeatedly(Return(QuicTime::Delta::Infinite())); 749 EXPECT_EQ(OK, stream_->InitializeStream(&request_, MEDIUM, 750 net_log_, callback_.callback())); 751 EXPECT_EQ(ERR_IO_PENDING, stream_->SendRequest(headers_, &response_, 752 callback_.callback())); 753 754 // Verify that the headers have not been compressed and buffered in 755 // the stream. 756 QuicReliableClientStream* reliable_stream = 757 QuicHttpStreamPeer::GetQuicReliableClientStream(stream_.get()); 758 EXPECT_FALSE(reliable_stream->HasBufferedData()); 759 EXPECT_FALSE(AtEof()); 760 761 EXPECT_CALL(*send_algorithm_, TimeUntilSend(_, _, _, _)). 762 WillRepeatedly(Return(QuicTime::Delta::Zero())); 763 764 // Data should flush out now. 765 connection_->OnCanWrite(); 766 EXPECT_FALSE(reliable_stream->HasBufferedData()); 767 EXPECT_TRUE(AtEof()); 768} 769 770} // namespace test 771} // namespace net 772