|  | // Copyright 2016 The Chromium Authors. All rights reserved. | 
|  | // Use of this source code is governed by a BSD-style license that can be | 
|  | // found in the LICENSE file. | 
|  |  | 
|  | #ifndef QUICHE_HTTP2_HPACK_DECODER_HPACK_BLOCK_COLLECTOR_H_ | 
|  | #define QUICHE_HTTP2_HPACK_DECODER_HPACK_BLOCK_COLLECTOR_H_ | 
|  |  | 
|  | // HpackBlockCollector implements HpackEntryDecoderListener in order to record | 
|  | // the calls using HpackEntryCollector instances (one per HPACK entry). This | 
|  | // supports testing of HpackBlockDecoder, which decodes entire HPACK blocks. | 
|  | // | 
|  | // In addition to implementing the callback methods, HpackBlockCollector also | 
|  | // supports comparing two HpackBlockCollector instances (i.e. an expected and | 
|  | // an actual), or a sole HPACK entry against an expected value. | 
|  |  | 
|  | #include <stddef.h> | 
|  |  | 
|  | #include <string> | 
|  | #include <vector> | 
|  |  | 
|  | #include "absl/strings/string_view.h" | 
|  | #include "http2/hpack/decoder/hpack_entry_collector.h" | 
|  | #include "http2/hpack/decoder/hpack_entry_decoder_listener.h" | 
|  | #include "http2/hpack/http2_hpack_constants.h" | 
|  | #include "http2/hpack/tools/hpack_block_builder.h" | 
|  | #include "http2/test_tools/http2_random.h" | 
|  |  | 
|  | namespace http2 { | 
|  | namespace test { | 
|  |  | 
|  | class HpackBlockCollector : public HpackEntryDecoderListener { | 
|  | public: | 
|  | HpackBlockCollector(); | 
|  | HpackBlockCollector(const HpackBlockCollector& other); | 
|  | ~HpackBlockCollector() override; | 
|  |  | 
|  | // Implementations of HpackEntryDecoderListener, forwarding to pending_entry_, | 
|  | // an HpackEntryCollector for the "in-progress" HPACK entry. OnIndexedHeader | 
|  | // and OnDynamicTableSizeUpdate are pending only for that one call, while | 
|  | // OnStartLiteralHeader is followed by many calls, ending with OnValueEnd. | 
|  | // Once all the calls for one HPACK entry have been received, PushPendingEntry | 
|  | // is used to append the pending_entry_ entry to the collected entries_. | 
|  | void OnIndexedHeader(size_t index) override; | 
|  | void OnDynamicTableSizeUpdate(size_t size) override; | 
|  | void OnStartLiteralHeader(HpackEntryType header_type, | 
|  | size_t maybe_name_index) override; | 
|  | void OnNameStart(bool huffman_encoded, size_t len) override; | 
|  | void OnNameData(const char* data, size_t len) override; | 
|  | void OnNameEnd() override; | 
|  | void OnValueStart(bool huffman_encoded, size_t len) override; | 
|  | void OnValueData(const char* data, size_t len) override; | 
|  | void OnValueEnd() override; | 
|  |  | 
|  | // Methods for creating a set of expectations (i.e. HPACK entries to compare | 
|  | // against those collected by another instance of HpackBlockCollector). | 
|  |  | 
|  | // Add an HPACK entry for an indexed header. | 
|  | void ExpectIndexedHeader(size_t index); | 
|  |  | 
|  | // Add an HPACK entry for a dynamic table size update. | 
|  | void ExpectDynamicTableSizeUpdate(size_t size); | 
|  |  | 
|  | // Add an HPACK entry for a header entry with an index for the name, and a | 
|  | // literal value. | 
|  | void ExpectNameIndexAndLiteralValue(HpackEntryType type, | 
|  | size_t index, | 
|  | bool value_huffman, | 
|  | const std::string& value); | 
|  |  | 
|  | // Add an HPACK entry for a header entry with a literal name and value. | 
|  | void ExpectLiteralNameAndValue(HpackEntryType type, | 
|  | bool name_huffman, | 
|  | const std::string& name, | 
|  | bool value_huffman, | 
|  | const std::string& value); | 
|  |  | 
|  | // Shuffle the entries, in support of generating an HPACK block of entries | 
|  | // in some random order. | 
|  | void ShuffleEntries(Http2Random* rng); | 
|  |  | 
|  | // Serialize entries_ to the HpackBlockBuilder. | 
|  | void AppendToHpackBlockBuilder(HpackBlockBuilder* hbb) const; | 
|  |  | 
|  | // Return AssertionSuccess if there is just one entry, and it is an | 
|  | // Indexed Header with the specified index. | 
|  | ::testing::AssertionResult ValidateSoleIndexedHeader(size_t ndx) const; | 
|  |  | 
|  | // Return AssertionSuccess if there is just one entry, and it is a | 
|  | // Dynamic Table Size Update with the specified size. | 
|  | ::testing::AssertionResult ValidateSoleDynamicTableSizeUpdate( | 
|  | size_t size) const; | 
|  |  | 
|  | // Return AssertionSuccess if there is just one entry, and it is a Header | 
|  | // entry with an index for the name and a literal value. | 
|  | ::testing::AssertionResult ValidateSoleLiteralValueHeader( | 
|  | HpackEntryType expected_type, | 
|  | size_t expected_index, | 
|  | bool expected_value_huffman, | 
|  | absl::string_view expected_value) const; | 
|  |  | 
|  | // Return AssertionSuccess if there is just one entry, and it is a Header | 
|  | // with a literal name and literal value. | 
|  | ::testing::AssertionResult ValidateSoleLiteralNameValueHeader( | 
|  | HpackEntryType expected_type, | 
|  | bool expected_name_huffman, | 
|  | absl::string_view expected_name, | 
|  | bool expected_value_huffman, | 
|  | absl::string_view expected_value) const; | 
|  |  | 
|  | bool IsNotPending() const { return pending_entry_.IsClear(); } | 
|  | bool IsClear() const { return IsNotPending() && entries_.empty(); } | 
|  | void Clear(); | 
|  |  | 
|  | ::testing::AssertionResult VerifyEq(const HpackBlockCollector& that) const; | 
|  |  | 
|  | private: | 
|  | // Push the value of pending_entry_ onto entries_, and clear pending_entry_. | 
|  | // The pending_entry_ must be complete. | 
|  | void PushPendingEntry(); | 
|  |  | 
|  | HpackEntryCollector pending_entry_; | 
|  | std::vector<HpackEntryCollector> entries_; | 
|  | }; | 
|  |  | 
|  | }  // namespace test | 
|  | }  // namespace http2 | 
|  |  | 
|  | #endif  // QUICHE_HTTP2_HPACK_DECODER_HPACK_BLOCK_COLLECTOR_H_ |