| 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 #ifndef NET_HTTP2_DECODER_PAYLOAD_DECODERS_PAYLOAD_DECODER_BASE_TEST_UTIL_H_ |  | 
| 6 #define NET_HTTP2_DECODER_PAYLOAD_DECODERS_PAYLOAD_DECODER_BASE_TEST_UTIL_H_ |  | 
| 7 |  | 
| 8 // Base class for testing concrete payload decoder classes. |  | 
| 9 |  | 
| 10 #include <stddef.h> |  | 
| 11 |  | 
| 12 #include <string> |  | 
| 13 |  | 
| 14 #include "base/bind.h" |  | 
| 15 #include "base/bind_helpers.h" |  | 
| 16 #include "base/callback.h" |  | 
| 17 #include "base/logging.h" |  | 
| 18 #include "base/strings/string_piece.h" |  | 
| 19 #include "net/http2/decoder/decode_buffer.h" |  | 
| 20 #include "net/http2/decoder/decode_status.h" |  | 
| 21 #include "net/http2/decoder/frame_decoder_state.h" |  | 
| 22 #include "net/http2/decoder/frame_parts.h" |  | 
| 23 #include "net/http2/decoder/http2_frame_decoder_listener.h" |  | 
| 24 #include "net/http2/http2_constants.h" |  | 
| 25 #include "net/http2/http2_constants_test_util.h" |  | 
| 26 #include "net/http2/http2_structures.h" |  | 
| 27 #include "net/http2/tools/http2_frame_builder.h" |  | 
| 28 #include "net/http2/tools/random_decoder_test.h" |  | 
| 29 #include "testing/gtest/include/gtest/gtest.h" |  | 
| 30 |  | 
| 31 namespace net { |  | 
| 32 namespace test { |  | 
| 33 |  | 
| 34 // Base class for tests of payload decoders. Below this there is a templated |  | 
| 35 // sub-class that adds a bunch of type specific features. |  | 
| 36 class PayloadDecoderBaseTest : public RandomDecoderTest { |  | 
| 37  protected: |  | 
| 38   PayloadDecoderBaseTest(); |  | 
| 39 |  | 
| 40   // Virtual functions to be implemented by the test classes for the individual |  | 
| 41   // payload decoders... |  | 
| 42 |  | 
| 43   // Start decoding the payload. |  | 
| 44   virtual DecodeStatus StartDecodingPayload(DecodeBuffer* db) = 0; |  | 
| 45 |  | 
| 46   // Resume decoding the payload. |  | 
| 47   virtual DecodeStatus ResumeDecodingPayload(DecodeBuffer* db) = 0; |  | 
| 48 |  | 
| 49   // In support of ensuring that we're really accessing and updating the |  | 
| 50   // decoder, prepare the decoder by, for example, overwriting the decoder. |  | 
| 51   virtual void PreparePayloadDecoder() = 0; |  | 
| 52 |  | 
| 53   // Get the listener to be inserted into the FrameDecoderState, ready for |  | 
| 54   // listening (e.g. reset if it is a FramePartsCollector). |  | 
| 55   virtual Http2FrameDecoderListener* PrepareListener() = 0; |  | 
| 56 |  | 
| 57   // Record a frame header for use on each call to StartDecoding. |  | 
| 58   void set_frame_header(const Http2FrameHeader& header) { |  | 
| 59     EXPECT_EQ(0, InvalidFlagMaskForFrameType(header.type) & header.flags); |  | 
| 60     if (!frame_header_is_set_ || frame_header_ != header) { |  | 
| 61       VLOG(2) << "set_frame_header: " << frame_header_; |  | 
| 62     } |  | 
| 63     frame_header_ = header; |  | 
| 64     frame_header_is_set_ = true; |  | 
| 65   } |  | 
| 66 |  | 
| 67   const Http2FrameHeader& frame_header() const { |  | 
| 68     CHECK(frame_header_is_set_); |  | 
| 69     return frame_header_; |  | 
| 70   } |  | 
| 71 |  | 
| 72   FrameDecoderState* mutable_state() { return &frame_decoder_state_; } |  | 
| 73 |  | 
| 74   // Randomize the payload decoder, sets the payload decoder's frame_header_, |  | 
| 75   // then start decoding the payload. Called by RandomDecoderTest. This method |  | 
| 76   // is final so that we can always perform certain actions when |  | 
| 77   // RandomDecoderTest starts the decoding of a payload, such as randomizing the |  | 
| 78   // the payload decoder, injecting the frame header and counting fast decoding |  | 
| 79   // cases. Sub-classes must implement StartDecodingPayload to perform their |  | 
| 80   // initial decoding of a frame's payload. |  | 
| 81   DecodeStatus StartDecoding(DecodeBuffer* db) final; |  | 
| 82 |  | 
| 83   // Called by RandomDecoderTest. This method is final so that we can always |  | 
| 84   // perform certain actions when RandomDecoderTest calls it, such as counting |  | 
| 85   // slow decode cases. Sub-classes must implement ResumeDecodingPayload to |  | 
| 86   // continue decoding the frame's payload, which must not all be in one buffer. |  | 
| 87   DecodeStatus ResumeDecoding(DecodeBuffer* db) final; |  | 
| 88 |  | 
| 89   // Given the specified payload (without the common frame header), decode |  | 
| 90   // it with several partitionings of the payload. |  | 
| 91   ::testing::AssertionResult DecodePayloadAndValidateSeveralWays( |  | 
| 92       base::StringPiece payload, |  | 
| 93       Validator validator); |  | 
| 94 |  | 
| 95   // TODO(jamessynge): Add helper method for verifying these are both non-zero, |  | 
| 96   // and call the new method from tests that expect successful decoding. |  | 
| 97   void ResetDecodeSpeedCounters() { |  | 
| 98     fast_decode_count_ = 0; |  | 
| 99     slow_decode_count_ = 0; |  | 
| 100   } |  | 
| 101 |  | 
| 102   // Count of payloads that are full decoded by StartDecodingPayload, or that |  | 
| 103   // an error was detected by StartDecodingPayload. |  | 
| 104   size_t fast_decode_count_ = 0; |  | 
| 105 |  | 
| 106   // Count of payloads that require calling ResumeDecodingPayload in order to |  | 
| 107   // decode them completely (or to detect an error during decoding). |  | 
| 108   size_t slow_decode_count_ = 0; |  | 
| 109 |  | 
| 110  private: |  | 
| 111   bool frame_header_is_set_ = false; |  | 
| 112   Http2FrameHeader frame_header_; |  | 
| 113   FrameDecoderState frame_decoder_state_; |  | 
| 114 }; |  | 
| 115 |  | 
| 116 // Base class for payload decoders of type Decoder, with corresponding test |  | 
| 117 // peer of type DecoderPeer, and using class Listener as the implementation |  | 
| 118 // of Http2FrameDecoderListenerInterface to be used during decoding. |  | 
| 119 // Typically Listener is a sub-class of FramePartsCollector. |  | 
| 120 // SupportedFrameType is set to false only for UnknownPayloadDecoder. |  | 
| 121 template <class Decoder, |  | 
| 122           class DecoderPeer, |  | 
| 123           class Listener, |  | 
| 124           bool SupportedFrameType = true> |  | 
| 125 class AbstractPayloadDecoderTest : public PayloadDecoderBaseTest { |  | 
| 126  public: |  | 
| 127   static bool SucceedingApproveSize(size_t size) { return true; } |  | 
| 128 |  | 
| 129  protected: |  | 
| 130   // An ApproveSize function returns true to approve decoding the specified |  | 
| 131   // size of payload, else false to skip that size. Typically used for negative |  | 
| 132   // tests; for example, decoding a SETTINGS frame at all sizes except for |  | 
| 133   // multiples of 6. |  | 
| 134   typedef base::Callback<bool(size_t size)> ApproveSize; |  | 
| 135 |  | 
| 136   AbstractPayloadDecoderTest() {} |  | 
| 137 |  | 
| 138   // These tests are in setup rather than the constructor for two reasons: |  | 
| 139   // 1) Constructors are not allowed to fail, so gUnit documents that EXPECT_* |  | 
| 140   //    and ASSERT_* are not allowed in constructors, and should instead be in |  | 
| 141   //    SetUp if they are needed before the body of the test is executed. |  | 
| 142   // 2) To allow the sub-class constructor to make any desired modifications to |  | 
| 143   //    the DecoderPeer before these tests are executed; in particular, |  | 
| 144   //    UnknownPayloadDecoderPeer has not got a fixed frame type, but it is |  | 
| 145   //    instead set during the test's constructor. |  | 
| 146   void SetUp() override { |  | 
| 147     PayloadDecoderBaseTest::SetUp(); |  | 
| 148 |  | 
| 149     // Confirm that DecoderPeer et al returns sensible values. Using auto as the |  | 
| 150     // variable type so that no (narrowing) conversions take place that hide |  | 
| 151     // problems; i.e. if someone changes KnownFlagsMaskForFrameType so that it |  | 
| 152     // doesn't return a uint8, and has bits above the low-order 8 bits set, this |  | 
| 153     // bit of paranoia should detect the problem before we get too far. |  | 
| 154     auto frame_type = DecoderPeer::FrameType(); |  | 
| 155     if (SupportedFrameType) { |  | 
| 156       EXPECT_TRUE(IsSupportedHttp2FrameType(frame_type)) << frame_type; |  | 
| 157     } else { |  | 
| 158       EXPECT_FALSE(IsSupportedHttp2FrameType(frame_type)) << frame_type; |  | 
| 159     } |  | 
| 160 |  | 
| 161     auto known_flags = KnownFlagsMaskForFrameType(frame_type); |  | 
| 162     EXPECT_EQ(known_flags, known_flags & 0xff); |  | 
| 163 |  | 
| 164     auto flags_to_avoid = DecoderPeer::FlagsAffectingPayloadDecoding(); |  | 
| 165     EXPECT_EQ(flags_to_avoid, flags_to_avoid & known_flags); |  | 
| 166   } |  | 
| 167 |  | 
| 168   void PreparePayloadDecoder() override { |  | 
| 169     payload_decoder_.~Decoder(); |  | 
| 170     new (&payload_decoder_) Decoder; |  | 
| 171   } |  | 
| 172 |  | 
| 173   Http2FrameDecoderListener* PrepareListener() override { |  | 
| 174     listener_.Reset(); |  | 
| 175     return &listener_; |  | 
| 176   } |  | 
| 177 |  | 
| 178   // Returns random flags, but only those valid for the frame type, yet not |  | 
| 179   // those that the DecoderPeer says will affect the decoding of the payload |  | 
| 180   // (e.g. the PRIORTY flag on a HEADERS frame or PADDED on DATA frames). |  | 
| 181   uint8_t RandFlags() { |  | 
| 182     return Random().Rand8() & |  | 
| 183            KnownFlagsMaskForFrameType(DecoderPeer::FrameType()) & |  | 
| 184            ~DecoderPeer::FlagsAffectingPayloadDecoding(); |  | 
| 185   } |  | 
| 186 |  | 
| 187   // Start decoding the payload. |  | 
| 188   DecodeStatus StartDecodingPayload(DecodeBuffer* db) override { |  | 
| 189     DVLOG(2) << "StartDecodingPayload, db->Remaining=" << db->Remaining(); |  | 
| 190     return payload_decoder_.StartDecodingPayload(mutable_state(), db); |  | 
| 191   } |  | 
| 192 |  | 
| 193   // Resume decoding the payload. |  | 
| 194   DecodeStatus ResumeDecodingPayload(DecodeBuffer* db) override { |  | 
| 195     DVLOG(2) << "ResumeDecodingPayload, db->Remaining=" << db->Remaining(); |  | 
| 196     return payload_decoder_.ResumeDecodingPayload(mutable_state(), db); |  | 
| 197   } |  | 
| 198 |  | 
| 199   // Wrap |validator| in another one which will check that we've reached the |  | 
| 200   // expected state of kDecodeError with OnFrameSizeError having been called by |  | 
| 201   AssertionResult ValidatorForDecodePayloadAndValidateSeveralWays( |  | 
| 202       const FrameParts& expected) { |  | 
| 203     VERIFY_FALSE(listener_.IsInProgress()); |  | 
| 204     VERIFY_EQ(1u, listener_.size()); |  | 
| 205     VERIFY_AND_RETURN_SUCCESS(expected.VerifyEquals(*listener_.frame(0))); |  | 
| 206   } |  | 
| 207 |  | 
| 208   // Decode one frame's payload and confirm that the listener recorded the |  | 
| 209   // expected FrameParts instance, and only FrameParts instance. The payload |  | 
| 210   // will be decoded several times with different partitionings of the payload, |  | 
| 211   // and after each the validator will be called. |  | 
| 212   AssertionResult DecodePayloadAndValidateSeveralWays( |  | 
| 213       base::StringPiece payload, |  | 
| 214       const FrameParts& expected) { |  | 
| 215     return PayloadDecoderBaseTest::DecodePayloadAndValidateSeveralWays( |  | 
| 216         payload, this->ValidateDoneAndEmpty(base::Bind( |  | 
| 217                      &AbstractPayloadDecoderTest:: |  | 
| 218                          ValidatorForDecodePayloadAndValidateSeveralWays, |  | 
| 219                      base::Unretained(this), base::ConstRef(expected)))); |  | 
| 220   } |  | 
| 221 |  | 
| 222   // Wrap |validator| in another one which will check that we've reached the |  | 
| 223   // expected state of kDecodeError with OnFrameSizeError having been called by |  | 
| 224   // the payload decoder. |  | 
| 225   AssertionResult ValidatorForVerifyDetectsFrameSizeError( |  | 
| 226       const Http2FrameHeader& header, |  | 
| 227       const Validator& validator, |  | 
| 228       const DecodeBuffer& input, |  | 
| 229       DecodeStatus status) { |  | 
| 230     DVLOG(2) << "VerifyDetectsFrameSizeError validator; status=" << status |  | 
| 231              << "; input.Remaining=" << input.Remaining(); |  | 
| 232     VERIFY_EQ(DecodeStatus::kDecodeError, status); |  | 
| 233     VERIFY_FALSE(listener_.IsInProgress()); |  | 
| 234     VERIFY_EQ(1u, listener_.size()); |  | 
| 235     const FrameParts* frame = listener_.frame(0); |  | 
| 236     VERIFY_EQ(header, frame->frame_header); |  | 
| 237     VERIFY_TRUE(frame->has_frame_size_error); |  | 
| 238     // Verify did not get OnPaddingTooLong, as we should only ever produce |  | 
| 239     // one of these two errors for a single frame. |  | 
| 240     VERIFY_FALSE(frame->opt_missing_length); |  | 
| 241     return validator.Run(input, status); |  | 
| 242   } |  | 
| 243 |  | 
| 244   // Decode one frame's payload, expecting that the final status will be |  | 
| 245   // kDecodeError, and that OnFrameSizeError will have been called on the |  | 
| 246   // listener. The payload will be decoded several times with different |  | 
| 247   // partitionings of the payload. The type WrappedValidator is either |  | 
| 248   // RandomDecoderTest::Validator, RandomDecoderTest::NoArgValidator or |  | 
| 249   // std::nullptr_t (not extra validation). |  | 
| 250   template <typename WrappedValidator> |  | 
| 251   ::testing::AssertionResult VerifyDetectsFrameSizeError( |  | 
| 252       base::StringPiece payload, |  | 
| 253       const Http2FrameHeader& header, |  | 
| 254       WrappedValidator wrapped_validator) { |  | 
| 255     set_frame_header(header); |  | 
| 256     // If wrapped_validator is not a RandomDecoderTest::Validator, make it so. |  | 
| 257     Validator validator = this->ToValidator(wrapped_validator); |  | 
| 258     VERIFY_AND_RETURN_SUCCESS( |  | 
| 259         PayloadDecoderBaseTest::DecodePayloadAndValidateSeveralWays( |  | 
| 260             payload, base::Bind(&AbstractPayloadDecoderTest:: |  | 
| 261                                     ValidatorForVerifyDetectsFrameSizeError, |  | 
| 262                                 base::Unretained(this), base::ConstRef(header), |  | 
| 263                                 base::ConstRef(validator)))); |  | 
| 264   } |  | 
| 265 |  | 
| 266   // Confirm that we get OnFrameSizeError when trying to decode unpadded_payload |  | 
| 267   // at all sizes from zero to unpadded_payload.size(), except those sizes not |  | 
| 268   // approved by approve_size. |  | 
| 269   // If total_pad_length is greater than zero, then that amount of padding |  | 
| 270   // is added to the payload (including the Pad Length field). |  | 
| 271   // The flags will be required_flags, PADDED if total_pad_length > 0, and some |  | 
| 272   // randomly selected flag bits not excluded by FlagsAffectingPayloadDecoding. |  | 
| 273   ::testing::AssertionResult VerifyDetectsMultipleFrameSizeErrors( |  | 
| 274       uint8_t required_flags, |  | 
| 275       base::StringPiece unpadded_payload, |  | 
| 276       ApproveSize approve_size, |  | 
| 277       int total_pad_length) { |  | 
| 278     // required_flags should come from those that are defined for the frame |  | 
| 279     // type AND are those that affect the decoding of the payload (otherwise, |  | 
| 280     // the flag shouldn't be required). |  | 
| 281     Http2FrameType frame_type = DecoderPeer::FrameType(); |  | 
| 282     VERIFY_EQ(required_flags, |  | 
| 283               required_flags & KnownFlagsMaskForFrameType(frame_type)); |  | 
| 284     VERIFY_EQ(required_flags, |  | 
| 285               required_flags & DecoderPeer::FlagsAffectingPayloadDecoding()); |  | 
| 286 |  | 
| 287     if (0 != (Http2FrameFlag::FLAG_PADDED & |  | 
| 288               KnownFlagsMaskForFrameType(frame_type))) { |  | 
| 289       // Frame type supports padding. |  | 
| 290       if (total_pad_length == 0) { |  | 
| 291         required_flags &= ~Http2FrameFlag::FLAG_PADDED; |  | 
| 292       } else { |  | 
| 293         required_flags |= Http2FrameFlag::FLAG_PADDED; |  | 
| 294       } |  | 
| 295     } else { |  | 
| 296       VERIFY_EQ(0, total_pad_length); |  | 
| 297     } |  | 
| 298 |  | 
| 299     bool validated = false; |  | 
| 300     for (size_t real_payload_size = 0; |  | 
| 301          real_payload_size <= unpadded_payload.size(); ++real_payload_size) { |  | 
| 302       if (!approve_size.Run(real_payload_size)) { |  | 
| 303         continue; |  | 
| 304       } |  | 
| 305       VLOG(1) << "real_payload_size=" << real_payload_size; |  | 
| 306       uint8_t flags = required_flags | RandFlags(); |  | 
| 307       Http2FrameBuilder fb; |  | 
| 308       if (total_pad_length > 0) { |  | 
| 309         // total_pad_length_ includes the size of the Pad Length field, and thus |  | 
| 310         // ranges from 0 (no PADDED flag) to 256 (Pad Length == 255). |  | 
| 311         fb.AppendUInt8(total_pad_length - 1); |  | 
| 312       } |  | 
| 313       // Append a subset of the unpadded_payload, which the decoder should |  | 
| 314       // determine is not a valid amount. |  | 
| 315       fb.Append(unpadded_payload.substr(0, real_payload_size)); |  | 
| 316       if (total_pad_length > 0) { |  | 
| 317         fb.AppendZeroes(total_pad_length - 1); |  | 
| 318       } |  | 
| 319       // We choose a random stream id because the payload decoders aren't |  | 
| 320       // checking stream ids. |  | 
| 321       uint32_t stream_id = RandStreamId(); |  | 
| 322       Http2FrameHeader header(fb.size(), frame_type, flags, stream_id); |  | 
| 323       VERIFY_SUCCESS(VerifyDetectsFrameSizeError( |  | 
| 324           fb.buffer(), header, base::Bind(&SucceedingValidator))); |  | 
| 325       validated = true; |  | 
| 326     } |  | 
| 327     VERIFY_TRUE(validated); |  | 
| 328     return ::testing::AssertionSuccess(); |  | 
| 329   } |  | 
| 330 |  | 
| 331   // As above, but for frames without padding. |  | 
| 332   ::testing::AssertionResult VerifyDetectsFrameSizeError( |  | 
| 333       uint8_t required_flags, |  | 
| 334       base::StringPiece unpadded_payload, |  | 
| 335       ApproveSize approve_size) { |  | 
| 336     Http2FrameType frame_type = DecoderPeer::FrameType(); |  | 
| 337     uint8_t known_flags = KnownFlagsMaskForFrameType(frame_type); |  | 
| 338     VERIFY_EQ(0, known_flags & Http2FrameFlag::FLAG_PADDED); |  | 
| 339     VERIFY_EQ(0, required_flags & Http2FrameFlag::FLAG_PADDED); |  | 
| 340     VERIFY_AND_RETURN_SUCCESS(VerifyDetectsMultipleFrameSizeErrors( |  | 
| 341         required_flags, unpadded_payload, approve_size, 0)); |  | 
| 342   } |  | 
| 343 |  | 
| 344   Listener listener_; |  | 
| 345   union { |  | 
| 346     // Confirm at compile time that Decoder can be in an anonymous union, |  | 
| 347     // i.e. complain loudly if Decoder has members that prevent this, as it |  | 
| 348     // becomes annoying and possibly difficult to deal with non-anonymous |  | 
| 349     // unions and such union members. |  | 
| 350     Decoder payload_decoder_; |  | 
| 351   }; |  | 
| 352 }; |  | 
| 353 |  | 
| 354 // A base class for tests parameterized by the total number of bytes of |  | 
| 355 // padding, including the Pad Length field (i.e. a total_pad_length of 0 |  | 
| 356 // means unpadded as there is then no room for the Pad Length field). |  | 
| 357 // The frame type must support padding. |  | 
| 358 template <class Decoder, class DecoderPeer, class Listener> |  | 
| 359 class AbstractPaddablePayloadDecoderTest |  | 
| 360     : public AbstractPayloadDecoderTest<Decoder, DecoderPeer, Listener>, |  | 
| 361       public ::testing::WithParamInterface<int> { |  | 
| 362   typedef AbstractPayloadDecoderTest<Decoder, DecoderPeer, Listener> Base; |  | 
| 363 |  | 
| 364  protected: |  | 
| 365   using Base::Random; |  | 
| 366   using Base::RandStreamId; |  | 
| 367   using Base::set_frame_header; |  | 
| 368   using Base::listener_; |  | 
| 369   typedef typename Base::Validator Validator; |  | 
| 370 |  | 
| 371   AbstractPaddablePayloadDecoderTest() : total_pad_length_(GetParam()) { |  | 
| 372     LOG(INFO) << "total_pad_length_ = " << total_pad_length_; |  | 
| 373   } |  | 
| 374 |  | 
| 375   // Note that total_pad_length_ includes the size of the Pad Length field, |  | 
| 376   // and thus ranges from 0 (no PADDED flag) to 256 (Pad Length == 255). |  | 
| 377   bool IsPadded() const { return total_pad_length_ > 0; } |  | 
| 378 |  | 
| 379   // Value of the Pad Length field. Only call if IsPadded. |  | 
| 380   size_t pad_length() const { |  | 
| 381     EXPECT_TRUE(IsPadded()); |  | 
| 382     return total_pad_length_ - 1; |  | 
| 383   } |  | 
| 384 |  | 
| 385   // Clear the frame builder and add the Pad Length field if appropriate. |  | 
| 386   void Reset() { |  | 
| 387     frame_builder_ = Http2FrameBuilder(); |  | 
| 388     if (IsPadded()) { |  | 
| 389       frame_builder_.AppendUInt8(pad_length()); |  | 
| 390     } |  | 
| 391   } |  | 
| 392 |  | 
| 393   void MaybeAppendTrailingPadding() { |  | 
| 394     if (IsPadded()) { |  | 
| 395       frame_builder_.AppendZeroes(pad_length()); |  | 
| 396     } |  | 
| 397   } |  | 
| 398 |  | 
| 399   uint8_t RandFlags() { |  | 
| 400     uint8_t flags = Base::RandFlags(); |  | 
| 401     if (IsPadded()) { |  | 
| 402       flags |= Http2FrameFlag::FLAG_PADDED; |  | 
| 403     } else { |  | 
| 404       flags &= ~Http2FrameFlag::FLAG_PADDED; |  | 
| 405     } |  | 
| 406     return flags; |  | 
| 407   } |  | 
| 408 |  | 
| 409   static ::testing::AssertionResult ValidatorForVerifyDetectsPaddingTooLong( |  | 
| 410       const Http2FrameHeader& header, |  | 
| 411       int expected_missing_length, |  | 
| 412       const Listener& listener, |  | 
| 413       const DecodeBuffer& input, |  | 
| 414       DecodeStatus status) { |  | 
| 415     VERIFY_EQ(DecodeStatus::kDecodeError, status); |  | 
| 416     VERIFY_FALSE(listener.IsInProgress()); |  | 
| 417     VERIFY_EQ(1u, listener.size()); |  | 
| 418     const FrameParts* frame = listener.frame(0); |  | 
| 419     VERIFY_EQ(header, frame->frame_header); |  | 
| 420     VERIFY_TRUE(frame->opt_missing_length); |  | 
| 421     VERIFY_EQ(expected_missing_length, frame->opt_missing_length.value()); |  | 
| 422     // Verify did not get OnFrameSizeError. |  | 
| 423     VERIFY_FALSE(frame->has_frame_size_error); |  | 
| 424     return ::testing::AssertionSuccess(); |  | 
| 425   } |  | 
| 426 |  | 
| 427   // Verify that we get OnPaddingTooLong when decoding payload, and that the |  | 
| 428   // amount of missing padding is as specified. header.IsPadded must be true, |  | 
| 429   // and the payload must be empty or the PadLength field must be too large. |  | 
| 430   ::testing::AssertionResult VerifyDetectsPaddingTooLong( |  | 
| 431       base::StringPiece payload, |  | 
| 432       const Http2FrameHeader& header, |  | 
| 433       int expected_missing_length) { |  | 
| 434     set_frame_header(header); |  | 
| 435     auto& listener = listener_; |  | 
| 436     VERIFY_AND_RETURN_SUCCESS( |  | 
| 437         PayloadDecoderBaseTest::DecodePayloadAndValidateSeveralWays( |  | 
| 438             payload, base::Bind(&AbstractPaddablePayloadDecoderTest:: |  | 
| 439                                     ValidatorForVerifyDetectsPaddingTooLong, |  | 
| 440                                 header, expected_missing_length, |  | 
| 441                                 base::ConstRef(listener)))); |  | 
| 442   } |  | 
| 443 |  | 
| 444   // Verifies that we get OnPaddingTooLong for a padded frame payload whose |  | 
| 445   // (randomly selected) payload length is less than total_pad_length_. |  | 
| 446   // Flags will be selected at random, except PADDED will be set and |  | 
| 447   // flags_to_avoid will not be set. The stream id is selected at random. |  | 
| 448   ::testing::AssertionResult VerifyDetectsPaddingTooLong() { |  | 
| 449     uint8_t flags = RandFlags() | Http2FrameFlag::FLAG_PADDED; |  | 
| 450 |  | 
| 451     // Create an all padding payload for total_pad_length_. |  | 
| 452     int payload_length = 0; |  | 
| 453     Http2FrameBuilder fb; |  | 
| 454     if (IsPadded()) { |  | 
| 455       fb.AppendUInt8(pad_length()); |  | 
| 456       fb.AppendZeroes(pad_length()); |  | 
| 457       VLOG(1) << "fb.size=" << fb.size(); |  | 
| 458       // Pick a random length for the payload that is shorter than neccesary. |  | 
| 459       payload_length = Random().Rand32() % fb.size(); |  | 
| 460     } |  | 
| 461 |  | 
| 462     VLOG(1) << "payload_length=" << payload_length; |  | 
| 463     std::string payload = fb.buffer().substr(0, payload_length); |  | 
| 464 |  | 
| 465     // The missing length is the amount we cut off the end, unless |  | 
| 466     // payload_length is zero, in which case the decoder knows only that 1 |  | 
| 467     // byte, the Pad Length field, is missing. |  | 
| 468     int missing_length = payload_length == 0 ? 1 : fb.size() - payload_length; |  | 
| 469     VLOG(1) << "missing_length=" << missing_length; |  | 
| 470 |  | 
| 471     const Http2FrameHeader header(payload_length, DecoderPeer::FrameType(), |  | 
| 472                                   flags, RandStreamId()); |  | 
| 473     VERIFY_AND_RETURN_SUCCESS( |  | 
| 474         VerifyDetectsPaddingTooLong(payload, header, missing_length)); |  | 
| 475   } |  | 
| 476 |  | 
| 477   // total_pad_length_ includes the size of the Pad Length field, and thus |  | 
| 478   // ranges from 0 (no PADDED flag) to 256 (Pad Length == 255). |  | 
| 479   const size_t total_pad_length_; |  | 
| 480   Http2FrameBuilder frame_builder_; |  | 
| 481 }; |  | 
| 482 |  | 
| 483 }  // namespace test |  | 
| 484 }  // namespace net |  | 
| 485 |  | 
| 486 #endif  // NET_HTTP2_DECODER_PAYLOAD_DECODERS_PAYLOAD_DECODER_BASE_TEST_UTIL_H_ |  | 
| OLD | NEW | 
|---|