OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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_data_stream.h" | 5 #include "net/quic/quic_data_stream.h" |
6 | 6 |
7 #include "net/quic/quic_ack_notifier.h" | 7 #include "net/quic/quic_ack_notifier.h" |
8 #include "net/quic/quic_connection.h" | 8 #include "net/quic/quic_connection.h" |
9 #include "net/quic/quic_spdy_compressor.h" | |
10 #include "net/quic/quic_spdy_decompressor.h" | |
11 #include "net/quic/quic_utils.h" | 9 #include "net/quic/quic_utils.h" |
12 #include "net/quic/quic_write_blocked_list.h" | 10 #include "net/quic/quic_write_blocked_list.h" |
13 #include "net/quic/spdy_utils.h" | 11 #include "net/quic/spdy_utils.h" |
14 #include "net/quic/test_tools/quic_session_peer.h" | 12 #include "net/quic/test_tools/quic_session_peer.h" |
15 #include "net/quic/test_tools/quic_test_utils.h" | 13 #include "net/quic/test_tools/quic_test_utils.h" |
16 #include "testing/gmock/include/gmock/gmock.h" | 14 #include "testing/gmock/include/gmock/gmock.h" |
17 | 15 |
18 using base::StringPiece; | 16 using base::StringPiece; |
19 using std::min; | 17 using std::min; |
20 using testing::_; | 18 using testing::_; |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
91 } | 89 } |
92 | 90 |
93 void Initialize(bool stream_should_process_data) { | 91 void Initialize(bool stream_should_process_data) { |
94 connection_ = new testing::StrictMock<MockConnection>( | 92 connection_ = new testing::StrictMock<MockConnection>( |
95 kIsServer, SupportedVersions(GetParam())); | 93 kIsServer, SupportedVersions(GetParam())); |
96 session_.reset(new testing::StrictMock<MockSession>(connection_)); | 94 session_.reset(new testing::StrictMock<MockSession>(connection_)); |
97 stream_.reset(new TestStream(kStreamId, session_.get(), | 95 stream_.reset(new TestStream(kStreamId, session_.get(), |
98 stream_should_process_data)); | 96 stream_should_process_data)); |
99 stream2_.reset(new TestStream(kStreamId + 2, session_.get(), | 97 stream2_.reset(new TestStream(kStreamId + 2, session_.get(), |
100 stream_should_process_data)); | 98 stream_should_process_data)); |
101 compressor_.reset(new QuicSpdyCompressor()); | |
102 decompressor_.reset(new QuicSpdyDecompressor); | |
103 write_blocked_list_ = | 99 write_blocked_list_ = |
104 QuicSessionPeer::GetWriteblockedStreams(session_.get()); | 100 QuicSessionPeer::GetWriteblockedStreams(session_.get()); |
105 } | 101 } |
106 | 102 |
107 string CompressHeaders(QuicPriority priority) { | |
108 return compressor_->CompressHeadersWithPriority(priority, headers_); | |
109 } | |
110 | |
111 size_t CompressedHeadersSize() { | |
112 return CompressHeaders(QuicUtils::HighestPriority()).size(); | |
113 } | |
114 | |
115 protected: | 103 protected: |
116 MockConnection* connection_; | 104 MockConnection* connection_; |
117 scoped_ptr<MockSession> session_; | 105 scoped_ptr<MockSession> session_; |
118 scoped_ptr<TestStream> stream_; | 106 scoped_ptr<TestStream> stream_; |
119 scoped_ptr<TestStream> stream2_; | 107 scoped_ptr<TestStream> stream2_; |
120 scoped_ptr<QuicSpdyCompressor> compressor_; | |
121 scoped_ptr<QuicSpdyDecompressor> decompressor_; | |
122 SpdyHeaderBlock headers_; | 108 SpdyHeaderBlock headers_; |
123 QuicWriteBlockedList* write_blocked_list_; | 109 QuicWriteBlockedList* write_blocked_list_; |
124 }; | 110 }; |
125 | 111 |
126 INSTANTIATE_TEST_CASE_P(Tests, QuicDataStreamTest, | 112 INSTANTIATE_TEST_CASE_P(Tests, QuicDataStreamTest, |
127 ::testing::ValuesIn(QuicSupportedVersions())); | 113 ::testing::ValuesIn(QuicSupportedVersions())); |
128 | 114 |
129 TEST_P(QuicDataStreamTest, ProcessHeaders) { | 115 TEST_P(QuicDataStreamTest, ProcessHeaders) { |
130 Initialize(kShouldProcessData); | 116 Initialize(kShouldProcessData); |
131 | 117 |
132 string headers = SpdyUtils::SerializeUncompressedHeaders(headers_); | 118 string headers = SpdyUtils::SerializeUncompressedHeaders(headers_); |
133 if (GetParam() > QUIC_VERSION_12) { | 119 stream_->OnStreamHeadersPriority(QuicUtils::HighestPriority()); |
134 stream_->OnStreamHeadersPriority(QuicUtils::HighestPriority()); | 120 stream_->OnStreamHeaders(headers); |
135 stream_->OnStreamHeaders(headers); | 121 EXPECT_EQ(headers, stream_->data()); |
136 EXPECT_EQ(headers, stream_->data()); | 122 stream_->OnStreamHeadersComplete(false, headers.size()); |
137 stream_->OnStreamHeadersComplete(false, CompressedHeadersSize()); | |
138 } else { | |
139 string compressed_headers = CompressHeaders(QuicUtils::HighestPriority()); | |
140 QuicStreamFrame frame(kStreamId, false, 0, | |
141 MakeIOVector(compressed_headers)); | |
142 | |
143 stream_->OnStreamFrame(frame); | |
144 } | |
145 EXPECT_EQ(QuicUtils::HighestPriority(), stream_->EffectivePriority()); | 123 EXPECT_EQ(QuicUtils::HighestPriority(), stream_->EffectivePriority()); |
146 EXPECT_EQ(headers, stream_->data()); | 124 EXPECT_EQ(headers, stream_->data()); |
147 EXPECT_FALSE(stream_->IsDoneReading()); | 125 EXPECT_FALSE(stream_->IsDoneReading()); |
148 } | 126 } |
149 | 127 |
150 TEST_P(QuicDataStreamTest, ProcessHeadersWithInvalidHeaderId) { | |
151 if (GetParam() > QUIC_VERSION_12) { | |
152 // Header ID is v12 specific. | |
153 return; | |
154 } | |
155 Initialize(kShouldProcessData); | |
156 | |
157 string compressed_headers = CompressHeaders(QuicUtils::HighestPriority()); | |
158 compressed_headers[4] = '\xFF'; // Illegal header id. | |
159 QuicStreamFrame frame(kStreamId, false, 0, MakeIOVector(compressed_headers)); | |
160 | |
161 EXPECT_CALL(*connection_, SendConnectionClose(QUIC_INVALID_HEADER_ID)); | |
162 stream_->OnStreamFrame(frame); | |
163 } | |
164 | |
165 TEST_P(QuicDataStreamTest, ProcessHeadersWithInvalidPriority) { | |
166 if (GetParam() > QUIC_VERSION_12) { | |
167 // Invalid priority is handled in QuicHeadersStream. | |
168 return; | |
169 } | |
170 Initialize(kShouldProcessData); | |
171 | |
172 string compressed_headers = CompressHeaders(QuicUtils::HighestPriority()); | |
173 compressed_headers[0] = '\xFF'; // Illegal priority. | |
174 QuicStreamFrame frame(kStreamId, false, 0, MakeIOVector(compressed_headers)); | |
175 | |
176 EXPECT_CALL(*connection_, SendConnectionClose(QUIC_INVALID_PRIORITY)); | |
177 stream_->OnStreamFrame(frame); | |
178 } | |
179 | |
180 TEST_P(QuicDataStreamTest, ProcessHeadersAndBody) { | 128 TEST_P(QuicDataStreamTest, ProcessHeadersAndBody) { |
181 Initialize(kShouldProcessData); | 129 Initialize(kShouldProcessData); |
182 | 130 |
183 string headers = SpdyUtils::SerializeUncompressedHeaders(headers_); | 131 string headers = SpdyUtils::SerializeUncompressedHeaders(headers_); |
184 string body = "this is the body"; | 132 string body = "this is the body"; |
185 | 133 |
186 if (GetParam() > QUIC_VERSION_12) { | 134 stream_->OnStreamHeaders(headers); |
187 stream_->OnStreamHeaders(headers); | 135 EXPECT_EQ(headers, stream_->data()); |
188 EXPECT_EQ(headers, stream_->data()); | 136 stream_->OnStreamHeadersComplete(false, headers.size()); |
189 stream_->OnStreamHeadersComplete(false, CompressedHeadersSize()); | 137 QuicStreamFrame frame(kStreamId, false, 0, MakeIOVector(body)); |
190 QuicStreamFrame frame(kStreamId, false, 0, MakeIOVector(body)); | 138 stream_->OnStreamFrame(frame); |
191 stream_->OnStreamFrame(frame); | |
192 } else { | |
193 string compressed_headers = CompressHeaders(QuicUtils::HighestPriority()); | |
194 string data = compressed_headers + body; | |
195 QuicStreamFrame frame(kStreamId, false, 0, MakeIOVector(data)); | |
196 stream_->OnStreamFrame(frame); | |
197 } | |
198 | 139 |
199 EXPECT_EQ(headers + body, stream_->data()); | 140 EXPECT_EQ(headers + body, stream_->data()); |
200 } | 141 } |
201 | 142 |
202 TEST_P(QuicDataStreamTest, ProcessHeadersAndBodyFragments) { | 143 TEST_P(QuicDataStreamTest, ProcessHeadersAndBodyFragments) { |
203 string headers = SpdyUtils::SerializeUncompressedHeaders(headers_); | 144 string headers = SpdyUtils::SerializeUncompressedHeaders(headers_); |
204 string body = "this is the body"; | 145 string body = "this is the body"; |
205 | 146 |
206 if (GetParam() > QUIC_VERSION_12) { | 147 for (size_t fragment_size = 1; fragment_size < body.size(); |
207 for (size_t fragment_size = 1; fragment_size < body.size(); | 148 ++fragment_size) { |
208 ++fragment_size) { | 149 Initialize(kShouldProcessData); |
209 Initialize(kShouldProcessData); | 150 for (size_t offset = 0; offset < headers.size(); |
210 for (size_t offset = 0; offset < headers.size(); | 151 offset += fragment_size) { |
211 offset += fragment_size) { | 152 size_t remaining_data = headers.size() - offset; |
212 size_t remaining_data = headers.size() - offset; | 153 StringPiece fragment(headers.data() + offset, |
213 StringPiece fragment(headers.data() + offset, | 154 min(fragment_size, remaining_data)); |
214 min(fragment_size, remaining_data)); | 155 stream_->OnStreamHeaders(fragment); |
215 stream_->OnStreamHeaders(fragment); | |
216 } | |
217 stream_->OnStreamHeadersComplete(false, CompressedHeadersSize()); | |
218 for (size_t offset = 0; offset < body.size(); offset += fragment_size) { | |
219 size_t remaining_data = body.size() - offset; | |
220 StringPiece fragment(body.data() + offset, | |
221 min(fragment_size, remaining_data)); | |
222 QuicStreamFrame frame(kStreamId, false, offset, MakeIOVector(fragment)); | |
223 stream_->OnStreamFrame(frame); | |
224 } | |
225 ASSERT_EQ(headers + body, | |
226 stream_->data()) << "fragment_size: " << fragment_size; | |
227 } | 156 } |
228 } else { | 157 stream_->OnStreamHeadersComplete(false, headers.size()); |
229 Initialize(kShouldProcessData); | 158 for (size_t offset = 0; offset < body.size(); offset += fragment_size) { |
230 string compressed_headers = CompressHeaders(QuicUtils::HighestPriority()); | 159 size_t remaining_data = body.size() - offset; |
231 string data = compressed_headers + body; | 160 StringPiece fragment(body.data() + offset, |
232 for (size_t fragment_size = 1; fragment_size < data.size(); | 161 min(fragment_size, remaining_data)); |
233 ++fragment_size) { | 162 QuicStreamFrame frame(kStreamId, false, offset, MakeIOVector(fragment)); |
234 Initialize(kShouldProcessData); | 163 stream_->OnStreamFrame(frame); |
235 for (size_t offset = 0; offset < data.size(); offset += fragment_size) { | |
236 size_t remaining_data = data.size() - offset; | |
237 StringPiece fragment(data.data() + offset, | |
238 min(fragment_size, remaining_data)); | |
239 QuicStreamFrame frame(kStreamId, false, offset, MakeIOVector(fragment)); | |
240 stream_->OnStreamFrame(frame); | |
241 } | |
242 ASSERT_EQ(headers + body, | |
243 stream_->data()) << "fragment_size: " << fragment_size; | |
244 } | 164 } |
| 165 ASSERT_EQ(headers + body, |
| 166 stream_->data()) << "fragment_size: " << fragment_size; |
245 } | 167 } |
246 } | 168 } |
247 | 169 |
248 TEST_P(QuicDataStreamTest, ProcessHeadersAndBodyFragmentsSplit) { | 170 TEST_P(QuicDataStreamTest, ProcessHeadersAndBodyFragmentsSplit) { |
249 string headers = SpdyUtils::SerializeUncompressedHeaders(headers_); | 171 string headers = SpdyUtils::SerializeUncompressedHeaders(headers_); |
250 string body = "this is the body"; | 172 string body = "this is the body"; |
251 | 173 |
252 if (GetParam() > QUIC_VERSION_12) { | 174 for (size_t split_point = 1; split_point < body.size() - 1; ++split_point) { |
253 for (size_t split_point = 1; split_point < body.size() - 1; ++split_point) { | 175 Initialize(kShouldProcessData); |
254 Initialize(kShouldProcessData); | 176 StringPiece headers1(headers.data(), split_point); |
255 StringPiece headers1(headers.data(), split_point); | 177 stream_->OnStreamHeaders(headers1); |
256 stream_->OnStreamHeaders(headers1); | |
257 | 178 |
258 StringPiece headers2(headers.data() + split_point, | 179 StringPiece headers2(headers.data() + split_point, |
259 headers.size() - split_point); | 180 headers.size() - split_point); |
260 stream_->OnStreamHeaders(headers2); | 181 stream_->OnStreamHeaders(headers2); |
261 stream_->OnStreamHeadersComplete(false, CompressedHeadersSize()); | 182 stream_->OnStreamHeadersComplete(false, headers.size()); |
262 | 183 |
263 StringPiece fragment1(body.data(), split_point); | 184 StringPiece fragment1(body.data(), split_point); |
264 QuicStreamFrame frame1(kStreamId, false, 0, MakeIOVector(fragment1)); | 185 QuicStreamFrame frame1(kStreamId, false, 0, MakeIOVector(fragment1)); |
265 stream_->OnStreamFrame(frame1); | 186 stream_->OnStreamFrame(frame1); |
266 | 187 |
267 StringPiece fragment2(body.data() + split_point, | 188 StringPiece fragment2(body.data() + split_point, |
268 body.size() - split_point); | 189 body.size() - split_point); |
269 QuicStreamFrame frame2( | 190 QuicStreamFrame frame2( |
270 kStreamId, false, split_point, MakeIOVector(fragment2)); | 191 kStreamId, false, split_point, MakeIOVector(fragment2)); |
271 stream_->OnStreamFrame(frame2); | 192 stream_->OnStreamFrame(frame2); |
272 | 193 |
273 ASSERT_EQ(headers + body, | 194 ASSERT_EQ(headers + body, |
274 stream_->data()) << "split_point: " << split_point; | 195 stream_->data()) << "split_point: " << split_point; |
275 } | |
276 } else { | |
277 Initialize(kShouldProcessData); | |
278 string compressed_headers = CompressHeaders(QuicUtils::LowestPriority()); | |
279 string data = compressed_headers + body; | |
280 | |
281 for (size_t split_point = 1; split_point < data.size() - 1; ++split_point) { | |
282 Initialize(kShouldProcessData); | |
283 | |
284 StringPiece fragment1(data.data(), split_point); | |
285 QuicStreamFrame frame1(kStreamId, false, 0, MakeIOVector(fragment1)); | |
286 stream_->OnStreamFrame(frame1); | |
287 | |
288 StringPiece fragment2(data.data() + split_point, | |
289 data.size() - split_point); | |
290 QuicStreamFrame frame2( | |
291 kStreamId, false, split_point, MakeIOVector(fragment2)); | |
292 stream_->OnStreamFrame(frame2); | |
293 | |
294 ASSERT_EQ(SpdyUtils::SerializeUncompressedHeaders(headers_) + body, | |
295 stream_->data()) << "split_point: " << split_point; | |
296 } | |
297 EXPECT_EQ(QuicUtils::LowestPriority(), stream_->EffectivePriority()); | |
298 } | 196 } |
299 } | 197 } |
300 | 198 |
301 TEST_P(QuicDataStreamTest, ProcessHeadersAndBodyReadv) { | 199 TEST_P(QuicDataStreamTest, ProcessHeadersAndBodyReadv) { |
302 Initialize(!kShouldProcessData); | 200 Initialize(!kShouldProcessData); |
303 | 201 |
304 string headers = SpdyUtils::SerializeUncompressedHeaders(headers_); | 202 string headers = SpdyUtils::SerializeUncompressedHeaders(headers_); |
305 string body = "this is the body"; | 203 string body = "this is the body"; |
306 | 204 |
307 if (GetParam() > QUIC_VERSION_12) { | 205 stream_->OnStreamHeaders(headers); |
308 stream_->OnStreamHeaders(headers); | 206 EXPECT_EQ(headers, stream_->data()); |
309 EXPECT_EQ(headers, stream_->data()); | 207 stream_->OnStreamHeadersComplete(false, headers.size()); |
310 stream_->OnStreamHeadersComplete(false, CompressedHeadersSize()); | 208 QuicStreamFrame frame(kStreamId, false, 0, MakeIOVector(body)); |
311 QuicStreamFrame frame(kStreamId, false, 0, MakeIOVector(body)); | 209 stream_->OnStreamFrame(frame); |
312 stream_->OnStreamFrame(frame); | |
313 } else { | |
314 string compressed_headers = CompressHeaders(QuicUtils::HighestPriority()); | |
315 string data = compressed_headers + body; | |
316 QuicStreamFrame frame(kStreamId, false, 0, MakeIOVector(data)); | |
317 stream_->OnStreamFrame(frame); | |
318 EXPECT_EQ(headers, stream_->data()); | |
319 } | |
320 | 210 |
321 char buffer[2048]; | 211 char buffer[2048]; |
322 ASSERT_LT(headers.length() + body.length(), arraysize(buffer)); | 212 ASSERT_LT(headers.length() + body.length(), arraysize(buffer)); |
323 struct iovec vec; | 213 struct iovec vec; |
324 vec.iov_base = buffer; | 214 vec.iov_base = buffer; |
325 vec.iov_len = arraysize(buffer); | 215 vec.iov_len = arraysize(buffer); |
326 | 216 |
327 size_t bytes_read = stream_->Readv(&vec, 1); | 217 size_t bytes_read = stream_->Readv(&vec, 1); |
328 EXPECT_EQ(headers.length(), bytes_read); | 218 EXPECT_EQ(headers.length(), bytes_read); |
329 EXPECT_EQ(headers, string(buffer, bytes_read)); | 219 EXPECT_EQ(headers, string(buffer, bytes_read)); |
330 | 220 |
331 bytes_read = stream_->Readv(&vec, 1); | 221 bytes_read = stream_->Readv(&vec, 1); |
332 EXPECT_EQ(body.length(), bytes_read); | 222 EXPECT_EQ(body.length(), bytes_read); |
333 EXPECT_EQ(body, string(buffer, bytes_read)); | 223 EXPECT_EQ(body, string(buffer, bytes_read)); |
334 } | 224 } |
335 | 225 |
336 TEST_P(QuicDataStreamTest, ProcessHeadersAndBodyIncrementalReadv) { | 226 TEST_P(QuicDataStreamTest, ProcessHeadersAndBodyIncrementalReadv) { |
337 Initialize(!kShouldProcessData); | 227 Initialize(!kShouldProcessData); |
338 | 228 |
339 string headers = SpdyUtils::SerializeUncompressedHeaders(headers_); | 229 string headers = SpdyUtils::SerializeUncompressedHeaders(headers_); |
340 string body = "this is the body"; | 230 string body = "this is the body"; |
341 if (GetParam() > QUIC_VERSION_12) { | 231 stream_->OnStreamHeaders(headers); |
342 stream_->OnStreamHeaders(headers); | 232 EXPECT_EQ(headers, stream_->data()); |
343 EXPECT_EQ(headers, stream_->data()); | 233 stream_->OnStreamHeadersComplete(false, headers.size()); |
344 stream_->OnStreamHeadersComplete(false, CompressedHeadersSize()); | 234 QuicStreamFrame frame(kStreamId, false, 0, MakeIOVector(body)); |
345 QuicStreamFrame frame(kStreamId, false, 0, MakeIOVector(body)); | 235 stream_->OnStreamFrame(frame); |
346 stream_->OnStreamFrame(frame); | 236 |
347 } else { | |
348 string compressed_headers = CompressHeaders(QuicUtils::HighestPriority()); | |
349 string data = compressed_headers + body; | |
350 QuicStreamFrame frame(kStreamId, false, 0, MakeIOVector(data)); | |
351 stream_->OnStreamFrame(frame); | |
352 EXPECT_EQ(headers, stream_->data()); | |
353 } | |
354 | 237 |
355 char buffer[1]; | 238 char buffer[1]; |
356 struct iovec vec; | 239 struct iovec vec; |
357 vec.iov_base = buffer; | 240 vec.iov_base = buffer; |
358 vec.iov_len = arraysize(buffer); | 241 vec.iov_len = arraysize(buffer); |
359 | 242 |
360 string data = headers + body; | 243 string data = headers + body; |
361 for (size_t i = 0; i < data.length(); ++i) { | 244 for (size_t i = 0; i < data.length(); ++i) { |
362 size_t bytes_read = stream_->Readv(&vec, 1); | 245 size_t bytes_read = stream_->Readv(&vec, 1); |
363 ASSERT_EQ(1u, bytes_read); | 246 ASSERT_EQ(1u, bytes_read); |
364 EXPECT_EQ(data.data()[i], buffer[0]); | 247 EXPECT_EQ(data.data()[i], buffer[0]); |
365 } | 248 } |
366 } | 249 } |
367 | 250 |
368 TEST_P(QuicDataStreamTest, ProcessHeadersUsingReadvWithMultipleIovecs) { | 251 TEST_P(QuicDataStreamTest, ProcessHeadersUsingReadvWithMultipleIovecs) { |
369 Initialize(!kShouldProcessData); | 252 Initialize(!kShouldProcessData); |
370 | 253 |
371 string headers = SpdyUtils::SerializeUncompressedHeaders(headers_); | 254 string headers = SpdyUtils::SerializeUncompressedHeaders(headers_); |
372 string body = "this is the body"; | 255 string body = "this is the body"; |
373 if (GetParam() > QUIC_VERSION_12) { | 256 stream_->OnStreamHeaders(headers); |
374 stream_->OnStreamHeaders(headers); | 257 EXPECT_EQ(headers, stream_->data()); |
375 EXPECT_EQ(headers, stream_->data()); | 258 stream_->OnStreamHeadersComplete(false, headers.size()); |
376 stream_->OnStreamHeadersComplete(false, CompressedHeadersSize()); | 259 QuicStreamFrame frame(kStreamId, false, 0, MakeIOVector(body)); |
377 QuicStreamFrame frame(kStreamId, false, 0, MakeIOVector(body)); | 260 stream_->OnStreamFrame(frame); |
378 stream_->OnStreamFrame(frame); | 261 |
379 } else { | |
380 string compressed_headers = CompressHeaders(QuicUtils::HighestPriority()); | |
381 string data = compressed_headers + body; | |
382 QuicStreamFrame frame(kStreamId, false, 0, MakeIOVector(data)); | |
383 stream_->OnStreamFrame(frame); | |
384 EXPECT_EQ(headers, stream_->data()); | |
385 } | |
386 | 262 |
387 char buffer1[1]; | 263 char buffer1[1]; |
388 char buffer2[1]; | 264 char buffer2[1]; |
389 struct iovec vec[2]; | 265 struct iovec vec[2]; |
390 vec[0].iov_base = buffer1; | 266 vec[0].iov_base = buffer1; |
391 vec[0].iov_len = arraysize(buffer1); | 267 vec[0].iov_len = arraysize(buffer1); |
392 vec[1].iov_base = buffer2; | 268 vec[1].iov_base = buffer2; |
393 vec[1].iov_len = arraysize(buffer2); | 269 vec[1].iov_len = arraysize(buffer2); |
394 string data = headers + body; | 270 string data = headers + body; |
395 for (size_t i = 0; i < data.length(); i += 2) { | 271 for (size_t i = 0; i < data.length(); i += 2) { |
396 size_t bytes_read = stream_->Readv(vec, 2); | 272 size_t bytes_read = stream_->Readv(vec, 2); |
397 ASSERT_EQ(2u, bytes_read) << i; | 273 ASSERT_EQ(2u, bytes_read) << i; |
398 ASSERT_EQ(data.data()[i], buffer1[0]) << i; | 274 ASSERT_EQ(data.data()[i], buffer1[0]) << i; |
399 ASSERT_EQ(data.data()[i + 1], buffer2[0]) << i; | 275 ASSERT_EQ(data.data()[i + 1], buffer2[0]) << i; |
400 } | 276 } |
401 } | 277 } |
402 | 278 |
403 TEST_P(QuicDataStreamTest, ProcessCorruptHeadersEarly) { | |
404 if (GetParam() > QUIC_VERSION_12) { | |
405 return; | |
406 } | |
407 Initialize(kShouldProcessData); | |
408 | |
409 string compressed_headers1 = CompressHeaders(QuicUtils::HighestPriority()); | |
410 QuicStreamFrame frame1( | |
411 stream_->id(), false, 0, MakeIOVector(compressed_headers1)); | |
412 string decompressed_headers1 = | |
413 SpdyUtils::SerializeUncompressedHeaders(headers_); | |
414 | |
415 headers_["content-type"] = "text/plain"; | |
416 string compressed_headers2 = CompressHeaders(QuicUtils::HighestPriority()); | |
417 // Corrupt the compressed data. | |
418 compressed_headers2[compressed_headers2.length() - 1] ^= 0xA1; | |
419 QuicStreamFrame frame2( | |
420 stream2_->id(), false, 0, MakeIOVector(compressed_headers2)); | |
421 string decompressed_headers2 = | |
422 SpdyUtils::SerializeUncompressedHeaders(headers_); | |
423 | |
424 // Deliver frame2 to stream2 out of order. The decompressor is not | |
425 // available yet, so no data will be processed. The compressed data | |
426 // will be buffered until OnDecompressorAvailable() is called | |
427 // to process it. | |
428 stream2_->OnStreamFrame(frame2); | |
429 EXPECT_EQ("", stream2_->data()); | |
430 | |
431 // Now deliver frame1 to stream1. The decompressor is available so | |
432 // the data will be processed, and the decompressor will become | |
433 // available for stream2. | |
434 stream_->OnStreamFrame(frame1); | |
435 EXPECT_EQ(decompressed_headers1, stream_->data()); | |
436 | |
437 // Verify that the decompressor is available, and inform stream2 | |
438 // that it can now decompress the buffered compressed data. Since | |
439 // the compressed data is corrupt, the stream will shutdown the session. | |
440 EXPECT_EQ(2u, session_->decompressor()->current_header_id()); | |
441 EXPECT_CALL(*connection_, SendConnectionClose(QUIC_DECOMPRESSION_FAILURE)); | |
442 stream2_->OnDecompressorAvailable(); | |
443 EXPECT_EQ("", stream2_->data()); | |
444 } | |
445 | |
446 TEST_P(QuicDataStreamTest, ProcessPartialHeadersEarly) { | |
447 if (GetParam() > QUIC_VERSION_12) { | |
448 return; | |
449 } | |
450 Initialize(kShouldProcessData); | |
451 | |
452 string compressed_headers1 = CompressHeaders(QuicUtils::HighestPriority()); | |
453 QuicStreamFrame frame1( | |
454 stream_->id(), false, 0, MakeIOVector(compressed_headers1)); | |
455 string decompressed_headers1 = | |
456 SpdyUtils::SerializeUncompressedHeaders(headers_); | |
457 | |
458 headers_["content-type"] = "text/plain"; | |
459 string compressed_headers2 = CompressHeaders(QuicUtils::HighestPriority()); | |
460 string partial_compressed_headers = | |
461 compressed_headers2.substr(0, compressed_headers2.length() / 2); | |
462 QuicStreamFrame frame2( | |
463 stream2_->id(), false, 0, MakeIOVector(partial_compressed_headers)); | |
464 string decompressed_headers2 = | |
465 SpdyUtils::SerializeUncompressedHeaders(headers_); | |
466 | |
467 // Deliver frame2 to stream2 out of order. The decompressor is not | |
468 // available yet, so no data will be processed. The compressed data | |
469 // will be buffered until OnDecompressorAvailable() is called | |
470 // to process it. | |
471 stream2_->OnStreamFrame(frame2); | |
472 EXPECT_EQ("", stream2_->data()); | |
473 | |
474 // Now deliver frame1 to stream1. The decompressor is available so | |
475 // the data will be processed, and the decompressor will become | |
476 // available for stream2. | |
477 stream_->OnStreamFrame(frame1); | |
478 EXPECT_EQ(decompressed_headers1, stream_->data()); | |
479 | |
480 // Verify that the decompressor is available, and inform stream2 | |
481 // that it can now decompress the buffered compressed data. Since | |
482 // the compressed data is incomplete it will not be passed to | |
483 // the stream. | |
484 EXPECT_EQ(2u, session_->decompressor()->current_header_id()); | |
485 stream2_->OnDecompressorAvailable(); | |
486 EXPECT_EQ("", stream2_->data()); | |
487 | |
488 // Now send remaining data and verify that we have now received the | |
489 // compressed headers. | |
490 string remaining_compressed_headers = | |
491 compressed_headers2.substr(partial_compressed_headers.length()); | |
492 | |
493 QuicStreamFrame frame3(stream2_->id(), false, | |
494 partial_compressed_headers.length(), | |
495 MakeIOVector(remaining_compressed_headers)); | |
496 stream2_->OnStreamFrame(frame3); | |
497 EXPECT_EQ(decompressed_headers2, stream2_->data()); | |
498 } | |
499 | |
500 TEST_P(QuicDataStreamTest, ProcessHeadersEarly) { | |
501 if (GetParam() > QUIC_VERSION_12) { | |
502 return; | |
503 } | |
504 Initialize(kShouldProcessData); | |
505 | |
506 string compressed_headers1 = CompressHeaders(QuicUtils::HighestPriority()); | |
507 QuicStreamFrame frame1( | |
508 stream_->id(), false, 0, MakeIOVector(compressed_headers1)); | |
509 string decompressed_headers1 = | |
510 SpdyUtils::SerializeUncompressedHeaders(headers_); | |
511 | |
512 headers_["content-type"] = "text/plain"; | |
513 string compressed_headers2 = CompressHeaders(QuicUtils::HighestPriority()); | |
514 QuicStreamFrame frame2( | |
515 stream2_->id(), false, 0, MakeIOVector(compressed_headers2)); | |
516 string decompressed_headers2 = | |
517 SpdyUtils::SerializeUncompressedHeaders(headers_); | |
518 | |
519 // Deliver frame2 to stream2 out of order. The decompressor is not | |
520 // available yet, so no data will be processed. The compressed data | |
521 // will be buffered until OnDecompressorAvailable() is called | |
522 // to process it. | |
523 stream2_->OnStreamFrame(frame2); | |
524 EXPECT_EQ("", stream2_->data()); | |
525 | |
526 // Now deliver frame1 to stream1. The decompressor is available so | |
527 // the data will be processed, and the decompressor will become | |
528 // available for stream2. | |
529 stream_->OnStreamFrame(frame1); | |
530 EXPECT_EQ(decompressed_headers1, stream_->data()); | |
531 | |
532 // Verify that the decompressor is available, and inform stream2 | |
533 // that it can now decompress the buffered compressed data. | |
534 EXPECT_EQ(2u, session_->decompressor()->current_header_id()); | |
535 stream2_->OnDecompressorAvailable(); | |
536 EXPECT_EQ(decompressed_headers2, stream2_->data()); | |
537 } | |
538 | |
539 TEST_P(QuicDataStreamTest, ProcessHeadersDelay) { | |
540 if (GetParam() > QUIC_VERSION_12) { | |
541 return; | |
542 } | |
543 Initialize(!kShouldProcessData); | |
544 | |
545 string compressed_headers = CompressHeaders(QuicUtils::HighestPriority()); | |
546 QuicStreamFrame frame1( | |
547 stream_->id(), false, 0, MakeIOVector(compressed_headers)); | |
548 string decompressed_headers = | |
549 SpdyUtils::SerializeUncompressedHeaders(headers_); | |
550 | |
551 // Send the headers to the stream and verify they were decompressed. | |
552 stream_->OnStreamFrame(frame1); | |
553 EXPECT_EQ(2u, session_->decompressor()->current_header_id()); | |
554 | |
555 // Verify that we are now able to handle the body data, | |
556 // even though the stream has not processed the headers. | |
557 EXPECT_CALL(*connection_, SendConnectionClose(QUIC_INVALID_HEADER_ID)) | |
558 .Times(0); | |
559 QuicStreamFrame frame2(stream_->id(), false, compressed_headers.length(), | |
560 MakeIOVector("body data")); | |
561 stream_->OnStreamFrame(frame2); | |
562 } | |
563 | |
564 } // namespace | 279 } // namespace |
565 } // namespace test | 280 } // namespace test |
566 } // namespace net | 281 } // namespace net |
OLD | NEW |