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