QUICHE team | fd50a40 | 2018-12-07 22:54:05 -0500 | [diff] [blame] | 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 QUICHE_HTTP2_HPACK_DECODER_HPACK_BLOCK_COLLECTOR_H_ |
| 6 | #define QUICHE_HTTP2_HPACK_DECODER_HPACK_BLOCK_COLLECTOR_H_ |
| 7 | |
| 8 | // HpackBlockCollector implements HpackEntryDecoderListener in order to record |
| 9 | // the calls using HpackEntryCollector instances (one per HPACK entry). This |
| 10 | // supports testing of HpackBlockDecoder, which decodes entire HPACK blocks. |
| 11 | // |
| 12 | // In addition to implementing the callback methods, HpackBlockCollector also |
| 13 | // supports comparing two HpackBlockCollector instances (i.e. an expected and |
| 14 | // an actual), or a sole HPACK entry against an expected value. |
| 15 | |
| 16 | #include <stddef.h> |
| 17 | |
bnc | 4790400 | 2019-08-16 11:49:48 -0700 | [diff] [blame] | 18 | #include <string> |
QUICHE team | fd50a40 | 2018-12-07 22:54:05 -0500 | [diff] [blame] | 19 | #include <vector> |
| 20 | |
vasilvv | b16f796 | 2020-10-13 10:48:38 -0700 | [diff] [blame] | 21 | #include "absl/strings/string_view.h" |
QUICHE team | 5be974e | 2020-12-29 18:35:24 -0500 | [diff] [blame] | 22 | #include "http2/hpack/decoder/hpack_entry_collector.h" |
| 23 | #include "http2/hpack/decoder/hpack_entry_decoder_listener.h" |
| 24 | #include "http2/hpack/http2_hpack_constants.h" |
| 25 | #include "http2/hpack/tools/hpack_block_builder.h" |
| 26 | #include "http2/test_tools/http2_random.h" |
QUICHE team | fd50a40 | 2018-12-07 22:54:05 -0500 | [diff] [blame] | 27 | |
| 28 | namespace http2 { |
| 29 | namespace test { |
| 30 | |
| 31 | class HpackBlockCollector : public HpackEntryDecoderListener { |
| 32 | public: |
| 33 | HpackBlockCollector(); |
| 34 | HpackBlockCollector(const HpackBlockCollector& other); |
| 35 | ~HpackBlockCollector() override; |
| 36 | |
| 37 | // Implementations of HpackEntryDecoderListener, forwarding to pending_entry_, |
| 38 | // an HpackEntryCollector for the "in-progress" HPACK entry. OnIndexedHeader |
| 39 | // and OnDynamicTableSizeUpdate are pending only for that one call, while |
| 40 | // OnStartLiteralHeader is followed by many calls, ending with OnValueEnd. |
| 41 | // Once all the calls for one HPACK entry have been received, PushPendingEntry |
| 42 | // is used to append the pending_entry_ entry to the collected entries_. |
| 43 | void OnIndexedHeader(size_t index) override; |
| 44 | void OnDynamicTableSizeUpdate(size_t size) override; |
| 45 | void OnStartLiteralHeader(HpackEntryType header_type, |
| 46 | size_t maybe_name_index) override; |
| 47 | void OnNameStart(bool huffman_encoded, size_t len) override; |
| 48 | void OnNameData(const char* data, size_t len) override; |
| 49 | void OnNameEnd() override; |
| 50 | void OnValueStart(bool huffman_encoded, size_t len) override; |
| 51 | void OnValueData(const char* data, size_t len) override; |
| 52 | void OnValueEnd() override; |
| 53 | |
| 54 | // Methods for creating a set of expectations (i.e. HPACK entries to compare |
| 55 | // against those collected by another instance of HpackBlockCollector). |
| 56 | |
| 57 | // Add an HPACK entry for an indexed header. |
| 58 | void ExpectIndexedHeader(size_t index); |
| 59 | |
| 60 | // Add an HPACK entry for a dynamic table size update. |
| 61 | void ExpectDynamicTableSizeUpdate(size_t size); |
| 62 | |
| 63 | // Add an HPACK entry for a header entry with an index for the name, and a |
| 64 | // literal value. |
| 65 | void ExpectNameIndexAndLiteralValue(HpackEntryType type, |
| 66 | size_t index, |
| 67 | bool value_huffman, |
bnc | 4790400 | 2019-08-16 11:49:48 -0700 | [diff] [blame] | 68 | const std::string& value); |
QUICHE team | fd50a40 | 2018-12-07 22:54:05 -0500 | [diff] [blame] | 69 | |
| 70 | // Add an HPACK entry for a header entry with a literal name and value. |
| 71 | void ExpectLiteralNameAndValue(HpackEntryType type, |
| 72 | bool name_huffman, |
bnc | 4790400 | 2019-08-16 11:49:48 -0700 | [diff] [blame] | 73 | const std::string& name, |
QUICHE team | fd50a40 | 2018-12-07 22:54:05 -0500 | [diff] [blame] | 74 | bool value_huffman, |
bnc | 4790400 | 2019-08-16 11:49:48 -0700 | [diff] [blame] | 75 | const std::string& value); |
QUICHE team | fd50a40 | 2018-12-07 22:54:05 -0500 | [diff] [blame] | 76 | |
| 77 | // Shuffle the entries, in support of generating an HPACK block of entries |
| 78 | // in some random order. |
| 79 | void ShuffleEntries(Http2Random* rng); |
| 80 | |
| 81 | // Serialize entries_ to the HpackBlockBuilder. |
| 82 | void AppendToHpackBlockBuilder(HpackBlockBuilder* hbb) const; |
| 83 | |
| 84 | // Return AssertionSuccess if there is just one entry, and it is an |
| 85 | // Indexed Header with the specified index. |
| 86 | ::testing::AssertionResult ValidateSoleIndexedHeader(size_t ndx) const; |
| 87 | |
| 88 | // Return AssertionSuccess if there is just one entry, and it is a |
| 89 | // Dynamic Table Size Update with the specified size. |
| 90 | ::testing::AssertionResult ValidateSoleDynamicTableSizeUpdate( |
| 91 | size_t size) const; |
| 92 | |
| 93 | // Return AssertionSuccess if there is just one entry, and it is a Header |
| 94 | // entry with an index for the name and a literal value. |
| 95 | ::testing::AssertionResult ValidateSoleLiteralValueHeader( |
| 96 | HpackEntryType expected_type, |
| 97 | size_t expected_index, |
| 98 | bool expected_value_huffman, |
vasilvv | b16f796 | 2020-10-13 10:48:38 -0700 | [diff] [blame] | 99 | absl::string_view expected_value) const; |
QUICHE team | fd50a40 | 2018-12-07 22:54:05 -0500 | [diff] [blame] | 100 | |
| 101 | // Return AssertionSuccess if there is just one entry, and it is a Header |
| 102 | // with a literal name and literal value. |
| 103 | ::testing::AssertionResult ValidateSoleLiteralNameValueHeader( |
| 104 | HpackEntryType expected_type, |
| 105 | bool expected_name_huffman, |
vasilvv | b16f796 | 2020-10-13 10:48:38 -0700 | [diff] [blame] | 106 | absl::string_view expected_name, |
QUICHE team | fd50a40 | 2018-12-07 22:54:05 -0500 | [diff] [blame] | 107 | bool expected_value_huffman, |
vasilvv | b16f796 | 2020-10-13 10:48:38 -0700 | [diff] [blame] | 108 | absl::string_view expected_value) const; |
QUICHE team | fd50a40 | 2018-12-07 22:54:05 -0500 | [diff] [blame] | 109 | |
| 110 | bool IsNotPending() const { return pending_entry_.IsClear(); } |
| 111 | bool IsClear() const { return IsNotPending() && entries_.empty(); } |
| 112 | void Clear(); |
| 113 | |
| 114 | ::testing::AssertionResult VerifyEq(const HpackBlockCollector& that) const; |
| 115 | |
| 116 | private: |
| 117 | // Push the value of pending_entry_ onto entries_, and clear pending_entry_. |
| 118 | // The pending_entry_ must be complete. |
| 119 | void PushPendingEntry(); |
| 120 | |
| 121 | HpackEntryCollector pending_entry_; |
| 122 | std::vector<HpackEntryCollector> entries_; |
| 123 | }; |
| 124 | |
| 125 | } // namespace test |
| 126 | } // namespace http2 |
| 127 | |
| 128 | #endif // QUICHE_HTTP2_HPACK_DECODER_HPACK_BLOCK_COLLECTOR_H_ |