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