OLD | NEW |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 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 | 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 #ifndef NET_HTTP2_TOOLS_RANDOM_DECODER_TEST_H_ | 5 #ifndef NET_HTTP2_TOOLS_RANDOM_DECODER_TEST_H_ |
6 #define NET_HTTP2_TOOLS_RANDOM_DECODER_TEST_H_ | 6 #define NET_HTTP2_TOOLS_RANDOM_DECODER_TEST_H_ |
7 | 7 |
8 // RandomDecoderTest is a base class for tests of decoding various kinds | 8 // RandomDecoderTest is a base class for tests of decoding various kinds |
9 // of HTTP/2 and HPACK encodings. | 9 // of HTTP/2 and HPACK encodings. |
10 | 10 |
11 // TODO(jamessynge): Move more methods into .cc file. | 11 // TODO(jamessynge): Move more methods into .cc file. |
12 | 12 |
13 #include <stddef.h> | 13 #include <stddef.h> |
14 | 14 |
| 15 #include <functional> |
15 #include <memory> | 16 #include <memory> |
16 #include <string> | 17 #include <string> |
17 #include <type_traits> | 18 #include <type_traits> |
18 | 19 |
19 #include "base/bind.h" | |
20 #include "base/callback.h" | |
21 #include "base/logging.h" | 20 #include "base/logging.h" |
22 #include "base/strings/string_piece.h" | 21 #include "base/strings/string_piece.h" |
23 #include "base/template_util.h" | 22 #include "base/template_util.h" |
24 #include "net/http2/decoder/decode_buffer.h" | 23 #include "net/http2/decoder/decode_buffer.h" |
25 #include "net/http2/decoder/decode_status.h" | 24 #include "net/http2/decoder/decode_status.h" |
26 #include "net/http2/tools/failure.h" | 25 #include "net/http2/tools/failure.h" |
27 #include "net/http2/tools/http2_random.h" | 26 #include "net/http2/tools/http2_random.h" |
28 #include "testing/gtest/include/gtest/gtest.h" | 27 #include "testing/gtest/include/gtest/gtest.h" |
29 | 28 |
30 namespace net { | 29 namespace net { |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
64 // SelectSize returns the size of the next DecodeBuffer to be passed to the | 63 // SelectSize returns the size of the next DecodeBuffer to be passed to the |
65 // decoder. Note that RandomDecoderTest allows that size to be zero, though | 64 // decoder. Note that RandomDecoderTest allows that size to be zero, though |
66 // some decoders can't deal with that on the first byte, hence the |first| | 65 // some decoders can't deal with that on the first byte, hence the |first| |
67 // parameter. | 66 // parameter. |
68 typedef std::function<size_t(bool first, size_t offset, size_t remaining)> | 67 typedef std::function<size_t(bool first, size_t offset, size_t remaining)> |
69 SelectSize; | 68 SelectSize; |
70 | 69 |
71 // Validator returns an AssertionResult so test can do: | 70 // Validator returns an AssertionResult so test can do: |
72 // EXPECT_THAT(DecodeAndValidate(..., validator)); | 71 // EXPECT_THAT(DecodeAndValidate(..., validator)); |
73 typedef ::testing::AssertionResult AssertionResult; | 72 typedef ::testing::AssertionResult AssertionResult; |
74 typedef base::Callback<AssertionResult(const DecodeBuffer& input, | 73 typedef std::function<AssertionResult(const DecodeBuffer& input, |
75 DecodeStatus status)> | 74 DecodeStatus status)> |
76 Validator; | 75 Validator; |
77 typedef base::Callback<AssertionResult()> NoArgValidator; | 76 typedef std::function<AssertionResult()> NoArgValidator; |
78 | 77 |
79 RandomDecoderTest(); | 78 RandomDecoderTest(); |
80 | 79 |
81 protected: | 80 protected: |
82 // TODO(jamessynge): Modify StartDecoding, etc. to (somehow) return | 81 // TODO(jamessynge): Modify StartDecoding, etc. to (somehow) return |
83 // AssertionResult so that the VERIFY_* methods exported from | 82 // AssertionResult so that the VERIFY_* methods exported from |
84 // gunit_helpers.h can be widely used. | 83 // gunit_helpers.h can be widely used. |
85 | 84 |
86 // Start decoding; call allows sub-class to Reset the decoder, or deal with | 85 // Start decoding; call allows sub-class to Reset the decoder, or deal with |
87 // the first byte if that is done in a unique fashion. Might be called with | 86 // the first byte if that is done in a unique fashion. Might be called with |
(...skipping 25 matching lines...) Expand all Loading... |
113 // We do this to test the ability to deal with arbitrary boundaries, as might | 112 // We do this to test the ability to deal with arbitrary boundaries, as might |
114 // happen in transport. | 113 // happen in transport. |
115 // Invokes |validator| with the final decode status and the original decode | 114 // Invokes |validator| with the final decode status and the original decode |
116 // buffer, with the cursor advanced as far as has been consumed by the decoder | 115 // buffer, with the cursor advanced as far as has been consumed by the decoder |
117 // and returns validator's result. | 116 // and returns validator's result. |
118 ::testing::AssertionResult DecodeSegmentsAndValidate( | 117 ::testing::AssertionResult DecodeSegmentsAndValidate( |
119 DecodeBuffer* original, | 118 DecodeBuffer* original, |
120 const SelectSize& select_size, | 119 const SelectSize& select_size, |
121 const Validator& validator) { | 120 const Validator& validator) { |
122 DecodeStatus status = DecodeSegments(original, select_size); | 121 DecodeStatus status = DecodeSegments(original, select_size); |
123 VERIFY_AND_RETURN_SUCCESS(validator.Run(*original, status)); | 122 VERIFY_AND_RETURN_SUCCESS(validator(*original, status)); |
124 } | 123 } |
125 | 124 |
126 // Returns a SelectSize function for fast decoding, i.e. passing all that | 125 // Returns a SelectSize function for fast decoding, i.e. passing all that |
127 // is available to the decoder. | 126 // is available to the decoder. |
128 static SelectSize SelectRemaining() { | 127 static SelectSize SelectRemaining() { |
129 return [](bool first, size_t offset, size_t remaining) -> size_t { | 128 return [](bool first, size_t offset, size_t remaining) -> size_t { |
130 return remaining; | 129 return remaining; |
131 }; | 130 }; |
132 } | 131 } |
133 | 132 |
(...skipping 11 matching lines...) Expand all Loading... |
145 SelectSize SelectRandom(bool return_non_zero_on_first); | 144 SelectSize SelectRandom(bool return_non_zero_on_first); |
146 | 145 |
147 // Decode |original| multiple times, with different segmentations of the | 146 // Decode |original| multiple times, with different segmentations of the |
148 // decode buffer, validating after each decode, and confirming that they | 147 // decode buffer, validating after each decode, and confirming that they |
149 // each decode the same amount. Returns on the first failure, else returns | 148 // each decode the same amount. Returns on the first failure, else returns |
150 // success. | 149 // success. |
151 AssertionResult DecodeAndValidateSeveralWays(DecodeBuffer* original, | 150 AssertionResult DecodeAndValidateSeveralWays(DecodeBuffer* original, |
152 bool return_non_zero_on_first, | 151 bool return_non_zero_on_first, |
153 const Validator& validator); | 152 const Validator& validator); |
154 | 153 |
155 static AssertionResult SucceedingValidator(const DecodeBuffer& input, | 154 static Validator ToValidator(std::nullptr_t) { |
156 DecodeStatus status) { | 155 return [](const DecodeBuffer& input, DecodeStatus status) { |
157 return ::testing::AssertionSuccess(); | 156 return ::testing::AssertionSuccess(); |
| 157 }; |
158 } | 158 } |
159 | 159 |
160 static Validator ToValidator(const Validator& validator) { return validator; } | 160 static Validator ToValidator(const Validator& validator) { |
161 | 161 if (validator == nullptr) { |
162 static AssertionResult RunNoArgValidator(const NoArgValidator& validator, | 162 return ToValidator(nullptr); |
163 const DecodeBuffer& input, | 163 } |
164 DecodeStatus status) { | 164 return validator; |
165 return validator.Run(); | |
166 } | 165 } |
167 | 166 |
168 static Validator ToValidator(const NoArgValidator& validator) { | 167 static Validator ToValidator(const NoArgValidator& validator) { |
169 return base::Bind(&RunNoArgValidator, validator); | 168 if (validator == nullptr) { |
| 169 return ToValidator(nullptr); |
| 170 } |
| 171 return [validator](const DecodeBuffer& input, DecodeStatus status) { |
| 172 return validator(); |
| 173 }; |
170 } | 174 } |
171 | 175 |
172 // Wraps a validator with another validator | 176 // Wraps a validator with another validator |
173 // that first checks that the DecodeStatus is kDecodeDone and | 177 // that first checks that the DecodeStatus is kDecodeDone and |
174 // that the DecodeBuffer is empty. | 178 // that the DecodeBuffer is empty. |
175 // TODO(jamessynge): Replace this overload with the next, as using this method | 179 // TODO(jamessynge): Replace this overload with the next, as using this method |
176 // usually means that the wrapped function doesn't need to be passed the | 180 // usually means that the wrapped function doesn't need to be passed the |
177 // DecodeBuffer nor the DecodeStatus. | 181 // DecodeBuffer nor the DecodeStatus. |
178 static AssertionResult ValidateDoneAndEmptyImpl(const Validator& wrapped, | 182 static Validator ValidateDoneAndEmpty(const Validator& wrapped) { |
179 const DecodeBuffer& input, | 183 return [wrapped](const DecodeBuffer& input, |
180 DecodeStatus status) { | 184 DecodeStatus status) -> AssertionResult { |
181 VERIFY_EQ(status, DecodeStatus::kDecodeDone); | 185 VERIFY_EQ(status, DecodeStatus::kDecodeDone); |
182 VERIFY_EQ(0u, input.Remaining()) << "\nOffset=" << input.Offset(); | 186 VERIFY_EQ(0u, input.Remaining()) << "\nOffset=" << input.Offset(); |
183 return wrapped.Run(input, status); | 187 if (wrapped) { |
| 188 return wrapped(input, status); |
| 189 } |
| 190 return ::testing::AssertionSuccess(); |
| 191 }; |
184 } | 192 } |
185 static Validator ValidateDoneAndEmpty(const Validator& wrapped) { | 193 static Validator ValidateDoneAndEmpty(NoArgValidator wrapped) { |
186 return base::Bind(&ValidateDoneAndEmptyImpl, wrapped); | 194 return [wrapped](const DecodeBuffer& input, |
187 } | 195 DecodeStatus status) -> AssertionResult { |
188 static AssertionResult ValidateDoneAndEmptyNoArgImpl( | 196 VERIFY_EQ(status, DecodeStatus::kDecodeDone); |
189 const NoArgValidator& wrapped, | 197 VERIFY_EQ(0u, input.Remaining()) << "\nOffset=" << input.Offset(); |
190 const DecodeBuffer& input, | 198 if (wrapped) { |
191 DecodeStatus status) { | 199 return wrapped(); |
192 VERIFY_EQ(status, DecodeStatus::kDecodeDone); | 200 } |
193 VERIFY_EQ(0u, input.Remaining()) << "\nOffset=" << input.Offset(); | 201 return ::testing::AssertionSuccess(); |
194 return wrapped.Run(); | 202 }; |
195 } | |
196 static Validator ValidateDoneAndEmpty(const NoArgValidator& wrapped) { | |
197 return base::Bind(&ValidateDoneAndEmptyNoArgImpl, wrapped); | |
198 } | 203 } |
199 static Validator ValidateDoneAndEmpty() { | 204 static Validator ValidateDoneAndEmpty() { |
200 return ValidateDoneAndEmpty(base::Bind(&SucceedingValidator)); | 205 NoArgValidator validator; |
| 206 return ValidateDoneAndEmpty(validator); |
201 } | 207 } |
202 | 208 |
203 // Wraps a validator with another validator | 209 // Wraps a validator with another validator |
204 // that first checks that the DecodeStatus is kDecodeDone and | 210 // that first checks that the DecodeStatus is kDecodeDone and |
205 // that the DecodeBuffer has the expected offset. | 211 // that the DecodeBuffer has the expected offset. |
206 // TODO(jamessynge): Replace this overload with the next, as using this method | 212 // TODO(jamessynge): Replace this overload with the next, as using this method |
207 // usually means that the wrapped function doesn't need to be passed the | 213 // usually means that the wrapped function doesn't need to be passed the |
208 // DecodeBuffer nor the DecodeStatus. | 214 // DecodeBuffer nor the DecodeStatus. |
209 static AssertionResult ValidateDoneAndOffsetImpl(uint32_t offset, | 215 static Validator ValidateDoneAndOffset(uint32_t offset, Validator wrapped) { |
210 const Validator& wrapped, | 216 return [wrapped, offset](const DecodeBuffer& input, |
211 const DecodeBuffer& input, | 217 DecodeStatus status) -> AssertionResult { |
212 DecodeStatus status) { | 218 VERIFY_EQ(status, DecodeStatus::kDecodeDone); |
213 VERIFY_EQ(status, DecodeStatus::kDecodeDone); | 219 VERIFY_EQ(offset, input.Offset()) << "\nRemaining=" << input.Remaining(); |
214 VERIFY_EQ(offset, input.Offset()) << "\nRemaining=" << input.Remaining(); | 220 if (wrapped) { |
215 return wrapped.Run(input, status); | 221 return wrapped(input, status); |
| 222 } |
| 223 return ::testing::AssertionSuccess(); |
| 224 }; |
216 } | 225 } |
217 static Validator ValidateDoneAndOffset(uint32_t offset, | 226 static Validator ValidateDoneAndOffset(uint32_t offset, |
218 const Validator& wrapped) { | 227 NoArgValidator wrapped) { |
219 // Make a copy of |wrapped| (by not using base::ConstRef) to avoid lifetime | 228 return [wrapped, offset](const DecodeBuffer& input, |
220 // issues if this method is called with a temporary Validator. | 229 DecodeStatus status) -> AssertionResult { |
221 return base::Bind(&ValidateDoneAndOffsetImpl, offset, wrapped); | 230 VERIFY_EQ(status, DecodeStatus::kDecodeDone); |
222 } | 231 VERIFY_EQ(offset, input.Offset()) << "\nRemaining=" << input.Remaining(); |
223 static AssertionResult ValidateDoneAndOffsetNoArgImpl( | 232 if (wrapped) { |
224 uint32_t offset, | 233 return wrapped(); |
225 const NoArgValidator& wrapped, | 234 } |
226 const DecodeBuffer& input, | 235 return ::testing::AssertionSuccess(); |
227 DecodeStatus status) { | 236 }; |
228 VERIFY_EQ(status, DecodeStatus::kDecodeDone); | |
229 VERIFY_EQ(offset, input.Offset()) << "\nRemaining=" << input.Remaining(); | |
230 return wrapped.Run(); | |
231 } | |
232 static Validator ValidateDoneAndOffset(uint32_t offset, | |
233 const NoArgValidator& wrapped) { | |
234 // Make a copy of |wrapped| (by not using base::ConstRef) to avoid lifetime | |
235 // issues if this method is called with a temporary Validator. | |
236 return base::Bind(&ValidateDoneAndOffsetNoArgImpl, offset, wrapped); | |
237 } | 237 } |
238 static Validator ValidateDoneAndOffset(uint32_t offset) { | 238 static Validator ValidateDoneAndOffset(uint32_t offset) { |
239 // Make a copy of |wrapped| (by not using base::ConstRef) to avoid lifetime | 239 NoArgValidator validator; |
240 // issues if this method is called with a temporary Validator. | 240 return ValidateDoneAndOffset(offset, validator); |
241 return ValidateDoneAndOffset(offset, base::Bind(&SucceedingValidator)); | |
242 } | 241 } |
243 | 242 |
244 // Expose |random_| as RandomBase so callers do not have to care about which | 243 // Expose |random_| as RandomBase so callers do not have to care about which |
245 // sub-class of RandomBase is used, nor can they rely on the specific | 244 // sub-class of RandomBase is used, nor can they rely on the specific |
246 // sub-class that RandomDecoderTest uses. | 245 // sub-class that RandomDecoderTest uses. |
247 RandomBase& Random() { return random_; } | 246 RandomBase& Random() { return random_; } |
248 RandomBase* RandomPtr() { return &random_; } | 247 RandomBase* RandomPtr() { return &random_; } |
249 | 248 |
250 uint32_t RandStreamId(); | 249 uint32_t RandStreamId(); |
251 | 250 |
252 bool stop_decode_on_done_ = true; | 251 bool stop_decode_on_done_ = true; |
253 | 252 |
254 private: | 253 private: |
255 Http2Random random_; | 254 Http2Random random_; |
256 }; | 255 }; |
257 | 256 |
258 } // namespace test | 257 } // namespace test |
259 } // namespace net | 258 } // namespace net |
260 | 259 |
261 #endif // NET_HTTP2_TOOLS_RANDOM_DECODER_TEST_H_ | 260 #endif // NET_HTTP2_TOOLS_RANDOM_DECODER_TEST_H_ |
OLD | NEW |