Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(256)

Side by Side Diff: net/quic/reliable_quic_stream_test.cc

Issue 100173005: Break out the basic reliable QUIC stream functionality from the (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « net/quic/reliable_quic_stream.cc ('k') | net/quic/test_tools/quic_data_stream_peer.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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/reliable_quic_stream.h" 5 #include "net/quic/reliable_quic_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" 9 #include "net/quic/quic_spdy_compressor.h"
10 #include "net/quic/quic_spdy_decompressor.h" 10 #include "net/quic/quic_spdy_decompressor.h"
(...skipping 25 matching lines...) Expand all
36 const bool kShouldProcessData = true; 36 const bool kShouldProcessData = true;
37 37
38 class TestStream : public ReliableQuicStream { 38 class TestStream : public ReliableQuicStream {
39 public: 39 public:
40 TestStream(QuicStreamId id, 40 TestStream(QuicStreamId id,
41 QuicSession* session, 41 QuicSession* session,
42 bool should_process_data) 42 bool should_process_data)
43 : ReliableQuicStream(id, session), 43 : ReliableQuicStream(id, session),
44 should_process_data_(should_process_data) {} 44 should_process_data_(should_process_data) {}
45 45
46 virtual uint32 ProcessData(const char* data, uint32 data_len) OVERRIDE { 46 virtual uint32 ProcessRawData(const char* data, uint32 data_len) OVERRIDE {
47 EXPECT_NE(0u, data_len); 47 EXPECT_NE(0u, data_len);
48 DVLOG(1) << "ProcessData data_len: " << data_len; 48 DVLOG(1) << "ProcessData data_len: " << data_len;
49 data_ += string(data, data_len); 49 data_ += string(data, data_len);
50 return should_process_data_ ? data_len : 0; 50 return should_process_data_ ? data_len : 0;
51 } 51 }
52 52
53 virtual QuicPriority EffectivePriority() const OVERRIDE { return 0; }
54
53 using ReliableQuicStream::WriteOrBufferData; 55 using ReliableQuicStream::WriteOrBufferData;
54 using ReliableQuicStream::CloseReadSide; 56 using ReliableQuicStream::CloseReadSide;
55 using ReliableQuicStream::CloseWriteSide; 57 using ReliableQuicStream::CloseWriteSide;
56 58
57 const string& data() const { return data_; } 59 const string& data() const { return data_; }
58 60
59 private: 61 private:
60 bool should_process_data_; 62 bool should_process_data_;
61 string data_; 63 string data_;
62 }; 64 };
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after
219 221
220 stream_->CloseReadSide(); 222 stream_->CloseReadSide();
221 stream_->CloseWriteSide(); 223 stream_->CloseWriteSide();
222 EXPECT_EQ(QUIC_STREAM_NO_ERROR, stream_->stream_error()); 224 EXPECT_EQ(QUIC_STREAM_NO_ERROR, stream_->stream_error());
223 EXPECT_EQ(QUIC_NO_ERROR, stream_->connection_error()); 225 EXPECT_EQ(QUIC_NO_ERROR, stream_->connection_error());
224 stream_->OnConnectionClosed(QUIC_INTERNAL_ERROR, false); 226 stream_->OnConnectionClosed(QUIC_INTERNAL_ERROR, false);
225 EXPECT_EQ(QUIC_STREAM_NO_ERROR, stream_->stream_error()); 227 EXPECT_EQ(QUIC_STREAM_NO_ERROR, stream_->stream_error());
226 EXPECT_EQ(QUIC_NO_ERROR, stream_->connection_error()); 228 EXPECT_EQ(QUIC_NO_ERROR, stream_->connection_error());
227 } 229 }
228 230
229 TEST_F(ReliableQuicStreamTest, ProcessHeaders) {
230 Initialize(kShouldProcessData);
231
232 string compressed_headers = compressor_->CompressHeadersWithPriority(
233 kHighestPriority, headers_);
234 QuicStreamFrame frame(kStreamId, false, 0, MakeIOVector(compressed_headers));
235
236 stream_->OnStreamFrame(frame);
237 EXPECT_EQ(SpdyUtils::SerializeUncompressedHeaders(headers_), stream_->data());
238 EXPECT_EQ(static_cast<QuicPriority>(kHighestPriority),
239 stream_->EffectivePriority());
240 }
241
242 TEST_F(ReliableQuicStreamTest, ProcessHeadersWithInvalidHeaderId) {
243 Initialize(kShouldProcessData);
244
245 string compressed_headers = compressor_->CompressHeadersWithPriority(
246 kHighestPriority, headers_);
247 compressed_headers[4] = '\xFF'; // Illegal header id.
248 QuicStreamFrame frame(kStreamId, false, 0, MakeIOVector(compressed_headers));
249
250 EXPECT_CALL(*connection_, SendConnectionClose(QUIC_INVALID_HEADER_ID));
251 stream_->OnStreamFrame(frame);
252 }
253
254 TEST_F(ReliableQuicStreamTest, ProcessHeadersWithInvalidPriority) {
255 Initialize(kShouldProcessData);
256
257 string compressed_headers = compressor_->CompressHeadersWithPriority(
258 kHighestPriority, headers_);
259 compressed_headers[0] = '\xFF'; // Illegal priority.
260 QuicStreamFrame frame(kStreamId, false, 0, MakeIOVector(compressed_headers));
261
262 EXPECT_CALL(*connection_, SendConnectionClose(QUIC_INVALID_PRIORITY));
263 stream_->OnStreamFrame(frame);
264 }
265
266 TEST_F(ReliableQuicStreamTest, ProcessHeadersAndBody) {
267 Initialize(kShouldProcessData);
268
269 string compressed_headers = compressor_->CompressHeadersWithPriority(
270 kHighestPriority, headers_);
271 string body = "this is the body";
272 string data = compressed_headers + body;
273 QuicStreamFrame frame(kStreamId, false, 0, MakeIOVector(data));
274
275 stream_->OnStreamFrame(frame);
276 EXPECT_EQ(SpdyUtils::SerializeUncompressedHeaders(headers_) + body,
277 stream_->data());
278 }
279
280 TEST_F(ReliableQuicStreamTest, ProcessHeadersAndBodyFragments) {
281 Initialize(kShouldProcessData);
282
283 string compressed_headers = compressor_->CompressHeadersWithPriority(
284 kLowestPriority, headers_);
285 string body = "this is the body";
286 string data = compressed_headers + body;
287
288 for (size_t fragment_size = 1; fragment_size < data.size(); ++fragment_size) {
289 Initialize(kShouldProcessData);
290 for (size_t offset = 0; offset < data.size(); offset += fragment_size) {
291 size_t remaining_data = data.length() - offset;
292 StringPiece fragment(data.data() + offset,
293 min(fragment_size, remaining_data));
294 QuicStreamFrame frame(kStreamId, false, offset, MakeIOVector(fragment));
295
296 stream_->OnStreamFrame(frame);
297 }
298 ASSERT_EQ(SpdyUtils::SerializeUncompressedHeaders(headers_) + body,
299 stream_->data()) << "fragment_size: " << fragment_size;
300 }
301
302 for (size_t split_point = 1; split_point < data.size() - 1; ++split_point) {
303 Initialize(kShouldProcessData);
304
305 StringPiece fragment1(data.data(), split_point);
306 QuicStreamFrame frame1(kStreamId, false, 0, MakeIOVector(fragment1));
307 stream_->OnStreamFrame(frame1);
308
309 StringPiece fragment2(data.data() + split_point, data.size() - split_point);
310 QuicStreamFrame frame2(
311 kStreamId, false, split_point, MakeIOVector(fragment2));
312 stream_->OnStreamFrame(frame2);
313
314 ASSERT_EQ(SpdyUtils::SerializeUncompressedHeaders(headers_) + body,
315 stream_->data()) << "split_point: " << split_point;
316 }
317 EXPECT_EQ(static_cast<QuicPriority>(kLowestPriority),
318 stream_->EffectivePriority());
319 }
320
321 TEST_F(ReliableQuicStreamTest, ProcessHeadersAndBodyReadv) {
322 Initialize(!kShouldProcessData);
323
324 string compressed_headers = compressor_->CompressHeadersWithPriority(
325 kHighestPriority, headers_);
326 string body = "this is the body";
327 string data = compressed_headers + body;
328 QuicStreamFrame frame(kStreamId, false, 0, MakeIOVector(data));
329 string uncompressed_headers =
330 SpdyUtils::SerializeUncompressedHeaders(headers_);
331 string uncompressed_data = uncompressed_headers + body;
332
333 stream_->OnStreamFrame(frame);
334 EXPECT_EQ(uncompressed_headers, stream_->data());
335
336 char buffer[2048];
337 ASSERT_LT(data.length(), arraysize(buffer));
338 struct iovec vec;
339 vec.iov_base = buffer;
340 vec.iov_len = arraysize(buffer);
341
342 size_t bytes_read = stream_->Readv(&vec, 1);
343 EXPECT_EQ(uncompressed_headers.length(), bytes_read);
344 EXPECT_EQ(uncompressed_headers, string(buffer, bytes_read));
345
346 bytes_read = stream_->Readv(&vec, 1);
347 EXPECT_EQ(body.length(), bytes_read);
348 EXPECT_EQ(body, string(buffer, bytes_read));
349 }
350
351 TEST_F(ReliableQuicStreamTest, ProcessHeadersAndBodyIncrementalReadv) {
352 Initialize(!kShouldProcessData);
353
354 string compressed_headers = compressor_->CompressHeadersWithPriority(
355 kHighestPriority, headers_);
356 string body = "this is the body";
357 string data = compressed_headers + body;
358 QuicStreamFrame frame(kStreamId, false, 0, MakeIOVector(data));
359 string uncompressed_headers =
360 SpdyUtils::SerializeUncompressedHeaders(headers_);
361 string uncompressed_data = uncompressed_headers + body;
362
363 stream_->OnStreamFrame(frame);
364 EXPECT_EQ(uncompressed_headers, stream_->data());
365
366 char buffer[1];
367 struct iovec vec;
368 vec.iov_base = buffer;
369 vec.iov_len = arraysize(buffer);
370 for (size_t i = 0; i < uncompressed_data.length(); ++i) {
371 size_t bytes_read = stream_->Readv(&vec, 1);
372 ASSERT_EQ(1u, bytes_read);
373 EXPECT_EQ(uncompressed_data.data()[i], buffer[0]);
374 }
375 }
376
377 TEST_F(ReliableQuicStreamTest, ProcessHeadersUsingReadvWithMultipleIovecs) {
378 Initialize(!kShouldProcessData);
379
380 string compressed_headers = compressor_->CompressHeadersWithPriority(
381 kHighestPriority, headers_);
382 string body = "this is the body";
383 string data = compressed_headers + body;
384 QuicStreamFrame frame(kStreamId, false, 0, MakeIOVector(data));
385 string uncompressed_headers =
386 SpdyUtils::SerializeUncompressedHeaders(headers_);
387 string uncompressed_data = uncompressed_headers + body;
388
389 stream_->OnStreamFrame(frame);
390 EXPECT_EQ(uncompressed_headers, stream_->data());
391
392 char buffer1[1];
393 char buffer2[1];
394 struct iovec vec[2];
395 vec[0].iov_base = buffer1;
396 vec[0].iov_len = arraysize(buffer1);
397 vec[1].iov_base = buffer2;
398 vec[1].iov_len = arraysize(buffer2);
399 for (size_t i = 0; i < uncompressed_data.length(); i += 2) {
400 size_t bytes_read = stream_->Readv(vec, 2);
401 ASSERT_EQ(2u, bytes_read) << i;
402 ASSERT_EQ(uncompressed_data.data()[i], buffer1[0]) << i;
403 ASSERT_EQ(uncompressed_data.data()[i + 1], buffer2[0]) << i;
404 }
405 }
406
407 TEST_F(ReliableQuicStreamTest, ProcessCorruptHeadersEarly) {
408 Initialize(kShouldProcessData);
409
410 string compressed_headers1 = compressor_->CompressHeadersWithPriority(
411 kHighestPriority, headers_);
412 QuicStreamFrame frame1(
413 stream_->id(), false, 0, MakeIOVector(compressed_headers1));
414 string decompressed_headers1 =
415 SpdyUtils::SerializeUncompressedHeaders(headers_);
416
417 headers_["content-type"] = "text/plain";
418 string compressed_headers2 = compressor_->CompressHeadersWithPriority(
419 kHighestPriority, headers_);
420 // Corrupt the compressed data.
421 compressed_headers2[compressed_headers2.length() - 1] ^= 0xA1;
422 QuicStreamFrame frame2(
423 stream2_->id(), false, 0, MakeIOVector(compressed_headers2));
424 string decompressed_headers2 =
425 SpdyUtils::SerializeUncompressedHeaders(headers_);
426
427 // Deliver frame2 to stream2 out of order. The decompressor is not
428 // available yet, so no data will be processed. The compressed data
429 // will be buffered until OnDecompressorAvailable() is called
430 // to process it.
431 stream2_->OnStreamFrame(frame2);
432 EXPECT_EQ("", stream2_->data());
433
434 // Now deliver frame1 to stream1. The decompressor is available so
435 // the data will be processed, and the decompressor will become
436 // available for stream2.
437 stream_->OnStreamFrame(frame1);
438 EXPECT_EQ(decompressed_headers1, stream_->data());
439
440 // Verify that the decompressor is available, and inform stream2
441 // that it can now decompress the buffered compressed data. Since
442 // the compressed data is corrupt, the stream will shutdown the session.
443 EXPECT_EQ(2u, session_->decompressor()->current_header_id());
444 EXPECT_CALL(*connection_, SendConnectionClose(QUIC_DECOMPRESSION_FAILURE));
445 stream2_->OnDecompressorAvailable();
446 EXPECT_EQ("", stream2_->data());
447 }
448
449 TEST_F(ReliableQuicStreamTest, ProcessPartialHeadersEarly) {
450 Initialize(kShouldProcessData);
451
452 string compressed_headers1 = compressor_->CompressHeadersWithPriority(
453 kHighestPriority, headers_);
454 QuicStreamFrame frame1(
455 stream_->id(), false, 0, MakeIOVector(compressed_headers1));
456 string decompressed_headers1 =
457 SpdyUtils::SerializeUncompressedHeaders(headers_);
458
459 headers_["content-type"] = "text/plain";
460 string compressed_headers2 = compressor_->CompressHeadersWithPriority(
461 kHighestPriority, headers_);
462 string partial_compressed_headers =
463 compressed_headers2.substr(0, compressed_headers2.length() / 2);
464 QuicStreamFrame frame2(
465 stream2_->id(), false, 0, MakeIOVector(partial_compressed_headers));
466 string decompressed_headers2 =
467 SpdyUtils::SerializeUncompressedHeaders(headers_);
468
469 // Deliver frame2 to stream2 out of order. The decompressor is not
470 // available yet, so no data will be processed. The compressed data
471 // will be buffered until OnDecompressorAvailable() is called
472 // to process it.
473 stream2_->OnStreamFrame(frame2);
474 EXPECT_EQ("", stream2_->data());
475
476 // Now deliver frame1 to stream1. The decompressor is available so
477 // the data will be processed, and the decompressor will become
478 // available for stream2.
479 stream_->OnStreamFrame(frame1);
480 EXPECT_EQ(decompressed_headers1, stream_->data());
481
482 // Verify that the decompressor is available, and inform stream2
483 // that it can now decompress the buffered compressed data. Since
484 // the compressed data is incomplete it will not be passed to
485 // the stream.
486 EXPECT_EQ(2u, session_->decompressor()->current_header_id());
487 stream2_->OnDecompressorAvailable();
488 EXPECT_EQ("", stream2_->data());
489
490 // Now send remaining data and verify that we have now received the
491 // compressed headers.
492 string remaining_compressed_headers =
493 compressed_headers2.substr(partial_compressed_headers.length());
494
495 QuicStreamFrame frame3(stream2_->id(), false,
496 partial_compressed_headers.length(),
497 MakeIOVector(remaining_compressed_headers));
498 stream2_->OnStreamFrame(frame3);
499 EXPECT_EQ(decompressed_headers2, stream2_->data());
500 }
501
502 TEST_F(ReliableQuicStreamTest, ProcessHeadersEarly) {
503 Initialize(kShouldProcessData);
504
505 string compressed_headers1 = compressor_->CompressHeadersWithPriority(
506 kHighestPriority, headers_);
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 = compressor_->CompressHeadersWithPriority(
514 kHighestPriority, headers_);
515 QuicStreamFrame frame2(
516 stream2_->id(), false, 0, MakeIOVector(compressed_headers2));
517 string decompressed_headers2 =
518 SpdyUtils::SerializeUncompressedHeaders(headers_);
519
520 // Deliver frame2 to stream2 out of order. The decompressor is not
521 // available yet, so no data will be processed. The compressed data
522 // will be buffered until OnDecompressorAvailable() is called
523 // to process it.
524 stream2_->OnStreamFrame(frame2);
525 EXPECT_EQ("", stream2_->data());
526
527 // Now deliver frame1 to stream1. The decompressor is available so
528 // the data will be processed, and the decompressor will become
529 // available for stream2.
530 stream_->OnStreamFrame(frame1);
531 EXPECT_EQ(decompressed_headers1, stream_->data());
532
533 // Verify that the decompressor is available, and inform stream2
534 // that it can now decompress the buffered compressed data.
535 EXPECT_EQ(2u, session_->decompressor()->current_header_id());
536 stream2_->OnDecompressorAvailable();
537 EXPECT_EQ(decompressed_headers2, stream2_->data());
538 }
539
540 TEST_F(ReliableQuicStreamTest, ProcessHeadersDelay) {
541 Initialize(!kShouldProcessData);
542
543 string compressed_headers = compressor_->CompressHeadersWithPriority(
544 kHighestPriority, headers_);
545 QuicStreamFrame frame1(
546 stream_->id(), false, 0, MakeIOVector(compressed_headers));
547 string decompressed_headers =
548 SpdyUtils::SerializeUncompressedHeaders(headers_);
549
550 // Send the headers to the stream and verify they were decompressed.
551 stream_->OnStreamFrame(frame1);
552 EXPECT_EQ(2u, session_->decompressor()->current_header_id());
553
554 // Verify that we are now able to handle the body data,
555 // even though the stream has not processed the headers.
556 EXPECT_CALL(*connection_, SendConnectionClose(QUIC_INVALID_HEADER_ID))
557 .Times(0);
558 QuicStreamFrame frame2(stream_->id(), false, compressed_headers.length(),
559 MakeIOVector("body data"));
560 stream_->OnStreamFrame(frame2);
561 }
562
563 } // namespace 231 } // namespace
564 } // namespace test 232 } // namespace test
565 } // namespace net 233 } // namespace net
OLDNEW
« no previous file with comments | « net/quic/reliable_quic_stream.cc ('k') | net/quic/test_tools/quic_data_stream_peer.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698