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/test_tools/payload_decoder_base_test_util.h"
6 
7 #include "quiche/http2/test_tools/frame_decoder_state_test_util.h"
8 #include "quiche/http2/test_tools/http2_structures_test_util.h"
9 #include "quiche/common/platform/api/quiche_test.h"
10 
11 namespace http2 {
12 namespace test {
PayloadDecoderBaseTest()13 PayloadDecoderBaseTest::PayloadDecoderBaseTest() {
14   // If the test adds more data after the frame payload,
15   // stop as soon as the payload is decoded.
16   stop_decode_on_done_ = true;
17   frame_header_is_set_ = false;
18   Randomize(&frame_header_, RandomPtr());
19 }
20 
StartDecoding(DecodeBuffer * db)21 DecodeStatus PayloadDecoderBaseTest::StartDecoding(DecodeBuffer* db) {
22   QUICHE_DVLOG(2) << "StartDecoding, db->Remaining=" << db->Remaining();
23   // Make sure sub-class has set frame_header_ so that we can inject it
24   // into the payload decoder below.
25   if (!frame_header_is_set_) {
26     ADD_FAILURE() << "frame_header_ is not set";
27     return DecodeStatus::kDecodeError;
28   }
29   // The contract with the payload decoders is that they won't receive a
30   // decode buffer that extends beyond the end of the frame.
31   if (db->Remaining() > frame_header_.payload_length) {
32     ADD_FAILURE() << "DecodeBuffer has too much data: " << db->Remaining()
33                   << " > " << frame_header_.payload_length;
34     return DecodeStatus::kDecodeError;
35   }
36 
37   // Prepare the payload decoder.
38   PreparePayloadDecoder();
39 
40   // Reconstruct the FrameDecoderState, prepare the listener, and add it to
41   // the FrameDecoderState.
42   frame_decoder_state_ = std::make_unique<FrameDecoderState>();
43   frame_decoder_state_->set_listener(PrepareListener());
44 
45   // Make sure that a listener was provided.
46   if (frame_decoder_state_->listener() == nullptr) {
47     ADD_FAILURE() << "PrepareListener must return a listener.";
48     return DecodeStatus::kDecodeError;
49   }
50 
51   // Now that nothing in the payload decoder should be valid, inject the
52   // Http2FrameHeader whose payload we're about to decode. That header is the
53   // only state that a payload decoder should expect is valid when its Start
54   // method is called.
55   FrameDecoderStatePeer::set_frame_header(frame_header_,
56                                           frame_decoder_state_.get());
57   DecodeStatus status = StartDecodingPayload(db);
58   if (status != DecodeStatus::kDecodeInProgress) {
59     // Keep track of this so that a concrete test can verify that both fast
60     // and slow decoding paths have been tested.
61     ++fast_decode_count_;
62   }
63   return status;
64 }
65 
ResumeDecoding(DecodeBuffer * db)66 DecodeStatus PayloadDecoderBaseTest::ResumeDecoding(DecodeBuffer* db) {
67   QUICHE_DVLOG(2) << "ResumeDecoding, db->Remaining=" << db->Remaining();
68   DecodeStatus status = ResumeDecodingPayload(db);
69   if (status != DecodeStatus::kDecodeInProgress) {
70     // Keep track of this so that a concrete test can verify that both fast
71     // and slow decoding paths have been tested.
72     ++slow_decode_count_;
73   }
74   return status;
75 }
76 
77 ::testing::AssertionResult
DecodePayloadAndValidateSeveralWays(absl::string_view payload,Validator validator)78 PayloadDecoderBaseTest::DecodePayloadAndValidateSeveralWays(
79     absl::string_view payload, Validator validator) {
80   HTTP2_VERIFY_TRUE(frame_header_is_set_);
81   // Cap the payload to be decoded at the declared payload length. This is
82   // required by the decoders' preconditions; they are designed on the
83   // assumption that they're never passed more than they're permitted to
84   // consume.
85   // Note that it is OK if the payload is too short; the validator may be
86   // designed to check for that.
87   if (payload.size() > frame_header_.payload_length) {
88     payload = absl::string_view(payload.data(), frame_header_.payload_length);
89   }
90   DecodeBuffer db(payload);
91   ResetDecodeSpeedCounters();
92   const bool kMayReturnZeroOnFirst = false;
93   return DecodeAndValidateSeveralWays(&db, kMayReturnZeroOnFirst, validator);
94 }
95 
96 }  // namespace test
97 }  // namespace http2
98