OLD | NEW |
| (Empty) |
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 "net/http2/hpack/decoder/hpack_string_decoder.h" | |
6 | |
7 // Tests of HpackStringDecoder. | |
8 | |
9 #include "base/bind.h" | |
10 #include "base/bind_helpers.h" | |
11 #include "base/strings/string_piece.h" | |
12 #include "net/http2/hpack/decoder/hpack_string_collector.h" | |
13 #include "net/http2/hpack/decoder/hpack_string_decoder_listener.h" | |
14 #include "net/http2/hpack/tools/hpack_block_builder.h" | |
15 #include "net/http2/tools/failure.h" | |
16 #include "net/http2/tools/http2_random.h" | |
17 #include "net/http2/tools/random_decoder_test.h" | |
18 #include "testing/gtest/include/gtest/gtest.h" | |
19 | |
20 using ::testing::AssertionResult; | |
21 using ::testing::AssertionSuccess; | |
22 using base::StringPiece; | |
23 using std::string; | |
24 | |
25 namespace net { | |
26 namespace test { | |
27 namespace { | |
28 | |
29 const bool kMayReturnZeroOnFirst = false; | |
30 const bool kCompressed = true; | |
31 const bool kUncompressed = false; | |
32 | |
33 enum StartMethod { | |
34 kStart, | |
35 kStartOnly, | |
36 kStartAndDecodeLength, | |
37 kStartSpecialCaseShort, | |
38 }; | |
39 | |
40 class HpackStringDecoderTest | |
41 : public RandomDecoderTest, | |
42 public ::testing::WithParamInterface<StartMethod> { | |
43 protected: | |
44 HpackStringDecoderTest() | |
45 : start_method_(GetParam()), listener_(&collector_) {} | |
46 | |
47 DecodeStatus StartDecoding(DecodeBuffer* b) override { | |
48 ++start_decoding_calls_; | |
49 collector_.Clear(); | |
50 switch (start_method_) { | |
51 case kStart: | |
52 return decoder_.Start(b, &listener_); | |
53 case kStartOnly: | |
54 return decoder_.StartOnly(b, &listener_); | |
55 case kStartAndDecodeLength: | |
56 return decoder_.StartAndDecodeLength(b, &listener_); | |
57 case kStartSpecialCaseShort: | |
58 return decoder_.StartSpecialCaseShort(b, &listener_); | |
59 default: | |
60 return DecodeStatus::kDecodeError; | |
61 } | |
62 } | |
63 | |
64 DecodeStatus ResumeDecoding(DecodeBuffer* b) override { | |
65 // Provides coverage of DebugString and StateToString. | |
66 // Not validating output. | |
67 VLOG(1) << decoder_.DebugString(); | |
68 VLOG(2) << collector_; | |
69 return decoder_.Resume(b, &listener_); | |
70 } | |
71 | |
72 AssertionResult Collected(StringPiece s, bool huffman_encoded) { | |
73 VLOG(1) << collector_; | |
74 return collector_.Collected(s, huffman_encoded); | |
75 } | |
76 | |
77 // Note that base::Bind() makes a copy of |expected_str| even though it is | |
78 // taken as a constant reference, so even if MakeValidator is called with a | |
79 // C-style string that is cast to a temporary std::string that gets destroyed | |
80 // after the call to MakeValidator, |expected_str| is still valid later when | |
81 // the Validator is run. | |
82 AssertionResult StringValidator(const string& expected_str, | |
83 bool expected_huffman, | |
84 const DecodeBuffer& input, | |
85 DecodeStatus status) { | |
86 AssertionResult result = Collected(expected_str, expected_huffman); | |
87 if (result) { | |
88 VERIFY_EQ(collector_, | |
89 HpackStringCollector(expected_str, expected_huffman)); | |
90 } else { | |
91 VERIFY_NE(collector_, | |
92 HpackStringCollector(expected_str, expected_huffman)); | |
93 } | |
94 VLOG(2) << collector_.ToString(); | |
95 collector_.Clear(); | |
96 VLOG(2) << collector_; | |
97 return result; | |
98 } | |
99 | |
100 Validator MakeValidator(const string& expected_str, bool expected_huffman) { | |
101 return base::Bind(&HpackStringDecoderTest::StringValidator, | |
102 base::Unretained(this), expected_str, expected_huffman); | |
103 } | |
104 | |
105 const StartMethod start_method_; | |
106 HpackStringDecoder decoder_; | |
107 HpackStringCollector collector_; | |
108 HpackStringDecoderVLoggingListener listener_; | |
109 size_t start_decoding_calls_ = 0; | |
110 }; | |
111 | |
112 TEST_P(HpackStringDecoderTest, DecodeEmptyString) { | |
113 { | |
114 Validator validator = ValidateDoneAndEmpty(MakeValidator("", kCompressed)); | |
115 const char kData[] = {0x80u}; | |
116 DecodeBuffer b(kData); | |
117 EXPECT_TRUE( | |
118 DecodeAndValidateSeveralWays(&b, kMayReturnZeroOnFirst, validator)); | |
119 } | |
120 { | |
121 // Make sure it stops after decoding the empty string. | |
122 Validator validator = | |
123 ValidateDoneAndOffset(1, MakeValidator("", kUncompressed)); | |
124 const char kData[] = {0x00, 0xffu}; | |
125 DecodeBuffer b(kData); | |
126 EXPECT_EQ(2u, b.Remaining()); | |
127 EXPECT_TRUE( | |
128 DecodeAndValidateSeveralWays(&b, kMayReturnZeroOnFirst, validator)); | |
129 EXPECT_EQ(1u, b.Remaining()); | |
130 } | |
131 } | |
132 | |
133 TEST_P(HpackStringDecoderTest, DecodeShortString) { | |
134 { | |
135 // Make sure it stops after decoding the non-empty string. | |
136 Validator validator = | |
137 ValidateDoneAndOffset(11, MakeValidator("start end.", kCompressed)); | |
138 const char kData[] = "\x8astart end.Don't peek at this."; | |
139 DecodeBuffer b(kData); | |
140 EXPECT_TRUE( | |
141 DecodeAndValidateSeveralWays(&b, kMayReturnZeroOnFirst, validator)); | |
142 } | |
143 { | |
144 Validator validator = | |
145 ValidateDoneAndOffset(11, MakeValidator("start end.", kUncompressed)); | |
146 StringPiece data("\x0astart end."); | |
147 DecodeBuffer b(data); | |
148 EXPECT_TRUE( | |
149 DecodeAndValidateSeveralWays(&b, kMayReturnZeroOnFirst, validator)); | |
150 } | |
151 } | |
152 | |
153 TEST_P(HpackStringDecoderTest, DecodeLongStrings) { | |
154 string name = Random().RandString(1024); | |
155 string value = Random().RandString(65536); | |
156 HpackBlockBuilder hbb; | |
157 | |
158 hbb.AppendString(false, name); | |
159 uint32_t offset_after_name = hbb.size(); | |
160 EXPECT_EQ(3 + name.size(), offset_after_name); | |
161 | |
162 hbb.AppendString(true, value); | |
163 uint32_t offset_after_value = hbb.size(); | |
164 EXPECT_EQ(3 + name.size() + 4 + value.size(), offset_after_value); | |
165 | |
166 DecodeBuffer b(hbb.buffer()); | |
167 | |
168 // Decode the name... | |
169 EXPECT_TRUE(DecodeAndValidateSeveralWays( | |
170 &b, kMayReturnZeroOnFirst, | |
171 ValidateDoneAndOffset(offset_after_name, | |
172 MakeValidator(name, kUncompressed)))); | |
173 EXPECT_EQ(offset_after_name, b.Offset()); | |
174 EXPECT_EQ(offset_after_value - offset_after_name, b.Remaining()); | |
175 | |
176 // Decode the value... | |
177 EXPECT_TRUE(DecodeAndValidateSeveralWays( | |
178 &b, kMayReturnZeroOnFirst, | |
179 ValidateDoneAndOffset(offset_after_value - offset_after_name, | |
180 MakeValidator(value, kCompressed)))); | |
181 EXPECT_EQ(offset_after_value, b.Offset()); | |
182 EXPECT_EQ(0u, b.Remaining()); | |
183 } | |
184 | |
185 INSTANTIATE_TEST_CASE_P(AllStartMethods, | |
186 HpackStringDecoderTest, | |
187 ::testing::Values(kStart, | |
188 kStartOnly, | |
189 kStartAndDecodeLength, | |
190 kStartSpecialCaseShort)); | |
191 | |
192 } // namespace | |
193 } // namespace test | |
194 } // namespace net | |
OLD | NEW |