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