1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "quiche/http2/hpack/decoder/hpack_string_decoder.h"
6 
7 // Tests of HpackStringDecoder.
8 
9 #include "absl/strings/string_view.h"
10 #include "quiche/http2/hpack/decoder/hpack_string_decoder_listener.h"
11 #include "quiche/http2/test_tools/hpack_block_builder.h"
12 #include "quiche/http2/test_tools/hpack_string_collector.h"
13 #include "quiche/http2/test_tools/http2_random.h"
14 #include "quiche/http2/test_tools/random_decoder_test_base.h"
15 #include "quiche/http2/test_tools/verify_macros.h"
16 #include "quiche/common/platform/api/quiche_test.h"
17 
18 namespace http2 {
19 namespace test {
20 namespace {
21 
22 const bool kMayReturnZeroOnFirst = false;
23 const bool kCompressed = true;
24 const bool kUncompressed = false;
25 
26 class HpackStringDecoderTest : public RandomDecoderTest {
27  protected:
HpackStringDecoderTest()28   HpackStringDecoderTest() : listener_(&collector_) {}
29 
StartDecoding(DecodeBuffer * b)30   DecodeStatus StartDecoding(DecodeBuffer* b) override {
31     ++start_decoding_calls_;
32     collector_.Clear();
33     return decoder_.Start(b, &listener_);
34   }
35 
ResumeDecoding(DecodeBuffer * b)36   DecodeStatus ResumeDecoding(DecodeBuffer* b) override {
37     // Provides coverage of DebugString and StateToString.
38     // Not validating output.
39     QUICHE_VLOG(1) << decoder_.DebugString();
40     QUICHE_VLOG(2) << collector_;
41     return decoder_.Resume(b, &listener_);
42   }
43 
Collected(absl::string_view s,bool huffman_encoded)44   AssertionResult Collected(absl::string_view s, bool huffman_encoded) {
45     QUICHE_VLOG(1) << collector_;
46     return collector_.Collected(s, huffman_encoded);
47   }
48 
49   // expected_str is a std::string rather than a const std::string& or
50   // absl::string_view so that the lambda makes a copy of the string, and thus
51   // the string to be passed to Collected outlives the call to MakeValidator.
MakeValidator(const std::string & expected_str,bool expected_huffman)52   Validator MakeValidator(const std::string& expected_str,
53                           bool expected_huffman) {
54     return [expected_str, expected_huffman, this](
55                const DecodeBuffer& /*input*/,
56                DecodeStatus /*status*/) -> AssertionResult {
57       AssertionResult result = Collected(expected_str, expected_huffman);
58       if (result) {
59         HTTP2_VERIFY_EQ(collector_,
60                         HpackStringCollector(expected_str, expected_huffman));
61       } else {
62         HTTP2_VERIFY_NE(collector_,
63                         HpackStringCollector(expected_str, expected_huffman));
64       }
65       QUICHE_VLOG(2) << collector_.ToString();
66       collector_.Clear();
67       QUICHE_VLOG(2) << collector_;
68       return result;
69     };
70   }
71 
72   HpackStringDecoder decoder_;
73   HpackStringCollector collector_;
74   HpackStringDecoderVLoggingListener listener_;
75   size_t start_decoding_calls_ = 0;
76 };
77 
TEST_F(HpackStringDecoderTest,DecodeEmptyString)78 TEST_F(HpackStringDecoderTest, DecodeEmptyString) {
79   {
80     Validator validator = ValidateDoneAndEmpty(MakeValidator("", kCompressed));
81     const char kData[] = {'\x80'};
82     DecodeBuffer b(kData);
83     EXPECT_TRUE(
84         DecodeAndValidateSeveralWays(&b, kMayReturnZeroOnFirst, validator));
85   }
86   {
87     // Make sure it stops after decoding the empty string.
88     Validator validator =
89         ValidateDoneAndOffset(1, MakeValidator("", kUncompressed));
90     const char kData[] = {'\x00', '\xff'};
91     DecodeBuffer b(kData);
92     EXPECT_EQ(2u, b.Remaining());
93     EXPECT_TRUE(
94         DecodeAndValidateSeveralWays(&b, kMayReturnZeroOnFirst, validator));
95     EXPECT_EQ(1u, b.Remaining());
96   }
97 }
98 
TEST_F(HpackStringDecoderTest,DecodeShortString)99 TEST_F(HpackStringDecoderTest, DecodeShortString) {
100   {
101     // Make sure it stops after decoding the non-empty string.
102     Validator validator =
103         ValidateDoneAndOffset(11, MakeValidator("start end.", kCompressed));
104     const char kData[] = "\x8astart end.Don't peek at this.";
105     DecodeBuffer b(kData);
106     EXPECT_TRUE(
107         DecodeAndValidateSeveralWays(&b, kMayReturnZeroOnFirst, validator));
108   }
109   {
110     Validator validator =
111         ValidateDoneAndOffset(11, MakeValidator("start end.", kUncompressed));
112     absl::string_view data("\x0astart end.");
113     DecodeBuffer b(data);
114     EXPECT_TRUE(
115         DecodeAndValidateSeveralWays(&b, kMayReturnZeroOnFirst, validator));
116   }
117 }
118 
TEST_F(HpackStringDecoderTest,DecodeLongStrings)119 TEST_F(HpackStringDecoderTest, DecodeLongStrings) {
120   std::string name = Random().RandString(1024);
121   std::string value = Random().RandString(65536);
122   HpackBlockBuilder hbb;
123 
124   hbb.AppendString(false, name);
125   uint32_t offset_after_name = hbb.size();
126   EXPECT_EQ(3 + name.size(), offset_after_name);
127 
128   hbb.AppendString(true, value);
129   uint32_t offset_after_value = hbb.size();
130   EXPECT_EQ(3 + name.size() + 4 + value.size(), offset_after_value);
131 
132   DecodeBuffer b(hbb.buffer());
133 
134   // Decode the name...
135   EXPECT_TRUE(DecodeAndValidateSeveralWays(
136       &b, kMayReturnZeroOnFirst,
137       ValidateDoneAndOffset(offset_after_name,
138                             MakeValidator(name, kUncompressed))));
139   EXPECT_EQ(offset_after_name, b.Offset());
140   EXPECT_EQ(offset_after_value - offset_after_name, b.Remaining());
141 
142   // Decode the value...
143   EXPECT_TRUE(DecodeAndValidateSeveralWays(
144       &b, kMayReturnZeroOnFirst,
145       ValidateDoneAndOffset(offset_after_value - offset_after_name,
146                             MakeValidator(value, kCompressed))));
147   EXPECT_EQ(offset_after_value, b.Offset());
148   EXPECT_EQ(0u, b.Remaining());
149 }
150 
151 }  // namespace
152 }  // namespace test
153 }  // namespace http2
154