Perf: Update size expectations on linux-rel
[chromium-blink-merge.git] / net / quic / quic_http_stream_test.cc
blobd53a7ccbb62df1e3acecce2cb3adfbb4678c4632
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/http/transport_security_state.h"
15 #include "net/quic/congestion_control/receive_algorithm_interface.h"
16 #include "net/quic/congestion_control/send_algorithm_interface.h"
17 #include "net/quic/crypto/crypto_protocol.h"
18 #include "net/quic/crypto/quic_decrypter.h"
19 #include "net/quic/crypto/quic_encrypter.h"
20 #include "net/quic/crypto/quic_server_info.h"
21 #include "net/quic/quic_client_session.h"
22 #include "net/quic/quic_connection.h"
23 #include "net/quic/quic_connection_helper.h"
24 #include "net/quic/quic_default_packet_writer.h"
25 #include "net/quic/quic_http_utils.h"
26 #include "net/quic/quic_reliable_client_stream.h"
27 #include "net/quic/quic_write_blocked_list.h"
28 #include "net/quic/spdy_utils.h"
29 #include "net/quic/test_tools/mock_clock.h"
30 #include "net/quic/test_tools/mock_crypto_client_stream_factory.h"
31 #include "net/quic/test_tools/mock_random.h"
32 #include "net/quic/test_tools/quic_connection_peer.h"
33 #include "net/quic/test_tools/quic_test_packet_maker.h"
34 #include "net/quic/test_tools/quic_test_utils.h"
35 #include "net/quic/test_tools/test_task_runner.h"
36 #include "net/socket/socket_test_util.h"
37 #include "net/spdy/spdy_frame_builder.h"
38 #include "net/spdy/spdy_framer.h"
39 #include "net/spdy/spdy_http_utils.h"
40 #include "net/spdy/spdy_protocol.h"
41 #include "testing/gmock/include/gmock/gmock.h"
42 #include "testing/gtest/include/gtest/gtest.h"
44 using testing::_;
45 using testing::AnyNumber;
46 using testing::Return;
48 namespace net {
49 namespace test {
50 namespace {
52 const char kUploadData[] = "Really nifty data!";
53 const char kServerHostname[] = "www.google.com";
54 const uint16 kServerPort = 80;
56 class TestQuicConnection : public QuicConnection {
57 public:
58 TestQuicConnection(const QuicVersionVector& versions,
59 QuicConnectionId connection_id,
60 IPEndPoint address,
61 QuicConnectionHelper* helper,
62 const QuicConnection::PacketWriterFactory& writer_factory)
63 : QuicConnection(connection_id,
64 address,
65 helper,
66 writer_factory,
67 true /* owns_writer */,
68 false /* is_server */,
69 versions) {
72 void SetSendAlgorithm(SendAlgorithmInterface* send_algorithm) {
73 QuicConnectionPeer::SetSendAlgorithm(this, send_algorithm);
76 void SetReceiveAlgorithm(ReceiveAlgorithmInterface* receive_algorithm) {
77 QuicConnectionPeer::SetReceiveAlgorithm(this, receive_algorithm);
81 class TestReceiveAlgorithm : public ReceiveAlgorithmInterface {
82 public:
83 virtual bool GenerateCongestionFeedback(
84 QuicCongestionFeedbackFrame* /*congestion_feedback*/) {
85 return false;
88 MOCK_METHOD3(RecordIncomingPacket,
89 void(QuicByteCount, QuicPacketSequenceNumber, QuicTime));
92 // Subclass of QuicHttpStream that closes itself when the first piece of data
93 // is received.
94 class AutoClosingStream : public QuicHttpStream {
95 public:
96 explicit AutoClosingStream(const base::WeakPtr<QuicClientSession>& session)
97 : QuicHttpStream(session) {
100 virtual int OnDataReceived(const char* data, int length) OVERRIDE {
101 Close(false);
102 return OK;
106 class TestPacketWriterFactory : public QuicConnection::PacketWriterFactory {
107 public:
108 explicit TestPacketWriterFactory(DatagramClientSocket* socket)
109 : socket_(socket) {}
110 virtual ~TestPacketWriterFactory() {}
112 virtual QuicPacketWriter* Create(QuicConnection* connection) const OVERRIDE {
113 return new QuicDefaultPacketWriter(socket_);
116 private:
117 DatagramClientSocket* socket_;
120 } // namespace
122 class QuicHttpStreamPeer {
123 public:
124 static QuicReliableClientStream* GetQuicReliableClientStream(
125 QuicHttpStream* stream) {
126 return stream->stream_;
130 class QuicHttpStreamTest : public ::testing::TestWithParam<QuicVersion> {
131 protected:
132 static const bool kFin = true;
133 static const bool kIncludeVersion = true;
134 static const bool kIncludeCongestionFeedback = true;
136 // Holds a packet to be written to the wire, and the IO mode that should
137 // be used by the mock socket when performing the write.
138 struct PacketToWrite {
139 PacketToWrite(IoMode mode, QuicEncryptedPacket* packet)
140 : mode(mode),
141 packet(packet) {
143 IoMode mode;
144 QuicEncryptedPacket* packet;
147 QuicHttpStreamTest()
148 : net_log_(BoundNetLog()),
149 use_closing_stream_(false),
150 read_buffer_(new IOBufferWithSize(4096)),
151 connection_id_(2),
152 stream_id_(kClientDataStreamId1),
153 maker_(GetParam(), connection_id_, &clock_),
154 random_generator_(0) {
155 IPAddressNumber ip;
156 CHECK(ParseIPLiteralToNumber("192.0.2.33", &ip));
157 peer_addr_ = IPEndPoint(ip, 443);
158 self_addr_ = IPEndPoint(ip, 8435);
159 clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(20));
162 ~QuicHttpStreamTest() {
163 session_->CloseSessionOnError(ERR_ABORTED);
164 for (size_t i = 0; i < writes_.size(); i++) {
165 delete writes_[i].packet;
169 // Adds a packet to the list of expected writes.
170 void AddWrite(scoped_ptr<QuicEncryptedPacket> packet) {
171 writes_.push_back(PacketToWrite(SYNCHRONOUS, packet.release()));
174 // Returns the packet to be written at position |pos|.
175 QuicEncryptedPacket* GetWrite(size_t pos) {
176 return writes_[pos].packet;
179 bool AtEof() {
180 return socket_data_->at_read_eof() && socket_data_->at_write_eof();
183 void ProcessPacket(scoped_ptr<QuicEncryptedPacket> packet) {
184 connection_->ProcessUdpPacket(self_addr_, peer_addr_, *packet);
187 // Configures the test fixture to use the list of expected writes.
188 void Initialize() {
189 mock_writes_.reset(new MockWrite[writes_.size()]);
190 for (size_t i = 0; i < writes_.size(); i++) {
191 mock_writes_[i] = MockWrite(writes_[i].mode,
192 writes_[i].packet->data(),
193 writes_[i].packet->length());
196 socket_data_.reset(new StaticSocketDataProvider(NULL, 0, mock_writes_.get(),
197 writes_.size()));
199 MockUDPClientSocket* socket = new MockUDPClientSocket(socket_data_.get(),
200 net_log_.net_log());
201 socket->Connect(peer_addr_);
202 runner_ = new TestTaskRunner(&clock_);
203 send_algorithm_ = new MockSendAlgorithm();
204 receive_algorithm_ = new TestReceiveAlgorithm();
205 EXPECT_CALL(*receive_algorithm_, RecordIncomingPacket(_, _, _)).
206 Times(AnyNumber());
207 EXPECT_CALL(*send_algorithm_,
208 OnPacketSent(_, _, _, _, _)).WillRepeatedly(Return(true));
209 EXPECT_CALL(*send_algorithm_, RetransmissionDelay()).WillRepeatedly(
210 Return(QuicTime::Delta::Zero()));
211 EXPECT_CALL(*send_algorithm_, GetCongestionWindow()).WillRepeatedly(
212 Return(kMaxPacketSize));
213 EXPECT_CALL(*send_algorithm_, TimeUntilSend(_, _, _)).
214 WillRepeatedly(Return(QuicTime::Delta::Zero()));
215 EXPECT_CALL(*send_algorithm_, BandwidthEstimate()).WillRepeatedly(
216 Return(QuicBandwidth::Zero()));
217 EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _)).Times(AnyNumber());
218 helper_.reset(new QuicConnectionHelper(runner_.get(), &clock_,
219 &random_generator_));
220 TestPacketWriterFactory writer_factory(socket);
221 connection_ = new TestQuicConnection(SupportedVersions(GetParam()),
222 connection_id_, peer_addr_,
223 helper_.get(), writer_factory);
224 connection_->set_visitor(&visitor_);
225 connection_->SetSendAlgorithm(send_algorithm_);
226 connection_->SetReceiveAlgorithm(receive_algorithm_);
227 crypto_config_.SetDefaults();
228 session_.reset(
229 new QuicClientSession(connection_,
230 scoped_ptr<DatagramClientSocket>(socket),
231 NULL,
232 &transport_security_state_,
233 make_scoped_ptr((QuicServerInfo*)NULL),
234 DefaultQuicConfig(),
235 base::MessageLoop::current()->
236 message_loop_proxy().get(),
237 NULL));
238 session_->InitializeSession(QuicServerId(kServerHostname, kServerPort,
239 false, PRIVACY_MODE_DISABLED),
240 &crypto_config_,
241 &crypto_client_stream_factory_);
242 session_->GetCryptoStream()->CryptoConnect();
243 EXPECT_TRUE(session_->IsCryptoHandshakeConfirmed());
244 stream_.reset(use_closing_stream_ ?
245 new AutoClosingStream(session_->GetWeakPtr()) :
246 new QuicHttpStream(session_->GetWeakPtr()));
249 void SetRequest(const std::string& method,
250 const std::string& path,
251 RequestPriority priority) {
252 request_headers_ = maker_.GetRequestHeaders(method, "http", path);
255 void SetResponse(const std::string& status, const std::string& body) {
256 response_headers_ = maker_.GetResponseHeaders(status);
257 response_data_ = body;
260 scoped_ptr<QuicEncryptedPacket> ConstructDataPacket(
261 QuicPacketSequenceNumber sequence_number,
262 bool should_include_version,
263 bool fin,
264 QuicStreamOffset offset,
265 base::StringPiece data) {
266 return maker_.MakeDataPacket(
267 sequence_number, stream_id_, should_include_version, fin, offset, data);
270 scoped_ptr<QuicEncryptedPacket> ConstructRequestHeadersPacket(
271 QuicPacketSequenceNumber sequence_number,
272 bool fin) {
273 return maker_.MakeRequestHeadersPacket(
274 sequence_number, stream_id_, kIncludeVersion, fin, request_headers_);
277 scoped_ptr<QuicEncryptedPacket> ConstructResponseHeadersPacket(
278 QuicPacketSequenceNumber sequence_number,
279 bool fin) {
280 return maker_.MakeResponseHeadersPacket(
281 sequence_number, stream_id_, !kIncludeVersion, fin, response_headers_);
284 scoped_ptr<QuicEncryptedPacket> ConstructRstStreamPacket(
285 QuicPacketSequenceNumber sequence_number) {
286 return maker_.MakeRstPacket(
287 sequence_number, true, stream_id_,
288 AdjustErrorForVersion(QUIC_RST_FLOW_CONTROL_ACCOUNTING, GetParam()));
291 scoped_ptr<QuicEncryptedPacket> ConstructAckAndRstStreamPacket(
292 QuicPacketSequenceNumber sequence_number) {
293 return maker_.MakeAckAndRstPacket(
294 sequence_number, !kIncludeVersion, stream_id_, QUIC_STREAM_CANCELLED,
295 2, 1, !kIncludeCongestionFeedback);
298 scoped_ptr<QuicEncryptedPacket> ConstructAckPacket(
299 QuicPacketSequenceNumber sequence_number,
300 QuicPacketSequenceNumber largest_received,
301 QuicPacketSequenceNumber least_unacked) {
302 return maker_.MakeAckPacket(sequence_number, largest_received,
303 least_unacked, !kIncludeCongestionFeedback);
306 BoundNetLog net_log_;
307 bool use_closing_stream_;
308 MockSendAlgorithm* send_algorithm_;
309 TestReceiveAlgorithm* receive_algorithm_;
310 scoped_refptr<TestTaskRunner> runner_;
311 scoped_ptr<MockWrite[]> mock_writes_;
312 MockClock clock_;
313 TestQuicConnection* connection_;
314 scoped_ptr<QuicConnectionHelper> helper_;
315 testing::StrictMock<MockConnectionVisitor> visitor_;
316 scoped_ptr<QuicHttpStream> stream_;
317 TransportSecurityState transport_security_state_;
318 scoped_ptr<QuicClientSession> session_;
319 QuicCryptoClientConfig crypto_config_;
320 TestCompletionCallback callback_;
321 HttpRequestInfo request_;
322 HttpRequestHeaders headers_;
323 HttpResponseInfo response_;
324 scoped_refptr<IOBufferWithSize> read_buffer_;
325 SpdyHeaderBlock request_headers_;
326 SpdyHeaderBlock response_headers_;
327 std::string request_data_;
328 std::string response_data_;
330 private:
331 const QuicConnectionId connection_id_;
332 const QuicStreamId stream_id_;
333 QuicTestPacketMaker maker_;
334 IPEndPoint self_addr_;
335 IPEndPoint peer_addr_;
336 MockRandom random_generator_;
337 MockCryptoClientStreamFactory crypto_client_stream_factory_;
338 scoped_ptr<StaticSocketDataProvider> socket_data_;
339 std::vector<PacketToWrite> writes_;
342 INSTANTIATE_TEST_CASE_P(Version, QuicHttpStreamTest,
343 ::testing::ValuesIn(QuicSupportedVersions()));
345 TEST_P(QuicHttpStreamTest, RenewStreamForAuth) {
346 Initialize();
347 EXPECT_EQ(NULL, stream_->RenewStreamForAuth());
350 TEST_P(QuicHttpStreamTest, CanFindEndOfResponse) {
351 Initialize();
352 EXPECT_TRUE(stream_->CanFindEndOfResponse());
355 TEST_P(QuicHttpStreamTest, IsConnectionReusable) {
356 Initialize();
357 EXPECT_FALSE(stream_->IsConnectionReusable());
360 TEST_P(QuicHttpStreamTest, GetRequest) {
361 SetRequest("GET", "/", DEFAULT_PRIORITY);
362 AddWrite(ConstructRequestHeadersPacket(1, kFin));
363 Initialize();
365 request_.method = "GET";
366 request_.url = GURL("http://www.google.com/");
368 EXPECT_EQ(OK, stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
369 net_log_, callback_.callback()));
370 EXPECT_EQ(OK, stream_->SendRequest(headers_, &response_,
371 callback_.callback()));
373 // Ack the request.
374 ProcessPacket(ConstructAckPacket(1, 0, 0));
376 EXPECT_EQ(ERR_IO_PENDING,
377 stream_->ReadResponseHeaders(callback_.callback()));
379 SetResponse("404 Not Found", std::string());
380 ProcessPacket(ConstructResponseHeadersPacket(2, kFin));
382 // Now that the headers have been processed, the callback will return.
383 EXPECT_EQ(OK, callback_.WaitForResult());
384 ASSERT_TRUE(response_.headers.get());
385 EXPECT_EQ(404, response_.headers->response_code());
386 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
387 EXPECT_FALSE(response_.response_time.is_null());
388 EXPECT_FALSE(response_.request_time.is_null());
390 // There is no body, so this should return immediately.
391 EXPECT_EQ(0, stream_->ReadResponseBody(read_buffer_.get(),
392 read_buffer_->size(),
393 callback_.callback()));
394 EXPECT_TRUE(stream_->IsResponseBodyComplete());
395 EXPECT_TRUE(AtEof());
398 // Regression test for http://crbug.com/288128
399 TEST_P(QuicHttpStreamTest, GetRequestLargeResponse) {
400 SetRequest("GET", "/", DEFAULT_PRIORITY);
401 AddWrite(ConstructRequestHeadersPacket(1, kFin));
402 Initialize();
404 request_.method = "GET";
405 request_.url = GURL("http://www.google.com/");
407 EXPECT_EQ(OK, stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
408 net_log_, callback_.callback()));
409 EXPECT_EQ(OK, stream_->SendRequest(headers_, &response_,
410 callback_.callback()));
412 // Ack the request.
413 ProcessPacket(ConstructAckPacket(1, 0, 0));
415 EXPECT_EQ(ERR_IO_PENDING,
416 stream_->ReadResponseHeaders(callback_.callback()));
418 SpdyHeaderBlock headers;
419 headers[":status"] = "200 OK";
420 headers[":version"] = "HTTP/1.1";
421 headers["content-type"] = "text/plain";
422 headers["big6"] = std::string(10000, 'x'); // Lots of x's.
424 std::string response = SpdyUtils::SerializeUncompressedHeaders(headers);
425 EXPECT_LT(4096u, response.length());
426 stream_->OnDataReceived(response.data(), response.length());
427 stream_->OnClose(QUIC_NO_ERROR);
429 // Now that the headers have been processed, the callback will return.
430 EXPECT_EQ(OK, callback_.WaitForResult());
431 ASSERT_TRUE(response_.headers.get());
432 EXPECT_EQ(200, response_.headers->response_code());
433 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
435 // There is no body, so this should return immediately.
436 EXPECT_EQ(0, stream_->ReadResponseBody(read_buffer_.get(),
437 read_buffer_->size(),
438 callback_.callback()));
439 EXPECT_TRUE(stream_->IsResponseBodyComplete());
440 EXPECT_TRUE(AtEof());
443 // Regression test for http://crbug.com/409101
444 TEST_P(QuicHttpStreamTest, SessionClosedBeforeSendRequest) {
445 SetRequest("GET", "/", DEFAULT_PRIORITY);
446 Initialize();
448 request_.method = "GET";
449 request_.url = GURL("http://www.google.com/");
451 EXPECT_EQ(OK, stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
452 net_log_, callback_.callback()));
454 session_->connection()->CloseConnection(QUIC_NO_ERROR, true);
456 EXPECT_EQ(ERR_CONNECTION_CLOSED,
457 stream_->SendRequest(headers_, &response_,
458 callback_.callback()));
461 // Regression test for http://crbug.com/409871
462 TEST_P(QuicHttpStreamTest, SessionClosedBeforeReadResponseHeaders) {
463 SetRequest("GET", "/", DEFAULT_PRIORITY);
464 AddWrite(ConstructRequestHeadersPacket(1, kFin));
465 Initialize();
467 request_.method = "GET";
468 request_.url = GURL("http://www.google.com/");
470 EXPECT_EQ(OK, stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
471 net_log_, callback_.callback()));
473 EXPECT_EQ(OK, stream_->SendRequest(headers_, &response_,
474 callback_.callback()));
476 session_->connection()->CloseConnection(QUIC_NO_ERROR, true);
478 EXPECT_NE(OK, stream_->ReadResponseHeaders(callback_.callback()));
481 TEST_P(QuicHttpStreamTest, SendPostRequest) {
482 SetRequest("POST", "/", DEFAULT_PRIORITY);
483 AddWrite(ConstructRequestHeadersPacket(1, !kFin));
484 AddWrite(ConstructDataPacket(2, kIncludeVersion, kFin, 0, kUploadData));
485 AddWrite(ConstructAckPacket(3, 3, 1));
487 Initialize();
489 ScopedVector<UploadElementReader> element_readers;
490 element_readers.push_back(
491 new UploadBytesElementReader(kUploadData, strlen(kUploadData)));
492 UploadDataStream upload_data_stream(element_readers.Pass(), 0);
493 request_.method = "POST";
494 request_.url = GURL("http://www.google.com/");
495 request_.upload_data_stream = &upload_data_stream;
496 ASSERT_EQ(OK, request_.upload_data_stream->Init(CompletionCallback()));
498 EXPECT_EQ(OK, stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
499 net_log_, callback_.callback()));
500 EXPECT_EQ(OK, stream_->SendRequest(headers_, &response_,
501 callback_.callback()));
503 // Ack both packets in the request.
504 ProcessPacket(ConstructAckPacket(1, 0, 0));
506 // Send the response headers (but not the body).
507 SetResponse("200 OK", std::string());
508 ProcessPacket(ConstructResponseHeadersPacket(2, !kFin));
510 // Since the headers have already arrived, this should return immediately.
511 EXPECT_EQ(OK, stream_->ReadResponseHeaders(callback_.callback()));
512 ASSERT_TRUE(response_.headers.get());
513 EXPECT_EQ(200, response_.headers->response_code());
514 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
516 // Send the response body.
517 const char kResponseBody[] = "Hello world!";
518 ProcessPacket(ConstructDataPacket(3, false, kFin, 0, kResponseBody));
519 // Since the body has already arrived, this should return immediately.
520 EXPECT_EQ(static_cast<int>(strlen(kResponseBody)),
521 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
522 callback_.callback()));
524 EXPECT_TRUE(stream_->IsResponseBodyComplete());
525 EXPECT_TRUE(AtEof());
528 TEST_P(QuicHttpStreamTest, SendChunkedPostRequest) {
529 SetRequest("POST", "/", DEFAULT_PRIORITY);
530 size_t chunk_size = strlen(kUploadData);
531 AddWrite(ConstructRequestHeadersPacket(1, !kFin));
532 AddWrite(ConstructDataPacket(2, kIncludeVersion, !kFin, 0, kUploadData));
533 AddWrite(ConstructDataPacket(3, kIncludeVersion, kFin, chunk_size,
534 kUploadData));
535 AddWrite(ConstructAckPacket(4, 3, 1));
536 Initialize();
538 UploadDataStream upload_data_stream(UploadDataStream::CHUNKED, 0);
539 upload_data_stream.AppendChunk(kUploadData, chunk_size, false);
541 request_.method = "POST";
542 request_.url = GURL("http://www.google.com/");
543 request_.upload_data_stream = &upload_data_stream;
544 ASSERT_EQ(OK, request_.upload_data_stream->Init(CompletionCallback()));
546 ASSERT_EQ(OK, stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
547 net_log_, callback_.callback()));
548 ASSERT_EQ(ERR_IO_PENDING, stream_->SendRequest(headers_, &response_,
549 callback_.callback()));
551 upload_data_stream.AppendChunk(kUploadData, chunk_size, true);
553 // Ack both packets in the request.
554 ProcessPacket(ConstructAckPacket(1, 0, 0));
556 // Send the response headers (but not the body).
557 SetResponse("200 OK", std::string());
558 ProcessPacket(ConstructResponseHeadersPacket(2, !kFin));
560 // Since the headers have already arrived, this should return immediately.
561 ASSERT_EQ(OK, stream_->ReadResponseHeaders(callback_.callback()));
562 ASSERT_TRUE(response_.headers.get());
563 EXPECT_EQ(200, response_.headers->response_code());
564 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
566 // Send the response body.
567 const char kResponseBody[] = "Hello world!";
568 ProcessPacket(ConstructDataPacket(3, false, kFin, response_data_.length(),
569 kResponseBody));
571 // Since the body has already arrived, this should return immediately.
572 ASSERT_EQ(static_cast<int>(strlen(kResponseBody)),
573 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
574 callback_.callback()));
576 EXPECT_TRUE(stream_->IsResponseBodyComplete());
577 EXPECT_TRUE(AtEof());
580 TEST_P(QuicHttpStreamTest, SendChunkedPostRequestWithFinalEmptyDataPacket) {
581 SetRequest("POST", "/", DEFAULT_PRIORITY);
582 size_t chunk_size = strlen(kUploadData);
583 AddWrite(ConstructRequestHeadersPacket(1, !kFin));
584 AddWrite(ConstructDataPacket(2, kIncludeVersion, !kFin, 0, kUploadData));
585 AddWrite(ConstructDataPacket(3, kIncludeVersion, kFin, chunk_size, ""));
586 AddWrite(ConstructAckPacket(4, 3, 1));
587 Initialize();
589 UploadDataStream upload_data_stream(UploadDataStream::CHUNKED, 0);
590 upload_data_stream.AppendChunk(kUploadData, chunk_size, false);
592 request_.method = "POST";
593 request_.url = GURL("http://www.google.com/");
594 request_.upload_data_stream = &upload_data_stream;
595 ASSERT_EQ(OK, request_.upload_data_stream->Init(CompletionCallback()));
597 ASSERT_EQ(OK, stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
598 net_log_, callback_.callback()));
599 ASSERT_EQ(ERR_IO_PENDING, stream_->SendRequest(headers_, &response_,
600 callback_.callback()));
602 upload_data_stream.AppendChunk(NULL, 0, true);
604 ProcessPacket(ConstructAckPacket(1, 0, 0));
606 // Send the response headers (but not the body).
607 SetResponse("200 OK", std::string());
608 ProcessPacket(ConstructResponseHeadersPacket(2, !kFin));
610 // Since the headers have already arrived, this should return immediately.
611 ASSERT_EQ(OK, stream_->ReadResponseHeaders(callback_.callback()));
612 ASSERT_TRUE(response_.headers.get());
613 EXPECT_EQ(200, response_.headers->response_code());
614 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
616 // Send the response body.
617 const char kResponseBody[] = "Hello world!";
618 ProcessPacket(ConstructDataPacket(3, false, kFin, response_data_.length(),
619 kResponseBody));
621 // Since the body has already arrived, this should return immediately.
622 ASSERT_EQ(static_cast<int>(strlen(kResponseBody)),
623 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
624 callback_.callback()));
626 EXPECT_TRUE(stream_->IsResponseBodyComplete());
627 EXPECT_TRUE(AtEof());
630 TEST_P(QuicHttpStreamTest, SendChunkedPostRequestWithOneEmptyDataPacket) {
631 SetRequest("POST", "/", DEFAULT_PRIORITY);
632 AddWrite(ConstructRequestHeadersPacket(1, !kFin));
633 AddWrite(ConstructDataPacket(2, kIncludeVersion, kFin, 0, ""));
634 AddWrite(ConstructAckPacket(3, 3, 1));
635 Initialize();
637 UploadDataStream upload_data_stream(UploadDataStream::CHUNKED, 0);
639 request_.method = "POST";
640 request_.url = GURL("http://www.google.com/");
641 request_.upload_data_stream = &upload_data_stream;
642 ASSERT_EQ(OK, request_.upload_data_stream->Init(CompletionCallback()));
644 ASSERT_EQ(OK, stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
645 net_log_, callback_.callback()));
646 ASSERT_EQ(ERR_IO_PENDING, stream_->SendRequest(headers_, &response_,
647 callback_.callback()));
649 upload_data_stream.AppendChunk(NULL, 0, true);
651 ProcessPacket(ConstructAckPacket(1, 0, 0));
653 // Send the response headers (but not the body).
654 SetResponse("200 OK", std::string());
655 ProcessPacket(ConstructResponseHeadersPacket(2, !kFin));
657 // Since the headers have already arrived, this should return immediately.
658 ASSERT_EQ(OK, stream_->ReadResponseHeaders(callback_.callback()));
659 ASSERT_TRUE(response_.headers.get());
660 EXPECT_EQ(200, response_.headers->response_code());
661 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
663 // Send the response body.
664 const char kResponseBody[] = "Hello world!";
665 ProcessPacket(ConstructDataPacket(3, false, kFin, response_data_.length(),
666 kResponseBody));
668 // Since the body has already arrived, this should return immediately.
669 ASSERT_EQ(static_cast<int>(strlen(kResponseBody)),
670 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
671 callback_.callback()));
673 EXPECT_TRUE(stream_->IsResponseBodyComplete());
674 EXPECT_TRUE(AtEof());
677 TEST_P(QuicHttpStreamTest, DestroyedEarly) {
678 SetRequest("GET", "/", DEFAULT_PRIORITY);
679 AddWrite(ConstructRequestHeadersPacket(1, kFin));
680 AddWrite(ConstructAckAndRstStreamPacket(2));
681 use_closing_stream_ = true;
682 Initialize();
684 request_.method = "GET";
685 request_.url = GURL("http://www.google.com/");
687 EXPECT_EQ(OK, stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
688 net_log_, callback_.callback()));
689 EXPECT_EQ(OK, stream_->SendRequest(headers_, &response_,
690 callback_.callback()));
692 // Ack the request.
693 ProcessPacket(ConstructAckPacket(1, 0, 0));
694 EXPECT_EQ(ERR_IO_PENDING,
695 stream_->ReadResponseHeaders(callback_.callback()));
697 // Send the response with a body.
698 SetResponse("404 OK", "hello world!");
699 // In the course of processing this packet, the QuicHttpStream close itself.
700 ProcessPacket(ConstructResponseHeadersPacket(2, kFin));
702 EXPECT_TRUE(AtEof());
705 TEST_P(QuicHttpStreamTest, Priority) {
706 SetRequest("GET", "/", MEDIUM);
707 AddWrite(ConstructRequestHeadersPacket(1, kFin));
708 AddWrite(ConstructAckAndRstStreamPacket(2));
709 use_closing_stream_ = true;
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 DCHECK_EQ(QuicWriteBlockedList::kHighestPriority,
723 reliable_stream->EffectivePriority());
725 EXPECT_EQ(OK, stream_->SendRequest(headers_, &response_,
726 callback_.callback()));
728 // Check that priority has now dropped back to MEDIUM.
729 DCHECK_EQ(MEDIUM, ConvertQuicPriorityToRequestPriority(
730 reliable_stream->EffectivePriority()));
732 // Ack the request.
733 ProcessPacket(ConstructAckPacket(1, 0, 0));
734 EXPECT_EQ(ERR_IO_PENDING,
735 stream_->ReadResponseHeaders(callback_.callback()));
737 // Send the response with a body.
738 SetResponse("404 OK", "hello world!");
739 // In the course of processing this packet, the QuicHttpStream close itself.
740 ProcessPacket(ConstructResponseHeadersPacket(2, kFin));
742 EXPECT_TRUE(AtEof());
745 // Regression test for http://crbug.com/294870
746 TEST_P(QuicHttpStreamTest, CheckPriorityWithNoDelegate) {
747 SetRequest("GET", "/", MEDIUM);
748 use_closing_stream_ = true;
750 AddWrite(ConstructRstStreamPacket(1));
752 Initialize();
754 request_.method = "GET";
755 request_.url = GURL("http://www.google.com/");
757 EXPECT_EQ(OK, stream_->InitializeStream(&request_, MEDIUM,
758 net_log_, callback_.callback()));
760 // Check that priority is highest.
761 QuicReliableClientStream* reliable_stream =
762 QuicHttpStreamPeer::GetQuicReliableClientStream(stream_.get());
763 DCHECK(reliable_stream);
764 QuicReliableClientStream::Delegate* delegate = reliable_stream->GetDelegate();
765 DCHECK(delegate);
766 DCHECK_EQ(QuicWriteBlockedList::kHighestPriority,
767 reliable_stream->EffectivePriority());
769 // Set Delegate to NULL and make sure EffectivePriority returns highest
770 // priority.
771 reliable_stream->SetDelegate(NULL);
772 DCHECK_EQ(QuicWriteBlockedList::kHighestPriority,
773 reliable_stream->EffectivePriority());
774 reliable_stream->SetDelegate(delegate);
777 } // namespace test
778 } // namespace net