rAc - revert invalid suggestions to edit mode
[chromium-blink-merge.git] / net / quic / quic_http_stream_test.cc
blob2695c8fbf94c852cb02353af42b326563ffeaa4a
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.
5 #include "net/quic/quic_http_stream.h"
7 #include <vector>
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"
42 using testing::_;
43 using testing::AnyNumber;
44 using testing::Return;
46 namespace net {
47 namespace test {
48 namespace {
50 const char kUploadData[] = "hello world!";
52 class 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) {
62 void SetSendAlgorithm(SendAlgorithmInterface* send_algorithm) {
63 QuicConnectionPeer::SetSendAlgorithm(this, send_algorithm);
66 void SetReceiveAlgorithm(ReceiveAlgorithmInterface* receive_algorithm) {
67 QuicConnectionPeer::SetReceiveAlgorithm(this, receive_algorithm);
71 class TestReceiveAlgorithm : public ReceiveAlgorithmInterface {
72 public:
73 virtual bool GenerateCongestionFeedback(
74 QuicCongestionFeedbackFrame* /*congestion_feedback*/) {
75 return false;
78 MOCK_METHOD3(RecordIncomingPacket,
79 void(QuicByteCount, QuicPacketSequenceNumber, QuicTime));
82 // Subclass of QuicHttpStream that closes itself when the first piece of data
83 // is received.
84 class AutoClosingStream : public QuicHttpStream {
85 public:
86 explicit AutoClosingStream(const base::WeakPtr<QuicClientSession>& session)
87 : QuicHttpStream(session) {
90 virtual int OnDataReceived(const char* data, int length) OVERRIDE {
91 Close(false);
92 return OK;
96 } // namespace
98 class QuicHttpStreamPeer {
99 public:
100 static QuicReliableClientStream* GetQuicReliableClientStream(
101 QuicHttpStream* stream) {
102 return stream->stream_;
106 class 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;
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) {
119 IoMode mode;
120 QuicEncryptedPacket* packet;
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);
137 ~QuicHttpStreamTest() {
138 session_->CloseSessionOnError(ERR_ABORTED);
139 for (size_t i = 0; i < writes_.size(); i++) {
140 delete writes_[i].packet;
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()));
149 // Returns the packet to be written at position |pos|.
150 QuicEncryptedPacket* GetWrite(size_t pos) {
151 return writes_[pos].packet;
154 bool AtEof() {
155 return socket_data_->at_read_eof() && socket_data_->at_write_eof();
158 void ProcessPacket(scoped_ptr<QuicEncryptedPacket> packet) {
159 connection_->ProcessUdpPacket(self_addr_, peer_addr_, *packet);
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());
171 socket_data_.reset(new StaticSocketDataProvider(NULL, 0, mock_writes_.get(),
172 writes_.size()));
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()));
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);
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;
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);
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_);
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_);
260 scoped_ptr<QuicEncryptedPacket> ConstructRstStreamPacket(
261 QuicPacketSequenceNumber sequence_number) {
262 return maker_.MakeRstPacket(
263 sequence_number, true, stream_id_, QUIC_STREAM_NO_ERROR);
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);
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);
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_;
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);
314 return compressor.CompressHeaders(headers);
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_;
328 INSTANTIATE_TEST_CASE_P(Version, QuicHttpStreamTest,
329 ::testing::ValuesIn(QuicSupportedVersions()));
331 TEST_P(QuicHttpStreamTest, RenewStreamForAuth) {
332 Initialize();
333 EXPECT_EQ(NULL, stream_->RenewStreamForAuth());
336 TEST_P(QuicHttpStreamTest, CanFindEndOfResponse) {
337 Initialize();
338 EXPECT_TRUE(stream_->CanFindEndOfResponse());
341 TEST_P(QuicHttpStreamTest, IsConnectionReusable) {
342 Initialize();
343 EXPECT_FALSE(stream_->IsConnectionReusable());
346 TEST_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_));
353 Initialize();
355 request_.method = "GET";
356 request_.url = GURL("http://www.google.com/");
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());
364 // Ack the request.
365 ProcessPacket(ConstructAckPacket(1, 0, 0));
367 EXPECT_EQ(ERR_IO_PENDING,
368 stream_->ReadResponseHeaders(callback_.callback()));
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_));
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"));
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());
391 // Regression test for http://crbug.com/288128
392 TEST_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_));
399 Initialize();
401 request_.method = "GET";
402 request_.url = GURL("http://www.google.com/");
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());
410 // Ack the request.
411 ProcessPacket(ConstructAckPacket(1, 0, 0));
413 EXPECT_EQ(ERR_IO_PENDING,
414 stream_->ReadResponseHeaders(callback_.callback()));
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.
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);
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"));
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());
441 TEST_P(QuicHttpStreamTest, GetRequestFullResponseInSinglePacket) {
442 SetRequest("GET", "/", DEFAULT_PRIORITY);
443 AddWrite(ConstructDataPacket(1, kIncludeVersion, kFin, 0, request_data_));
444 Initialize();
446 if (GetParam() > QUIC_VERSION_12) {
447 // we can't put the request and response into a single frame.
448 return;
451 request_.method = "GET";
452 request_.url = GURL("http://www.google.com/");
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());
460 // Ack the request.
461 ProcessPacket(ConstructAckPacket(1, 0, 0));
463 EXPECT_EQ(ERR_IO_PENDING,
464 stream_->ReadResponseHeaders(callback_.callback()));
466 // Send the response with a body.
467 SetResponse("200 OK", "hello world!");
468 ProcessPacket(ConstructDataPacket(2, false, kFin, 0, response_data_));
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"));
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());
485 TEST_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));
495 AddWrite(ConstructAckPacket(3, 3, 1));
497 Initialize();
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()));
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());
514 // Ack both packets in the request.
515 ProcessPacket(ConstructAckPacket(1, 0, 0));
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_));
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"));
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));
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()));
544 EXPECT_TRUE(stream_->IsResponseBodyComplete());
545 EXPECT_TRUE(AtEof());
548 TEST_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));
564 AddWrite(ConstructAckPacket(4, 3, 1));
565 Initialize();
567 UploadDataStream upload_data_stream(UploadDataStream::CHUNKED, 0);
568 upload_data_stream.AppendChunk(kUploadData, chunk_size, false);
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()));
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());
581 upload_data_stream.AppendChunk(kUploadData, chunk_size, true);
583 // Ack both packets in the request.
584 ProcessPacket(ConstructAckPacket(1, 0, 0));
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_));
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"));
600 // Send the response body.
601 const char kResponseBody[] = "Hello world!";
602 ProcessPacket(ConstructDataPacket(3, false, kFin, response_data_.length(),
603 kResponseBody));
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()));
610 EXPECT_TRUE(stream_->IsResponseBodyComplete());
611 EXPECT_TRUE(AtEof());
614 TEST_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_));
621 AddWrite(ConstructAckAndRstStreamPacket(2));
622 use_closing_stream_ = true;
623 Initialize();
625 request_.method = "GET";
626 request_.url = GURL("http://www.google.com/");
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());
634 // Ack the request.
635 ProcessPacket(ConstructAckPacket(1, 0, 0));
636 EXPECT_EQ(ERR_IO_PENDING,
637 stream_->ReadResponseHeaders(callback_.callback()));
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_));
648 EXPECT_TRUE(AtEof());
651 TEST_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_));
658 AddWrite(ConstructAckAndRstStreamPacket(2));
659 use_closing_stream_ = true;
660 Initialize();
662 request_.method = "GET";
663 request_.url = GURL("http://www.google.com/");
665 EXPECT_EQ(OK, stream_->InitializeStream(&request_, MEDIUM,
666 net_log_, callback_.callback()));
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());
675 EXPECT_EQ(OK, stream_->SendRequest(headers_, &response_,
676 callback_.callback()));
677 EXPECT_EQ(&response_, stream_->GetResponseInfo());
679 // Check that priority has now dropped back to MEDIUM.
680 DCHECK_EQ(MEDIUM, ConvertQuicPriorityToRequestPriority(
681 reliable_stream->EffectivePriority()));
683 // Ack the request.
684 ProcessPacket(ConstructAckPacket(1, 0, 0));
685 EXPECT_EQ(ERR_IO_PENDING,
686 stream_->ReadResponseHeaders(callback_.callback()));
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_));
698 EXPECT_TRUE(AtEof());
701 // Regression test for http://crbug.com/294870
702 TEST_P(QuicHttpStreamTest, CheckPriorityWithNoDelegate) {
703 SetRequest("GET", "/", MEDIUM);
704 use_closing_stream_ = true;
706 if (GetParam() > QUIC_VERSION_13) {
707 AddWrite(ConstructRstStreamPacket(1));
710 Initialize();
712 request_.method = "GET";
713 request_.url = GURL("http://www.google.com/");
715 EXPECT_EQ(OK, stream_->InitializeStream(&request_, MEDIUM,
716 net_log_, callback_.callback()));
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());
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);
735 TEST_P(QuicHttpStreamTest, DontCompressHeadersWhenNotWritable) {
736 SetRequest("GET", "/", MEDIUM);
737 AddWrite(ConstructDataPacket(1, kIncludeVersion, kFin, 0, request_data_));
738 Initialize();
740 if (GetParam() > QUIC_VERSION_12) {
741 // The behavior tested here is obsolete.
742 return;
744 request_.method = "GET";
745 request_.url = GURL("http://www.google.com/");
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()));
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());
761 EXPECT_CALL(*send_algorithm_, TimeUntilSend(_, _, _, _)).
762 WillRepeatedly(Return(QuicTime::Delta::Zero()));
764 // Data should flush out now.
765 connection_->OnCanWrite();
766 EXPECT_FALSE(reliable_stream->HasBufferedData());
767 EXPECT_TRUE(AtEof());
770 } // namespace test
771 } // namespace net