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

Side by Side Diff: net/spdy/hpack/hpack_input_stream_test.cc

Issue 1914193002: Implements incremental decode in HPACK. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 7 months 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
« no previous file with comments | « net/spdy/hpack/hpack_input_stream.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 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/spdy/hpack/hpack_input_stream.h" 5 #include "net/spdy/hpack/hpack_input_stream.h"
6 6
7 #include <bitset> 7 #include <bitset>
8 #include <string> 8 #include <string>
9 #include <vector> 9 #include <vector>
10 10
11 #include "base/logging.h" 11 #include "base/logging.h"
12 #include "base/strings/string_piece.h" 12 #include "base/strings/string_piece.h"
13 #include "net/spdy/hpack/hpack_constants.h" 13 #include "net/spdy/hpack/hpack_constants.h"
14 #include "net/spdy/spdy_test_utils.h" 14 #include "net/spdy/spdy_test_utils.h"
15 #include "net/test/gtest_util.h" 15 #include "net/test/gtest_util.h"
16 #include "testing/gtest/include/gtest/gtest.h" 16 #include "testing/gtest/include/gtest/gtest.h"
17 17
18 namespace net { 18 namespace net {
19 19
20 namespace { 20 namespace test {
21 21
22 using base::StringPiece; 22 using base::StringPiece;
23 using std::string; 23 using std::string;
24 using test::a2b_hex; 24 using test::a2b_hex;
25 25
26 const size_t kLiteralBound = 1024; 26 const size_t kLiteralBound = 1024;
27 27
28 // Hex representation of encoded length and Huffman string. 28 // Hex representation of encoded length and Huffman string.
29 const char kEncodedHuffmanFixture[] = 29 const char kEncodedHuffmanFixture[] =
30 "2d" // Length prefix. 30 "2d" // Length prefix.
31 "94e7821dd7f2e6c7b335dfdfcd5b3960" 31 "94e7821dd7f2e6c7b335dfdfcd5b3960"
32 "d5af27087f3672c1ab270fb5291f9587" 32 "d5af27087f3672c1ab270fb5291f9587"
33 "316065c003ed4ee5b1063d5007"; 33 "316065c003ed4ee5b1063d5007";
34 34
35 const char kDecodedHuffmanFixture[] = 35 const char kDecodedHuffmanFixture[] =
36 "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1"; 36 "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1";
37 37
38 class HpackInputStreamPeer {
39 public:
40 explicit HpackInputStreamPeer(HpackInputStream* input_stream)
41 : input_stream_(input_stream) {}
42
43 void SetBitOffsetForTest(size_t bit_offset) {
44 input_stream_->bit_offset_ = bit_offset;
45 }
46
47 uint32_t ParsedBytesCurrent() { return input_stream_->parsed_bytes_current_; }
48
49 private:
50 HpackInputStream* input_stream_;
51 };
52
38 // Utility function to decode an assumed-valid uint32_t with an N-bit 53 // Utility function to decode an assumed-valid uint32_t with an N-bit
39 // prefix. 54 // prefix.
40 uint32_t DecodeValidUint32(uint8_t N, StringPiece str) { 55 uint32_t DecodeValidUint32(uint8_t N, StringPiece str) {
41 EXPECT_GT(N, 0); 56 EXPECT_GT(N, 0);
42 EXPECT_LE(N, 8); 57 EXPECT_LE(N, 8);
43 HpackInputStream input_stream(kLiteralBound, str); 58 HpackInputStream input_stream(kLiteralBound, str);
44 input_stream.SetBitOffsetForTest(8 - N); 59 HpackInputStreamPeer input_stream_peer(&input_stream);
60 input_stream_peer.SetBitOffsetForTest(8 - N);
45 uint32_t I; 61 uint32_t I;
46 EXPECT_TRUE(input_stream.DecodeNextUint32(&I)); 62 EXPECT_TRUE(input_stream.DecodeNextUint32(&I));
63 EXPECT_EQ(str.size(), input_stream_peer.ParsedBytesCurrent());
64 EXPECT_FALSE(input_stream.NeedMoreData());
47 return I; 65 return I;
48 } 66 }
49 67
50 // Utility function to decode an assumed-invalid uint32_t with an N-bit 68 // Utility function to decode an assumed-invalid uint32_t with an N-bit
51 // prefix. 69 // prefix.
52 void ExpectDecodeUint32Invalid(uint8_t N, StringPiece str) { 70 void ExpectDecodeUint32Invalid(uint8_t N, StringPiece str) {
53 EXPECT_GT(N, 0); 71 EXPECT_GT(N, 0);
54 EXPECT_LE(N, 8); 72 EXPECT_LE(N, 8);
55 HpackInputStream input_stream(kLiteralBound, str); 73 HpackInputStream input_stream(kLiteralBound, str);
56 input_stream.SetBitOffsetForTest(8 - N); 74 HpackInputStreamPeer input_stream_peer(&input_stream);
75 input_stream_peer.SetBitOffsetForTest(8 - N);
57 uint32_t I; 76 uint32_t I;
58 EXPECT_FALSE(input_stream.DecodeNextUint32(&I)); 77 EXPECT_FALSE(input_stream.DecodeNextUint32(&I));
59 } 78 }
60 79
61 uint32_t bits32(const string& bitstring) { 80 uint32_t bits32(const string& bitstring) {
62 return std::bitset<32>(bitstring).to_ulong(); 81 return std::bitset<32>(bitstring).to_ulong();
63 } 82 }
64 83
65 // The {Number}ByteIntegersEightBitPrefix tests below test that 84 // The {Number}ByteIntegersEightBitPrefix tests below test that
66 // certain integers are decoded correctly with an 8-bit prefix in 85 // certain integers are decoded correctly with an 8-bit prefix in
(...skipping 404 matching lines...) Expand 10 before | Expand all | Expand 10 after
471 ExpectDecodeUint32Invalid(2, "\x03\x80\x80\x80\x80\x80\x01"); 490 ExpectDecodeUint32Invalid(2, "\x03\x80\x80\x80\x80\x80\x01");
472 ExpectDecodeUint32Invalid(2, "\xff\xff\xff\xff\xff\xff\xff"); 491 ExpectDecodeUint32Invalid(2, "\xff\xff\xff\xff\xff\xff\xff");
473 ExpectDecodeUint32Invalid(1, "\x01\x80\x80\x80\x80\x80\x00"); 492 ExpectDecodeUint32Invalid(1, "\x01\x80\x80\x80\x80\x80\x00");
474 ExpectDecodeUint32Invalid(1, "\x01\x80\x80\x80\x80\x80\x01"); 493 ExpectDecodeUint32Invalid(1, "\x01\x80\x80\x80\x80\x80\x01");
475 ExpectDecodeUint32Invalid(1, "\xff\xff\xff\xff\xff\xff\xff"); 494 ExpectDecodeUint32Invalid(1, "\xff\xff\xff\xff\xff\xff\xff");
476 } 495 }
477 496
478 // Decoding a valid encoded string literal should work. 497 // Decoding a valid encoded string literal should work.
479 TEST(HpackInputStreamTest, DecodeNextIdentityString) { 498 TEST(HpackInputStreamTest, DecodeNextIdentityString) {
480 HpackInputStream input_stream(kLiteralBound, "\x0estring literal"); 499 HpackInputStream input_stream(kLiteralBound, "\x0estring literal");
500 HpackInputStreamPeer input_stream_peer(&input_stream);
481 501
482 EXPECT_TRUE(input_stream.HasMoreData()); 502 EXPECT_TRUE(input_stream.HasMoreData());
483 StringPiece string_piece; 503 StringPiece string_piece;
484 EXPECT_TRUE(input_stream.DecodeNextIdentityString(&string_piece)); 504 EXPECT_TRUE(input_stream.DecodeNextIdentityString(&string_piece));
485 EXPECT_EQ("string literal", string_piece); 505 EXPECT_EQ("string literal", string_piece);
486 EXPECT_FALSE(input_stream.HasMoreData()); 506 EXPECT_FALSE(input_stream.HasMoreData());
507 EXPECT_EQ(string_piece.size() + 1, input_stream_peer.ParsedBytesCurrent());
508 EXPECT_FALSE(input_stream.NeedMoreData());
487 } 509 }
488 510
489 // Decoding an encoded string literal with size larger than 511 // Decoding an encoded string literal with size larger than
490 // |max_string_literal_size_| should fail. 512 // |max_string_literal_size_| should fail.
491 TEST(HpackInputStreamTest, DecodeNextIdentityStringSizeLimit) { 513 TEST(HpackInputStreamTest, DecodeNextIdentityStringSizeLimit) {
492 HpackInputStream input_stream(13, "\x0estring literal"); 514 HpackInputStream input_stream(13, "\x0estring literal");
493 515
494 EXPECT_TRUE(input_stream.HasMoreData()); 516 EXPECT_TRUE(input_stream.HasMoreData());
495 StringPiece string_piece; 517 StringPiece string_piece;
496 EXPECT_FALSE(input_stream.DecodeNextIdentityString(&string_piece)); 518 EXPECT_FALSE(input_stream.DecodeNextIdentityString(&string_piece));
519 EXPECT_FALSE(input_stream.NeedMoreData());
497 } 520 }
498 521
499 // Decoding an encoded string literal with size larger than the 522 // Decoding an encoded string literal with size larger than the
500 // remainder of the buffer should fail. 523 // remainder of the buffer should fail.
501 TEST(HpackInputStreamTest, DecodeNextIdentityStringNotEnoughInput) { 524 TEST(HpackInputStreamTest, DecodeNextIdentityStringNotEnoughInput) {
502 // Set the length to be one more than it should be. 525 // Set the length to be one more than it should be.
503 HpackInputStream input_stream(kLiteralBound, "\x0fstring literal"); 526 HpackInputStream input_stream(kLiteralBound, "\x0fstring literal");
504 527
505 EXPECT_TRUE(input_stream.HasMoreData()); 528 EXPECT_TRUE(input_stream.HasMoreData());
506 StringPiece string_piece; 529 StringPiece string_piece;
507 EXPECT_FALSE(input_stream.DecodeNextIdentityString(&string_piece)); 530 EXPECT_FALSE(input_stream.DecodeNextIdentityString(&string_piece));
531 EXPECT_TRUE(input_stream.NeedMoreData());
508 } 532 }
509 533
510 TEST(HpackInputStreamTest, DecodeNextHuffmanString) { 534 TEST(HpackInputStreamTest, DecodeNextHuffmanString) {
511 string output, input(a2b_hex(kEncodedHuffmanFixture)); 535 string output, input(a2b_hex(kEncodedHuffmanFixture));
512 HpackInputStream input_stream(arraysize(kDecodedHuffmanFixture) - 1, input); 536 HpackInputStream input_stream(arraysize(kDecodedHuffmanFixture) - 1, input);
537 HpackInputStreamPeer input_stream_peer(&input_stream);
513 538
514 EXPECT_TRUE(input_stream.HasMoreData()); 539 EXPECT_TRUE(input_stream.HasMoreData());
515 EXPECT_TRUE(input_stream.DecodeNextHuffmanString(&output)); 540 EXPECT_TRUE(input_stream.DecodeNextHuffmanString(&output));
516 EXPECT_EQ(kDecodedHuffmanFixture, output); 541 EXPECT_EQ(kDecodedHuffmanFixture, output);
517 EXPECT_FALSE(input_stream.HasMoreData()); 542 EXPECT_FALSE(input_stream.HasMoreData());
543 EXPECT_FALSE(input_stream.NeedMoreData());
544 EXPECT_EQ(46u, input_stream_peer.ParsedBytesCurrent());
518 } 545 }
519 546
520 TEST(HpackInputStreamTest, DecodeNextHuffmanStringSizeLimit) { 547 TEST(HpackInputStreamTest, DecodeNextHuffmanStringSizeLimit) {
521 string output, input(a2b_hex(kEncodedHuffmanFixture)); 548 string output, input(a2b_hex(kEncodedHuffmanFixture));
522 // Max string literal is one byte shorter than the decoded fixture. 549 // Max string literal is one byte shorter than the decoded fixture.
523 HpackInputStream input_stream(arraysize(kDecodedHuffmanFixture) - 2, input); 550 HpackInputStream input_stream(arraysize(kDecodedHuffmanFixture) - 2, input);
524 551
525 // Decoded string overflows the max string literal. 552 // Decoded string overflows the max string literal.
526 EXPECT_TRUE(input_stream.HasMoreData()); 553 EXPECT_TRUE(input_stream.HasMoreData());
527 EXPECT_FALSE(input_stream.DecodeNextHuffmanString(&output)); 554 EXPECT_FALSE(input_stream.DecodeNextHuffmanString(&output));
555 EXPECT_FALSE(input_stream.NeedMoreData());
528 } 556 }
529 557
530 TEST(HpackInputStreamTest, DecodeNextHuffmanStringNotEnoughInput) { 558 TEST(HpackInputStreamTest, DecodeNextHuffmanStringNotEnoughInput) {
531 string output, input(a2b_hex(kEncodedHuffmanFixture)); 559 string output, input(a2b_hex(kEncodedHuffmanFixture));
532 input[0]++; // Input prefix is one byte larger than available input. 560 input[0]++; // Input prefix is one byte larger than available input.
533 HpackInputStream input_stream(arraysize(kDecodedHuffmanFixture) - 1, input); 561 HpackInputStream input_stream(arraysize(kDecodedHuffmanFixture) - 1, input);
534 562
535 // Not enough buffer for declared encoded length. 563 // Not enough buffer for declared encoded length.
536 EXPECT_TRUE(input_stream.HasMoreData()); 564 EXPECT_TRUE(input_stream.HasMoreData());
537 EXPECT_FALSE(input_stream.DecodeNextHuffmanString(&output)); 565 EXPECT_FALSE(input_stream.DecodeNextHuffmanString(&output));
566 EXPECT_TRUE(input_stream.NeedMoreData());
538 } 567 }
539 568
540 TEST(HpackInputStreamTest, PeekBitsAndConsume) { 569 TEST(HpackInputStreamTest, PeekBitsAndConsume) {
541 HpackInputStream input_stream(kLiteralBound, "\xad\xab\xad\xab\xad"); 570 HpackInputStream input_stream(kLiteralBound, "\xad\xab\xad\xab\xad");
542 571
543 uint32_t bits = 0; 572 uint32_t bits = 0;
544 size_t peeked_count = 0; 573 size_t peeked_count = 0;
545 574
546 // Read 0xad. 575 // Read 0xad.
547 EXPECT_TRUE(input_stream.PeekBits(&peeked_count, &bits)); 576 EXPECT_TRUE(input_stream.PeekBits(&peeked_count, &bits));
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after
698 input_stream.ConsumeBits(3); 727 input_stream.ConsumeBits(3);
699 input_stream.ConsumeByteRemainder(); 728 input_stream.ConsumeByteRemainder();
700 EXPECT_TRUE(input_stream.HasMoreData()); 729 EXPECT_TRUE(input_stream.HasMoreData());
701 730
702 input_stream.ConsumeBits(6); 731 input_stream.ConsumeBits(6);
703 EXPECT_TRUE(input_stream.HasMoreData()); 732 EXPECT_TRUE(input_stream.HasMoreData());
704 input_stream.ConsumeByteRemainder(); 733 input_stream.ConsumeByteRemainder();
705 EXPECT_FALSE(input_stream.HasMoreData()); 734 EXPECT_FALSE(input_stream.HasMoreData());
706 } 735 }
707 736
708 } // namespace 737 TEST(HpackInputStreamTest, IncompleteHeaderMatchPrefixAndConsume) {
738 HpackInputStream input_stream(kLiteralBound, "");
739 HpackInputStreamPeer input_stream_peer(&input_stream);
740 EXPECT_FALSE(input_stream.MatchPrefixAndConsume(kIndexedOpcode));
741 EXPECT_EQ(0u, input_stream_peer.ParsedBytesCurrent());
742 EXPECT_TRUE(input_stream.NeedMoreData());
743 }
744
745 TEST(HpackInputStreamTest, IncompleteHeaderDecodeNextUint32) {
746 // First byte only
747 HpackInputStream input_stream1(kLiteralBound, "\xff");
748 HpackInputStreamPeer input_stream1_peer(&input_stream1);
749 EXPECT_TRUE(input_stream1.MatchPrefixAndConsume(kIndexedOpcode));
750 uint32_t result;
751 EXPECT_FALSE(input_stream1.DecodeNextUint32(&result));
752 EXPECT_TRUE(input_stream1.NeedMoreData());
753 EXPECT_EQ(1u, input_stream1_peer.ParsedBytesCurrent());
754
755 // No last byte
756 HpackInputStream input_stream2(kLiteralBound, "\xff\x80\x80\x80");
757 HpackInputStreamPeer input_stream2_peer(&input_stream2);
758 EXPECT_TRUE(input_stream2.MatchPrefixAndConsume(kIndexedOpcode));
759 EXPECT_FALSE(input_stream2.DecodeNextUint32(&result));
760 EXPECT_TRUE(input_stream2.NeedMoreData());
761 EXPECT_EQ(4u, input_stream2_peer.ParsedBytesCurrent());
762
763 // Error happens before finishing parsing.
764 HpackInputStream input_stream3(kLiteralBound, "\xff\xff\xff\xff\xff\xff\xff");
765 HpackInputStreamPeer input_stream3_peer(&input_stream3);
766 EXPECT_TRUE(input_stream3.MatchPrefixAndConsume(kIndexedOpcode));
767 EXPECT_FALSE(input_stream3.DecodeNextUint32(&result));
768 EXPECT_FALSE(input_stream3.NeedMoreData());
769 EXPECT_EQ(6u, input_stream3_peer.ParsedBytesCurrent());
770 }
771
772 TEST(HpackInputStreamTest, IncompleteHeaderDecodeNextIdentityString) {
773 HpackInputStream input_stream1(kLiteralBound, "\x0estring litera");
774 HpackInputStreamPeer input_stream1_peer(&input_stream1);
775 StringPiece string_piece;
776 EXPECT_FALSE(input_stream1.DecodeNextIdentityString(&string_piece));
777 // Only parsed first byte.
778 EXPECT_EQ(1u, input_stream1_peer.ParsedBytesCurrent());
779 EXPECT_TRUE(input_stream1.NeedMoreData());
780
781 HpackInputStream input_stream2(kLiteralBound, "\x0e");
782 HpackInputStreamPeer input_stream2_peer(&input_stream2);
783 EXPECT_FALSE(input_stream2.DecodeNextIdentityString(&string_piece));
784 // Only parsed first byte.
785 EXPECT_EQ(1u, input_stream2_peer.ParsedBytesCurrent());
786 EXPECT_TRUE(input_stream2.NeedMoreData());
787 }
788
789 TEST(HpackInputStreamTest, IncompleteHeaderDecodeNextHuffmanString) {
790 string output, input(a2b_hex(kEncodedHuffmanFixture));
791 input.resize(input.size() - 1); // Remove last byte.
792 HpackInputStream input_stream1(arraysize(kDecodedHuffmanFixture) - 1, input);
793 HpackInputStreamPeer input_stream1_peer(&input_stream1);
794 EXPECT_FALSE(input_stream1.DecodeNextHuffmanString(&output));
795 EXPECT_EQ(1u, input_stream1_peer.ParsedBytesCurrent());
796 EXPECT_TRUE(input_stream1.NeedMoreData());
797
798 input.erase(1, input.size()); // Remove all bytes except the first one.
799 HpackInputStream input_stream2(arraysize(kDecodedHuffmanFixture) - 1, input);
800 HpackInputStreamPeer input_stream2_peer(&input_stream2);
801 EXPECT_FALSE(input_stream2.DecodeNextHuffmanString(&output));
802 EXPECT_EQ(1u, input_stream2_peer.ParsedBytesCurrent());
803 EXPECT_TRUE(input_stream2.NeedMoreData());
804 }
805
806 } // namespace test
709 807
710 } // namespace net 808 } // namespace net
OLDNEW
« no previous file with comments | « net/spdy/hpack/hpack_input_stream.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698