From 7819a9d1c5735089f52cb338f02c016f87644c78 Mon Sep 17 00:00:00 2001 From: Raul Gutierrez Segales Date: Tue, 23 Feb 2021 10:39:52 -0500 Subject: [PATCH] Revert "HTTP2: Add DumpState support for HTTP2 (#14923)" This reverts commit 3f740bc90d32ac442e70da46ebf4d03a1bdb479d. Because it breaks builds on RHEL 8 and Ubuntu 18. See: https://github.com/envoyproxy/envoy/pull/15093 Signed-off-by: Raul Gutierrez Segales --- docs/root/version_history/current.rst | 2 +- source/common/common/dump_state_utils.h | 2 - source/common/common/utility.cc | 6 - source/common/http/http2/BUILD | 1 - source/common/http/http2/codec_impl.cc | 80 +---------- source/common/http/http2/codec_impl.h | 23 +-- .../common/http/http2/protocol_constraints.cc | 15 -- .../common/http/http2/protocol_constraints.h | 5 +- test/common/common/utility_test.cc | 15 -- test/common/http/http2/codec_impl_test.cc | 136 ------------------ .../http/http2/protocol_constraints_test.cc | 22 --- 11 files changed, 5 insertions(+), 302 deletions(-) diff --git a/docs/root/version_history/current.rst b/docs/root/version_history/current.rst index 24f8dbfd20cb..4f8016018a16 100644 --- a/docs/root/version_history/current.rst +++ b/docs/root/version_history/current.rst @@ -90,7 +90,7 @@ New Features * ext_authz: added :ref:`allowed_client_headers_on_success ` to support sending response headers to downstream clients on OK external authorization checks via HTTP. * grpc_json_transcoder: added :ref:`request_validation_options ` to reject invalid requests early. * grpc_json_transcoder: filter can now be configured on per-route/per-vhost level as well. Leaving empty list of services in the filter configuration disables transcoding on the specific route. -* http: added support for `Envoy::ScopeTrackedObject` for HTTP/1 and HTTP/2 dispatching. Crashes while inside the dispatching loop should dump debug information. +* http: added support for `Envoy::ScopeTrackedObject` for HTTP/1 dispatching. Crashes while inside the dispatching loop should dump debug information. * http: added support for :ref:`preconnecting `. Preconnecting is off by default, but recommended for clusters serving latency-sensitive traffic, especially if using HTTP/1.1. * http: change frame flood and abuse checks to the upstream HTTP/2 codec to ON by default. It can be disabled by setting the `envoy.reloadable_features.upstream_http2_flood_checks` runtime key to false. * json: introduced new JSON parser (https://github.com/nlohmann/json) to replace RapidJSON. The new parser is disabled by default. To test the new RapidJSON parser, enable the runtime feature `envoy.reloadable_features.remove_legacy_json`. diff --git a/source/common/common/dump_state_utils.h b/source/common/common/dump_state_utils.h index d6902b43af3f..f2821195fd9d 100644 --- a/source/common/common/dump_state_utils.h +++ b/source/common/common/dump_state_utils.h @@ -21,7 +21,6 @@ namespace Envoy { // Macro assumes local member variables // os (ostream) // indent_level (int) -// spaces (const char *) #define DUMP_DETAILS(member) \ do { \ os << spaces << #member ": "; \ @@ -36,7 +35,6 @@ namespace Envoy { // Macro assumes local member variables // os (ostream) // indent_level (int) -// spaces (const char *) #define DUMP_OPT_REF_DETAILS(member) \ do { \ os << spaces << #member ": "; \ diff --git a/source/common/common/utility.cc b/source/common/common/utility.cc index 47167d41c289..b8664ba0b165 100644 --- a/source/common/common/utility.cc +++ b/source/common/common/utility.cc @@ -476,12 +476,6 @@ void StringUtil::escapeToOstream(std::ostream& os, absl::string_view view) { case '\t': os << "\\t"; break; - case '\v': - os << "\\v"; - break; - case '\0': - os << "\\0"; - break; case '"': os << "\\\""; break; diff --git a/source/common/http/http2/BUILD b/source/common/http/http2/BUILD index 7e31b3e97a47..826e3f2beeef 100644 --- a/source/common/http/http2/BUILD +++ b/source/common/http/http2/BUILD @@ -126,7 +126,6 @@ envoy_cc_library( ":codec_stats_lib", "//include/envoy/network:connection_interface", "//source/common/common:assert_lib", - "//source/common/common:dump_state_utils", "//source/common/http:status_lib", "@envoy_api//envoy/config/core/v3:pkg_cc_proto", ], diff --git a/source/common/http/http2/codec_impl.cc b/source/common/http/http2/codec_impl.cc index 1759f9c843f1..9d85dcbeb5b3 100644 --- a/source/common/http/http2/codec_impl.cc +++ b/source/common/http/http2/codec_impl.cc @@ -1,9 +1,7 @@ #include "common/http/http2/codec_impl.h" -#include #include #include -#include #include #include "envoy/event/dispatcher.h" @@ -13,10 +11,8 @@ #include "common/common/assert.h" #include "common/common/cleanup.h" -#include "common/common/dump_state_utils.h" #include "common/common/enum_to_int.h" #include "common/common/fmt.h" -#include "common/common/scope_tracker.h" #include "common/common/utility.h" #include "common/http/codes.h" #include "common/http/exception.h" @@ -645,17 +641,12 @@ Http::Status ConnectionImpl::dispatch(Buffer::Instance& data) { } Http::Status ConnectionImpl::innerDispatch(Buffer::Instance& data) { - ScopeTrackerScopeState scope(this, connection_.dispatcher()); ENVOY_CONN_LOG(trace, "dispatching {} bytes", connection_, data.length()); // Make sure that dispatching_ is set to false after dispatching, even when // ConnectionImpl::dispatch returns early or throws an exception (consider removing if there is a // single return after exception removal (#10878)). - Cleanup cleanup([this]() { - dispatching_ = false; - current_slice_ = nullptr; - }); + Cleanup cleanup([this]() { dispatching_ = false; }); for (const Buffer::RawSlice& slice : data.getRawSlices()) { - current_slice_ = &slice; dispatching_ = true; ssize_t rc = nghttp2_session_mem_recv(session_, static_cast(slice.mem_), slice.len_); @@ -674,7 +665,6 @@ Http::Status ConnectionImpl::innerDispatch(Buffer::Instance& data) { return codecProtocolError(nghttp2_strerror(rc)); } - current_slice_ = nullptr; dispatching_ = false; } @@ -1396,74 +1386,6 @@ ConnectionImpl::ClientHttp2Options::ClientHttp2Options( options_, ::Envoy::Http2::Utility::OptionsLimits::DEFAULT_MAX_CONCURRENT_STREAMS); } -void ConnectionImpl::dumpState(std::ostream& os, int indent_level) const { - const char* spaces = spacesForLevel(indent_level); - os << spaces << "Http2::ConnectionImpl " << this << DUMP_MEMBER(max_headers_kb_) - << DUMP_MEMBER(max_headers_count_) << DUMP_MEMBER(per_stream_buffer_limit_) - << DUMP_MEMBER(allow_metadata_) << DUMP_MEMBER(stream_error_on_invalid_http_messaging_) - << DUMP_MEMBER(is_outbound_flood_monitored_control_frame_) - << DUMP_MEMBER(skip_encoding_empty_trailers_) << DUMP_MEMBER(dispatching_) - << DUMP_MEMBER(raised_goaway_) << DUMP_MEMBER(pending_deferred_reset_) << '\n'; - - // Dump the protocol constraints - DUMP_DETAILS(&protocol_constraints_); - - os << spaces << "Number of active streams: " << active_streams_.size() << " Active Streams:\n"; - std::for_each_n(active_streams_.begin(), std::min(active_streams_.size(), 100), - [&](auto& stream) { DUMP_DETAILS(stream); }); - - // Dump the active slice - if (current_slice_ == nullptr) { - // No current slice, use macro for consistent formatting. - os << spaces << "current_slice_: null\n"; - } else { - auto slice_view = - absl::string_view(static_cast(current_slice_->mem_), current_slice_->len_); - - os << spaces << "current slice length: " << slice_view.length() << " contents: \""; - StringUtil::escapeToOstream(os, slice_view); - os << "\"\n"; - } -} - -void ConnectionImpl::StreamImpl::dumpState(std::ostream& os, int indent_level) const { - const char* spaces = spacesForLevel(indent_level); - os << spaces << "ConnectionImpl::StreamImpl " << this << DUMP_MEMBER(stream_id_) - << DUMP_MEMBER(unconsumed_bytes_) << DUMP_MEMBER(read_disable_count_) - << DUMP_MEMBER(local_end_stream_sent_) << DUMP_MEMBER(remote_end_stream_) - << DUMP_MEMBER(data_deferred_) << DUMP_MEMBER(received_noninformational_headers_) - << DUMP_MEMBER(pending_receive_buffer_high_watermark_called_) - << DUMP_MEMBER(pending_send_buffer_high_watermark_called_) - << DUMP_MEMBER(reset_due_to_messaging_error_) - << DUMP_MEMBER_AS(cookies_, cookies_.getStringView()); - - DUMP_DETAILS(pending_trailers_to_encode_); -} - -void ConnectionImpl::ClientStreamImpl::dumpState(std::ostream& os, int indent_level) const { - const char* spaces = spacesForLevel(indent_level); - StreamImpl::dumpState(os, indent_level); - - // Dump header map - if (absl::holds_alternative(headers_or_trailers_)) { - DUMP_DETAILS(absl::get(headers_or_trailers_)); - } else { - DUMP_DETAILS(absl::get(headers_or_trailers_)); - } -} - -void ConnectionImpl::ServerStreamImpl::dumpState(std::ostream& os, int indent_level) const { - const char* spaces = spacesForLevel(indent_level); - StreamImpl::dumpState(os, indent_level); - - // Dump header map - if (absl::holds_alternative(headers_or_trailers_)) { - DUMP_DETAILS(absl::get(headers_or_trailers_)); - } else { - DUMP_DETAILS(absl::get(headers_or_trailers_)); - } -} - ClientConnectionImpl::ClientConnectionImpl( Network::Connection& connection, Http::ConnectionCallbacks& callbacks, CodecStats& stats, Random::RandomGenerator& random_generator, diff --git a/source/common/http/http2/codec_impl.h b/source/common/http/http2/codec_impl.h index d4739eb6a570..cc8e898c2f96 100644 --- a/source/common/http/http2/codec_impl.h +++ b/source/common/http/http2/codec_impl.h @@ -4,12 +4,10 @@ #include #include #include -#include #include #include #include "envoy/common/random_generator.h" -#include "envoy/common/scope_tracker.h" #include "envoy/config/core/v3/protocol.pb.h" #include "envoy/event/deferred_deletable.h" #include "envoy/http/codec.h" @@ -92,9 +90,7 @@ class ProdNghttp2SessionFactory : public Nghttp2SessionFactory { /** * Base class for HTTP/2 client and server codecs. */ -class ConnectionImpl : public virtual Connection, - protected Logger::Loggable, - public ScopeTrackedObject { +class ConnectionImpl : public virtual Connection, protected Logger::Loggable { public: ConnectionImpl(Network::Connection& connection, CodecStats& stats, Random::RandomGenerator& random_generator, @@ -133,9 +129,6 @@ class ConnectionImpl : public virtual Connection, */ virtual Http::Status innerDispatch(Buffer::Instance& data); - // ScopeTrackedObject - void dumpState(std::ostream& os, int indent_level) const override; - protected: friend class ProdNghttp2SessionFactory; @@ -179,8 +172,7 @@ class ConnectionImpl : public virtual Connection, public Stream, public LinkedObject, public Event::DeferredDeletable, - public StreamCallbackHelper, - public ScopeTrackedObject { + public StreamCallbackHelper { StreamImpl(ConnectionImpl& parent, uint32_t buffer_limit); ~StreamImpl() override; @@ -235,9 +227,6 @@ class ConnectionImpl : public virtual Connection, stream_idle_timeout_ = timeout; } - // ScopeTrackedObject - void dumpState(std::ostream& os, int indent_level) const override; - // This code assumes that details is a static string, so that we // can avoid copying it. void setDetails(absl::string_view details) { @@ -369,9 +358,6 @@ class ConnectionImpl : public virtual Connection, } void enableTcpTunneling() override {} - // ScopeTrackedObject - void dumpState(std::ostream& os, int indent_level) const override; - ResponseDecoder& response_decoder_; absl::variant headers_or_trailers_; std::string upgrade_type_; @@ -414,9 +400,6 @@ class ConnectionImpl : public virtual Connection, encodeTrailersBase(trailers); } - // ScopeTrackedObject - void dumpState(std::ostream& os, int indent_level) const override; - RequestDecoder* request_decoder_{}; absl::variant headers_or_trailers_; @@ -548,8 +531,6 @@ class ConnectionImpl : public virtual Connection, void onKeepaliveResponse(); void onKeepaliveResponseTimeout(); - // Tracks the current slice we're processing in the dispatch loop. - const Buffer::RawSlice* current_slice_ = nullptr; bool dispatching_ : 1; bool raised_goaway_ : 1; bool pending_deferred_reset_ : 1; diff --git a/source/common/http/http2/protocol_constraints.cc b/source/common/http/http2/protocol_constraints.cc index 5d8f38a44c40..09a057e539b3 100644 --- a/source/common/http/http2/protocol_constraints.cc +++ b/source/common/http/http2/protocol_constraints.cc @@ -1,7 +1,6 @@ #include "common/http/http2/protocol_constraints.h" #include "common/common/assert.h" -#include "common/common/dump_state_utils.h" namespace Envoy { namespace Http { @@ -113,20 +112,6 @@ Status ProtocolConstraints::checkInboundFrameLimits() { return okStatus(); } -void ProtocolConstraints::dumpState(std::ostream& os, int indent_level) const { - const char* spaces = spacesForLevel(indent_level); - - os << spaces << "ProtocolConstraints " << this << DUMP_MEMBER(outbound_frames_) - << DUMP_MEMBER(max_outbound_frames_) << DUMP_MEMBER(outbound_control_frames_) - << DUMP_MEMBER(max_outbound_control_frames_) - << DUMP_MEMBER(consecutive_inbound_frames_with_empty_payload_) - << DUMP_MEMBER(max_consecutive_inbound_frames_with_empty_payload_) - << DUMP_MEMBER(opened_streams_) << DUMP_MEMBER(inbound_priority_frames_) - << DUMP_MEMBER(max_inbound_priority_frames_per_stream_) - << DUMP_MEMBER(inbound_window_update_frames_) << DUMP_MEMBER(outbound_data_frames_) - << DUMP_MEMBER(max_inbound_window_update_frames_per_data_frame_sent_) << '\n'; -} - } // namespace Http2 } // namespace Http } // namespace Envoy diff --git a/source/common/http/http2/protocol_constraints.h b/source/common/http/http2/protocol_constraints.h index 017db57289e0..06a294edd0ac 100644 --- a/source/common/http/http2/protocol_constraints.h +++ b/source/common/http/http2/protocol_constraints.h @@ -22,7 +22,7 @@ namespace Http2 { // 2. detection of outbound DATA or HEADER frame floods. // 4. zero length, PRIORITY and WINDOW_UPDATE floods. -class ProtocolConstraints : public ScopeTrackedObject { +class ProtocolConstraints { public: using ReleasorProc = std::function; @@ -54,9 +54,6 @@ class ProtocolConstraints : public ScopeTrackedObject { Status checkOutboundFrameLimits(); - // ScopeTrackedObject - void dumpState(std::ostream& os, int indent_level) const override; - private: void releaseOutboundFrame(); void releaseOutboundControlFrame(); diff --git a/test/common/common/utility_test.cc b/test/common/common/utility_test.cc index 96bde3fb79a4..5ebde35e63d2 100644 --- a/test/common/common/utility_test.cc +++ b/test/common/common/utility_test.cc @@ -317,21 +317,6 @@ TEST(StringUtil, escapeToOstream) { StringUtil::escapeToOstream(ostream, R"(\\)"); EXPECT_EQ(ostream.contents(), R"(\\\\)"); } - - { - std::array buffer; - OutputBufferStream ostream{buffer.data(), buffer.size()}; - StringUtil::escapeToOstream(ostream, "vertical\vtab"); - EXPECT_EQ(ostream.contents(), "vertical\\vtab"); - } - - { - using namespace std::string_literals; - std::array buffer; - OutputBufferStream ostream{buffer.data(), buffer.size()}; - StringUtil::escapeToOstream(ostream, "null\0char"s); - EXPECT_EQ(ostream.contents(), "null\\0char"); - } } TEST(StringUtil, toUpper) { diff --git a/test/common/http/http2/codec_impl_test.cc b/test/common/http/http2/codec_impl_test.cc index 7b0bba690f81..4eeec27321e0 100644 --- a/test/common/http/http2/codec_impl_test.cc +++ b/test/common/http/http2/codec_impl_test.cc @@ -1,12 +1,9 @@ #include #include -#include "envoy/buffer/buffer.h" #include "envoy/http/codec.h" #include "envoy/stats/scope.h" -#include "common/buffer/buffer_impl.h" -#include "common/common/utility.h" #include "common/http/exception.h" #include "common/http/header_map_impl.h" #include "common/http/http2/codec_impl.h" @@ -33,14 +30,11 @@ using testing::_; using testing::AnyNumber; using testing::AtLeast; -using testing::EndsWith; -using testing::HasSubstr; using testing::InSequence; using testing::Invoke; using testing::InvokeWithoutArgs; using testing::NiceMock; using testing::Return; -using testing::StartsWith; namespace Envoy { namespace Http { @@ -971,136 +965,6 @@ TEST_P(Http2CodecImplTest, ConnectionKeepaliveJitter) { EXPECT_EQ(max_observed.count(), max_expected.count()); } -TEST_P(Http2CodecImplTest, DumpsStreamlessConnectionWithoutAllocatingMemory) { - initialize(); - std::array buffer; - OutputBufferStream ostream{buffer.data(), buffer.size()}; - - Stats::TestUtil::MemoryTest memory_test; - server_->dumpState(ostream, 1); - - EXPECT_EQ(memory_test.consumedBytes(), 0); - // Check the entire dump to ensure correct formating. - // This test might be a little brittle because of this, and hence in the other - // dump tests we focus on the particular substring of interest. - EXPECT_THAT(ostream.contents(), StartsWith(" Http2::ConnectionImpl")); - EXPECT_THAT( - ostream.contents(), - HasSubstr( - "max_headers_kb_: 60, max_headers_count_: 100, " - "per_stream_buffer_limit_: 268435456, allow_metadata_: 0, " - "stream_error_on_invalid_http_messaging_: 0, is_outbound_flood_monitored_control_frame_: " - "0, skip_encoding_empty_trailers_: 1, dispatching_: 0, raised_goaway_: 0, " - "pending_deferred_reset_: 0\n" - " &protocol_constraints_: \n" - " ProtocolConstraints")); - EXPECT_THAT(ostream.contents(), - EndsWith("outbound_frames_: 0, max_outbound_frames_: 10000, " - "outbound_control_frames_: 0, max_outbound_control_frames_: 1000, " - "consecutive_inbound_frames_with_empty_payload_: 0, " - "max_consecutive_inbound_frames_with_empty_payload_: 1, opened_streams_: 0, " - "inbound_priority_frames_: 0, max_inbound_priority_frames_per_stream_: 100, " - "inbound_window_update_frames_: 0, outbound_data_frames_: 0, " - "max_inbound_window_update_frames_per_data_frame_sent_: 10\n" - " Number of active streams: 0 Active Streams:\n" - " current_slice_: null\n")); -} - -TEST_P(Http2CodecImplTest, ShouldDumpActiveStreamsWithoutAllocatingMemory) { - initialize(); - MockStreamCallbacks callbacks; - request_encoder_->getStream().addCallbacks(callbacks); - - TestRequestHeaderMapImpl request_headers; - HttpTestUtility::addDefaultHeaders(request_headers); - TestRequestHeaderMapImpl expected_headers; - HttpTestUtility::addDefaultHeaders(expected_headers); - EXPECT_CALL(request_decoder_, decodeHeaders_(HeaderMapEqual(&expected_headers), false)); - EXPECT_TRUE(request_encoder_->encodeHeaders(request_headers, false).ok()); - - TestResponseHeaderMapImpl response_headers{{":status", "200"}}; - EXPECT_CALL(response_decoder_, decodeHeaders_(_, true)); - response_encoder_->encodeHeaders(response_headers, true); - - // Dump server - { - std::array buffer; - OutputBufferStream ostream{buffer.data(), buffer.size()}; - // Check no memory allocated. - Stats::TestUtil::MemoryTest memory_test; - server_->dumpState(ostream, 1); - EXPECT_EQ(memory_test.consumedBytes(), 0); - - // Check contents for active stream, trailers to encode and header map. - EXPECT_THAT(ostream.contents(), HasSubstr(" Number of active streams: 1 Active Streams:\n" - " stream: \n" - " ConnectionImpl::StreamImpl")); - EXPECT_THAT(ostream.contents(), - HasSubstr("pending_trailers_to_encode_: null\n" - " absl::get(headers_or_trailers_): \n" - " ':scheme', 'http'\n" - " ':method', 'GET'\n" - " ':authority', 'host'\n" - " ':path', '/'\n" - " current_slice_: null")); - } - - // Dump client - { - std::array buffer; - OutputBufferStream ostream{buffer.data(), buffer.size()}; - // Check no memory allocated. - Stats::TestUtil::MemoryTest memory_test; - client_->dumpState(ostream, 1); - EXPECT_EQ(memory_test.consumedBytes(), 0); - - // Check contents for active stream, trailers to encode and header map. - EXPECT_THAT(ostream.contents(), HasSubstr(" Number of active streams: 1 Active Streams:\n" - " stream: \n" - " ConnectionImpl::StreamImpl")); - EXPECT_THAT(ostream.contents(), - HasSubstr("pending_trailers_to_encode_: null\n" - " absl::get(headers_or_trailers_): \n" - " ':status', '200'\n" - " current_slice_: null")); - } -} - -TEST_P(Http2CodecImplTest, ShouldDumpCurrentSliceWithoutAllocatingMemory) { - initialize(); - std::array buffer; - OutputBufferStream ostream{buffer.data(), buffer.size()}; - MockStreamCallbacks callbacks; - request_encoder_->getStream().addCallbacks(callbacks); - - // Send headers - TestRequestHeaderMapImpl request_headers; - HttpTestUtility::addDefaultHeaders(request_headers); - TestRequestHeaderMapImpl expected_headers; - HttpTestUtility::addDefaultHeaders(expected_headers); - EXPECT_CALL(request_decoder_, decodeHeaders_(HeaderMapEqual(&expected_headers), false)); - EXPECT_TRUE(request_encoder_->encodeHeaders(request_headers, false).ok()); - - // Send data payload, dump buffer as decoding data - EXPECT_CALL(request_decoder_, decodeData(_, false)).WillOnce(Invoke([&](Buffer::Instance&, bool) { - // dumpState here while we had a current slice of data. No Memory should be - // allocated. - Stats::TestUtil::MemoryTest memory_test; - server_->dumpState(ostream, 1); - EXPECT_EQ(memory_test.consumedBytes(), 0); - })); - Buffer::OwnedImpl hello("hello envoy"); - request_encoder_->encodeData(hello, false); - - // Check contents for the current slice information - { - EXPECT_THAT( - ostream.contents(), - EndsWith( - "current slice length: 20 contents: \"\\0\\0\\v\\0\\0\\0\\0\\0\x1hello envoy\"\n")); - } -} - class Http2CodecImplDeferredResetTest : public Http2CodecImplTest {}; TEST_P(Http2CodecImplDeferredResetTest, DeferredResetClient) { diff --git a/test/common/http/http2/protocol_constraints_test.cc b/test/common/http/http2/protocol_constraints_test.cc index f3308759b9e9..5ddca183a115 100644 --- a/test/common/http/http2/protocol_constraints_test.cc +++ b/test/common/http/http2/protocol_constraints_test.cc @@ -1,4 +1,3 @@ -#include "common/common/utility.h" #include "common/http/http2/protocol_constraints.h" #include "test/common/stats/stat_test_utility.h" @@ -6,8 +5,6 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" -using testing::HasSubstr; - namespace Envoy { namespace Http { namespace Http2 { @@ -197,25 +194,6 @@ TEST_F(ProtocolConstraintsTest, WindowUpdate) { EXPECT_EQ(1, stats_store_.counter("http2.inbound_window_update_frames_flood").value()); } -TEST_F(ProtocolConstraintsTest, DumpsStateWithoutAllocatingMemory) { - std::array buffer; - OutputBufferStream ostream{buffer.data(), buffer.size()}; - ProtocolConstraints constraints(http2CodecStats(), options_); - - Stats::TestUtil::MemoryTest memory_test; - constraints.dumpState(ostream, 0); - EXPECT_EQ(memory_test.consumedBytes(), 0); - EXPECT_THAT(ostream.contents(), HasSubstr("ProtocolConstraints ")); - EXPECT_THAT( - ostream.contents(), - HasSubstr(" outbound_frames_: 0, max_outbound_frames_: 0, outbound_control_frames_: 0, " - "max_outbound_control_frames_: 0, consecutive_inbound_frames_with_empty_payload_: " - "0, max_consecutive_inbound_frames_with_empty_payload_: 0, opened_streams_: 0, " - "inbound_priority_frames_: 0, max_inbound_priority_frames_per_stream_: 0, " - "inbound_window_update_frames_: 0, outbound_data_frames_: 0, " - "max_inbound_window_update_frames_per_data_frame_sent_: 0")); -} - } // namespace Http2 } // namespace Http } // namespace Envoy