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_entry_decoder.h" | |
6 | |
7 // Tests of HpackEntryDecoder. | |
8 | |
9 #include "base/bind.h" | |
10 #include "base/bind_helpers.h" | |
11 #include "net/http2/hpack/decoder/hpack_entry_collector.h" | |
12 #include "net/http2/hpack/tools/hpack_block_builder.h" | |
13 #include "net/http2/tools/failure.h" | |
14 #include "net/http2/tools/http2_random.h" | |
15 #include "net/http2/tools/random_decoder_test.h" | |
16 #include "testing/gtest/include/gtest/gtest.h" | |
17 | |
18 using ::testing::AssertionResult; | |
19 using std::string; | |
20 | |
21 namespace net { | |
22 namespace test { | |
23 namespace { | |
24 | |
25 class HpackEntryDecoderTest : public RandomDecoderTest { | |
26 public: | |
27 AssertionResult ValidateIndexedHeader(uint32_t ndx) { | |
28 VERIFY_AND_RETURN_SUCCESS(collector_.ValidateIndexedHeader(ndx)); | |
29 } | |
30 | |
31 AssertionResult ValidateForIndexedLiteralValue_Literal() { | |
32 VERIFY_AND_RETURN_SUCCESS(collector_.ValidateLiteralValueHeader( | |
33 HpackEntryType::kIndexedLiteralHeader, 0x40, false, "custom-header")); | |
34 } | |
35 | |
36 AssertionResult ValidateForIndexedLiteralNameValue_Literal() { | |
37 VERIFY_AND_RETURN_SUCCESS(collector_.ValidateLiteralNameValueHeader( | |
38 HpackEntryType::kIndexedLiteralHeader, false, "custom-key", false, | |
39 "custom-header")); | |
40 } | |
41 | |
42 AssertionResult ValidateForDynamicTableSizeUpdate_Literal() { | |
43 VERIFY_AND_RETURN_SUCCESS(collector_.ValidateDynamicTableSizeUpdate(31)); | |
44 } | |
45 | |
46 protected: | |
47 HpackEntryDecoderTest() : listener_(&collector_) {} | |
48 | |
49 DecodeStatus StartDecoding(DecodeBuffer* b) override { | |
50 collector_.Clear(); | |
51 return decoder_.Start(b, &listener_); | |
52 } | |
53 | |
54 DecodeStatus ResumeDecoding(DecodeBuffer* b) override { | |
55 return decoder_.Resume(b, &listener_); | |
56 } | |
57 | |
58 AssertionResult DecodeAndValidateSeveralWays(DecodeBuffer* db, | |
59 Validator validator) { | |
60 // StartDecoding, above, requires the DecodeBuffer be non-empty so that it | |
61 // can call Start with the prefix byte. | |
62 bool return_non_zero_on_first = true; | |
63 return RandomDecoderTest::DecodeAndValidateSeveralWays( | |
64 db, return_non_zero_on_first, validator); | |
65 } | |
66 | |
67 AssertionResult DecodeAndValidateSeveralWays(const HpackBlockBuilder& hbb, | |
68 Validator validator) { | |
69 DecodeBuffer db(hbb.buffer()); | |
70 return DecodeAndValidateSeveralWays(&db, validator); | |
71 } | |
72 | |
73 HpackEntryDecoder decoder_; | |
74 HpackEntryCollector collector_; | |
75 HpackEntryDecoderVLoggingListener listener_; | |
76 }; | |
77 | |
78 TEST_F(HpackEntryDecoderTest, IndexedHeader_Literals) { | |
79 { | |
80 const char input[] = {0x82u}; // == Index 2 == | |
81 DecodeBuffer b(input); | |
82 NoArgValidator do_check = | |
83 base::Bind(&HpackEntryDecoderTest::ValidateIndexedHeader, | |
84 base::Unretained(this), 2); | |
85 EXPECT_TRUE( | |
86 DecodeAndValidateSeveralWays(&b, ValidateDoneAndEmpty(do_check))); | |
87 EXPECT_TRUE(do_check.Run()); | |
88 } | |
89 collector_.Clear(); | |
90 { | |
91 const char input[] = {0xfeu}; // == Index 126 == | |
92 DecodeBuffer b(input); | |
93 NoArgValidator do_check = | |
94 base::Bind(&HpackEntryDecoderTest::ValidateIndexedHeader, | |
95 base::Unretained(this), 126); | |
96 EXPECT_TRUE( | |
97 DecodeAndValidateSeveralWays(&b, ValidateDoneAndEmpty(do_check))); | |
98 EXPECT_TRUE(do_check.Run()); | |
99 } | |
100 collector_.Clear(); | |
101 { | |
102 const char input[] = {0xffu, 0x00}; // == Index 127 == | |
103 DecodeBuffer b(input); | |
104 NoArgValidator do_check = | |
105 base::Bind(&HpackEntryDecoderTest::ValidateIndexedHeader, | |
106 base::Unretained(this), 127); | |
107 EXPECT_TRUE( | |
108 DecodeAndValidateSeveralWays(&b, ValidateDoneAndEmpty(do_check))); | |
109 EXPECT_TRUE(do_check.Run()); | |
110 } | |
111 } | |
112 | |
113 TEST_F(HpackEntryDecoderTest, IndexedHeader_Various) { | |
114 // Indices chosen to hit encoding and table boundaries. | |
115 for (const uint32_t ndx : {1, 2, 61, 62, 63, 126, 127, 254, 255, 256}) { | |
116 HpackBlockBuilder hbb; | |
117 hbb.AppendIndexedHeader(ndx); | |
118 | |
119 NoArgValidator do_check = | |
120 base::Bind(&HpackEntryDecoderTest::ValidateIndexedHeader, | |
121 base::Unretained(this), ndx); | |
122 EXPECT_TRUE( | |
123 DecodeAndValidateSeveralWays(hbb, ValidateDoneAndEmpty(do_check))); | |
124 EXPECT_TRUE(do_check.Run()); | |
125 } | |
126 } | |
127 | |
128 TEST_F(HpackEntryDecoderTest, IndexedLiteralValue_Literal) { | |
129 const char input[] = | |
130 "\x7f" // == Literal indexed, name index 0x40 == | |
131 "\x01" // 2nd byte of name index (0x01 + 0x3f == 0x40) | |
132 "\x0d" // Value length (13) | |
133 "custom-header"; // Value | |
134 DecodeBuffer b(input, sizeof input - 1); | |
135 NoArgValidator do_check = | |
136 base::Bind(&HpackEntryDecoderTest::ValidateForIndexedLiteralValue_Literal, | |
137 base::Unretained(this)); | |
138 EXPECT_TRUE(DecodeAndValidateSeveralWays(&b, ValidateDoneAndEmpty(do_check))); | |
139 EXPECT_TRUE(do_check.Run()); | |
140 } | |
141 | |
142 TEST_F(HpackEntryDecoderTest, IndexedLiteralNameValue_Literal) { | |
143 const char input[] = | |
144 "\x40" // == Literal indexed == | |
145 "\x0a" // Name length (10) | |
146 "custom-key" // Name | |
147 "\x0d" // Value length (13) | |
148 "custom-header"; // Value | |
149 | |
150 DecodeBuffer b(input, sizeof input - 1); | |
151 NoArgValidator do_check = base::Bind( | |
152 &HpackEntryDecoderTest::ValidateForIndexedLiteralNameValue_Literal, | |
153 base::Unretained(this)); | |
154 EXPECT_TRUE(DecodeAndValidateSeveralWays(&b, ValidateDoneAndEmpty(do_check))); | |
155 EXPECT_TRUE(do_check.Run()); | |
156 } | |
157 | |
158 TEST_F(HpackEntryDecoderTest, DynamicTableSizeUpdate_Literal) { | |
159 // Size update, length 31. | |
160 const char input[] = "\x3f\x00"; | |
161 DecodeBuffer b(input, 2); | |
162 NoArgValidator do_check = base::Bind( | |
163 &HpackEntryDecoderTest::ValidateForDynamicTableSizeUpdate_Literal, | |
164 base::Unretained(this)); | |
165 EXPECT_TRUE(DecodeAndValidateSeveralWays(&b, ValidateDoneAndEmpty(do_check))); | |
166 EXPECT_TRUE(do_check.Run()); | |
167 } | |
168 | |
169 class HpackLiteralEntryDecoderTest | |
170 : public HpackEntryDecoderTest, | |
171 public ::testing::WithParamInterface<HpackEntryType> { | |
172 public: | |
173 AssertionResult ValidateForRandNameIndexAndLiteralValue( | |
174 uint32_t ndx, | |
175 bool value_is_huffman_encoded, | |
176 const string& value) { | |
177 VERIFY_AND_RETURN_SUCCESS(collector_.ValidateLiteralValueHeader( | |
178 entry_type_, ndx, value_is_huffman_encoded, value)); | |
179 } | |
180 | |
181 AssertionResult ValidateForRandLiteralNameAndValue( | |
182 bool name_is_huffman_encoded, | |
183 const string& name, | |
184 bool value_is_huffman_encoded, | |
185 const string& value) { | |
186 VERIFY_AND_RETURN_SUCCESS(collector_.ValidateLiteralNameValueHeader( | |
187 entry_type_, name_is_huffman_encoded, name, value_is_huffman_encoded, | |
188 value)); | |
189 } | |
190 | |
191 protected: | |
192 HpackLiteralEntryDecoderTest() : entry_type_(GetParam()) {} | |
193 | |
194 const HpackEntryType entry_type_; | |
195 }; | |
196 | |
197 INSTANTIATE_TEST_CASE_P( | |
198 AllLiteralTypes, | |
199 HpackLiteralEntryDecoderTest, | |
200 testing::Values(HpackEntryType::kIndexedLiteralHeader, | |
201 HpackEntryType::kUnindexedLiteralHeader, | |
202 HpackEntryType::kNeverIndexedLiteralHeader)); | |
203 | |
204 TEST_P(HpackLiteralEntryDecoderTest, RandNameIndexAndLiteralValue) { | |
205 for (int n = 0; n < 10; n++) { | |
206 const uint32_t ndx = 1 + Random().Rand8(); | |
207 const bool value_is_huffman_encoded = (n % 2) == 0; | |
208 const string value = Random().RandString(Random().Rand8()); | |
209 HpackBlockBuilder hbb; | |
210 hbb.AppendNameIndexAndLiteralValue(entry_type_, ndx, | |
211 value_is_huffman_encoded, value); | |
212 NoArgValidator do_check = base::Bind( | |
213 &HpackLiteralEntryDecoderTest::ValidateForRandNameIndexAndLiteralValue, | |
214 base::Unretained(this), ndx, value_is_huffman_encoded, value); | |
215 EXPECT_TRUE( | |
216 DecodeAndValidateSeveralWays(hbb, ValidateDoneAndEmpty(do_check))); | |
217 EXPECT_TRUE(do_check.Run()); | |
218 } | |
219 } | |
220 | |
221 TEST_P(HpackLiteralEntryDecoderTest, RandLiteralNameAndValue) { | |
222 for (int n = 0; n < 10; n++) { | |
223 const bool name_is_huffman_encoded = (n & 1) == 0; | |
224 const int name_len = 1 + Random().Rand8(); | |
225 const string name = Random().RandString(name_len); | |
226 const bool value_is_huffman_encoded = (n & 2) == 0; | |
227 const int value_len = Random().Skewed(10); | |
228 const string value = Random().RandString(value_len); | |
229 HpackBlockBuilder hbb; | |
230 hbb.AppendLiteralNameAndValue(entry_type_, name_is_huffman_encoded, name, | |
231 value_is_huffman_encoded, value); | |
232 NoArgValidator do_check = base::Bind( | |
233 &HpackLiteralEntryDecoderTest::ValidateForRandLiteralNameAndValue, | |
234 base::Unretained(this), name_is_huffman_encoded, name, | |
235 value_is_huffman_encoded, value); | |
236 EXPECT_TRUE( | |
237 DecodeAndValidateSeveralWays(hbb, ValidateDoneAndEmpty(do_check))); | |
238 EXPECT_TRUE(do_check.Run()); | |
239 } | |
240 } | |
241 | |
242 } // namespace | |
243 } // namespace test | |
244 } // namespace net | |
OLD | NEW |