From a4ad9c26197ee93b20a5df1aba91aa522f6820c8 Mon Sep 17 00:00:00 2001 From: code Date: Tue, 17 Sep 2024 20:51:19 +0800 Subject: [PATCH 01/65] route: use reference wrapper for get all filter config (#36079) Commit Message: route: use reference wrapper for get all filter config Additional Description: @alyssawilk I think we have a information gap at #36028. The pointer is better for the `perFilterConfigs()` because we always need to do a dynamic_cast. pointer is simpler and won't result in potential exception throwing. But the `Utility::getAllPerFilterConfigs()` could use the reference wrapper because it take a template parameter and will return the typed configs. Risk Level: low. Testing: n/a. Docs Changes: n/a. Release Notes: n/a. Platform Specific Features: n/a. --------- Signed-off-by: wangbaiping --- .../filters/http/source/golang_filter.cc | 11 +-- source/common/http/utility.h | 7 +- .../filters/http/cors/cors_filter.cc | 93 +++++++++---------- .../filters/http/cors/cors_filter.h | 12 +-- .../custom_response/custom_response_filter.cc | 5 +- .../filters/http/ext_authz/ext_authz.cc | 7 +- .../filters/http/ext_proc/ext_proc.cc | 7 +- .../http/header_mutation/header_mutation.cc | 15 ++- .../http/header_mutation/header_mutation.h | 2 +- .../filters/http/cors/cors_filter_test.cc | 20 ++-- 10 files changed, 84 insertions(+), 95 deletions(-) diff --git a/contrib/golang/filters/http/source/golang_filter.cc b/contrib/golang/filters/http/source/golang_filter.cc index 226a6656ec..cc4bd5c294 100644 --- a/contrib/golang/filters/http/source/golang_filter.cc +++ b/contrib/golang/filters/http/source/golang_filter.cc @@ -1377,16 +1377,13 @@ void Filter::deferredDeleteRequest(HttpRequestInternal* req) { uint64_t Filter::getMergedConfigId() { Http::StreamFilterCallbacks* callbacks = decoding_state_.getFilterCallbacks(); + auto id = config_->getConfigId(); + // get all of the per route config auto route_config_list = Http::Utility::getAllPerFilterConfig(callbacks); - ENVOY_LOG(debug, "golang filter route config list length: {}.", route_config_list.size()); - - auto id = config_->getConfigId(); - for (auto it : route_config_list) { - ASSERT(it != nullptr, "route config should not be null"); - auto route_config = *it; - id = route_config.getPluginConfigId(id, config_->pluginName()); + for (const FilterConfigPerRoute& typed_config : route_config_list) { + id = typed_config.getPluginConfigId(id, config_->pluginName()); } return id; diff --git a/source/common/http/utility.h b/source/common/http/utility.h index d1b2d0d093..eaee0c34fa 100644 --- a/source/common/http/utility.h +++ b/source/common/http/utility.h @@ -2,6 +2,7 @@ #include #include +#include #include #include #include @@ -572,11 +573,11 @@ const ConfigType* resolveMostSpecificPerFilterConfig(const Http::StreamFilterCal * and their lifetime is the same as the matched route. */ template -absl::InlinedVector +absl::InlinedVector, 4> getAllPerFilterConfig(const Http::StreamFilterCallbacks* callbacks) { ASSERT(callbacks != nullptr); - absl::InlinedVector all_configs; + absl::InlinedVector, 4> all_configs; for (const auto* config : callbacks->perFilterConfigs()) { const ConfigType* typed_config = dynamic_cast(config); @@ -584,7 +585,7 @@ getAllPerFilterConfig(const Http::StreamFilterCallbacks* callbacks) { ENVOY_LOG_MISC(debug, "Failed to retrieve the correct type of route specific filter config"); continue; } - all_configs.push_back(typed_config); + all_configs.push_back(*typed_config); } return all_configs; diff --git a/source/extensions/filters/http/cors/cors_filter.cc b/source/extensions/filters/http/cors/cors_filter.cc index 98ecb2a17c..49fba6d4a5 100644 --- a/source/extensions/filters/http/cors/cors_filter.cc +++ b/source/extensions/filters/http/cors/cors_filter.cc @@ -66,10 +66,17 @@ void CorsFilter::initializeCorsPolicies() { // If no cors policy is configured in the per filter config, then the cors policy fields in the // route configuration will be ignored. if (policies_.empty()) { - policies_ = { - decoder_callbacks_->route()->routeEntry()->corsPolicy(), - decoder_callbacks_->route()->virtualHost().corsPolicy(), - }; + const auto route = decoder_callbacks_->route(); + ASSERT(route != nullptr); + ASSERT(route->routeEntry() != nullptr); + + if (auto* typed_cfg = route->routeEntry()->corsPolicy(); typed_cfg != nullptr) { + policies_.push_back(*typed_cfg); + } + + if (auto* typed_cfg = route->virtualHost().corsPolicy(); typed_cfg != nullptr) { + policies_.push_back(*typed_cfg); + } } } @@ -204,11 +211,7 @@ void CorsFilter::setDecoderFilterCallbacks(Http::StreamDecoderFilterCallbacks& c } bool CorsFilter::isOriginAllowed(const Http::HeaderString& origin) { - const auto allow_origins = allowOrigins(); - if (allow_origins == nullptr) { - return false; - } - for (const auto& allow_origin : *allow_origins) { + for (const auto& allow_origin : allowOrigins()) { if (allow_origin->match("*") || allow_origin->match(origin.getStringView())) { return true; } @@ -216,92 +219,88 @@ bool CorsFilter::isOriginAllowed(const Http::HeaderString& origin) { return false; } -const std::vector* CorsFilter::allowOrigins() { - for (const auto policy : policies_) { - if (policy && !policy->allowOrigins().empty()) { - return &policy->allowOrigins(); +absl::Span CorsFilter::allowOrigins() { + for (const Router::CorsPolicy& policy : policies_) { + if (!policy.allowOrigins().empty()) { + return policy.allowOrigins(); } } - return nullptr; + return {}; } bool CorsFilter::forwardNotMatchingPreflights() { - for (const auto policy : policies_) { - if (policy && policy->forwardNotMatchingPreflights()) { - return policy->forwardNotMatchingPreflights().value(); + for (const Router::CorsPolicy& policy : policies_) { + if (policy.forwardNotMatchingPreflights()) { + return policy.forwardNotMatchingPreflights().value(); } } return true; } -const std::string& CorsFilter::allowMethods() { - for (const auto policy : policies_) { - if (policy && !policy->allowMethods().empty()) { - return policy->allowMethods(); +absl::string_view CorsFilter::allowMethods() { + for (const Router::CorsPolicy& policy : policies_) { + if (!policy.allowMethods().empty()) { + return policy.allowMethods(); } } return EMPTY_STRING; } -const std::string& CorsFilter::allowHeaders() { - for (const auto policy : policies_) { - if (policy && !policy->allowHeaders().empty()) { - return policy->allowHeaders(); +absl::string_view CorsFilter::allowHeaders() { + for (const Router::CorsPolicy& policy : policies_) { + if (!policy.allowHeaders().empty()) { + return policy.allowHeaders(); } } return EMPTY_STRING; } -const std::string& CorsFilter::exposeHeaders() { - for (const auto policy : policies_) { - if (policy && !policy->exposeHeaders().empty()) { - return policy->exposeHeaders(); +absl::string_view CorsFilter::exposeHeaders() { + for (const Router::CorsPolicy& policy : policies_) { + if (!policy.exposeHeaders().empty()) { + return policy.exposeHeaders(); } } return EMPTY_STRING; } -const std::string& CorsFilter::maxAge() { - for (const auto policy : policies_) { - if (policy && !policy->maxAge().empty()) { - return policy->maxAge(); +absl::string_view CorsFilter::maxAge() { + for (const Router::CorsPolicy& policy : policies_) { + if (!policy.maxAge().empty()) { + return policy.maxAge(); } } return EMPTY_STRING; } bool CorsFilter::allowCredentials() { - for (const auto policy : policies_) { - if (policy && policy->allowCredentials()) { - return policy->allowCredentials().value(); + for (const Router::CorsPolicy& policy : policies_) { + if (policy.allowCredentials()) { + return policy.allowCredentials().value(); } } return false; } bool CorsFilter::allowPrivateNetworkAccess() { - for (const auto policy : policies_) { - if (policy && policy->allowPrivateNetworkAccess()) { - return policy->allowPrivateNetworkAccess().value(); + for (const Router::CorsPolicy& policy : policies_) { + if (policy.allowPrivateNetworkAccess()) { + return policy.allowPrivateNetworkAccess().value(); } } return false; } bool CorsFilter::shadowEnabled() { - for (const auto policy : policies_) { - if (policy) { - return policy->shadowEnabled(); - } + for (const Router::CorsPolicy& policy : policies_) { + return policy.shadowEnabled(); } return false; } bool CorsFilter::enabled() { - for (const auto policy : policies_) { - if (policy) { - return policy->enabled(); - } + for (const Router::CorsPolicy& policy : policies_) { + return policy.enabled(); } return false; } diff --git a/source/extensions/filters/http/cors/cors_filter.h b/source/extensions/filters/http/cors/cors_filter.h index 0c8cf535a9..a89a488b3f 100644 --- a/source/extensions/filters/http/cors/cors_filter.h +++ b/source/extensions/filters/http/cors/cors_filter.h @@ -88,11 +88,11 @@ class CorsFilter : public Http::StreamFilter { private: friend class CorsFilterTest; - const std::vector* allowOrigins(); - const std::string& allowMethods(); - const std::string& allowHeaders(); - const std::string& exposeHeaders(); - const std::string& maxAge(); + absl::Span allowOrigins(); + absl::string_view allowMethods(); + absl::string_view allowHeaders(); + absl::string_view exposeHeaders(); + absl::string_view maxAge(); bool allowCredentials(); bool allowPrivateNetworkAccess(); bool shadowEnabled(); @@ -102,7 +102,7 @@ class CorsFilter : public Http::StreamFilter { Http::StreamDecoderFilterCallbacks* decoder_callbacks_{}; Http::StreamEncoderFilterCallbacks* encoder_callbacks_{}; - absl::InlinedVector policies_; + absl::InlinedVector, 4> policies_; bool is_cors_request_{}; std::string latched_origin_; diff --git a/source/extensions/filters/http/custom_response/custom_response_filter.cc b/source/extensions/filters/http/custom_response/custom_response_filter.cc index d133c8b753..52e5aefe3e 100644 --- a/source/extensions/filters/http/custom_response/custom_response_filter.cc +++ b/source/extensions/filters/http/custom_response/custom_response_filter.cc @@ -48,13 +48,12 @@ Http::FilterHeadersStatus CustomResponseFilter::encodeHeaders(Http::ResponseHead // policy. Note that since the traversal is least to most specific, we can't // return early when a match is found. PolicySharedPtr policy; - for (const auto* typed_config : + for (const FilterConfig& typed_config : Http::Utility::getAllPerFilterConfig(encoder_callbacks_)) { - ASSERT(typed_config != nullptr); // Check if a match is found first to avoid overwriting policy with an // empty shared_ptr. - auto maybe_policy = typed_config->getPolicy(headers, encoder_callbacks_->streamInfo()); + auto maybe_policy = typed_config.getPolicy(headers, encoder_callbacks_->streamInfo()); if (maybe_policy) { policy = maybe_policy; } diff --git a/source/extensions/filters/http/ext_authz/ext_authz.cc b/source/extensions/filters/http/ext_authz/ext_authz.cc index b1713614ca..962aede2c2 100644 --- a/source/extensions/filters/http/ext_authz/ext_authz.cc +++ b/source/extensions/filters/http/ext_authz/ext_authz.cc @@ -192,13 +192,12 @@ void Filter::initiateCall(const Http::RequestHeaderMap& headers) { } absl::optional maybe_merged_per_route_config; - for (const auto* cfg : + for (const FilterConfigPerRoute& cfg : Http::Utility::getAllPerFilterConfig(decoder_callbacks_)) { - ASSERT(cfg != nullptr); if (maybe_merged_per_route_config.has_value()) { - maybe_merged_per_route_config.value().merge(*cfg); + maybe_merged_per_route_config.value().merge(cfg); } else { - maybe_merged_per_route_config = *cfg; + maybe_merged_per_route_config = cfg; } } diff --git a/source/extensions/filters/http/ext_proc/ext_proc.cc b/source/extensions/filters/http/ext_proc/ext_proc.cc index 8af46dc4da..3013ea1d82 100644 --- a/source/extensions/filters/http/ext_proc/ext_proc.cc +++ b/source/extensions/filters/http/ext_proc/ext_proc.cc @@ -1279,13 +1279,12 @@ void Filter::mergePerRouteConfig() { route_config_merged_ = true; absl::optional merged_config; - for (const auto* typed_cfg : + for (const FilterConfigPerRoute& typed_cfg : Http::Utility::getAllPerFilterConfig(decoder_callbacks_)) { - ASSERT(typed_cfg != nullptr); if (!merged_config.has_value()) { - merged_config.emplace(*typed_cfg); + merged_config.emplace(typed_cfg); } else { - merged_config.emplace(FilterConfigPerRoute(merged_config.value(), *typed_cfg)); + merged_config.emplace(FilterConfigPerRoute(merged_config.value(), typed_cfg)); } } diff --git a/source/extensions/filters/http/header_mutation/header_mutation.cc b/source/extensions/filters/http/header_mutation/header_mutation.cc index e61635a580..259f180d17 100644 --- a/source/extensions/filters/http/header_mutation/header_mutation.cc +++ b/source/extensions/filters/http/header_mutation/header_mutation.cc @@ -46,12 +46,11 @@ Http::FilterHeadersStatus HeaderMutation::decodeHeaders(Http::RequestHeaderMap& // `getAllPerFilterConfig` above returns). // Thus, here we reverse iterate the vector when `most_specific_wins` is false. for (auto it = route_configs_.rbegin(); it != route_configs_.rend(); ++it) { - (*it)->mutations().mutateRequestHeaders(headers, ctx, decoder_callbacks_->streamInfo()); + (*it).get().mutations().mutateRequestHeaders(headers, ctx, decoder_callbacks_->streamInfo()); } } else { - for (const auto* route_config : route_configs_) { - route_config->mutations().mutateRequestHeaders(headers, ctx, - decoder_callbacks_->streamInfo()); + for (const PerRouteHeaderMutation& route_config : route_configs_) { + route_config.mutations().mutateRequestHeaders(headers, ctx, decoder_callbacks_->streamInfo()); } } @@ -70,12 +69,12 @@ Http::FilterHeadersStatus HeaderMutation::encodeHeaders(Http::ResponseHeaderMap& if (!config_->mostSpecificHeaderMutationsWins()) { for (auto it = route_configs_.rbegin(); it != route_configs_.rend(); ++it) { - (*it)->mutations().mutateResponseHeaders(headers, ctx, encoder_callbacks_->streamInfo()); + (*it).get().mutations().mutateResponseHeaders(headers, ctx, encoder_callbacks_->streamInfo()); } } else { - for (const auto* route_config : route_configs_) { - route_config->mutations().mutateResponseHeaders(headers, ctx, - encoder_callbacks_->streamInfo()); + for (const PerRouteHeaderMutation& route_config : route_configs_) { + route_config.mutations().mutateResponseHeaders(headers, ctx, + encoder_callbacks_->streamInfo()); } } diff --git a/source/extensions/filters/http/header_mutation/header_mutation.h b/source/extensions/filters/http/header_mutation/header_mutation.h index 5286d83404..254c9ca076 100644 --- a/source/extensions/filters/http/header_mutation/header_mutation.h +++ b/source/extensions/filters/http/header_mutation/header_mutation.h @@ -82,7 +82,7 @@ class HeaderMutation : public Http::PassThroughFilter, public Logger::Loggable route_configs_{}; + absl::InlinedVector, 4> route_configs_{}; }; } // namespace HeaderMutation diff --git a/test/extensions/filters/http/cors/cors_filter_test.cc b/test/extensions/filters/http/cors/cors_filter_test.cc index c699fe543e..17c1c5818d 100644 --- a/test/extensions/filters/http/cors/cors_filter_test.cc +++ b/test/extensions/filters/http/cors/cors_filter_test.cc @@ -87,8 +87,8 @@ TEST_F(CorsFilterTest, InitializeCorsPoliciesTest) { EXPECT_EQ(Http::FilterHeadersStatus::Continue, filter_.decodeHeaders(request_headers, true)); EXPECT_EQ(false, isCorsRequest()); EXPECT_EQ(2, filter_.policiesForTest().size()); - EXPECT_EQ(cors_policy_.get(), filter_.policiesForTest().at(0)); - EXPECT_EQ(cors_policy_.get(), filter_.policiesForTest().at(1)); + EXPECT_EQ(cors_policy_.get(), &filter_.policiesForTest().at(0).get()); + EXPECT_EQ(cors_policy_.get(), &filter_.policiesForTest().at(1).get()); } // Only 'typed_per_filter_config' of virtual host has cors policy. @@ -104,7 +104,7 @@ TEST_F(CorsFilterTest, InitializeCorsPoliciesTest) { EXPECT_EQ(Http::FilterHeadersStatus::Continue, filter_.decodeHeaders(request_headers, true)); EXPECT_EQ(false, isCorsRequest()); EXPECT_EQ(1, filter_.policiesForTest().size()); - EXPECT_EQ(cors_policy_.get(), filter_.policiesForTest().at(0)); + EXPECT_EQ(cors_policy_.get(), &filter_.policiesForTest().at(0).get()); } // No cors policy in the 'typed_per_filter_config'. @@ -121,9 +121,7 @@ TEST_F(CorsFilterTest, InitializeCorsPoliciesTest) { EXPECT_EQ(Http::FilterHeadersStatus::Continue, filter_.decodeHeaders(request_headers, true)); EXPECT_EQ(false, isCorsRequest()); - EXPECT_EQ(2, filter_.policiesForTest().size()); - EXPECT_EQ(nullptr, filter_.policiesForTest().at(0)); - EXPECT_EQ(nullptr, filter_.policiesForTest().at(1)); + EXPECT_EQ(0, filter_.policiesForTest().size()); } { filter_ = CorsFilter(config_); @@ -139,9 +137,8 @@ TEST_F(CorsFilterTest, InitializeCorsPoliciesTest) { EXPECT_EQ(Http::FilterHeadersStatus::Continue, filter_.decodeHeaders(request_headers, true)); EXPECT_EQ(false, isCorsRequest()); - EXPECT_EQ(2, filter_.policiesForTest().size()); - EXPECT_EQ(cors_policy_.get(), filter_.policiesForTest().at(0)); - EXPECT_EQ(nullptr, filter_.policiesForTest().at(1)); + EXPECT_EQ(1, filter_.policiesForTest().size()); + EXPECT_EQ(cors_policy_.get(), &filter_.policiesForTest().at(0).get()); } { filter_ = CorsFilter(config_); @@ -157,9 +154,8 @@ TEST_F(CorsFilterTest, InitializeCorsPoliciesTest) { EXPECT_EQ(Http::FilterHeadersStatus::Continue, filter_.decodeHeaders(request_headers, false)); EXPECT_EQ(false, isCorsRequest()); - EXPECT_EQ(2, filter_.policiesForTest().size()); - EXPECT_EQ(nullptr, filter_.policiesForTest().at(0)); - EXPECT_EQ(cors_policy_.get(), filter_.policiesForTest().at(1)); + EXPECT_EQ(1, filter_.policiesForTest().size()); + EXPECT_EQ(cors_policy_.get(), &filter_.policiesForTest().at(0).get()); } } From 634f71e38b706b10d3591098dbda5eb65fc34097 Mon Sep 17 00:00:00 2001 From: alyssawilk Date: Tue, 17 Sep 2024 10:02:41 -0400 Subject: [PATCH 02/65] formatter: removing exceptions from substitution format string (#36168) Risk Level: low Testing: updated tests Docs Changes: n/a Release Notes: n/a https://github.com/envoyproxy/envoy-mobile/issues/176 Signed-off-by: Alyssa Wilk --- .../formatter/substitution_format_string.h | 24 ++++++----- source/common/local_reply/local_reply.cc | 4 +- source/common/tcp_proxy/tcp_proxy.cc | 6 ++- .../common/stream_access_log_common_impl.h | 5 ++- .../extensions/access_loggers/file/config.cc | 13 ++++-- .../access_loggers/fluentd/config.cc | 6 ++- .../access_loggers/open_telemetry/config.cc | 5 ++- .../common/set_filter_state/filter_config.cc | 6 ++- .../network/generic_proxy/file_access_log.h | 16 ++++--- .../filters/udp/udp_proxy/config.cc | 12 ++++-- .../local_response_policy.cc | 6 ++- .../matching/actions/format_string/config.cc | 5 ++- .../substitution_format_string_test.cc | 43 +++++++++---------- .../open_telemetry/access_log_impl_test.cc | 2 +- .../substitution_formatter_test.cc | 2 +- .../network/generic_proxy/proxy_test.cc | 2 +- test/extensions/formatter/cel/cel_test.cc | 14 +++--- .../formatter/metadata/metadata_test.cc | 4 +- .../req_without_query_test.cc | 15 ++++--- tools/code_format/config.yaml | 1 - 20 files changed, 109 insertions(+), 82 deletions(-) diff --git a/source/common/formatter/substitution_format_string.h b/source/common/formatter/substitution_format_string.h index fc1d6f5e6e..c66c77eaff 100644 --- a/source/common/formatter/substitution_format_string.h +++ b/source/common/formatter/substitution_format_string.h @@ -29,7 +29,7 @@ class SubstitutionFormatStringUtils { * Parse list of formatter configurations to commands. */ template - static std::vector> + static absl::StatusOr>> parseFormatters(const FormattersConfig& formatters, Server::Configuration::GenericFactoryContext& context) { std::vector> commands; @@ -37,13 +37,13 @@ class SubstitutionFormatStringUtils { auto* factory = Envoy::Config::Utility::getFactory>(formatter); if (!factory) { - throwEnvoyExceptionOrPanic(absl::StrCat("Formatter not found: ", formatter.name())); + return absl::InvalidArgumentError(absl::StrCat("Formatter not found: ", formatter.name())); } auto typed_config = Envoy::Config::Utility::translateAnyToFactoryConfig( formatter.typed_config(), context.messageValidationVisitor(), *factory); auto parser = factory->createCommandParserFromProto(*typed_config, context); if (!parser) { - throwEnvoyExceptionOrPanic( + return absl::InvalidArgumentError( absl::StrCat("Failed to create command parser: ", formatter.name())); } commands.push_back(std::move(parser)); @@ -56,26 +56,28 @@ class SubstitutionFormatStringUtils { * Generate a formatter object from config SubstitutionFormatString. */ template - static FormatterBasePtr + static absl::StatusOr> fromProtoConfig(const envoy::config::core::v3::SubstitutionFormatString& config, Server::Configuration::GenericFactoryContext& context) { // Instantiate formatter extensions. auto commands = parseFormatters(config.formatters(), context); + RETURN_IF_NOT_OK_REF(commands.status()); switch (config.format_case()) { case envoy::config::core::v3::SubstitutionFormatString::FormatCase::kTextFormat: return std::make_unique>( - config.text_format(), config.omit_empty_values(), commands); + config.text_format(), config.omit_empty_values(), *commands); case envoy::config::core::v3::SubstitutionFormatString::FormatCase::kJsonFormat: return createJsonFormatter( config.json_format(), true, config.omit_empty_values(), config.has_json_format_options() ? config.json_format_options().sort_properties() : false, - commands); - case envoy::config::core::v3::SubstitutionFormatString::FormatCase::kTextFormatSource: + *commands); + case envoy::config::core::v3::SubstitutionFormatString::FormatCase::kTextFormatSource: { + auto data_source_or_error = Config::DataSource::read(config.text_format_source(), true, + context.serverFactoryContext().api()); + RETURN_IF_NOT_OK(data_source_or_error.status()); return std::make_unique>( - THROW_OR_RETURN_VALUE(Config::DataSource::read(config.text_format_source(), true, - context.serverFactoryContext().api()), - std::string), - config.omit_empty_values(), commands); + *data_source_or_error, config.omit_empty_values(), *commands); + } case envoy::config::core::v3::SubstitutionFormatString::FormatCase::FORMAT_NOT_SET: PANIC_DUE_TO_PROTO_UNSET; } diff --git a/source/common/local_reply/local_reply.cc b/source/common/local_reply/local_reply.cc index 8de608a225..10bd821388 100644 --- a/source/common/local_reply/local_reply.cc +++ b/source/common/local_reply/local_reply.cc @@ -22,7 +22,9 @@ class BodyFormatter { BodyFormatter(const envoy::config::core::v3::SubstitutionFormatString& config, Server::Configuration::GenericFactoryContext& context) - : formatter_(Formatter::SubstitutionFormatStringUtils::fromProtoConfig(config, context)), + : formatter_(THROW_OR_RETURN_VALUE( + Formatter::SubstitutionFormatStringUtils::fromProtoConfig(config, context), + Formatter::FormatterBasePtr)), content_type_( !config.content_type().empty() ? config.content_type() : config.format_case() == diff --git a/source/common/tcp_proxy/tcp_proxy.cc b/source/common/tcp_proxy/tcp_proxy.cc index 6de501b25d..c4e2e58722 100644 --- a/source/common/tcp_proxy/tcp_proxy.cc +++ b/source/common/tcp_proxy/tcp_proxy.cc @@ -707,8 +707,10 @@ TunnelingConfigHelperImpl::TunnelingConfigHelperImpl( envoy::config::core::v3::SubstitutionFormatString substitution_format_config; substitution_format_config.mutable_text_format_source()->set_inline_string( config_message.tunneling_config().hostname()); - hostname_fmt_ = Formatter::SubstitutionFormatStringUtils::fromProtoConfig( - substitution_format_config, context); + hostname_fmt_ = + THROW_OR_RETURN_VALUE(Formatter::SubstitutionFormatStringUtils::fromProtoConfig( + substitution_format_config, context), + Formatter::FormatterBasePtr); } std::string TunnelingConfigHelperImpl::host(const StreamInfo::StreamInfo& stream_info) const { diff --git a/source/extensions/access_loggers/common/stream_access_log_common_impl.h b/source/extensions/access_loggers/common/stream_access_log_common_impl.h index 1713b91825..5b07233124 100644 --- a/source/extensions/access_loggers/common/stream_access_log_common_impl.h +++ b/source/extensions/access_loggers/common/stream_access_log_common_impl.h @@ -18,8 +18,9 @@ createStreamAccessLogInstance(const Protobuf::Message& config, AccessLog::Filter MessageUtil::downcastAndValidate(config, context.messageValidationVisitor()); Formatter::FormatterPtr formatter; if (fal_config.access_log_format_case() == T::AccessLogFormatCase::kLogFormat) { - formatter = - Formatter::SubstitutionFormatStringUtils::fromProtoConfig(fal_config.log_format(), context); + formatter = THROW_OR_RETURN_VALUE( + Formatter::SubstitutionFormatStringUtils::fromProtoConfig(fal_config.log_format(), context), + Formatter::FormatterBasePtr); } else if (fal_config.access_log_format_case() == T::AccessLogFormatCase::ACCESS_LOG_FORMAT_NOT_SET) { formatter = Formatter::HttpSubstitutionFormatUtils::defaultSubstitutionFormatter(); diff --git a/source/extensions/access_loggers/file/config.cc b/source/extensions/access_loggers/file/config.cc index a21c693436..2761aa5064 100644 --- a/source/extensions/access_loggers/file/config.cc +++ b/source/extensions/access_loggers/file/config.cc @@ -35,7 +35,9 @@ FileAccessLogFactory::createAccessLogInstance(const Protobuf::Message& config, } else { envoy::config::core::v3::SubstitutionFormatString sff_config; sff_config.mutable_text_format_source()->set_inline_string(fal_config.format()); - formatter = Formatter::SubstitutionFormatStringUtils::fromProtoConfig(sff_config, context); + formatter = THROW_OR_RETURN_VALUE( + Formatter::SubstitutionFormatStringUtils::fromProtoConfig(sff_config, context), + Formatter::FormatterBasePtr); } break; case envoy::extensions::access_loggers::file::v3::FileAccessLog::AccessLogFormatCase::kJsonFormat: @@ -46,12 +48,15 @@ FileAccessLogFactory::createAccessLogInstance(const Protobuf::Message& config, kTypedJsonFormat: { envoy::config::core::v3::SubstitutionFormatString sff_config; *sff_config.mutable_json_format() = fal_config.typed_json_format(); - formatter = Formatter::SubstitutionFormatStringUtils::fromProtoConfig(sff_config, context); + formatter = THROW_OR_RETURN_VALUE( + Formatter::SubstitutionFormatStringUtils::fromProtoConfig(sff_config, context), + Formatter::FormatterBasePtr); break; } case envoy::extensions::access_loggers::file::v3::FileAccessLog::AccessLogFormatCase::kLogFormat: - formatter = - Formatter::SubstitutionFormatStringUtils::fromProtoConfig(fal_config.log_format(), context); + formatter = THROW_OR_RETURN_VALUE( + Formatter::SubstitutionFormatStringUtils::fromProtoConfig(fal_config.log_format(), context), + Formatter::FormatterBasePtr); break; case envoy::extensions::access_loggers::file::v3::FileAccessLog::AccessLogFormatCase:: ACCESS_LOG_FORMAT_NOT_SET: diff --git a/source/extensions/access_loggers/fluentd/config.cc b/source/extensions/access_loggers/fluentd/config.cc index 877bd69de2..a6614137e6 100644 --- a/source/extensions/access_loggers/fluentd/config.cc +++ b/source/extensions/access_loggers/fluentd/config.cc @@ -60,8 +60,10 @@ FluentdAccessLogFactory::createAccessLogInstance(const Protobuf::Message& config // payload. // TODO(ohadvano): Improve the formatting operation by creating a dedicated formatter that // will directly serialize the record to msgpack payload. - auto commands = - Formatter::SubstitutionFormatStringUtils::parseFormatters(proto_config.formatters(), context); + auto commands = THROW_OR_RETURN_VALUE( + Formatter::SubstitutionFormatStringUtils::parseFormatters(proto_config.formatters(), context), + std::vector>); + Formatter::FormatterPtr json_formatter = Formatter::SubstitutionFormatStringUtils::createJsonFormatter(proto_config.record(), true, false, false, commands); diff --git a/source/extensions/access_loggers/open_telemetry/config.cc b/source/extensions/access_loggers/open_telemetry/config.cc index 237c5c9fa8..5b9e817f52 100644 --- a/source/extensions/access_loggers/open_telemetry/config.cc +++ b/source/extensions/access_loggers/open_telemetry/config.cc @@ -41,8 +41,9 @@ AccessLogFactory::createAccessLogInstance(const Protobuf::Message& config, const envoy::extensions::access_loggers::open_telemetry::v3::OpenTelemetryAccessLogConfig&>( config, context.messageValidationVisitor()); - auto commands = - Formatter::SubstitutionFormatStringUtils::parseFormatters(proto_config.formatters(), context); + auto commands = THROW_OR_RETURN_VALUE( + Formatter::SubstitutionFormatStringUtils::parseFormatters(proto_config.formatters(), context), + std::vector>); return std::make_shared( std::move(filter), proto_config, context.serverFactoryContext().threadLocal(), diff --git a/source/extensions/filters/common/set_filter_state/filter_config.cc b/source/extensions/filters/common/set_filter_state/filter_config.cc index 5188b097af..a14e672e89 100644 --- a/source/extensions/filters/common/set_filter_state/filter_config.cc +++ b/source/extensions/filters/common/set_filter_state/filter_config.cc @@ -50,8 +50,10 @@ Config::parse(const Protobuf::RepeatedPtrField& proto_val break; } value.skip_if_empty_ = proto_value.skip_if_empty(); - value.value_ = Formatter::SubstitutionFormatStringUtils::fromProtoConfig( - proto_value.format_string(), context); + value.value_ = + THROW_OR_RETURN_VALUE(Formatter::SubstitutionFormatStringUtils::fromProtoConfig( + proto_value.format_string(), context), + Formatter::FormatterBasePtr); values.push_back(std::move(value)); } return values; diff --git a/source/extensions/filters/network/generic_proxy/file_access_log.h b/source/extensions/filters/network/generic_proxy/file_access_log.h index 779b4c08fc..30eabb239e 100644 --- a/source/extensions/filters/network/generic_proxy/file_access_log.h +++ b/source/extensions/filters/network/generic_proxy/file_access_log.h @@ -59,8 +59,9 @@ class FileAccessLogFactoryBase : public AccessLog::AccessLogInstanceFactoryBase< } else { envoy::config::core::v3::SubstitutionFormatString sff_config; sff_config.mutable_text_format_source()->set_inline_string(typed_config.format()); - formatter = - Formatter::SubstitutionFormatStringUtils::fromProtoConfig(sff_config, context); + formatter = THROW_OR_RETURN_VALUE( + Formatter::SubstitutionFormatStringUtils::fromProtoConfig(sff_config, context), + Formatter::FormatterBasePtr); } break; case envoy::extensions::access_loggers::file::v3::FileAccessLog::AccessLogFormatCase:: @@ -72,14 +73,17 @@ class FileAccessLogFactoryBase : public AccessLog::AccessLogInstanceFactoryBase< kTypedJsonFormat: { envoy::config::core::v3::SubstitutionFormatString sff_config; *sff_config.mutable_json_format() = typed_config.typed_json_format(); - formatter = - Formatter::SubstitutionFormatStringUtils::fromProtoConfig(sff_config, context); + formatter = THROW_OR_RETURN_VALUE( + Formatter::SubstitutionFormatStringUtils::fromProtoConfig(sff_config, context), + Formatter::FormatterBasePtr); break; } case envoy::extensions::access_loggers::file::v3::FileAccessLog::AccessLogFormatCase:: kLogFormat: - formatter = Formatter::SubstitutionFormatStringUtils::fromProtoConfig( - typed_config.log_format(), context); + formatter = + THROW_OR_RETURN_VALUE(Formatter::SubstitutionFormatStringUtils::fromProtoConfig( + typed_config.log_format(), context), + Formatter::FormatterBasePtr); break; case envoy::extensions::access_loggers::file::v3::FileAccessLog::AccessLogFormatCase:: ACCESS_LOG_FORMAT_NOT_SET: diff --git a/source/extensions/filters/udp/udp_proxy/config.cc b/source/extensions/filters/udp/udp_proxy/config.cc index 436368faf0..200e7099c7 100644 --- a/source/extensions/filters/udp/udp_proxy/config.cc +++ b/source/extensions/filters/udp/udp_proxy/config.cc @@ -61,8 +61,10 @@ TunnelingConfigImpl::TunnelingConfigImpl(const TunnelingConfig& config, envoy::config::core::v3::SubstitutionFormatString proxy_substitution_format_config; proxy_substitution_format_config.mutable_text_format_source()->set_inline_string( config.proxy_host()); - proxy_host_formatter_ = Formatter::SubstitutionFormatStringUtils::fromProtoConfig( - proxy_substitution_format_config, context); + proxy_host_formatter_ = + THROW_OR_RETURN_VALUE(Formatter::SubstitutionFormatStringUtils::fromProtoConfig( + proxy_substitution_format_config, context), + Formatter::FormatterBasePtr); if (config.has_proxy_port()) { uint32_t port = config.proxy_port().value(); @@ -76,8 +78,10 @@ TunnelingConfigImpl::TunnelingConfigImpl(const TunnelingConfig& config, envoy::config::core::v3::SubstitutionFormatString target_substitution_format_config; target_substitution_format_config.mutable_text_format_source()->set_inline_string( config.target_host()); - target_host_formatter_ = Formatter::SubstitutionFormatStringUtils::fromProtoConfig( - target_substitution_format_config, context); + target_host_formatter_ = + THROW_OR_RETURN_VALUE(Formatter::SubstitutionFormatStringUtils::fromProtoConfig( + target_substitution_format_config, context), + Formatter::FormatterBasePtr); } UdpProxyFilterConfigImpl::UdpProxyFilterConfigImpl( diff --git a/source/extensions/http/custom_response/local_response_policy/local_response_policy.cc b/source/extensions/http/custom_response/local_response_policy/local_response_policy.cc index 4880fb2098..4777165781 100644 --- a/source/extensions/http/custom_response/local_response_policy/local_response_policy.cc +++ b/source/extensions/http/custom_response/local_response_policy/local_response_policy.cc @@ -39,8 +39,10 @@ LocalResponsePolicy::LocalResponsePolicy( // by this PR and will be fixed in the future. Server::GenericFactoryContextImpl generic_context(context, context.messageValidationVisitor()); if (config.has_body_format()) { - formatter_ = Formatter::SubstitutionFormatStringUtils::fromProtoConfig(config.body_format(), - generic_context); + formatter_ = + THROW_OR_RETURN_VALUE(Formatter::SubstitutionFormatStringUtils::fromProtoConfig( + config.body_format(), generic_context), + Formatter::FormatterBasePtr); } } diff --git a/source/extensions/matching/actions/format_string/config.cc b/source/extensions/matching/actions/format_string/config.cc index ff8cb31418..3de72f9ec1 100644 --- a/source/extensions/matching/actions/format_string/config.cc +++ b/source/extensions/matching/actions/format_string/config.cc @@ -32,8 +32,9 @@ ActionFactory::createActionFactoryCb(const Protobuf::Message& proto_config, proto_config, validator); Server::GenericFactoryContextImpl generic_context(context, validator); - Formatter::FormatterConstSharedPtr formatter = - Formatter::SubstitutionFormatStringUtils::fromProtoConfig(config, generic_context); + Formatter::FormatterConstSharedPtr formatter = THROW_OR_RETURN_VALUE( + Formatter::SubstitutionFormatStringUtils::fromProtoConfig(config, generic_context), + Formatter::FormatterBasePtr); return [formatter]() { return std::make_unique(formatter); }; } diff --git a/test/common/formatter/substitution_format_string_test.cc b/test/common/formatter/substitution_format_string_test.cc index 6d74620d2a..e2d01dd133 100644 --- a/test/common/formatter/substitution_format_string_test.cc +++ b/test/common/formatter/substitution_format_string_test.cc @@ -47,7 +47,7 @@ TEST_F(SubstitutionFormatStringUtilsTest, TestFromProtoConfigText) { )EOF"; TestUtility::loadFromYaml(yaml, config_); - auto formatter = SubstitutionFormatStringUtils::fromProtoConfig(config_, context_); + auto formatter = *SubstitutionFormatStringUtils::fromProtoConfig(config_, context_); EXPECT_EQ("plain text, path=/bar/foo, code=200", formatter->formatWithContext(formatter_context_, stream_info_)); } @@ -63,7 +63,7 @@ TEST_F(SubstitutionFormatStringUtilsTest, TestFromProtoConfigJson) { )EOF"; TestUtility::loadFromYaml(yaml, config_); - auto formatter = SubstitutionFormatStringUtils::fromProtoConfig(config_, context_); + auto formatter = *SubstitutionFormatStringUtils::fromProtoConfig(config_, context_); const auto out_json = formatter->formatWithContext(formatter_context_, stream_info_); const std::string expected = R"EOF({ @@ -86,10 +86,11 @@ TEST_F(SubstitutionFormatStringUtilsTest, TestInvalidConfigs) { }; for (const auto& yaml : invalid_configs) { TestUtility::loadFromYaml(yaml, config_); - EXPECT_THROW_WITH_MESSAGE(SubstitutionFormatStringUtils::fromProtoConfig(config_, context_), - EnvoyException, - "Only string values, nested structs, list values and number values " - "are supported in structured access log format."); + EXPECT_THROW_WITH_MESSAGE( + SubstitutionFormatStringUtils::fromProtoConfig(config_, context_).IgnoreError(), + EnvoyException, + "Only string values, nested structs, list values and number values " + "are supported in structured access log format."); } } @@ -107,7 +108,7 @@ TEST_F(SubstitutionFormatStringUtilsTest, TestFromProtoConfigFormatterExtension) )EOF"; TestUtility::loadFromYaml(yaml, config_); - auto formatter = SubstitutionFormatStringUtils::fromProtoConfig(config_, context_); + auto formatter = *SubstitutionFormatStringUtils::fromProtoConfig(config_, context_); EXPECT_EQ("plain text TestFormatter", formatter->formatWithContext(formatter_context_, stream_info_)); } @@ -127,9 +128,8 @@ TEST_F(SubstitutionFormatStringUtilsTest, )EOF"; TestUtility::loadFromYaml(yaml, config_); - EXPECT_THROW_WITH_MESSAGE(SubstitutionFormatStringUtils::fromProtoConfig(config_, context_), - EnvoyException, - "Failed to create command parser: envoy.formatter.FailFormatter"); + EXPECT_EQ(SubstitutionFormatStringUtils::fromProtoConfig(config_, context_).status().message(), + "Failed to create command parser: envoy.formatter.FailFormatter"); } TEST_F(SubstitutionFormatStringUtilsTest, TestFromProtoConfigFormatterExtensionUnknown) { @@ -143,9 +143,8 @@ TEST_F(SubstitutionFormatStringUtilsTest, TestFromProtoConfigFormatterExtensionU )EOF"; TestUtility::loadFromYaml(yaml, config_); - EXPECT_THROW_WITH_MESSAGE(SubstitutionFormatStringUtils::fromProtoConfig(config_, context_), - EnvoyException, - "Formatter not found: envoy.formatter.TestFormatterUnknown"); + EXPECT_EQ(SubstitutionFormatStringUtils::fromProtoConfig(config_, context_).status().message(), + "Formatter not found: envoy.formatter.TestFormatterUnknown"); } TEST_F(SubstitutionFormatStringUtilsTest, TestFromProtoConfigJsonWithExtension) { @@ -166,7 +165,7 @@ TEST_F(SubstitutionFormatStringUtilsTest, TestFromProtoConfigJsonWithExtension) )EOF"; TestUtility::loadFromYaml(yaml, config_); - auto formatter = SubstitutionFormatStringUtils::fromProtoConfig(config_, context_); + auto formatter = *SubstitutionFormatStringUtils::fromProtoConfig(config_, context_); const auto out_json = formatter->formatWithContext(formatter_context_, stream_info_); const std::string expected = R"EOF({ @@ -201,7 +200,7 @@ TEST_F(SubstitutionFormatStringUtilsTest, TestFromProtoConfigJsonWithMultipleExt )EOF"; TestUtility::loadFromYaml(yaml, config_); - auto formatter = SubstitutionFormatStringUtils::fromProtoConfig(config_, context_); + auto formatter = *SubstitutionFormatStringUtils::fromProtoConfig(config_, context_); const auto out_json = formatter->formatWithContext(formatter_context_, stream_info_); const std::string expected = R"EOF({ @@ -225,9 +224,8 @@ TEST_F(SubstitutionFormatStringUtilsTest, TestParseFormattersWithUnknownExtensio TestUtility::loadFromYaml(yaml, proto); *entry1 = proto; - EXPECT_THROW_WITH_MESSAGE(SubstitutionFormatStringUtils::parseFormatters(config, context_), - EnvoyException, - "Formatter not found: envoy.formatter.TestFormatterUnknown"); + EXPECT_EQ(SubstitutionFormatStringUtils::parseFormatters(config, context_).status().message(), + "Formatter not found: envoy.formatter.TestFormatterUnknown"); } TEST_F(SubstitutionFormatStringUtilsTest, TestParseFormattersWithInvalidFormatter) { @@ -246,9 +244,8 @@ TEST_F(SubstitutionFormatStringUtilsTest, TestParseFormattersWithInvalidFormatte TestUtility::loadFromYaml(yaml, proto); *entry1 = proto; - EXPECT_THROW_WITH_MESSAGE(SubstitutionFormatStringUtils::parseFormatters(config, context_), - EnvoyException, - "Failed to create command parser: envoy.formatter.FailFormatter"); + EXPECT_EQ(SubstitutionFormatStringUtils::parseFormatters(config, context_).status().message(), + "Failed to create command parser: envoy.formatter.FailFormatter"); } TEST_F(SubstitutionFormatStringUtilsTest, TestParseFormattersWithSingleExtension) { @@ -267,7 +264,7 @@ TEST_F(SubstitutionFormatStringUtilsTest, TestParseFormattersWithSingleExtension TestUtility::loadFromYaml(yaml, proto); *entry1 = proto; - auto commands = SubstitutionFormatStringUtils::parseFormatters(config, context_); + auto commands = *SubstitutionFormatStringUtils::parseFormatters(config, context_); ASSERT_EQ(1, commands.size()); absl::optional max_length = {}; @@ -306,7 +303,7 @@ TEST_F(SubstitutionFormatStringUtilsTest, TestParseFormattersWithMultipleExtensi TestUtility::loadFromYaml(additional_command_yaml, additional_command_proto); *entry2 = additional_command_proto; - auto commands = SubstitutionFormatStringUtils::parseFormatters(config, context_); + auto commands = *SubstitutionFormatStringUtils::parseFormatters(config, context_); ASSERT_EQ(2, commands.size()); absl::optional max_length = {}; diff --git a/test/extensions/access_loggers/open_telemetry/access_log_impl_test.cc b/test/extensions/access_loggers/open_telemetry/access_log_impl_test.cc index 532d2b288e..db253e6680 100644 --- a/test/extensions/access_loggers/open_telemetry/access_log_impl_test.cc +++ b/test/extensions/access_loggers/open_telemetry/access_log_impl_test.cc @@ -84,7 +84,7 @@ class AccessLogTest : public testing::Test { return logger_; }); auto commands = - Formatter::SubstitutionFormatStringUtils::parseFormatters(config_.formatters(), context_); + *Formatter::SubstitutionFormatStringUtils::parseFormatters(config_.formatters(), context_); return std::make_unique(FilterPtr{filter_}, config_, tls_, logger_cache_, commands); } diff --git a/test/extensions/access_loggers/open_telemetry/substitution_formatter_test.cc b/test/extensions/access_loggers/open_telemetry/substitution_formatter_test.cc index 54fe710a47..ab51c3eb2e 100644 --- a/test/extensions/access_loggers/open_telemetry/substitution_formatter_test.cc +++ b/test/extensions/access_loggers/open_telemetry/substitution_formatter_test.cc @@ -915,7 +915,7 @@ TEST(SubstitutionFormatterTest, CELFormatterTest) { "@type": type.googleapis.com/envoy.extensions.formatter.cel.v3.Cel )EOF", otel_config); - auto commands = Formatter::SubstitutionFormatStringUtils::parseFormatters( + auto commands = *Formatter::SubstitutionFormatStringUtils::parseFormatters( otel_config.formatters(), context); OpenTelemetryFormatter formatter(otel_config.resource_attributes(), commands); diff --git a/test/extensions/filters/network/generic_proxy/proxy_test.cc b/test/extensions/filters/network/generic_proxy/proxy_test.cc index 6f6121a64d..31900ba301 100644 --- a/test/extensions/filters/network/generic_proxy/proxy_test.cc +++ b/test/extensions/filters/network/generic_proxy/proxy_test.cc @@ -108,7 +108,7 @@ class FilterConfigTest : public testing::Test { envoy::config::core::v3::SubstitutionFormatString sff_config; sff_config.mutable_text_format_source()->set_inline_string(format); auto formatter = - Envoy::Formatter::SubstitutionFormatStringUtils::fromProtoConfig( + *Envoy::Formatter::SubstitutionFormatStringUtils::fromProtoConfig( sff_config, factory_context_); return std::make_shared( diff --git a/test/extensions/formatter/cel/cel_test.cc b/test/extensions/formatter/cel/cel_test.cc index 77f9d1b69d..ff4e4425cd 100644 --- a/test/extensions/formatter/cel/cel_test.cc +++ b/test/extensions/formatter/cel/cel_test.cc @@ -77,7 +77,7 @@ TEST_F(CELFormatterTest, TestRequestHeader) { TestUtility::loadFromYaml(yaml, config_); auto formatter = - Envoy::Formatter::SubstitutionFormatStringUtils::fromProtoConfig(config_, context_); + *Envoy::Formatter::SubstitutionFormatStringUtils::fromProtoConfig(config_, context_); EXPECT_EQ("GET", formatter->formatWithContext(formatter_context_, stream_info_)); } @@ -93,7 +93,7 @@ TEST_F(CELFormatterTest, TestMissingRequestHeader) { TestUtility::loadFromYaml(yaml, config_); auto formatter = - Envoy::Formatter::SubstitutionFormatStringUtils::fromProtoConfig(config_, context_); + *Envoy::Formatter::SubstitutionFormatStringUtils::fromProtoConfig(config_, context_); EXPECT_EQ("-", formatter->formatWithContext(formatter_context_, stream_info_)); } @@ -109,7 +109,7 @@ TEST_F(CELFormatterTest, TestWithoutMaxLength) { TestUtility::loadFromYaml(yaml, config_); auto formatter = - Envoy::Formatter::SubstitutionFormatStringUtils::fromProtoConfig(config_, context_); + *Envoy::Formatter::SubstitutionFormatStringUtils::fromProtoConfig(config_, context_); EXPECT_EQ("/original/path?secret=parameter", formatter->formatWithContext(formatter_context_, stream_info_)); } @@ -126,7 +126,7 @@ TEST_F(CELFormatterTest, TestMaxLength) { TestUtility::loadFromYaml(yaml, config_); auto formatter = - Envoy::Formatter::SubstitutionFormatStringUtils::fromProtoConfig(config_, context_); + *Envoy::Formatter::SubstitutionFormatStringUtils::fromProtoConfig(config_, context_); EXPECT_EQ("/original", formatter->formatWithContext(formatter_context_, stream_info_)); } @@ -142,7 +142,7 @@ TEST_F(CELFormatterTest, TestContains) { TestUtility::loadFromYaml(yaml, config_); auto formatter = - Envoy::Formatter::SubstitutionFormatStringUtils::fromProtoConfig(config_, context_); + *Envoy::Formatter::SubstitutionFormatStringUtils::fromProtoConfig(config_, context_); EXPECT_EQ("true", formatter->formatWithContext(formatter_context_, stream_info_)); } @@ -158,7 +158,7 @@ TEST_F(CELFormatterTest, TestComplexCelExpression) { TestUtility::loadFromYaml(yaml, config_); auto formatter = - Envoy::Formatter::SubstitutionFormatStringUtils::fromProtoConfig(config_, context_); + *Envoy::Formatter::SubstitutionFormatStringUtils::fromProtoConfig(config_, context_); EXPECT_EQ("true /original false", formatter->formatWithContext(formatter_context_, stream_info_)); } @@ -174,7 +174,7 @@ TEST_F(CELFormatterTest, TestInvalidExpression) { TestUtility::loadFromYaml(yaml, config_); EXPECT_THROW_WITH_REGEX( - Envoy::Formatter::SubstitutionFormatStringUtils::fromProtoConfig(config_, context_), + *Envoy::Formatter::SubstitutionFormatStringUtils::fromProtoConfig(config_, context_), EnvoyException, "Not able to parse filter expression: .*"); } #endif diff --git a/test/extensions/formatter/metadata/metadata_test.cc b/test/extensions/formatter/metadata/metadata_test.cc index acb03df661..f6d434036f 100644 --- a/test/extensions/formatter/metadata/metadata_test.cc +++ b/test/extensions/formatter/metadata/metadata_test.cc @@ -37,7 +37,9 @@ class MetadataFormatterTest : public ::testing::Test { )EOF", tag, type); TestUtility::loadFromYaml(yaml, config_); - return Envoy::Formatter::SubstitutionFormatStringUtils::fromProtoConfig(config_, context_); + return THROW_OR_RETURN_VALUE( + Envoy::Formatter::SubstitutionFormatStringUtils::fromProtoConfig(config_, context_), + Envoy::Formatter::FormatterBasePtr); } Http::TestRequestHeaderMapImpl request_headers_; diff --git a/test/extensions/formatter/req_without_query/req_without_query_test.cc b/test/extensions/formatter/req_without_query/req_without_query_test.cc index bda43e2626..e019ef4e91 100644 --- a/test/extensions/formatter/req_without_query/req_without_query_test.cc +++ b/test/extensions/formatter/req_without_query/req_without_query_test.cc @@ -44,7 +44,7 @@ TEST_F(ReqWithoutQueryTest, TestStripQueryString) { TestUtility::loadFromYaml(yaml, config_); auto formatter = - Envoy::Formatter::SubstitutionFormatStringUtils::fromProtoConfig(config_, context_); + *Envoy::Formatter::SubstitutionFormatStringUtils::fromProtoConfig(config_, context_); EXPECT_EQ("/request/path", formatter->formatWithContext(formatter_context_, stream_info_)); } @@ -61,7 +61,7 @@ TEST_F(ReqWithoutQueryTest, TestSelectMainHeader) { TestUtility::loadFromYaml(yaml, config_); auto formatter = - Envoy::Formatter::SubstitutionFormatStringUtils::fromProtoConfig(config_, context_); + *Envoy::Formatter::SubstitutionFormatStringUtils::fromProtoConfig(config_, context_); EXPECT_EQ("/original/path", formatter->formatWithContext(formatter_context_, stream_info_)); } @@ -78,7 +78,7 @@ TEST_F(ReqWithoutQueryTest, TestSelectAlternativeHeader) { TestUtility::loadFromYaml(yaml, config_); auto formatter = - Envoy::Formatter::SubstitutionFormatStringUtils::fromProtoConfig(config_, context_); + *Envoy::Formatter::SubstitutionFormatStringUtils::fromProtoConfig(config_, context_); EXPECT_EQ("/request/path", formatter->formatWithContext(formatter_context_, stream_info_)); } @@ -95,7 +95,7 @@ TEST_F(ReqWithoutQueryTest, TestTruncateHeader) { TestUtility::loadFromYaml(yaml, config_); auto formatter = - Envoy::Formatter::SubstitutionFormatStringUtils::fromProtoConfig(config_, context_); + *Envoy::Formatter::SubstitutionFormatStringUtils::fromProtoConfig(config_, context_); EXPECT_EQ("/requ", formatter->formatWithContext(formatter_context_, stream_info_)); } @@ -112,7 +112,7 @@ TEST_F(ReqWithoutQueryTest, TestNonExistingHeader) { TestUtility::loadFromYaml(yaml, config_); auto formatter = - Envoy::Formatter::SubstitutionFormatStringUtils::fromProtoConfig(config_, context_); + *Envoy::Formatter::SubstitutionFormatStringUtils::fromProtoConfig(config_, context_); EXPECT_EQ("-", formatter->formatWithContext(formatter_context_, stream_info_)); } @@ -139,7 +139,7 @@ TEST_F(ReqWithoutQueryTest, TestFormatJson) { TestUtility::loadFromYaml(yaml, config_); auto formatter = - Envoy::Formatter::SubstitutionFormatStringUtils::fromProtoConfig(config_, context_); + *Envoy::Formatter::SubstitutionFormatStringUtils::fromProtoConfig(config_, context_); const std::string actual = formatter->formatWithContext(formatter_context_, stream_info_); EXPECT_TRUE(TestUtility::jsonStringEqual(actual, expected)); } @@ -156,7 +156,8 @@ TEST_F(ReqWithoutQueryTest, TestParserNotRecognizingCommand) { )EOF"; TestUtility::loadFromYaml(yaml, config_); - EXPECT_THROW(Envoy::Formatter::SubstitutionFormatStringUtils::fromProtoConfig(config_, context_), + EXPECT_THROW(Envoy::Formatter::SubstitutionFormatStringUtils::fromProtoConfig(config_, context_) + .IgnoreError(), EnvoyException); } diff --git a/tools/code_format/config.yaml b/tools/code_format/config.yaml index 286208a3ba..bbc5d3f81d 100644 --- a/tools/code_format/config.yaml +++ b/tools/code_format/config.yaml @@ -110,7 +110,6 @@ paths: - source/common/formatter/stream_info_formatter.h - source/common/formatter/stream_info_formatter.cc - source/common/formatter/substitution_formatter.h - - source/common/formatter/substitution_format_string.h - source/common/stats/tag_extractor_impl.cc - source/common/protobuf/yaml_utility.cc - source/common/protobuf/utility.cc From 6c2e7ebef4aa41d9700d59e2316b118dcbf912b0 Mon Sep 17 00:00:00 2001 From: alyssawilk Date: Tue, 17 Sep 2024 11:59:00 -0400 Subject: [PATCH 03/65] docs: update owners to reflect RedHat access (#36183) Removing an employee who has moved on. Signed-off-by: Alyssa Wilk --- OWNERS.md | 1 - 1 file changed, 1 deletion(-) diff --git a/OWNERS.md b/OWNERS.md index c001eb66a1..3ba38ffed2 100644 --- a/OWNERS.md +++ b/OWNERS.md @@ -76,7 +76,6 @@ without further review. * All senior maintainers * Tony Allen ([tonya11en](https://github.com/tonya11en)) (tony@allen.gg) -* Otto van der Schaaf ([oschaaf](https://github.com/oschaaf)) (oschaaf@redhat.com) * Tim Walsh ([twghu](https://github.com/twghu)) (twalsh@redhat.com) * Pradeep Rao ([pradeepcrao](https://github.com/pradeepcrao)) (pcrao@google.com) * Kateryna Nezdolii ([nezdolik](https://github.com/nezdolik)) (kateryna.nezdolii@gmail.com) From a1e12cd10f26eaa741e31bbf0770e8baee75dfe7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20R=2E=20Sede=C3=B1o?= Date: Tue, 17 Sep 2024 12:38:37 -0400 Subject: [PATCH 04/65] bump googleapis (#36182) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Risk Level: low Testing: Signed-off-by: Alejandro R SedeƱo --- api/bazel/repository_locations.bzl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/api/bazel/repository_locations.bzl b/api/bazel/repository_locations.bzl index 6c353c8591..dc3c4389c3 100644 --- a/api/bazel/repository_locations.bzl +++ b/api/bazel/repository_locations.bzl @@ -79,9 +79,9 @@ REPOSITORY_LOCATIONS_SPEC = dict( project_name = "Google APIs", project_desc = "Public interface definitions of Google APIs", project_url = "https://github.com/googleapis/googleapis", - version = "114a745b2841a044e98cdbb19358ed29fcf4a5f1", - sha256 = "9b4e0d0a04a217c06b426aefd03b82581a9510ca766d2d1c70e52bb2ad4a0703", - release_date = "2023-01-10", + version = "fd52b5754b2b268bc3a22a10f29844f206abb327", + sha256 = "97fc354dddfd3ea03e7bf2ad74129291ed6fad7ff39d3bd8daec738a3672eb8a", + release_date = "2024-09-16", strip_prefix = "googleapis-{version}", urls = ["https://github.com/googleapis/googleapis/archive/{version}.tar.gz"], use_category = ["api"], From cea046f058c29d727ada8aea92316089e6451694 Mon Sep 17 00:00:00 2001 From: bsurber <73970703+bsurber@users.noreply.github.com> Date: Tue, 17 Sep 2024 12:54:19 -0700 Subject: [PATCH 05/65] rlqs: Implement RLQS stream restarts if the stream goes down mid-use. (#36170) Commit Message: Implement RLQS stream restarts if the stream goes down mid-use. Additional Description: Stream restarts are done during periodic usage reporting, which limits retry spam while backends are offline. Risk Level: Testing: Integration testing updated to exercise the filter before and after stream closure. Docs Changes: Release Notes: Platform Specific Features: --------- Signed-off-by: Brian Surber --- .../filters/http/rate_limit_quota/client.h | 2 +- .../http/rate_limit_quota/client_impl.cc | 36 +++++++----- .../http/rate_limit_quota/client_impl.h | 2 +- .../filters/http/rate_limit_quota/filter.cc | 2 +- .../http/rate_limit_quota/client_test.cc | 33 ++++++++++- .../http/rate_limit_quota/client_test_utils.h | 12 ++-- .../http/rate_limit_quota/integration_test.cc | 55 +++++++++++-------- .../filters/http/rate_limit_quota/mocks.h | 2 +- 8 files changed, 95 insertions(+), 49 deletions(-) diff --git a/source/extensions/filters/http/rate_limit_quota/client.h b/source/extensions/filters/http/rate_limit_quota/client.h index a8d31c39b0..198b919d5b 100644 --- a/source/extensions/filters/http/rate_limit_quota/client.h +++ b/source/extensions/filters/http/rate_limit_quota/client.h @@ -37,7 +37,7 @@ class RateLimitClient { public: virtual ~RateLimitClient() = default; - virtual absl::Status startStream(const StreamInfo::StreamInfo& stream_info) PURE; + virtual absl::Status startStream(const StreamInfo::StreamInfo* stream_info) PURE; virtual void closeStream() PURE; virtual void sendUsageReport(absl::optional bucket_id) PURE; diff --git a/source/extensions/filters/http/rate_limit_quota/client_impl.cc b/source/extensions/filters/http/rate_limit_quota/client_impl.cc index 7d886a49e7..876060592e 100644 --- a/source/extensions/filters/http/rate_limit_quota/client_impl.cc +++ b/source/extensions/filters/http/rate_limit_quota/client_impl.cc @@ -64,14 +64,17 @@ RateLimitQuotaUsageReports RateLimitClientImpl::buildReport(absl::optional bucket_id) { - if (stream_ != nullptr) { - // Build the report and then send the report to RLQS server. - // `end_stream` should always be set to false as we don't want to close the stream locally. - stream_->sendMessage(buildReport(bucket_id), /*end_stream=*/false); - } else { - // Don't send any reports if stream has already been closed. - ENVOY_LOG(debug, "The stream has already been closed; no reports will be sent."); + if (stream_ == nullptr) { + ENVOY_LOG(debug, "The RLQS stream has been closed and must be restarted to send reports."); + if (absl::Status err = startStream(nullptr); !err.ok()) { + ENVOY_LOG(error, "Failed to start the stream to send reports."); + return; + } } + + // Build the report and then send the report to RLQS server. + // `end_stream` should always be set to false as we don't want to close the stream locally. + stream_->sendMessage(buildReport(bucket_id), /*end_stream=*/false); } void RateLimitClientImpl::onReceiveMessage(RateLimitQuotaResponsePtr&& response) { @@ -165,20 +168,27 @@ void RateLimitClientImpl::onRemoteClose(Grpc::Status::GrpcStatus status, stream_ = nullptr; } -absl::Status RateLimitClientImpl::startStream(const StreamInfo::StreamInfo& stream_info) { +absl::Status RateLimitClientImpl::startStream(const StreamInfo::StreamInfo* stream_info) { // Starts stream if it has not been opened yet. if (stream_ == nullptr) { ENVOY_LOG(debug, "Trying to start the new gRPC stream"); + auto stream_options = Http::AsyncClient::RequestOptions(); + if (stream_info) { + stream_options.setParentContext(Http::AsyncClient::ParentContext{stream_info}); + } stream_ = aync_client_.start( *Protobuf::DescriptorPool::generated_pool()->FindMethodByName( "envoy.service.rate_limit_quota.v3.RateLimitQuotaService.StreamRateLimitQuotas"), - *this, - Http::AsyncClient::RequestOptions().setParentContext( - Http::AsyncClient::ParentContext{&stream_info})); + *this, stream_options); + } + + // If still null after attempting a start. + if (stream_ == nullptr) { + return absl::InternalError("Failed to start the stream"); } - // Returns error status if start failed (i.e., stream_ is nullptr). - return stream_ == nullptr ? absl::InternalError("Failed to start the stream") : absl::OkStatus(); + ENVOY_LOG(debug, "gRPC stream has been started"); + return absl::OkStatus(); } } // namespace RateLimitQuota diff --git a/source/extensions/filters/http/rate_limit_quota/client_impl.h b/source/extensions/filters/http/rate_limit_quota/client_impl.h index b471755d24..c4584c26b8 100644 --- a/source/extensions/filters/http/rate_limit_quota/client_impl.h +++ b/source/extensions/filters/http/rate_limit_quota/client_impl.h @@ -45,7 +45,7 @@ class RateLimitClientImpl : public RateLimitClient, void onRemoteClose(Grpc::Status::GrpcStatus status, const std::string& message) override; // RateLimitClient methods. - absl::Status startStream(const StreamInfo::StreamInfo& stream_info) override; + absl::Status startStream(const StreamInfo::StreamInfo* stream_info) override; void closeStream() override; // Send the usage report to RLQS server void sendUsageReport(absl::optional bucket_id) override; diff --git a/source/extensions/filters/http/rate_limit_quota/filter.cc b/source/extensions/filters/http/rate_limit_quota/filter.cc index 65535753c3..e5671033cc 100644 --- a/source/extensions/filters/http/rate_limit_quota/filter.cc +++ b/source/extensions/filters/http/rate_limit_quota/filter.cc @@ -185,7 +185,7 @@ RateLimitQuotaFilter::sendImmediateReport(const size_t bucket_id, // Start the streaming on the first request. // It will be a no-op if the stream is already active. - auto status = client_.rate_limit_client->startStream(callbacks_->streamInfo()); + auto status = client_.rate_limit_client->startStream(&callbacks_->streamInfo()); if (!status.ok()) { ENVOY_LOG(error, "Failed to start the gRPC stream: ", status.message()); // TODO(tyxia) Check `NoAssignmentBehavior` behavior instead of fail-open here. diff --git a/test/extensions/filters/http/rate_limit_quota/client_test.cc b/test/extensions/filters/http/rate_limit_quota/client_test.cc index 1fee6b6f46..336b47b7ff 100644 --- a/test/extensions/filters/http/rate_limit_quota/client_test.cc +++ b/test/extensions/filters/http/rate_limit_quota/client_test.cc @@ -18,7 +18,7 @@ class RateLimitClientTest : public testing::Test { }; TEST_F(RateLimitClientTest, OpenAndCloseStream) { - EXPECT_OK(test_client.client_->startStream(test_client.stream_info_)); + EXPECT_OK(test_client.client_->startStream(&test_client.stream_info_)); EXPECT_CALL(test_client.stream_, closeStream()); EXPECT_CALL(test_client.stream_, resetStream()); test_client.client_->closeStream(); @@ -27,7 +27,7 @@ TEST_F(RateLimitClientTest, OpenAndCloseStream) { TEST_F(RateLimitClientTest, SendUsageReport) { ::envoy::service::rate_limit_quota::v3::BucketId bucket_id; TestUtility::loadFromYaml(SingleBukcetId, bucket_id); - EXPECT_OK(test_client.client_->startStream(test_client.stream_info_)); + EXPECT_OK(test_client.client_->startStream(&test_client.stream_info_)); bool end_stream = false; // Send quota usage report and ensure that we get it. EXPECT_CALL(test_client.stream_, sendMessageRaw_(_, end_stream)); @@ -39,7 +39,7 @@ TEST_F(RateLimitClientTest, SendUsageReport) { } TEST_F(RateLimitClientTest, SendRequestAndReceiveResponse) { - EXPECT_OK(test_client.client_->startStream(test_client.stream_info_)); + EXPECT_OK(test_client.client_->startStream(&test_client.stream_info_)); ASSERT_NE(test_client.stream_callbacks_, nullptr); auto empty_request_headers = Http::RequestHeaderMapImpl::create(); @@ -66,6 +66,33 @@ TEST_F(RateLimitClientTest, SendRequestAndReceiveResponse) { test_client.client_->onRemoteClose(0, ""); } +TEST_F(RateLimitClientTest, RestartStreamWhileInUse) { + ::envoy::service::rate_limit_quota::v3::BucketId bucket_id; + TestUtility::loadFromYaml(SingleBukcetId, bucket_id); + EXPECT_OK(test_client.client_->startStream(&test_client.stream_info_)); + + bool end_stream = false; + // Send quota usage report and ensure that we get it. + EXPECT_CALL(test_client.stream_, sendMessageRaw_(_, end_stream)); + const size_t bucket_id_hash = MessageUtil::hash(bucket_id); + test_client.client_->sendUsageReport(bucket_id_hash); + EXPECT_CALL(test_client.stream_, closeStream()); + EXPECT_CALL(test_client.stream_, resetStream()); + test_client.client_->closeStream(); + + // Expect the stream to reopen while trying to send the next usage report. + EXPECT_CALL(test_client.stream_, sendMessageRaw_(_, end_stream)); + test_client.client_->sendUsageReport(bucket_id_hash); + EXPECT_CALL(test_client.stream_, closeStream()); + EXPECT_CALL(test_client.stream_, resetStream()); + test_client.client_->closeStream(); + + // Expect the client to handle a restart failure. + EXPECT_CALL(*test_client.async_client_, startRaw(_, _, _, _)).WillOnce(testing::Return(nullptr)); + WAIT_FOR_LOG_CONTAINS("error", "Failed to start the stream to send reports.", + { test_client.client_->sendUsageReport(bucket_id_hash); }); +} + } // namespace } // namespace RateLimitQuota } // namespace HttpFilters diff --git a/test/extensions/filters/http/rate_limit_quota/client_test_utils.h b/test/extensions/filters/http/rate_limit_quota/client_test_utils.h index 2f19f9b48b..e6624af9b4 100644 --- a/test/extensions/filters/http/rate_limit_quota/client_test_utils.h +++ b/test/extensions/filters/http/rate_limit_quota/client_test_utils.h @@ -70,12 +70,12 @@ class RateLimitTestClient { } Grpc::RawAsyncClientSharedPtr mockCreateAsyncClient(Unused, Unused, Unused) { - auto async_client = std::make_shared(); - EXPECT_CALL(*async_client, startRaw("envoy.service.rate_limit_quota.v3.RateLimitQuotaService", - "StreamRateLimitQuotas", _, _)) - .WillOnce(Invoke(this, &RateLimitTestClient::mockStartRaw)); + async_client_ = std::make_shared(); + EXPECT_CALL(*async_client_, startRaw("envoy.service.rate_limit_quota.v3.RateLimitQuotaService", + "StreamRateLimitQuotas", _, _)) + .WillRepeatedly(Invoke(this, &RateLimitTestClient::mockStartRaw)); - return async_client; + return async_client_; } Grpc::RawAsyncStream* mockStartRaw(Unused, Unused, Grpc::RawAsyncStreamCallbacks& callbacks, @@ -97,7 +97,7 @@ class RateLimitTestClient { Grpc::RawAsyncStreamCallbacks* stream_callbacks_; Grpc::Status::GrpcStatus grpc_status_ = Grpc::Status::WellKnownGrpcStatus::Ok; RateLimitClientPtr client_; - // std::unique_ptr client_; + std::shared_ptr async_client_ = nullptr; MockRateLimitQuotaCallbacks callbacks_; bool external_inited_ = false; bool start_failed_ = false; diff --git a/test/extensions/filters/http/rate_limit_quota/integration_test.cc b/test/extensions/filters/http/rate_limit_quota/integration_test.cc index dc37a9720b..37d4a97df6 100644 --- a/test/extensions/filters/http/rate_limit_quota/integration_test.cc +++ b/test/extensions/filters/http/rate_limit_quota/integration_test.cc @@ -787,42 +787,51 @@ TEST_P(RateLimitQuotaIntegrationTest, BasicFlowPeriodicalReportWithStreamClosed) EXPECT_TRUE(response_->complete()); EXPECT_EQ(response_->headers().getStatusValue(), "200"); + // ValidMatcherConfig. + int report_interval_sec = 60; // Trigger the report periodically. for (int i = 0; i < 6; ++i) { if (i == 2) { // Close the stream. - rlqs_stream_->finishGrpcStream(Grpc::Status::Ok); + WAIT_FOR_LOG_CONTAINS("debug", "gRPC stream closed remotely with status", + { rlqs_stream_->finishGrpcStream(Grpc::Status::Canceled); }); + ASSERT_TRUE(rlqs_stream_->waitForReset()); } // Advance the time by report_interval. simTime().advanceTimeWait(std::chrono::milliseconds(report_interval_sec * 1000)); - // Only perform rlqs server check and response before stream is remotely closed. - if (i < 2) { - // Checks that the rate limit server has received the periodical reports. - ASSERT_TRUE(rlqs_stream_->waitForGrpcMessage(*dispatcher_, reports)); + if (i == 2) { + // Stream should be restarted when next required for usage reporting. + ASSERT_TRUE(rlqs_connection_->waitForNewStream(*dispatcher_, rlqs_stream_)); + rlqs_stream_->startGrpcStream(); + } - // Verify the usage report content. - ASSERT_THAT(reports.bucket_quota_usages_size(), 1); - const auto& usage = reports.bucket_quota_usages(0); - // Report only represents the usage since last report. - // In the periodical report case here, the number of request allowed and denied is 0 since no - // new requests comes in. - EXPECT_EQ(usage.num_requests_allowed(), 0); - EXPECT_EQ(usage.num_requests_denied(), 0); - // time_elapsed equals to periodical reporting interval. - EXPECT_EQ(Protobuf::util::TimeUtil::DurationToSeconds(usage.time_elapsed()), - report_interval_sec); + // Only perform rlqs server check and response before stream is remotely + // closed. Checks that the rate limit server has received the periodical + // reports. + ASSERT_TRUE(rlqs_stream_->waitForGrpcMessage(*dispatcher_, reports)); + + // Verify the usage report content. + ASSERT_THAT(reports.bucket_quota_usages_size(), 1); + const auto& usage = reports.bucket_quota_usages(0); + // Report only represents the usage since last report. + // In the periodical report case here, the number of request allowed and + // denied is 0 since no new requests comes in. + EXPECT_EQ(usage.num_requests_allowed(), 0); + EXPECT_EQ(usage.num_requests_denied(), 0); + // time_elapsed equals to periodical reporting interval. + EXPECT_EQ(Protobuf::util::TimeUtil::DurationToSeconds(usage.time_elapsed()), + report_interval_sec); - // Build the rlqs server response. - envoy::service::rate_limit_quota::v3::RateLimitQuotaResponse rlqs_response2; - auto* bucket_action2 = rlqs_response2.add_bucket_action(); + // Build the rlqs server response. + envoy::service::rate_limit_quota::v3::RateLimitQuotaResponse rlqs_response2; + auto* bucket_action2 = rlqs_response2.add_bucket_action(); - for (const auto& [key, value] : custom_headers_cpy) { - (*bucket_action2->mutable_bucket_id()->mutable_bucket()).insert({key, value}); - } - rlqs_stream_->sendGrpcMessage(rlqs_response2); + for (const auto& [key, value] : custom_headers_cpy) { + (*bucket_action2->mutable_bucket_id()->mutable_bucket()).insert({key, value}); } + rlqs_stream_->sendGrpcMessage(rlqs_response2); } } diff --git a/test/extensions/filters/http/rate_limit_quota/mocks.h b/test/extensions/filters/http/rate_limit_quota/mocks.h index 01d374ec6c..aedd75e3e9 100644 --- a/test/extensions/filters/http/rate_limit_quota/mocks.h +++ b/test/extensions/filters/http/rate_limit_quota/mocks.h @@ -28,7 +28,7 @@ class MockRateLimitClient : public RateLimitClient { MockRateLimitClient() = default; ~MockRateLimitClient() override = default; - MOCK_METHOD(absl::Status, startStream, (const StreamInfo::StreamInfo&)); + MOCK_METHOD(absl::Status, startStream, (const StreamInfo::StreamInfo*)); MOCK_METHOD(void, closeStream, ()); MOCK_METHOD(void, sendUsageReport, (absl::optional)); From 88543c9c37f389ff6d2650bb7aae211563ab0485 Mon Sep 17 00:00:00 2001 From: Rickyp Date: Tue, 17 Sep 2024 18:39:32 -0400 Subject: [PATCH 06/65] quic: Adding QUIC listener option to reject new connections (#36070) Commit Message: Implementing reject_new_connections QUIC listener option. Additional Description: The goal is to implement a mechanism to configure the bootstrap to reject H3 traffic as early as possible in the QUIC layer. This is done by replying to the client with an empty QUIC version negotiation packet to leverage the incompatible version negotiation logic from RFC 9368. This feature is off by default. Risk Level: Low Testing: UTs Docs Changes: N/A Release Notes: added new_features/quic note --------- Signed-off-by: Ricardo Perez --- api/envoy/config/listener/v3/quic_config.proto | 7 ++++++- changelogs/current.yaml | 5 +++++ source/common/quic/active_quic_listener.cc | 11 +++++++---- source/common/quic/active_quic_listener.h | 4 +++- test/integration/quic_http_integration_test.cc | 16 ++++++++++++++++ 5 files changed, 37 insertions(+), 6 deletions(-) diff --git a/api/envoy/config/listener/v3/quic_config.proto b/api/envoy/config/listener/v3/quic_config.proto index 6ba5bbc56b..6c0a5bd201 100644 --- a/api/envoy/config/listener/v3/quic_config.proto +++ b/api/envoy/config/listener/v3/quic_config.proto @@ -25,7 +25,7 @@ option (udpa.annotations.file_status).package_version_status = ACTIVE; // [#protodoc-title: QUIC listener config] // Configuration specific to the UDP QUIC listener. -// [#next-free-field: 13] +// [#next-free-field: 14] message QuicProtocolOptions { option (udpa.annotations.versioning).previous_message_type = "envoy.api.v2.listener.QuicProtocolOptions"; @@ -94,4 +94,9 @@ message QuicProtocolOptions { // If not specified, no cmsg will be saved to QuicReceivedPacket. repeated core.v3.SocketCmsgHeaders save_cmsg_config = 12 [(validate.rules).repeated = {max_items: 1}]; + + // If true, the listener will reject connection-establishing packets at the + // QUIC layer by replying with an empty version negotiation packet to the + // client. + bool reject_new_connections = 13; } diff --git a/changelogs/current.yaml b/changelogs/current.yaml index a8f9ca6d88..e60a462af2 100644 --- a/changelogs/current.yaml +++ b/changelogs/current.yaml @@ -248,6 +248,11 @@ new_features: QUIC server and client support certificate compression, which can in some cases reduce the number of round trips required to setup a connection. This change temporarily disabled by setting the runtime flag ``envoy.reloadable_features.quic_support_certificate_compression`` to ``false``. +- area: quic + change: | + Added QUIC protocol option :ref:`reject_new_connections + ` to reject connection-establishing + packets at the QUIC layer. - area: tls change: | Added an extension point :ref:`custom_tls_certificate_selector diff --git a/source/common/quic/active_quic_listener.cc b/source/common/quic/active_quic_listener.cc index 002b8f5866..691c4a9c29 100644 --- a/source/common/quic/active_quic_listener.cc +++ b/source/common/quic/active_quic_listener.cc @@ -37,14 +37,17 @@ ActiveQuicListener::ActiveQuicListener( EnvoyQuicCryptoServerStreamFactoryInterface& crypto_server_stream_factory, EnvoyQuicProofSourceFactoryInterface& proof_source_factory, QuicConnectionIdGeneratorPtr&& cid_generator, QuicConnectionIdWorkerSelector worker_selector, - EnvoyQuicConnectionDebugVisitorFactoryInterfaceOptRef debug_visitor_factory) + EnvoyQuicConnectionDebugVisitorFactoryInterfaceOptRef debug_visitor_factory, + bool reject_new_connections) : Server::ActiveUdpListenerBase( worker_index, concurrency, parent, *listen_socket, std::make_unique( dispatcher, listen_socket, *this, dispatcher.timeSource(), listener_config.udpListenerConfig()->config().downstream_socket_config()), &listener_config), - dispatcher_(dispatcher), version_manager_(quic::CurrentSupportedHttp3Versions()), + dispatcher_(dispatcher), + version_manager_(reject_new_connections ? quic::ParsedQuicVersionVector() + : quic::CurrentSupportedHttp3Versions()), kernel_worker_routing_(kernel_worker_routing), packets_to_read_to_connection_count_ratio_(packets_to_read_to_connection_count_ratio), crypto_server_stream_factory_(crypto_server_stream_factory), @@ -264,7 +267,7 @@ ActiveQuicListenerFactory::ActiveQuicListenerFactory( PROTOBUF_GET_WRAPPED_OR_DEFAULT(config, packets_to_read_to_connection_count_ratio, DEFAULT_PACKETS_TO_READ_PER_CONNECTION)), receive_ecn_(Runtime::runtimeFeatureEnabled("envoy.reloadable_features.quic_receive_ecn")), - context_(context) { + context_(context), reject_new_connections_(config.reject_new_connections()) { const int64_t idle_network_timeout_ms = config.has_idle_timeout() ? DurationUtil::durationToMilliseconds(config.idle_timeout()) : 300000; @@ -434,7 +437,7 @@ ActiveQuicListenerFactory::createActiveQuicListener( listener_config, quic_config, kernel_worker_routing, enabled, quic_stat_names, packets_to_read_to_connection_count_ratio, receive_ecn_, crypto_server_stream_factory, proof_source_factory, std::move(cid_generator), worker_selector_, - connection_debug_visitor_factory_); + connection_debug_visitor_factory_, reject_new_connections_); } } // namespace Quic diff --git a/source/common/quic/active_quic_listener.h b/source/common/quic/active_quic_listener.h index e0f62c0298..0ec62ac7df 100644 --- a/source/common/quic/active_quic_listener.h +++ b/source/common/quic/active_quic_listener.h @@ -41,7 +41,8 @@ class ActiveQuicListener : public Envoy::Server::ActiveUdpListenerBase, EnvoyQuicProofSourceFactoryInterface& proof_source_factory, QuicConnectionIdGeneratorPtr&& cid_generator, QuicConnectionIdWorkerSelector worker_selector, - EnvoyQuicConnectionDebugVisitorFactoryInterfaceOptRef debug_visitor_factory); + EnvoyQuicConnectionDebugVisitorFactoryInterfaceOptRef debug_visitor_factory, + bool reject_new_connections = false); ~ActiveQuicListener() override; @@ -159,6 +160,7 @@ class ActiveQuicListenerFactory : public Network::ActiveUdpListenerFactory, QuicConnectionIdWorkerSelector worker_selector_; bool kernel_worker_routing_{}; Server::Configuration::ServerFactoryContext& context_; + bool reject_new_connections_{}; static bool disable_kernel_bpf_packet_routing_for_test_; }; diff --git a/test/integration/quic_http_integration_test.cc b/test/integration/quic_http_integration_test.cc index b2dc7b4fa1..65251998c9 100644 --- a/test/integration/quic_http_integration_test.cc +++ b/test/integration/quic_http_integration_test.cc @@ -2380,6 +2380,22 @@ TEST_P(QuicHttpIntegrationTest, SendDisableActiveMigration) { ASSERT_TRUE(response->complete()); } +TEST_P(QuicHttpIntegrationTest, RejectTraffic) { + config_helper_.addConfigModifier([=](envoy::config::bootstrap::v3::Bootstrap& bootstrap) -> void { + bootstrap.mutable_static_resources() + ->mutable_listeners(0) + ->mutable_udp_listener_config() + ->mutable_quic_options() + ->set_reject_new_connections(true); + }); + + initialize(); + codec_client_ = makeRawHttpConnection(makeClientConnection(lookupPort("http")), absl::nullopt); + EXPECT_TRUE(codec_client_->disconnected()); + EXPECT_EQ(quic::QUIC_INVALID_VERSION, + static_cast(codec_client_->connection())->error()); +} + // Validate that the transport parameter is not sent when `send_disable_active_migration` is // unset. TEST_P(QuicHttpIntegrationTest, UnsetSendDisableActiveMigration) { From c9ae398d91040a076085c52fe33b0c77572cf71f Mon Sep 17 00:00:00 2001 From: alyssawilk Date: Wed, 18 Sep 2024 01:03:53 -0400 Subject: [PATCH 07/65] syscalls: minor refactor, adding coverage (#36075) minor refactor no longer fast-failing if the system can't create sockets. Risk Level: low Testing: added tests, manually tested fd failure Docs Changes: n/a Release Notes: n/a --------- Signed-off-by: Fredy Wijaya Signed-off-by: Alyssa Wilk Co-authored-by: Fredy Wijaya --- source/common/api/posix/os_sys_calls_impl.cc | 13 ++----------- test/common/api/os_sys_calls_test.cc | 15 +++++++++++++++ test/per_file_coverage.sh | 2 -- 3 files changed, 17 insertions(+), 13 deletions(-) diff --git a/source/common/api/posix/os_sys_calls_impl.cc b/source/common/api/posix/os_sys_calls_impl.cc index 3fab0afc1b..ad078c7f4d 100644 --- a/source/common/api/posix/os_sys_calls_impl.cc +++ b/source/common/api/posix/os_sys_calls_impl.cc @@ -109,9 +109,6 @@ bool OsSysCallsImpl::supportsUdpGro() const { #else static const bool is_supported = [] { int fd = ::socket(AF_INET, SOCK_DGRAM | SOCK_NONBLOCK, IPPROTO_UDP); - if (fd < 0) { - return false; - } int val = 1; bool result = (0 == ::setsockopt(fd, IPPROTO_UDP, UDP_GRO, &val, sizeof(val))); ::close(fd); @@ -127,9 +124,6 @@ bool OsSysCallsImpl::supportsUdpGso() const { #else static const bool is_supported = [] { int fd = ::socket(AF_INET, SOCK_DGRAM | SOCK_NONBLOCK, IPPROTO_UDP); - if (fd < 0) { - return false; - } int optval; socklen_t optlen = sizeof(optval); bool result = (0 <= ::getsockopt(fd, IPPROTO_UDP, UDP_SEGMENT, &optval, &optlen)); @@ -160,9 +154,6 @@ bool OsSysCallsImpl::supportsIpTransparent(Network::Address::IpVersion ip_versio static constexpr auto transparent_supported = [](int family) { auto opt_tp = family == AF_INET ? ENVOY_SOCKET_IP_TRANSPARENT : ENVOY_SOCKET_IPV6_TRANSPARENT; int fd = ::socket(family, SOCK_DGRAM | SOCK_NONBLOCK, IPPROTO_UDP); - if (fd < 0) { - return false; - } int val = 1; bool result = (0 == ::setsockopt(fd, opt_tp.level(), opt_tp.option(), &val, sizeof(val))); ::close(fd); @@ -348,9 +339,9 @@ SysCallBoolResult OsSysCallsImpl::socketTcpInfo([[maybe_unused]] os_fd_t sockfd, tcp_info->tcpi_snd_cwnd = unix_tcp_info.tcpi_snd_cwnd * mss; } return {!SOCKET_FAILURE(result), !SOCKET_FAILURE(result) ? 0 : errno}; -#endif - +#else return {false, EOPNOTSUPP}; +#endif } bool OsSysCallsImpl::supportsGetifaddrs() const { return true; } diff --git a/test/common/api/os_sys_calls_test.cc b/test/common/api/os_sys_calls_test.cc index 126e109409..96e4d35e95 100644 --- a/test/common/api/os_sys_calls_test.cc +++ b/test/common/api/os_sys_calls_test.cc @@ -68,4 +68,19 @@ TEST(OsSyscallsTest, OpenPwritePreadFstatCloseStatUnlink) { TestEnvironment::removePath(path); } +TEST(OsSyscallsTest, SupportsIpTransparent) { + bool supported = Api::OsSysCallsSingleton::get().supportsIpTransparent( + TestEnvironment::getIpVersionsForTest()[0]); + EXPECT_FALSE(supported); +} + +TEST(OsSyscallsTest, SupportsMptcp) { + bool supported = Api::OsSysCallsSingleton::get().supportsMptcp(); + EXPECT_TRUE(supported); +} + +TEST(OsSyscallsTest, IoCtlInvalidFd) { + EXPECT_NE(0, Api::OsSysCallsSingleton::get().ioctl(0, 0, nullptr, 0, nullptr, 0, nullptr).errno_); +} + } // namespace Envoy diff --git a/test/per_file_coverage.sh b/test/per_file_coverage.sh index eae1d69683..c5bc35cf78 100755 --- a/test/per_file_coverage.sh +++ b/test/per_file_coverage.sh @@ -4,8 +4,6 @@ # for existing directories with low coverage. declare -a KNOWN_LOW_COVERAGE=( "source/common:96.2" -"source/common/api:84.5" # flaky due to posix: be careful adjusting -"source/common/api/posix:83.8" # flaky (accept failover non-deterministic): be careful adjusting "source/common/common/posix:96.2" # flaky due to posix: be careful adjusting "source/common/config:96.1" "source/common/crypto:95.5" From 7fb927d10a67aa6ca6737a003547ac8a707df673 Mon Sep 17 00:00:00 2001 From: "dependency-envoy[bot]" <148525496+dependency-envoy[bot]@users.noreply.github.com> Date: Wed, 18 Sep 2024 13:21:43 +0000 Subject: [PATCH 08/65] deps: Bump `proxy_wasm_rust_sdk` -> 0.2.2 (#35323) Fix #35321 also update `rules_rust` -> 0.48.0 Fix #35291 Signed-off-by: dependency-envoy[bot] <148525496+dependency-envoy[bot]@users.noreply.github.com> Signed-off-by: Ryan Northey --- .bazelrc | 1 + .../cargo/remote/BUILD.protobuf-2.24.1.bazel | 2 +- bazel/repository_locations.bzl | 12 +++++----- .../extensions/bootstrap/wasm/test_data/BUILD | 2 +- .../filters/http/wasm/test_data/BUILD | 22 +++++++++---------- .../filters/network/wasm/test_data/BUILD | 8 +++---- 6 files changed, 24 insertions(+), 23 deletions(-) diff --git a/.bazelrc b/.bazelrc index 10c6b7439f..9bfd858fe7 100644 --- a/.bazelrc +++ b/.bazelrc @@ -25,6 +25,7 @@ build --copt=-DABSL_MIN_LOG_LEVEL=4 build --define envoy_mobile_listener=enabled build --experimental_repository_downloader_retries=2 build --enable_platform_specific_config +build --incompatible_merge_fixed_and_default_shell_env # Pass CC, CXX and LLVM_CONFIG variables from the environment. # We assume they have stable values, so this won't cause action cache misses. diff --git a/bazel/external/cargo/remote/BUILD.protobuf-2.24.1.bazel b/bazel/external/cargo/remote/BUILD.protobuf-2.24.1.bazel index 9917db62f5..b818daadb7 100644 --- a/bazel/external/cargo/remote/BUILD.protobuf-2.24.1.bazel +++ b/bazel/external/cargo/remote/BUILD.protobuf-2.24.1.bazel @@ -33,7 +33,7 @@ licenses([ # buildifier: disable=out-of-order-load # buildifier: disable=load-on-top load( - "@rules_rust//cargo:cargo_build_script.bzl", + "@rules_rust//cargo:defs.bzl", "cargo_build_script", ) diff --git a/bazel/repository_locations.bzl b/bazel/repository_locations.bzl index d382a58b13..d7c5e6e3fe 100644 --- a/bazel/repository_locations.bzl +++ b/bazel/repository_locations.bzl @@ -1424,12 +1424,12 @@ REPOSITORY_LOCATIONS_SPEC = dict( project_name = "WebAssembly for Proxies (Rust SDK)", project_desc = "WebAssembly for Proxies (Rust SDK)", project_url = "https://github.com/proxy-wasm/proxy-wasm-rust-sdk", - version = "0.2.1", - sha256 = "23f3f2d8c4c8069a2e72693b350d7442b7722d334f73169eea78804ff70cde20", + version = "0.2.2", + sha256 = "3d9e8f39f0356016c8ae6c74c0224eae1b44168be0ddf79e387d918a8f2cb4c6", strip_prefix = "proxy-wasm-rust-sdk-{version}", urls = ["https://github.com/proxy-wasm/proxy-wasm-rust-sdk/archive/v{version}.tar.gz"], use_category = ["test_only"], - release_date = "2022-11-22", + release_date = "2024-07-21", cpe = "N/A", license = "Apache-2.0", license_url = "https://github.com/proxy-wasm/proxy-wasm-rust-sdk/blob/v{version}/LICENSE", @@ -1452,9 +1452,9 @@ REPOSITORY_LOCATIONS_SPEC = dict( project_name = "Bazel rust rules", project_desc = "Bazel rust rules (used by Wasm)", project_url = "https://github.com/bazelbuild/rules_rust", - version = "0.35.0", + version = "0.48.0", strip_prefix = "rules_rust-{version}", - sha256 = "3120c7aa3a146dfe6be8d5f23f4cf10af7d0f74a5aed8b94a818f88643bd24c3", + sha256 = "a4b8ede7723088dff1e909632c4282e51ddbe0e44c38eea013ee0f12d348b1c7", urls = ["https://github.com/bazelbuild/rules_rust/archive/{version}.tar.gz"], use_category = [ "controlplane", @@ -1463,7 +1463,7 @@ REPOSITORY_LOCATIONS_SPEC = dict( ], implied_untracked_deps = ["rules_cc"], extensions = ["envoy.wasm.runtime.wasmtime"], - release_date = "2023-12-27", + release_date = "2024-07-19", cpe = "N/A", license = "Apache-2.0", license_url = "https://github.com/bazelbuild/rules_rust/blob/{version}/LICENSE.txt", diff --git a/test/extensions/bootstrap/wasm/test_data/BUILD b/test/extensions/bootstrap/wasm/test_data/BUILD index e0003964ed..53f36ba5ab 100644 --- a/test/extensions/bootstrap/wasm/test_data/BUILD +++ b/test/extensions/bootstrap/wasm/test_data/BUILD @@ -15,7 +15,7 @@ wasm_rust_binary( wasi = True, deps = [ "@proxy_wasm_rust_sdk//:proxy_wasm", - "@proxy_wasm_rust_sdk//bazel/cargo:log", + "@proxy_wasm_rust_sdk//bazel/cargo/remote:log", ], ) diff --git a/test/extensions/filters/http/wasm/test_data/BUILD b/test/extensions/filters/http/wasm/test_data/BUILD index 3cebdbc4fc..dc89c15852 100644 --- a/test/extensions/filters/http/wasm/test_data/BUILD +++ b/test/extensions/filters/http/wasm/test_data/BUILD @@ -15,7 +15,7 @@ wasm_rust_binary( srcs = ["async_call_rust.rs"], deps = [ "@proxy_wasm_rust_sdk//:proxy_wasm", - "@proxy_wasm_rust_sdk//bazel/cargo:log", + "@proxy_wasm_rust_sdk//bazel/cargo/remote:log", ], ) @@ -24,7 +24,7 @@ wasm_rust_binary( srcs = ["body_rust.rs"], deps = [ "@proxy_wasm_rust_sdk//:proxy_wasm", - "@proxy_wasm_rust_sdk//bazel/cargo:log", + "@proxy_wasm_rust_sdk//bazel/cargo/remote:log", ], ) @@ -33,7 +33,7 @@ wasm_rust_binary( srcs = ["close_stream_rust.rs"], deps = [ "@proxy_wasm_rust_sdk//:proxy_wasm", - "@proxy_wasm_rust_sdk//bazel/cargo:log", + "@proxy_wasm_rust_sdk//bazel/cargo/remote:log", ], ) @@ -43,7 +43,7 @@ wasm_rust_binary( deps = [ "//bazel/external/cargo:protobuf", "@proxy_wasm_rust_sdk//:proxy_wasm", - "@proxy_wasm_rust_sdk//bazel/cargo:log", + "@proxy_wasm_rust_sdk//bazel/cargo/remote:log", ], ) @@ -53,7 +53,7 @@ wasm_rust_binary( deps = [ "//bazel/external/cargo:protobuf", "@proxy_wasm_rust_sdk//:proxy_wasm", - "@proxy_wasm_rust_sdk//bazel/cargo:log", + "@proxy_wasm_rust_sdk//bazel/cargo/remote:log", ], ) @@ -63,7 +63,7 @@ wasm_rust_binary( wasi = True, deps = [ "@proxy_wasm_rust_sdk//:proxy_wasm", - "@proxy_wasm_rust_sdk//bazel/cargo:log", + "@proxy_wasm_rust_sdk//bazel/cargo/remote:log", ], ) @@ -72,7 +72,7 @@ wasm_rust_binary( srcs = ["metadata_rust.rs"], deps = [ "@proxy_wasm_rust_sdk//:proxy_wasm", - "@proxy_wasm_rust_sdk//bazel/cargo:log", + "@proxy_wasm_rust_sdk//bazel/cargo/remote:log", ], ) @@ -81,7 +81,7 @@ wasm_rust_binary( srcs = ["panic_rust.rs"], deps = [ "@proxy_wasm_rust_sdk//:proxy_wasm", - "@proxy_wasm_rust_sdk//bazel/cargo:log", + "@proxy_wasm_rust_sdk//bazel/cargo/remote:log", ], ) @@ -90,7 +90,7 @@ wasm_rust_binary( srcs = ["resume_call_rust.rs"], deps = [ "@proxy_wasm_rust_sdk//:proxy_wasm", - "@proxy_wasm_rust_sdk//bazel/cargo:log", + "@proxy_wasm_rust_sdk//bazel/cargo/remote:log", ], ) @@ -99,7 +99,7 @@ wasm_rust_binary( srcs = ["shared_data_rust.rs"], deps = [ "@proxy_wasm_rust_sdk//:proxy_wasm", - "@proxy_wasm_rust_sdk//bazel/cargo:log", + "@proxy_wasm_rust_sdk//bazel/cargo/remote:log", ], ) @@ -108,7 +108,7 @@ wasm_rust_binary( srcs = ["shared_queue_rust.rs"], deps = [ "@proxy_wasm_rust_sdk//:proxy_wasm", - "@proxy_wasm_rust_sdk//bazel/cargo:log", + "@proxy_wasm_rust_sdk//bazel/cargo/remote:log", ], ) diff --git a/test/extensions/filters/network/wasm/test_data/BUILD b/test/extensions/filters/network/wasm/test_data/BUILD index 7095acc432..5767f8ba51 100644 --- a/test/extensions/filters/network/wasm/test_data/BUILD +++ b/test/extensions/filters/network/wasm/test_data/BUILD @@ -14,7 +14,7 @@ wasm_rust_binary( srcs = ["close_stream_rust.rs"], deps = [ "@proxy_wasm_rust_sdk//:proxy_wasm", - "@proxy_wasm_rust_sdk//bazel/cargo:log", + "@proxy_wasm_rust_sdk//bazel/cargo/remote:log", ], ) @@ -23,7 +23,7 @@ wasm_rust_binary( srcs = ["logging_rust.rs"], deps = [ "@proxy_wasm_rust_sdk//:proxy_wasm", - "@proxy_wasm_rust_sdk//bazel/cargo:log", + "@proxy_wasm_rust_sdk//bazel/cargo/remote:log", ], ) @@ -32,7 +32,7 @@ wasm_rust_binary( srcs = ["panic_rust.rs"], deps = [ "@proxy_wasm_rust_sdk//:proxy_wasm", - "@proxy_wasm_rust_sdk//bazel/cargo:log", + "@proxy_wasm_rust_sdk//bazel/cargo/remote:log", ], ) @@ -41,7 +41,7 @@ wasm_rust_binary( srcs = ["resume_call_rust.rs"], deps = [ "@proxy_wasm_rust_sdk//:proxy_wasm", - "@proxy_wasm_rust_sdk//bazel/cargo:log", + "@proxy_wasm_rust_sdk//bazel/cargo/remote:log", ], ) From 9e9986b4b56a174814bdc2d7ca2bf8c4973c0841 Mon Sep 17 00:00:00 2001 From: "dependency-envoy[bot]" <148525496+dependency-envoy[bot]@users.noreply.github.com> Date: Wed, 18 Sep 2024 16:01:48 +0100 Subject: [PATCH 09/65] deps: Bump `bazel_features` -> 1.17.0 (#36195) Fix #36138 Signed-off-by: dependency-envoy[bot] <148525496+dependency-envoy[bot]@users.noreply.github.com> --- bazel/repository_locations.bzl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/bazel/repository_locations.bzl b/bazel/repository_locations.bzl index d7c5e6e3fe..94f70cfb36 100644 --- a/bazel/repository_locations.bzl +++ b/bazel/repository_locations.bzl @@ -33,11 +33,11 @@ REPOSITORY_LOCATIONS_SPEC = dict( project_name = "Bazel features", project_desc = "Support Bazel feature detection from starlark", project_url = "https://github.com/bazel-contrib/bazel_features", - version = "1.15.0", - sha256 = "ba1282c1aa1d1fffdcf994ab32131d7c7551a9bc960fbf05f42d55a1b930cbfb", + version = "1.17.0", + sha256 = "bdc12fcbe6076180d835c9dd5b3685d509966191760a0eb10b276025fcb76158", urls = ["https://github.com/bazel-contrib/bazel_features/releases/download/v{version}/bazel_features-v{version}.tar.gz"], strip_prefix = "bazel_features-{version}", - release_date = "2024-08-09", + release_date = "2024-09-13", use_category = ["build"], license = "Apache-2.0", license_url = "https://github.com/bazel-contrib/bazel_features/blob/v{version}/LICENSE", From ead1c021777a33fea5b9da7be9f66c78118d8ac1 Mon Sep 17 00:00:00 2001 From: "Adi (Suissa) Peleg" Date: Wed, 18 Sep 2024 11:53:13 -0400 Subject: [PATCH 10/65] upstream-filter: update default upstream filter type (#36186) Prior to this the debug logs contain the following: ``` [source/common/http/filter_chain_helper.h:160] config: Failed to convert protobuf message to JSON string: INVALID_ARGUMENT: @type must contain at least one / and a nonempty host; got: envoy.extensions.filters.http.upstream_codec.v3.UpstreamCodec ``` After this PR they contain: ``` [source/common/http/filter_chain_helper.h:160] config: {"@type":"type.googleapis.com/envoy.extensions.filters.http.upstream_codec.v3.UpstreamCodec"} ``` Risk Level: low - seems to be impacting debug logs only Testing: N/A Docs Changes: N/A Release Notes: N/A Platform Specific Features: N/A Signed-off-by: Adi Suissa-Peleg --- source/common/upstream/upstream_impl.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/source/common/upstream/upstream_impl.cc b/source/common/upstream/upstream_impl.cc index 805ceb849c..a336aa2689 100644 --- a/source/common/upstream/upstream_impl.cc +++ b/source/common/upstream/upstream_impl.cc @@ -1388,7 +1388,8 @@ ClusterInfoImpl::ClusterInfoImpl( if (http_filters.empty()) { auto* codec_filter = http_filters.Add(); codec_filter->set_name("envoy.filters.http.upstream_codec"); - codec_filter->mutable_typed_config()->set_type_url(upstream_codec_type_url); + codec_filter->mutable_typed_config()->set_type_url( + absl::StrCat("type.googleapis.com/", upstream_codec_type_url)); } else { const auto last_type_url = Config::Utility::getFactoryType(http_filters[http_filters.size() - 1].typed_config()); From 291b194449779fb5544b8f24af88f9acba154f51 Mon Sep 17 00:00:00 2001 From: Raven Black Date: Wed, 18 Sep 2024 11:55:21 -0400 Subject: [PATCH 11/65] Refactor async files library to use dispatcher for synchronization (#36063) Using mutexes in the async file library was a premature optimization that made it significantly more complicated and error-prone to use from the client side. The benefit was the ability to perform multiple file operations sequentially without handing control back to the calling thread, but the cost in complexity was not worth it. This change is a hefty simplification, the main benefit of which is, in this model, cancellation is simple - previously calling cancel couldn't guarantee anything so the client object would still have to handle the case of a callback potentially being called after the object's own destruction. In this simplified model, calling cancel from the originating thread, before the callback has been called, guarantees that the callback will not be called. Similar simplification may be possible in `cache_filter`, but it's not quite as clear; cache_filter currently uses `dispatcher->post` to ensure thread locality, which is now guaranteed by the cache API so that usage is unnecessary, but it also uses `dispatcher->post` to ensure that callbacks are not called during the current function context (so that, e.g. `continueDecoding()` isn't potentially called before `decodeHeaders` returns `StopAllIterationAndWatermark`, as would happen with the simple in-memory cache which calls the callback immediately). Since this is already a giant PR, and it already works as a simplification with `cache_filter` unchanged, I'm electing to defer a simplifying pass over `cache_filter` to a followup PR. Risk Level: Small, only WIP filters use the library, and all existing tests (with appropriate modifications) still pass - the only test removed was one testing the "not handing control back to the caller" sequential action behavior, which now doesn't exist. (And there are apparently some crash-bugs in the existing stuff, so there's some negative risk in that this might fix a bug!) Testing: Existing coverage. Docs Changes: Yes, code-only. Release Notes: n/a Platform Specific Features: n/a --------- Signed-off-by: Raven Black --- source/extensions/common/async_files/BUILD | 3 +- .../extensions/common/async_files/README.md | 54 +-- .../common/async_files/async_file_action.cc | 26 -- .../common/async_files/async_file_action.h | 64 +-- .../async_files/async_file_context_base.cc | 5 +- .../async_files/async_file_context_base.h | 4 +- .../async_file_context_thread_pool.cc | 104 +++-- .../async_file_context_thread_pool.h | 28 +- .../common/async_files/async_file_handle.h | 27 +- .../common/async_files/async_file_manager.cc | 31 -- .../common/async_files/async_file_manager.h | 67 +-- .../async_file_manager_thread_pool.cc | 203 ++++++--- .../async_file_manager_thread_pool.h | 31 +- .../filters/http/file_system_buffer/filter.cc | 74 ++-- .../filters/http/file_system_buffer/filter.h | 7 +- .../http/file_system_buffer/fragment.cc | 71 ++-- .../http/file_system_buffer/fragment.h | 9 +- .../file_system_http_cache.cc | 158 +++---- .../file_system_http_cache.h | 12 +- .../file_system_http_cache/insert_context.cc | 276 ++++++------ .../file_system_http_cache/insert_context.h | 66 ++- .../file_system_http_cache/lookup_context.cc | 269 ++++++------ .../file_system_http_cache/lookup_context.h | 31 +- .../async_file_handle_thread_pool_test.cc | 258 ++++++------ .../async_file_manager_thread_pool_test.cc | 253 +++++------ ...ile_manager_thread_pool_with_mocks_test.cc | 233 ++++++----- test/extensions/common/async_files/mocks.cc | 119 +++--- test/extensions/common/async_files/mocks.h | 87 ++-- .../http_cache_implementation_test_common.cc | 215 +++++----- .../http_cache_implementation_test_common.h | 28 +- .../http/file_system_buffer/filter_test.cc | 41 +- .../http/file_system_buffer/fragment_test.cc | 156 ++++--- .../file_system_http_cache_test.cc | 392 ++++++++++++------ 33 files changed, 1803 insertions(+), 1599 deletions(-) delete mode 100644 source/extensions/common/async_files/async_file_action.cc delete mode 100644 source/extensions/common/async_files/async_file_manager.cc diff --git a/source/extensions/common/async_files/BUILD b/source/extensions/common/async_files/BUILD index 8b9a420829..0858edabe4 100644 --- a/source/extensions/common/async_files/BUILD +++ b/source/extensions/common/async_files/BUILD @@ -11,7 +11,6 @@ envoy_extension_package() envoy_cc_library( name = "async_files_base", srcs = [ - "async_file_action.cc", "async_file_context_base.cc", ], hdrs = [ @@ -22,6 +21,7 @@ envoy_cc_library( ], deps = [ ":status_after_file_error", + "//envoy/event:dispatcher_interface", "//source/common/buffer:buffer_lib", "//source/common/common:utility_lib", "@com_google_absl//absl/base", @@ -53,7 +53,6 @@ envoy_cc_library( envoy_cc_library( name = "async_files", srcs = [ - "async_file_manager.cc", "async_file_manager_factory.cc", ], hdrs = [ diff --git a/source/extensions/common/async_files/README.md b/source/extensions/common/async_files/README.md index 822e0827da..ecbd7f42a2 100644 --- a/source/extensions/common/async_files/README.md +++ b/source/extensions/common/async_files/README.md @@ -3,62 +3,26 @@ An `AsyncFileManager` should be a singleton or similarly long-lived scope. It represents a thread pool for performing file operations asynchronously. -`AsyncFileManager` can create `AsyncFileHandle`s via `createAnonymousFile` or `openExistingFile`, -can postpone queuing file actions using `whenReady`, and can delete files via `unlink`. +`AsyncFileManager` can create `AsyncFileHandle`s via `createAnonymousFile` or `openExistingFile`, can stat a file by name with `stat`, and can delete files via `unlink`. # AsyncFileHandle An `AsyncFileHandle` represents a context in which asynchronous file operations can be performed. It is associated with at most one file at a time. -Each action on an AsyncFileHandle is effectively an "enqueue" action, in that it places the action in the manager's execution queue, it does not immediately perform the requested action. Actions on an `AsyncFileHandle` can be *chained*, by enqueuing another action during the callback from a previous action, e.g. - -``` -manager->createAnonymousFile("/tmp", [](absl::StatusOr opened) { - if (!opened.ok()) { - std::cout << "oh no, an error: " << opened.status() << std::endl; - return; - } - auto handle = opened.value(); - handle->write(someBuffer, 0, [handle](absl::StatusOr written) { - if (!written.ok()) { - std::cout << "oh no, an error: " << written.status() << std::endl; - return; - } - std::cout << "wrote " << written.value() << " bytes" << std::endl; - handle->close([](absl::Status closed) { - if (!closed.ok()) { - std::cout << "oh no, an error: " << closed << std::endl; - } - }).IgnoreError(); // A returned error only occurs if the file handle was closed. - }).IgnoreError(); // A returned error only occurs if the file handle was closed. -}); -``` - -Will open an unnamed file, write 5 bytes, and close it. (This is just for explanatory purposes, in practice you would most likely want the callbacks to call something on `this` rather than nesting lambdas!) - -Chaining actions, as opposed to enqueuing, passing the result to a main thread, and from there enqueuing again, will not yield the thread in a thread-pool based implementation. An advantage of this is that, for example, if 5 workers all wanted to write a 100kb file at the same moment, with unchained requests in a one-thread threadpool the sequence would most likely resemble - -``` -OPEN-OPEN-OPEN-OPEN-OPEN-WRITE-WRITE-WRITE-WRITE-WRITE-CLOSE-CLOSE-CLOSE-CLOSE-CLOSE -``` - -Versus with appropriately chained requests in a one-thread threadpool the sequence would be guaranteed to be - -``` -OPEN-WRITE-CLOSE-OPEN-WRITE-CLOSE-OPEN-WRITE-CLOSE-OPEN-WRITE-CLOSE-OPEN-WRITE-CLOSE -``` - -Expand this concept to 100+ files all asking to be written at once and you can immediately see the advantages of chaining; not having the resource issues of many files open at the same time, more localized access, etc. +Each action on an AsyncFileHandle is effectively an "enqueue" action, in that it places the action in the manager's execution queue, it does not immediately perform the requested action. ## cancellation -Each action function returns a cancellation function which can be called to remove an action from the queue and prevent the callback from being called. If the execution is already in progress, it may be undone (e.g. a file open operation will close the file if it is opening when cancel is called). The cancel function will block if the callback is already in progress when cancel is called, until the callback completes. This should not be a long block, as callbacks should be short (see callbacks below). - -As such, a client should ensure that the cleanup order is consistent - if a callback captures a file handle, the client should clean up that file handle (if present) *after* calling cancel, in case the file was opened during the call to cancel. +Each action function returns a cancellation function which can be called to remove an action from the queue and prevent the callback from being called. If the execution is already in progress, it may be undone (e.g. a file open operation will close the file if it is opening when cancel is called). The cancel function must only be called from the same thread as the +dispatcher that was provided to the original request, to ensure that cancellation and callback +cannot be happening concurrently. ## callbacks -The callbacks passed to `AsyncFileHandle` and `AsyncFileManager` are scheduled in a thread or thread pool belonging to the AsyncFileManager - therefore they should be doing minimal work, not blocking (for more than a trivial data-guard lock), and return promptly. If any significant work or blocking is required, the result of the previous action should be passed from the callback to another thread (via some dispatcher or other queuing mechanism) so the manager's thread can continue performing file operations for other clients. +The callbacks passed to `AsyncFileHandle` and `AsyncFileManager` functions are called from +the thread associated with the provided `dispatcher`, if the action was not cancelled first. + +The implementation of `AsyncFileManager` ensures that a `cancel` call from the thread associated with the dispatcher, if called prior to the callback's execution, is guaranteed to prevent the callback from being called, there is no race. ## Possible actions diff --git a/source/extensions/common/async_files/async_file_action.cc b/source/extensions/common/async_files/async_file_action.cc deleted file mode 100644 index 9687039cbe..0000000000 --- a/source/extensions/common/async_files/async_file_action.cc +++ /dev/null @@ -1,26 +0,0 @@ -#include "source/extensions/common/async_files/async_file_action.h" - -#include - -namespace Envoy { -namespace Extensions { -namespace Common { -namespace AsyncFiles { - -void AsyncFileAction::cancel() { - auto previousState = state_.exchange(State::Cancelled); - if (previousState == State::InCallback) { - // A gentle spin-lock. This situation should be rare, and callbacks are - // supposed to be quick, so we don't need a real lock here. - while (state_.load() != State::Done) { - std::this_thread::yield(); - } - } else if (previousState == State::Done) { - state_.store(State::Done); - } -} - -} // namespace AsyncFiles -} // namespace Common -} // namespace Extensions -} // namespace Envoy diff --git a/source/extensions/common/async_files/async_file_action.h b/source/extensions/common/async_files/async_file_action.h index ea8bfed063..6afa7c809f 100644 --- a/source/extensions/common/async_files/async_file_action.h +++ b/source/extensions/common/async_files/async_file_action.h @@ -19,33 +19,28 @@ namespace AsyncFiles { // * If the action is already executing, CancelFunction causes the removal of any resource-consuming // return value (e.g. file handles), and prevents the callback. // * If the action is still just queued, CancelFunction prevents its execution. -using CancelFunction = std::function; +using CancelFunction = absl::AnyInvocable; // Actions to be passed to asyncFileManager->enqueue. class AsyncFileAction { public: virtual ~AsyncFileAction() = default; - // Cancel the action, as much as possible. - // - // If the action has not been started, it will become a no-op. - // - // If the action has started, onCancelledBeforeCallback will be called, - // and the callback will not. - // - // If the callback is already being called, cancel will block until the - // callback has completed. - // - // If the action is already complete, cancel does nothing. - void cancel(); - - // Performs the action represented by this instance, and calls the callback - // on completion or on error. + // Performs the action represented by this instance, and captures the + // result. virtual void execute() PURE; -protected: - enum class State { Queued, Executing, InCallback, Done, Cancelled }; - std::atomic state_{State::Queued}; + // Calls the captured callback with the captured result. + virtual void onComplete() PURE; + + // Performs any action to undo side-effects of the execution if the callback + // has not yet been called (e.g. closing a file that was just opened, removing + // a hard-link that was just created). + // Not necessary for things that don't make persistent resources, + // e.g. cancelling a write does not have to undo the write. + virtual void onCancelledBeforeCallback() {} + virtual bool hasActionIfCancelledBeforeCallback() const { return false; } + virtual bool executesEvenIfCancelled() const { return false; } }; // All concrete AsyncFileActions are a subclass of AsyncFileActionWithResult. @@ -59,38 +54,19 @@ class AsyncFileAction { // the result should be passed to another thread for handling. template class AsyncFileActionWithResult : public AsyncFileAction { public: - explicit AsyncFileActionWithResult(std::function on_complete) - : on_complete_(on_complete) {} + explicit AsyncFileActionWithResult(absl::AnyInvocable on_complete) + : on_complete_(std::move(on_complete)) {} - void execute() final { - State expected = State::Queued; - if (!state_.compare_exchange_strong(expected, State::Executing)) { - ASSERT(expected == State::Cancelled); - return; - } - expected = State::Executing; - T result = executeImpl(); - if (!state_.compare_exchange_strong(expected, State::InCallback)) { - ASSERT(expected == State::Cancelled); - onCancelledBeforeCallback(std::move(result)); - return; - } - on_complete_(std::move(result)); - state_.store(State::Done); - } + void execute() final { result_ = executeImpl(); } + void onComplete() final { std::move(on_complete_)(std::move(result_.value())); } protected: - // Performs any action to undo side-effects of the execution if the callback - // has not yet been called (e.g. closing a file that was just opened). - // Not necessary for things that don't make persistent resources, - // e.g. cancelling a write does not have to undo the write. - virtual void onCancelledBeforeCallback(T){}; - + absl::optional result_; // Implementation of the actual action. virtual T executeImpl() PURE; private: - std::function on_complete_; + absl::AnyInvocable on_complete_; }; } // namespace AsyncFiles diff --git a/source/extensions/common/async_files/async_file_context_base.cc b/source/extensions/common/async_files/async_file_context_base.cc index 20c7fc9948..070d710224 100644 --- a/source/extensions/common/async_files/async_file_context_base.cc +++ b/source/extensions/common/async_files/async_file_context_base.cc @@ -17,8 +17,9 @@ namespace AsyncFiles { AsyncFileContextBase::AsyncFileContextBase(AsyncFileManager& manager) : manager_(manager) {} -CancelFunction AsyncFileContextBase::enqueue(std::shared_ptr action) { - return manager_.enqueue(std::move(action)); +CancelFunction AsyncFileContextBase::enqueue(Event::Dispatcher* dispatcher, + std::unique_ptr action) { + return manager_.enqueue(dispatcher, std::move(action)); } } // namespace AsyncFiles diff --git a/source/extensions/common/async_files/async_file_context_base.h b/source/extensions/common/async_files/async_file_context_base.h index 37614b450d..b01652b62c 100644 --- a/source/extensions/common/async_files/async_file_context_base.h +++ b/source/extensions/common/async_files/async_file_context_base.h @@ -2,6 +2,8 @@ #include +#include "envoy/event/dispatcher.h" + #include "source/extensions/common/async_files/async_file_handle.h" #include "absl/status/statusor.h" @@ -23,7 +25,7 @@ class AsyncFileContextBase : public AsyncFileContext { protected: // Queue up an action with the AsyncFileManager. - CancelFunction enqueue(std::shared_ptr action); + CancelFunction enqueue(Event::Dispatcher* dispatcher, std::unique_ptr action); explicit AsyncFileContextBase(AsyncFileManager& manager); diff --git a/source/extensions/common/async_files/async_file_context_thread_pool.cc b/source/extensions/common/async_files/async_file_context_thread_pool.cc index 43a07ef051..5391559ff9 100644 --- a/source/extensions/common/async_files/async_file_context_thread_pool.cc +++ b/source/extensions/common/async_files/async_file_context_thread_pool.cc @@ -21,8 +21,9 @@ namespace { template class AsyncFileActionThreadPool : public AsyncFileActionWithResult { public: - explicit AsyncFileActionThreadPool(AsyncFileHandle handle, std::function on_complete) - : AsyncFileActionWithResult(on_complete), handle_(std::move(handle)) {} + explicit AsyncFileActionThreadPool(AsyncFileHandle handle, + absl::AnyInvocable on_complete) + : AsyncFileActionWithResult(std::move(on_complete)), handle_(std::move(handle)) {} protected: int& fileDescriptor() { return context()->fileDescriptor(); } @@ -39,8 +40,9 @@ template class AsyncFileActionThreadPool : public AsyncFileActionWi class ActionStat : public AsyncFileActionThreadPool> { public: - ActionStat(AsyncFileHandle handle, std::function)> on_complete) - : AsyncFileActionThreadPool>(handle, on_complete) {} + ActionStat(AsyncFileHandle handle, + absl::AnyInvocable)> on_complete) + : AsyncFileActionThreadPool>(handle, std::move(on_complete)) {} absl::StatusOr executeImpl() override { ASSERT(fileDescriptor() != -1); @@ -56,8 +58,9 @@ class ActionStat : public AsyncFileActionThreadPool> class ActionCreateHardLink : public AsyncFileActionThreadPool { public: ActionCreateHardLink(AsyncFileHandle handle, absl::string_view filename, - std::function on_complete) - : AsyncFileActionThreadPool(handle, on_complete), filename_(filename) {} + absl::AnyInvocable on_complete) + : AsyncFileActionThreadPool(handle, std::move(on_complete)), + filename_(filename) {} absl::Status executeImpl() override { ASSERT(fileDescriptor() != -1); @@ -70,11 +73,12 @@ class ActionCreateHardLink : public AsyncFileActionThreadPool { return absl::OkStatus(); } - void onCancelledBeforeCallback(absl::Status result) override { - if (result.ok()) { + void onCancelledBeforeCallback() override { + if (result_.value().ok()) { posix().unlink(filename_.c_str()); } } + bool hasActionIfCancelledBeforeCallback() const override { return true; } private: const std::string filename_; @@ -85,8 +89,9 @@ class ActionCloseFile : public AsyncFileActionThreadPool { // Here we take a copy of the AsyncFileContext's file descriptor, because the close function // sets the AsyncFileContext's file descriptor to -1. This way there will be no race of trying // to use the handle again while the close is in flight. - explicit ActionCloseFile(AsyncFileHandle handle, std::function on_complete) - : AsyncFileActionThreadPool(handle, on_complete), + explicit ActionCloseFile(AsyncFileHandle handle, + absl::AnyInvocable on_complete) + : AsyncFileActionThreadPool(handle, std::move(on_complete)), file_descriptor_(fileDescriptor()) {} absl::Status executeImpl() override { @@ -97,6 +102,8 @@ class ActionCloseFile : public AsyncFileActionThreadPool { return absl::OkStatus(); } + bool executesEvenIfCancelled() const override { return true; } + private: const int file_descriptor_; }; @@ -104,8 +111,9 @@ class ActionCloseFile : public AsyncFileActionThreadPool { class ActionReadFile : public AsyncFileActionThreadPool> { public: ActionReadFile(AsyncFileHandle handle, off_t offset, size_t length, - std::function)> on_complete) - : AsyncFileActionThreadPool>(handle, on_complete), + absl::AnyInvocable)> on_complete) + : AsyncFileActionThreadPool>(handle, + std::move(on_complete)), offset_(offset), length_(length) {} absl::StatusOr executeImpl() override { @@ -133,8 +141,9 @@ class ActionReadFile : public AsyncFileActionThreadPool> { public: ActionWriteFile(AsyncFileHandle handle, Buffer::Instance& contents, off_t offset, - std::function)> on_complete) - : AsyncFileActionThreadPool>(handle, on_complete), offset_(offset) { + absl::AnyInvocable)> on_complete) + : AsyncFileActionThreadPool>(handle, std::move(on_complete)), + offset_(offset) { contents_.move(contents); } @@ -166,8 +175,9 @@ class ActionWriteFile : public AsyncFileActionThreadPool> class ActionDuplicateFile : public AsyncFileActionThreadPool> { public: ActionDuplicateFile(AsyncFileHandle handle, - std::function)> on_complete) - : AsyncFileActionThreadPool>(handle, on_complete) {} + absl::AnyInvocable)> on_complete) + : AsyncFileActionThreadPool>(handle, std::move(on_complete)) { + } absl::StatusOr executeImpl() override { ASSERT(fileDescriptor() != -1); @@ -178,61 +188,69 @@ class ActionDuplicateFile : public AsyncFileActionThreadPool(context()->manager(), newfd.return_value_); } - void onCancelledBeforeCallback(absl::StatusOr result) override { - if (result.ok()) { - result.value()->close([](absl::Status) {}).IgnoreError(); + void onCancelledBeforeCallback() override { + if (result_.value().ok()) { + result_.value().value()->close(nullptr, [](absl::Status) {}).IgnoreError(); } } + bool hasActionIfCancelledBeforeCallback() const override { return true; } }; } // namespace -absl::StatusOr -AsyncFileContextThreadPool::stat(std::function)> on_complete) { - return checkFileAndEnqueue(std::make_shared(handle(), std::move(on_complete))); +absl::StatusOr AsyncFileContextThreadPool::stat( + Event::Dispatcher* dispatcher, + absl::AnyInvocable)> on_complete) { + return checkFileAndEnqueue(dispatcher, + std::make_unique(handle(), std::move(on_complete))); } absl::StatusOr -AsyncFileContextThreadPool::createHardLink(absl::string_view filename, - std::function on_complete) { - return checkFileAndEnqueue( - std::make_shared(handle(), filename, std::move(on_complete))); +AsyncFileContextThreadPool::createHardLink(Event::Dispatcher* dispatcher, + absl::string_view filename, + absl::AnyInvocable on_complete) { + return checkFileAndEnqueue(dispatcher, std::make_unique( + handle(), filename, std::move(on_complete))); } -absl::Status AsyncFileContextThreadPool::close(std::function on_complete) { - auto status = - checkFileAndEnqueue(std::make_shared(handle(), std::move(on_complete))) - .status(); +absl::StatusOr +AsyncFileContextThreadPool::close(Event::Dispatcher* dispatcher, + absl::AnyInvocable on_complete) { + auto ret = checkFileAndEnqueue( + dispatcher, std::make_unique(handle(), std::move(on_complete))); fileDescriptor() = -1; - return status; + return ret; } absl::StatusOr AsyncFileContextThreadPool::read( - off_t offset, size_t length, - std::function)> on_complete) { - return checkFileAndEnqueue( - std::make_shared(handle(), offset, length, std::move(on_complete))); + Event::Dispatcher* dispatcher, off_t offset, size_t length, + absl::AnyInvocable)> on_complete) { + return checkFileAndEnqueue(dispatcher, std::make_unique(handle(), offset, length, + std::move(on_complete))); } absl::StatusOr -AsyncFileContextThreadPool::write(Buffer::Instance& contents, off_t offset, - std::function)> on_complete) { - return checkFileAndEnqueue( - std::make_shared(handle(), contents, offset, std::move(on_complete))); +AsyncFileContextThreadPool::write(Event::Dispatcher* dispatcher, Buffer::Instance& contents, + off_t offset, + absl::AnyInvocable)> on_complete) { + return checkFileAndEnqueue(dispatcher, std::make_unique( + handle(), contents, offset, std::move(on_complete))); } absl::StatusOr AsyncFileContextThreadPool::duplicate( - std::function)> on_complete) { + Event::Dispatcher* dispatcher, + absl::AnyInvocable)> on_complete) { return checkFileAndEnqueue( - std::make_shared(handle(), std::move(on_complete))); + dispatcher, std::make_unique(handle(), std::move(on_complete))); } absl::StatusOr -AsyncFileContextThreadPool::checkFileAndEnqueue(std::shared_ptr action) { +AsyncFileContextThreadPool::checkFileAndEnqueue(Event::Dispatcher* dispatcher, + std::unique_ptr action) { if (fileDescriptor() == -1) { return absl::FailedPreconditionError("file was already closed"); } - return enqueue(action); + return enqueue(dispatcher, std::move(action)); } AsyncFileContextThreadPool::AsyncFileContextThreadPool(AsyncFileManager& manager, int fd) diff --git a/source/extensions/common/async_files/async_file_context_thread_pool.h b/source/extensions/common/async_files/async_file_context_thread_pool.h index 8c14d75be8..6f344375fc 100644 --- a/source/extensions/common/async_files/async_file_context_thread_pool.h +++ b/source/extensions/common/async_files/async_file_context_thread_pool.h @@ -21,27 +21,35 @@ class AsyncFileContextThreadPool final : public AsyncFileContextBase { public: explicit AsyncFileContextThreadPool(AsyncFileManager& manager, int fd); + // CancelFunction should not be called during or after the callback. + // CancelFunction should only be called from the same thread that created + // the context. + // The callback will be dispatched to the same thread that created the context. absl::StatusOr - stat(std::function)> on_complete) override; + stat(Event::Dispatcher* dispatcher, + absl::AnyInvocable)> on_complete) override; absl::StatusOr - createHardLink(absl::string_view filename, - std::function on_complete) override; - absl::Status close(std::function on_complete) override; + createHardLink(Event::Dispatcher* dispatcher, absl::string_view filename, + absl::AnyInvocable on_complete) override; + absl::StatusOr close(Event::Dispatcher* dispatcher, + absl::AnyInvocable on_complete) override; absl::StatusOr - read(off_t offset, size_t length, - std::function)> on_complete) override; + read(Event::Dispatcher* dispatcher, off_t offset, size_t length, + absl::AnyInvocable)> on_complete) override; absl::StatusOr - write(Buffer::Instance& contents, off_t offset, - std::function)> on_complete) override; + write(Event::Dispatcher* dispatcher, Buffer::Instance& contents, off_t offset, + absl::AnyInvocable)> on_complete) override; absl::StatusOr - duplicate(std::function)> on_complete) override; + duplicate(Event::Dispatcher* dispatcher, + absl::AnyInvocable)> on_complete) override; int& fileDescriptor() { return file_descriptor_; } ~AsyncFileContextThreadPool() override; protected: - absl::StatusOr checkFileAndEnqueue(std::shared_ptr action); + absl::StatusOr checkFileAndEnqueue(Event::Dispatcher* dispatcher, + std::unique_ptr action); int file_descriptor_; }; diff --git a/source/extensions/common/async_files/async_file_handle.h b/source/extensions/common/async_files/async_file_handle.h index a8e54a4166..e52885dc2c 100644 --- a/source/extensions/common/async_files/async_file_handle.h +++ b/source/extensions/common/async_files/async_file_handle.h @@ -3,6 +3,8 @@ #include #include +#include "envoy/event/dispatcher.h" + #include "source/common/buffer/buffer_impl.h" #include "source/extensions/common/async_files/async_file_action.h" @@ -19,14 +21,16 @@ class AsyncFileContext : public std::enable_shared_from_this { public: // Gets a stat struct for the file. virtual absl::StatusOr - stat(std::function)> on_complete) PURE; + stat(Event::Dispatcher* dispatcher, + absl::AnyInvocable)> on_complete) PURE; // Action to hard link the file that is currently open. Typically for use in tandem with // createAnonymousFile to turn that file into a named file after finishing writing its contents. // // If cancelled before the callback is called but after creating the file, unlinks the file. virtual absl::StatusOr - createHardLink(absl::string_view filename, std::function on_complete) PURE; + createHardLink(Event::Dispatcher* dispatcher, absl::string_view filename, + absl::AnyInvocable on_complete) PURE; // Enqueues an action to close the currently open file. // It is an error to use an AsyncFileContext after calling close. @@ -35,18 +39,18 @@ class AsyncFileContext : public std::enable_shared_from_this { // Note that because an AsyncFileHandle is a shared_ptr, it is okay to // call close during the handle's owner's destructor - that will queue the close // event, which will keep the handle alive until after the close operation - // is completed. (But be careful that the on_complete callback doesn't require any - // context from the destroyed owner!) - // close cannot be cancelled. - virtual absl::Status close(std::function on_complete) PURE; + // is completed. + // Cancelling close can abort the callback, but the close action will always complete. + virtual absl::StatusOr + close(Event::Dispatcher* dispatcher, absl::AnyInvocable on_complete) PURE; // Enqueues an action to read from the currently open file, at position offset, up to the number // of bytes specified by length. The size of the buffer passed to on_complete informs you if less // than the requested amount was read. It is an error to read on an AsyncFileContext that does not // have a file open. There must not already be an action queued for this handle. virtual absl::StatusOr - read(off_t offset, size_t length, - std::function)> on_complete) PURE; + read(Event::Dispatcher* dispatcher, off_t offset, size_t length, + absl::AnyInvocable)> on_complete) PURE; // Enqueues an action to write to the currently open file, at position offset, the bytes contained // by contents. It is an error to call write on an AsyncFileContext that does not have a file @@ -58,15 +62,16 @@ class AsyncFileContext : public std::enable_shared_from_this { // on_complete is called with the number of bytes written on success. // There must not already be an action queued for this handle. virtual absl::StatusOr - write(Buffer::Instance& contents, off_t offset, - std::function)> on_complete) PURE; + write(Event::Dispatcher* dispatcher, Buffer::Instance& contents, off_t offset, + absl::AnyInvocable)> on_complete) PURE; // Creates a new AsyncFileHandle referencing the same file. // Note that a file handle duplicated in this way shares positioning and permissions // with the original. Since AsyncFileContext functions are all position-explicit, this should not // matter. virtual absl::StatusOr duplicate( - std::function>)> on_complete) PURE; + Event::Dispatcher* dispatcher, + absl::AnyInvocable>)> on_complete) PURE; protected: virtual ~AsyncFileContext() = default; diff --git a/source/extensions/common/async_files/async_file_manager.cc b/source/extensions/common/async_files/async_file_manager.cc deleted file mode 100644 index 2de25a67dc..0000000000 --- a/source/extensions/common/async_files/async_file_manager.cc +++ /dev/null @@ -1,31 +0,0 @@ -#include "source/extensions/common/async_files/async_file_manager.h" - -#include -#include - -#include "source/common/common/macros.h" -#include "source/extensions/common/async_files/async_file_action.h" - -namespace Envoy { -namespace Extensions { -namespace Common { -namespace AsyncFiles { - -namespace { -class ActionWhenReady : public AsyncFileActionWithResult { -public: - explicit ActionWhenReady(std::function on_complete) - : AsyncFileActionWithResult(on_complete) {} - - absl::Status executeImpl() override { return absl::OkStatus(); } -}; -} // namespace - -CancelFunction AsyncFileManager::whenReady(std::function on_complete) { - return enqueue(std::make_shared(std::move(on_complete))); -} - -} // namespace AsyncFiles -} // namespace Common -} // namespace Extensions -} // namespace Envoy diff --git a/source/extensions/common/async_files/async_file_manager.h b/source/extensions/common/async_files/async_file_manager.h index d515d49c63..c9f0c2c250 100644 --- a/source/extensions/common/async_files/async_file_manager.h +++ b/source/extensions/common/async_files/async_file_manager.h @@ -2,6 +2,8 @@ #include +#include "envoy/event/dispatcher.h" + #include "source/extensions/common/async_files/async_file_action.h" #include "source/extensions/common/async_files/async_file_handle.h" @@ -34,8 +36,8 @@ class AsyncFileManager { // Returns a cancellation function, which aborts the operation (and closes // the file if opened) unless the callback has already been called. virtual CancelFunction - createAnonymousFile(absl::string_view path, - std::function)> on_complete) PURE; + createAnonymousFile(Event::Dispatcher* dispatcher, absl::string_view path, + absl::AnyInvocable)> on_complete) PURE; // A mode for opening existing files. enum class Mode { ReadOnly, WriteOnly, ReadWrite }; @@ -46,53 +48,56 @@ class AsyncFileManager { // Returns a cancellation function, which aborts the operation (and closes // the file if opened) unless the callback has already been called. virtual CancelFunction - openExistingFile(absl::string_view filename, Mode mode, - std::function)> on_complete) PURE; + openExistingFile(Event::Dispatcher* dispatcher, absl::string_view filename, Mode mode, + absl::AnyInvocable)> on_complete) PURE; // Action to stat a file. // on_complete receives a stat structure on success, or an error on failure. // // Returns a cancellation function, which aborts the operation // unless the callback has already been called. - virtual CancelFunction stat(absl::string_view filename, - std::function)> on_complete) PURE; + virtual CancelFunction + stat(Event::Dispatcher* dispatcher, absl::string_view filename, + absl::AnyInvocable)> on_complete) PURE; // Action to delete a named file. // on_complete receives OK on success, or an error on failure. // // Returns a cancellation function, which aborts the operation // unless it has already been performed. - virtual CancelFunction unlink(absl::string_view filename, - std::function on_complete) PURE; - - // whenReady can be used to only perform an action when the caller hits the - // front of the thread pool's queue - this can be used to defer requesting - // a file action until it could actually take place. For example, if you're - // offloading data from memory to disk temporarily, if you queue the write - // immediately then the filesystem thread owns the data until the write - // completes, which may be blocked by heavy traffic, and it turns out you - // want the data back before then - you can't get it back, you have to wait - // for the write to complete and then read it back. - // - // If you used whenReady, you could keep the data belonging to the client - // until it's actually the client's turn to do disk access. When whenReady's - // callback is called, if you request the write at that time the performance - // will be almost identical to if you had requested the write earlier, but - // you have the opportunity to change your mind and do something different - // in the meantime. - // - // The cost of using whenReady is that it requires the client to be lock - // controlled (since the callback occurs in a different thread than the thread - // the state belongs to), versus simpler unchained operations can use queue - // based actions and not worry about ownership. - CancelFunction whenReady(std::function on_complete); + virtual CancelFunction unlink(Event::Dispatcher* dispatcher, absl::string_view filename, + absl::AnyInvocable on_complete) PURE; // Return a string description of the configuration of the manager. // (This is mostly to facilitate testing.) virtual std::string describe() const PURE; + // To facilitate testing, blocks until all queued actions have been performed and + // callbacks posted. + // This does not guarantee that the callbacks have been executed, only that they + // have been sent to the dispatcher. + virtual void waitForIdle() PURE; + +protected: + class QueuedAction { + public: + QueuedAction(std::unique_ptr action, Event::Dispatcher* dispatcher) + : action_(std::move(action)), dispatcher_(dispatcher), + state_(std::make_shared>(State::Queued)) {} + QueuedAction() = default; + std::unique_ptr action_; + Event::Dispatcher* dispatcher_ = nullptr; + enum class State { Queued, Executing, InCallback, Done, Cancelled }; + std::shared_ptr> state_; + }; + private: - virtual CancelFunction enqueue(const std::shared_ptr context) PURE; + // Puts an action in the queue for execution. + virtual CancelFunction enqueue(Event::Dispatcher* dispatcher, + std::unique_ptr action) PURE; + // Puts an action in the queue for its `onCancelledBeforeCallback` function to be + // called. + virtual void postCancelledActionForCleanup(std::unique_ptr action) PURE; friend class AsyncFileContextBase; friend class AsyncFileManagerTest; diff --git a/source/extensions/common/async_files/async_file_manager_thread_pool.cc b/source/extensions/common/async_files/async_file_manager_thread_pool.cc index 1dfd7b84e4..dd6c0a3a86 100644 --- a/source/extensions/common/async_files/async_file_manager_thread_pool.cc +++ b/source/extensions/common/async_files/async_file_manager_thread_pool.cc @@ -15,17 +15,6 @@ namespace Extensions { namespace Common { namespace AsyncFiles { -namespace { -// ThreadNextAction is per worker thread; if enqueue is called from a callback -// the action goes directly into ThreadNextAction, otherwise it goes into the -// queue and is eventually pulled out into ThreadNextAction by a worker thread. -thread_local std::shared_ptr ThreadNextAction; - -// ThreadIsWorker is set to true for worker threads, and will be false -// for all other threads. -thread_local bool ThreadIsWorker = false; -} // namespace - AsyncFileManagerThreadPool::AsyncFileManagerThreadPool( const envoy::extensions::common::async_files::v3::AsyncFileManagerConfig& config, Api::OsSysCalls& posix) @@ -50,6 +39,7 @@ AsyncFileManagerThreadPool::~AsyncFileManagerThreadPool() ABSL_LOCKS_EXCLUDED(qu absl::MutexLock lock(&queue_mutex_); terminate_ = true; } + // This destructor will be blocked by this loop until all queued file actions are complete. while (!thread_pool_.empty()) { thread_pool_.back().join(); thread_pool_.pop_back(); @@ -60,46 +50,123 @@ std::string AsyncFileManagerThreadPool::describe() const { return absl::StrCat("thread_pool_size = ", thread_pool_.size()); } -std::function AsyncFileManagerThreadPool::enqueue(std::shared_ptr action) { - auto cancel_func = [action]() { action->cancel(); }; - // If an action is being enqueued from within a callback, we don't have to actually queue it, - // we can just set it as the thread's next action - this acts to chain the actions without - // yielding to another file. - if (ThreadIsWorker) { - ASSERT(!ThreadNextAction); // only do one file action per callback. - ThreadNextAction = std::move(action); - return cancel_func; - } +void AsyncFileManagerThreadPool::waitForIdle() { + const auto condition = [this]() ABSL_EXCLUSIVE_LOCKS_REQUIRED(queue_mutex_) { + return active_workers_ == 0 && queue_.empty() && cleanup_queue_.empty(); + }; absl::MutexLock lock(&queue_mutex_); - queue_.push(std::move(action)); + queue_mutex_.Await(absl::Condition(&condition)); +} + +absl::AnyInvocable +AsyncFileManagerThreadPool::enqueue(Event::Dispatcher* dispatcher, + std::unique_ptr action) { + QueuedAction entry{std::move(action), dispatcher}; + auto cancel_func = [dispatcher, state = entry.state_]() { + ASSERT(dispatcher == nullptr || dispatcher->isThreadSafe()); + state->store(QueuedAction::State::Cancelled); + }; + absl::MutexLock lock(&queue_mutex_); + queue_.push(std::move(entry)); return cancel_func; } +void AsyncFileManagerThreadPool::postCancelledActionForCleanup( + std::unique_ptr action) { + absl::MutexLock lock(&queue_mutex_); + cleanup_queue_.push(std::move(action)); +} + +void AsyncFileManagerThreadPool::executeAction(QueuedAction&& queued_action) { + using State = QueuedAction::State; + State expected = State::Queued; + std::shared_ptr> state = std::move(queued_action.state_); + std::unique_ptr action = std::move(queued_action.action_); + if (!state->compare_exchange_strong(expected, State::Executing)) { + ASSERT(expected == State::Cancelled); + if (action->executesEvenIfCancelled()) { + action->execute(); + } + return; + } + action->execute(); + expected = State::Executing; + if (!state->compare_exchange_strong(expected, State::InCallback)) { + ASSERT(expected == State::Cancelled); + action->onCancelledBeforeCallback(); + return; + } + if (queued_action.dispatcher_ == nullptr) { + // No need to bother arranging the callback, because a dispatcher was not provided. + return; + } + // If it is necessary to explicitly undo an action on cancel then the lambda will need a + // pointer to this manager that is guaranteed to outlive the lambda, in order to be able + // to perform that cancel operation on a thread belonging to the file manager. + // So capture a shared_ptr if necessary, but, to avoid unnecessary shared_ptr wrangling, + // leave it empty if the action doesn't have an associated cancel operation. + std::shared_ptr manager; + if (action->hasActionIfCancelledBeforeCallback()) { + manager = shared_from_this(); + } + queued_action.dispatcher_->post([manager = std::move(manager), action = std::move(action), + state = std::move(state)]() mutable { + // This callback runs on the caller's thread. + State expected = State::InCallback; + if (state->compare_exchange_strong(expected, State::Done)) { + // Action was not cancelled; run the captured callback on the caller's thread. + action->onComplete(); + return; + } + ASSERT(expected == State::Cancelled); + if (manager == nullptr) { + // Action had a "do nothing" cancellation so we don't need to post a cleanup action. + return; + } + // If an action with side-effects was cancelled after being posted, its + // side-effects need to be undone as the caller can no longer receive the + // returned context. That undo action will need to be done on one of the + // file manager's threads, as it is file related, so post it to the thread pool. + manager->postCancelledActionForCleanup(std::move(action)); + }); +} + void AsyncFileManagerThreadPool::worker() { - ThreadIsWorker = true; + const auto condition = [this]() ABSL_EXCLUSIVE_LOCKS_REQUIRED(queue_mutex_) { + return !queue_.empty() || !cleanup_queue_.empty() || terminate_; + }; + { + absl::MutexLock lock(&queue_mutex_); + active_workers_++; + } while (true) { - const auto condition = [this]() ABSL_EXCLUSIVE_LOCKS_REQUIRED(queue_mutex_) { - return !queue_.empty() || terminate_; - }; + QueuedAction action; + std::unique_ptr cleanup_action; { absl::MutexLock lock(&queue_mutex_); + active_workers_--; queue_mutex_.Await(absl::Condition(&condition)); - if (terminate_) { + if (terminate_ && queue_.empty() && cleanup_queue_.empty()) { return; } - ThreadNextAction = std::move(queue_.front()); - queue_.pop(); + active_workers_++; + if (!queue_.empty()) { + action = std::move(queue_.front()); + queue_.pop(); + } + if (!cleanup_queue_.empty()) { + cleanup_action = std::move(cleanup_queue_.front()); + cleanup_queue_.pop(); + } + } + if (action.action_ != nullptr) { + executeAction(std::move(action)); + action.action_ = nullptr; + } + if (cleanup_action != nullptr) { + std::move(cleanup_action)->onCancelledBeforeCallback(); + cleanup_action = nullptr; } - resolveActions(); - } -} - -void AsyncFileManagerThreadPool::resolveActions() { - while (ThreadNextAction) { - // Move the action out of ThreadNextAction so that its callback can enqueue - // a different ThreadNextAction without self-destructing. - std::shared_ptr action = std::move(ThreadNextAction); - action->execute(); } } @@ -108,15 +175,17 @@ namespace { class ActionWithFileResult : public AsyncFileActionWithResult> { public: ActionWithFileResult(AsyncFileManagerThreadPool& manager, - std::function)> on_complete) - : AsyncFileActionWithResult(on_complete), manager_(manager) {} + absl::AnyInvocable)> on_complete) + : AsyncFileActionWithResult(std::move(on_complete)), manager_(manager) {} protected: - void onCancelledBeforeCallback(absl::StatusOr result) override { - if (result.ok()) { - result.value()->close([](absl::Status) {}).IgnoreError(); + void onCancelledBeforeCallback() override { + if (result_.value().ok()) { + result_.value().value()->close(nullptr, [](absl::Status) {}).IgnoreError(); } } + bool hasActionIfCancelledBeforeCallback() const override { return true; } + AsyncFileManagerThreadPool& manager_; Api::OsSysCalls& posix() { return manager_.posix(); } }; @@ -124,8 +193,8 @@ class ActionWithFileResult : public AsyncFileActionWithResult)> on_complete) - : ActionWithFileResult(manager, on_complete), path_(path) {} + absl::AnyInvocable)> on_complete) + : ActionWithFileResult(manager, std::move(on_complete)), path_(path) {} absl::StatusOr executeImpl() override { Api::SysCallIntResult open_result; @@ -187,8 +256,8 @@ class ActionOpenExistingFile : public ActionWithFileResult { public: ActionOpenExistingFile(AsyncFileManagerThreadPool& manager, absl::string_view filename, AsyncFileManager::Mode mode, - std::function)> on_complete) - : ActionWithFileResult(manager, on_complete), filename_(filename), mode_(mode) {} + absl::AnyInvocable)> on_complete) + : ActionWithFileResult(manager, std::move(on_complete)), filename_(filename), mode_(mode) {} absl::StatusOr executeImpl() override { auto open_result = posix().open(filename_.c_str(), openFlags()); @@ -217,8 +286,8 @@ class ActionOpenExistingFile : public ActionWithFileResult { class ActionStat : public AsyncFileActionWithResult> { public: ActionStat(Api::OsSysCalls& posix, absl::string_view filename, - std::function)> on_complete) - : AsyncFileActionWithResult(on_complete), posix_(posix), filename_(filename) {} + absl::AnyInvocable)> on_complete) + : AsyncFileActionWithResult(std::move(on_complete)), posix_(posix), filename_(filename) {} absl::StatusOr executeImpl() override { struct stat ret; @@ -237,8 +306,8 @@ class ActionStat : public AsyncFileActionWithResult> class ActionUnlink : public AsyncFileActionWithResult { public: ActionUnlink(Api::OsSysCalls& posix, absl::string_view filename, - std::function on_complete) - : AsyncFileActionWithResult(on_complete), posix_(posix), filename_(filename) {} + absl::AnyInvocable on_complete) + : AsyncFileActionWithResult(std::move(on_complete)), posix_(posix), filename_(filename) {} absl::Status executeImpl() override { Api::SysCallIntResult unlink_result = posix_.unlink(filename_.c_str()); @@ -256,25 +325,31 @@ class ActionUnlink : public AsyncFileActionWithResult { } // namespace CancelFunction AsyncFileManagerThreadPool::createAnonymousFile( - absl::string_view path, std::function)> on_complete) { - return enqueue(std::make_shared(*this, path, on_complete)); + Event::Dispatcher* dispatcher, absl::string_view path, + absl::AnyInvocable)> on_complete) { + return enqueue(dispatcher, + std::make_unique(*this, path, std::move(on_complete))); } CancelFunction AsyncFileManagerThreadPool::openExistingFile( - absl::string_view filename, Mode mode, - std::function)> on_complete) { - return enqueue(std::make_shared(*this, filename, mode, on_complete)); + Event::Dispatcher* dispatcher, absl::string_view filename, Mode mode, + absl::AnyInvocable)> on_complete) { + return enqueue(dispatcher, std::make_unique(*this, filename, mode, + std::move(on_complete))); } -CancelFunction -AsyncFileManagerThreadPool::stat(absl::string_view filename, - std::function)> on_complete) { - return enqueue(std::make_shared(posix(), filename, on_complete)); +CancelFunction AsyncFileManagerThreadPool::stat( + Event::Dispatcher* dispatcher, absl::string_view filename, + absl::AnyInvocable)> on_complete) { + return enqueue(dispatcher, + std::make_unique(posix(), filename, std::move(on_complete))); } -CancelFunction AsyncFileManagerThreadPool::unlink(absl::string_view filename, - std::function on_complete) { - return enqueue(std::make_shared(posix(), filename, on_complete)); +CancelFunction +AsyncFileManagerThreadPool::unlink(Event::Dispatcher* dispatcher, absl::string_view filename, + absl::AnyInvocable on_complete) { + return enqueue(dispatcher, + std::make_unique(posix(), filename, std::move(on_complete))); } } // namespace AsyncFiles diff --git a/source/extensions/common/async_files/async_file_manager_thread_pool.h b/source/extensions/common/async_files/async_file_manager_thread_pool.h index 2a82202384..81c927eda7 100644 --- a/source/extensions/common/async_files/async_file_manager_thread_pool.h +++ b/source/extensions/common/async_files/async_file_manager_thread_pool.h @@ -24,23 +24,25 @@ namespace AsyncFiles { // performed the previous action in the chain immediately performs the newly chained // action. class AsyncFileManagerThreadPool : public AsyncFileManager, + public std::enable_shared_from_this, protected Logger::Loggable { public: explicit AsyncFileManagerThreadPool( const envoy::extensions::common::async_files::v3::AsyncFileManagerConfig& config, Api::OsSysCalls& posix); ~AsyncFileManagerThreadPool() ABSL_LOCKS_EXCLUDED(queue_mutex_) override; + CancelFunction createAnonymousFile( + Event::Dispatcher* dispatcher, absl::string_view path, + absl::AnyInvocable)> on_complete) override; CancelFunction - createAnonymousFile(absl::string_view path, - std::function)> on_complete) override; - CancelFunction - openExistingFile(absl::string_view filename, Mode mode, - std::function)> on_complete) override; - CancelFunction stat(absl::string_view filename, - std::function)> on_complete) override; - CancelFunction unlink(absl::string_view filename, - std::function on_complete) override; + openExistingFile(Event::Dispatcher* dispatcher, absl::string_view filename, Mode mode, + absl::AnyInvocable)> on_complete) override; + CancelFunction stat(Event::Dispatcher* dispatcher, absl::string_view filename, + absl::AnyInvocable)> on_complete) override; + CancelFunction unlink(Event::Dispatcher* dispatcher, absl::string_view filename, + absl::AnyInvocable on_complete) override; std::string describe() const override; + void waitForIdle() override; Api::OsSysCalls& posix() const { return posix_; } #ifdef O_TMPFILE @@ -56,13 +58,18 @@ class AsyncFileManagerThreadPool : public AsyncFileManager, #endif // O_TMPFILE private: - std::function enqueue(std::shared_ptr action) + absl::AnyInvocable enqueue(Event::Dispatcher* dispatcher, + std::unique_ptr action) + ABSL_LOCKS_EXCLUDED(queue_mutex_) override; + void postCancelledActionForCleanup(std::unique_ptr action) ABSL_LOCKS_EXCLUDED(queue_mutex_) override; void worker() ABSL_LOCKS_EXCLUDED(queue_mutex_); - void resolveActions(); absl::Mutex queue_mutex_; - std::queue> queue_ ABSL_GUARDED_BY(queue_mutex_); + void executeAction(QueuedAction&& action); + std::queue queue_ ABSL_GUARDED_BY(queue_mutex_); + int active_workers_ ABSL_GUARDED_BY(queue_mutex_) = 0; + std::queue> cleanup_queue_ ABSL_GUARDED_BY(queue_mutex_); bool terminate_ ABSL_GUARDED_BY(queue_mutex_) = false; std::vector thread_pool_; diff --git a/source/extensions/filters/http/file_system_buffer/filter.cc b/source/extensions/filters/http/file_system_buffer/filter.cc index 56764975b0..fbb4420a7d 100644 --- a/source/extensions/filters/http/file_system_buffer/filter.cc +++ b/source/extensions/filters/http/file_system_buffer/filter.cc @@ -283,7 +283,7 @@ bool FileSystemBufferFilter::maybeOutputResponse() { void BufferedStreamState::close() { if (async_file_handle_) { - auto queued = async_file_handle_->close([](absl::Status) {}); + auto queued = async_file_handle_->close(nullptr, [](absl::Status) {}); ASSERT(queued.ok()); } } @@ -375,11 +375,11 @@ bool FileSystemBufferFilter::maybeStorage(BufferedStreamState& state, state.storage_used_ -= size; state.memory_used_ += size; ENVOY_STREAM_LOG(debug, "retrieving buffer fragment (size={}) from storage", callbacks, size); - auto queued = - (**earliest_storage_fragment) - .fromStorage(state.async_file_handle_, getSafeDispatch(), getOnFileActionCompleted()); + auto queued = (**earliest_storage_fragment) + .fromStorage(state.async_file_handle_, request_callbacks_->dispatcher(), + getOnFileActionCompleted()); ASSERT(queued.ok()); - cancel_in_flight_async_action_ = queued.value(); + cancel_in_flight_async_action_ = std::move(queued.value()); return true; } } @@ -389,30 +389,19 @@ bool FileSystemBufferFilter::maybeStorage(BufferedStreamState& state, if (!state.async_file_handle_) { // File isn't open yet - open it and then check again if we still need to store data. ENVOY_STREAM_LOG(debug, "memory buffer exceeded - creating buffer file", callbacks); - // We can't use getSafeDispatcher here because we need to close the file if the filter - // was deleted before the callback, not just do nothing. + // The callback won't be called if the filter was destroyed, and if the file was + // racily created it will be closed. cancel_in_flight_async_action_ = config_->asyncFileManager().createAnonymousFile( - config_->storageBufferPath(), - [this, is_destroyed = is_destroyed_, dispatcher = &request_callbacks_->dispatcher(), - &state](absl::StatusOr file_handle) { - dispatcher->post([this, is_destroyed, &state, file_handle]() { - if (*is_destroyed) { - // If we opened a file but the filter went away in the meantime, close the file - // to avoid leaving a dangling file handle. - if (file_handle.ok()) { - file_handle.value()->close([](absl::Status) {}).IgnoreError(); - } - return; - } - if (!file_handle.ok()) { - filterError(fmt::format("{} failed to create buffer file: {}", filterName(), - file_handle.status().ToString())); - return; - } - state.async_file_handle_ = std::move(file_handle.value()); - cancel_in_flight_async_action_ = nullptr; - onStateChange(); - }); + &request_callbacks_->dispatcher(), config_->storageBufferPath(), + [this, &state](absl::StatusOr file_handle) { + if (!file_handle.ok()) { + filterError(fmt::format("{} failed to create buffer file: {}", filterName(), + file_handle.status().ToString())); + return; + } + state.async_file_handle_ = std::move(file_handle.value()); + cancel_in_flight_async_action_ = nullptr; + onStateChange(); }); return true; } @@ -424,18 +413,19 @@ bool FileSystemBufferFilter::maybeStorage(BufferedStreamState& state, state.storage_consumed_ += size; state.memory_used_ -= size; ENVOY_STREAM_LOG(debug, "sending buffer fragment (size={}) to storage", callbacks, size); - auto to_storage = fragment->toStorage(state.async_file_handle_, state.storage_offset_, - getSafeDispatch(), getOnFileActionCompleted()); + auto to_storage = + fragment->toStorage(state.async_file_handle_, state.storage_offset_, + request_callbacks_->dispatcher(), getOnFileActionCompleted()); ASSERT(to_storage.ok()); - cancel_in_flight_async_action_ = to_storage.value(); + cancel_in_flight_async_action_ = std::move(to_storage.value()); state.storage_offset_ += size; return true; } return false; } -std::function FileSystemBufferFilter::getOnFileActionCompleted() { - // This callback is only run via getSafeDispatch, so is safe to capture 'this' - +absl::AnyInvocable FileSystemBufferFilter::getOnFileActionCompleted() { + // This callback is aborted in onDestroy, so is safe to capture 'this' - // it won't be called if the filter has been deleted. return [this](absl::Status status) { cancel_in_flight_async_action_ = nullptr; @@ -447,19 +437,17 @@ std::function FileSystemBufferFilter::getOnFileActionComplet }; } -std::function)> FileSystemBufferFilter::getSafeDispatch() { - return [is_destroyed = is_destroyed_, - dispatcher = &request_callbacks_->dispatcher()](std::function callback) { - dispatcher->post([is_destroyed, callback = std::move(callback)]() { - if (!*is_destroyed) { - callback(); - } - }); - }; +void FileSystemBufferFilter::safeDispatch(absl::AnyInvocable fn) { + request_callbacks_->dispatcher().post( + [is_destroyed = is_destroyed_, fn = std::move(fn)]() mutable { + if (!*is_destroyed) { + std::move(fn)(); + } + }); } void FileSystemBufferFilter::dispatchStateChanged() { - getSafeDispatch()([this]() { onStateChange(); }); + safeDispatch([this]() { onStateChange(); }); } } // namespace FileSystemBuffer diff --git a/source/extensions/filters/http/file_system_buffer/filter.h b/source/extensions/filters/http/file_system_buffer/filter.h index d53feb0794..be452c41d6 100644 --- a/source/extensions/filters/http/file_system_buffer/filter.h +++ b/source/extensions/filters/http/file_system_buffer/filter.h @@ -102,14 +102,15 @@ class FileSystemBufferFilter : public Http::StreamFilter, // These operations are asynchronous; the impacted buffer fragments are in an unusable state until // the operation completes. bool maybeStorage(BufferedStreamState& state, Http::StreamFilterCallbacks& callbacks); - std::function getOnFileActionCompleted(); + absl::AnyInvocable getOnFileActionCompleted(); // Called if an unrecoverable error occurs in the filter (e.g. a file operation fails). Internal // server error. void filterError(absl::string_view err); - // Returns a safe dispatch function that aborts if the filter has been destroyed. - std::function)> getSafeDispatch(); + // Dispatch a callback wrapped such that it is not called if the filter has been destroyed + // by the time it pops off the dispatch queue. + void safeDispatch(absl::AnyInvocable fn); // Queue an onStateChange in the dispatcher. This is used to get the next piece of work back // into the Envoy thread from an AsyncFiles thread, or to queue work that may not be allowed diff --git a/source/extensions/filters/http/file_system_buffer/fragment.cc b/source/extensions/filters/http/file_system_buffer/fragment.cc index d2da3bbd1c..bebde1364e 100644 --- a/source/extensions/filters/http/file_system_buffer/fragment.cc +++ b/source/extensions/filters/http/file_system_buffer/fragment.cc @@ -35,60 +35,53 @@ std::unique_ptr Fragment::extract() { std::unique_ptr MemoryFragment::extract() { return std::move(buffer_); } -absl::StatusOr -Fragment::toStorage(AsyncFileHandle file, off_t offset, - std::function)> dispatch, - std::function on_done) { +absl::StatusOr Fragment::toStorage(AsyncFileHandle file, off_t offset, + Event::Dispatcher& dispatcher, + absl::AnyInvocable on_done) { ASSERT(isMemory()); auto data = absl::get(data_).extract(); data_.emplace(); + // This callback is only called if the filter was not destroyed in the meantime, + // so it is safe to use `this`. return file->write( - *data, offset, - [this, dispatch = std::move(dispatch), size = size_, on_done = std::move(on_done), - offset](absl::StatusOr result) { - // size is captured because we can't safely use 'this' until we're in the dispatch callback. + &dispatcher, *data, offset, + [this, on_done = std::move(on_done), offset](absl::StatusOr result) mutable { if (!result.ok()) { - dispatch([status = result.status(), on_done = std::move(on_done)]() { on_done(status); }); - } else if (result.value() != size) { + std::move(on_done)(result.status()); + } else if (result.value() != size_) { auto status = absl::AbortedError( - fmt::format("buffer write wrote {} bytes, wanted {}", result.value(), size)); - dispatch( - [on_done = std::move(on_done), status = std::move(status)]() { on_done(status); }); + fmt::format("buffer write wrote {} bytes, wanted {}", result.value(), size_)); + std::move(on_done)(status); } else { - dispatch([this, status = result.status(), offset, on_done = std::move(on_done)] { - data_.emplace(offset); - on_done(absl::OkStatus()); - }); + data_.emplace(offset); + std::move(on_done)(absl::OkStatus()); } }); } absl::StatusOr -Fragment::fromStorage(AsyncFileHandle file, std::function)> dispatch, - std::function on_done) { +Fragment::fromStorage(AsyncFileHandle file, Event::Dispatcher& dispatcher, + absl::AnyInvocable on_done) { ASSERT(isStorage()); off_t offset = absl::get(data_).offset(); data_.emplace(); - return file->read( - offset, size_, - [this, dispatch = std::move(dispatch), size = size_, - on_done = std::move(on_done)](absl::StatusOr> result) { - // size is captured because we can't safely use 'this' until we're in the dispatch callback. - if (!result.ok()) { - dispatch([on_done = std::move(on_done), status = result.status()]() { on_done(status); }); - } else if (result.value()->length() != size) { - auto status = absl::AbortedError( - fmt::format("buffer read got {} bytes, wanted {}", result.value()->length(), size)); - dispatch( - [on_done = std::move(on_done), status = std::move(status)]() { on_done(status); }); - } else { - auto buffer = std::shared_ptr(std::move(result.value())); - dispatch([this, on_done = std::move(on_done), buffer = std::move(buffer)]() { - data_.emplace(*buffer); - on_done(absl::OkStatus()); - }); - } - }); + // This callback is only called if the filter was not destroyed in the meantime, + // so it is safe to use `this`. + return file->read(&dispatcher, offset, size_, + [this, on_done = std::move(on_done)]( + absl::StatusOr> result) mutable { + if (!result.ok()) { + std::move(on_done)(result.status()); + } else if (result.value()->length() != size_) { + auto status = + absl::AbortedError(fmt::format("buffer read got {} bytes, wanted {}", + result.value()->length(), size_)); + std::move(on_done)(status); + } else { + data_.emplace(*result.value()); + std::move(on_done)(absl::OkStatus()); + } + }); } } // namespace FileSystemBuffer diff --git a/source/extensions/filters/http/file_system_buffer/fragment.h b/source/extensions/filters/http/file_system_buffer/fragment.h index 2e6efe2704..f38667da8e 100644 --- a/source/extensions/filters/http/file_system_buffer/fragment.h +++ b/source/extensions/filters/http/file_system_buffer/fragment.h @@ -70,8 +70,8 @@ class Fragment { // When called from a filter, the dispatcher function must abort without calling the // callback if the filter or fragment has been destroyed. absl::StatusOr toStorage(AsyncFileHandle file, off_t offset, - std::function)> dispatch, - std::function on_done); + Event::Dispatcher& dispatcher, + absl::AnyInvocable on_done); // Starts the transition for this fragment from storage to memory. // @@ -79,9 +79,8 @@ class Fragment { // // When called from a filter, the dispatcher function must abort without calling the // callback if the filter or fragment has been destroyed. - absl::StatusOr fromStorage(AsyncFileHandle file, - std::function)> dispatch, - std::function on_done); + absl::StatusOr fromStorage(AsyncFileHandle file, Event::Dispatcher& dispatcher, + absl::AnyInvocable on_done); // Moves the buffer from a memory instance to the returned value and resets the fragment to // size 0. diff --git a/source/extensions/http/cache/file_system_http_cache/file_system_http_cache.cc b/source/extensions/http/cache/file_system_http_cache/file_system_http_cache.cc index 687a0e40d8..1e5a49c6c6 100644 --- a/source/extensions/http/cache/file_system_http_cache/file_system_http_cache.cc +++ b/source/extensions/http/cache/file_system_http_cache/file_system_http_cache.cc @@ -25,7 +25,7 @@ const size_t FileSystemHttpCache::max_update_headers_copy_chunk_size_ = 128 * 10 const CacheStats& FileSystemHttpCache::stats() const { return shared_->stats_; } const ConfigProto& FileSystemHttpCache::config() const { return shared_->config_; } -void FileSystemHttpCache::writeVaryNodeToDisk(const Key& key, +void FileSystemHttpCache::writeVaryNodeToDisk(Event::Dispatcher& dispatcher, const Key& key, const Http::ResponseHeaderMap& response_headers, std::shared_ptr cleanup) { auto vary_values = VaryHeaderUtils::getVaryValues(response_headers); @@ -35,8 +35,9 @@ void FileSystemHttpCache::writeVaryNodeToDisk(const Key& key, h->set_value(absl::StrJoin(vary_values, ",")); std::string filename = absl::StrCat(cachePath(), generateFilename(key)); async_file_manager_->createAnonymousFile( - cachePath(), [headers, filename = std::move(filename), - cleanup](absl::StatusOr open_result) { + &dispatcher, cachePath(), + [headers, filename = std::move(filename), cleanup, + dispatcher = &dispatcher](absl::StatusOr open_result) { if (!open_result.ok()) { ENVOY_LOG(warn, "writing vary node, failed to createAnonymousFile: {}", open_result.status()); @@ -51,20 +52,20 @@ void FileSystemHttpCache::writeVaryNodeToDisk(const Key& key, buf2.add(buf); size_t sz = buf2.length(); auto queued = file_handle->write( - buf2, 0, - [file_handle, cleanup, sz, + dispatcher, buf2, 0, + [dispatcher, file_handle, cleanup, sz, filename = std::move(filename)](absl::StatusOr write_result) { if (!write_result.ok() || write_result.value() != sz) { ENVOY_LOG(warn, "writing vary node, failed to write: {}", write_result.status()); - file_handle->close([](absl::Status) {}).IgnoreError(); + file_handle->close(nullptr, [](absl::Status) {}).IgnoreError(); return; } auto queued = file_handle->createHardLink( - filename, [cleanup, file_handle](absl::Status link_result) { + dispatcher, filename, [cleanup, file_handle](absl::Status link_result) { if (!link_result.ok()) { ENVOY_LOG(warn, "writing vary node, failed to link: {}", link_result); } - file_handle->close([](absl::Status) {}).IgnoreError(); + file_handle->close(nullptr, [](absl::Status) {}).IgnoreError(); }); ASSERT(queued.ok()); }); @@ -114,35 +115,37 @@ FileSystemHttpCache::makeVaryKey(const Key& base, const VaryAllowList& vary_allo return vary_key; } -LookupContextPtr FileSystemHttpCache::makeLookupContext(LookupRequest&& lookup, - Http::StreamDecoderFilterCallbacks&) { - return std::make_unique(*this, std::move(lookup)); +LookupContextPtr +FileSystemHttpCache::makeLookupContext(LookupRequest&& lookup, + Http::StreamDecoderFilterCallbacks& callbacks) { + return std::make_unique(callbacks.dispatcher(), *this, std::move(lookup)); } // Helper class to reduce the lambda depth of updateHeaders. class HeaderUpdateContext : public Logger::Loggable { public: - HeaderUpdateContext(const FileSystemHttpCache& cache, const Key& key, - std::shared_ptr cleanup, + HeaderUpdateContext(Event::Dispatcher& dispatcher, const FileSystemHttpCache& cache, + const Key& key, std::shared_ptr cleanup, const Http::ResponseHeaderMap& response_headers, const ResponseMetadata& metadata, std::function on_complete) - : filepath_(absl::StrCat(cache.cachePath(), cache.generateFilename(key))), + : dispatcher_(dispatcher), + filepath_(absl::StrCat(cache.cachePath(), cache.generateFilename(key))), cache_path_(cache.cachePath()), cleanup_(cleanup), async_file_manager_(cache.asyncFileManager()), response_headers_(Http::createHeaderMap(response_headers)), response_metadata_(metadata), on_complete_(on_complete) {} void begin(std::shared_ptr ctx) { - async_file_manager_->openExistingFile(filepath_, - Common::AsyncFiles::AsyncFileManager::Mode::ReadOnly, - [ctx, this](absl::StatusOr open_result) { - if (!open_result.ok()) { - fail("failed to open", open_result.status()); - return; - } - read_handle_ = std::move(open_result.value()); - unlinkOriginal(ctx); - }); + async_file_manager_->openExistingFile( + dispatcher(), filepath_, Common::AsyncFiles::AsyncFileManager::Mode::ReadOnly, + [ctx = std::move(ctx), this](absl::StatusOr open_result) { + if (!open_result.ok()) { + fail("failed to open", open_result.status()); + return; + } + read_handle_ = std::move(open_result.value()); + unlinkOriginal(std::move(ctx)); + }); } ~HeaderUpdateContext() { @@ -150,44 +153,46 @@ class HeaderUpdateContext : public Logger::Loggable { // write_handle_ can only be set if read_handle_ is set, so this ordering is safe. if (read_handle_) { read_handle_ - ->close([write_handle = write_handle_](absl::Status) { - if (write_handle) { - write_handle->close([](absl::Status) {}).IgnoreError(); - } - }) + ->close(dispatcher(), + [write_handle = write_handle_](absl::Status) { + if (write_handle) { + write_handle->close(nullptr, [](absl::Status) {}).IgnoreError(); + } + }) .IgnoreError(); } } private: void unlinkOriginal(std::shared_ptr ctx) { - async_file_manager_->unlink(filepath_, [ctx, this](absl::Status unlink_result) { - if (!unlink_result.ok()) { - ENVOY_LOG(warn, "file_system_http_cache: {} for update cache file {}: {}", "unlink failed", - filepath_, unlink_result); - // But keep going, because unlink might have failed because the file was already - // deleted after we opened it. Worth a try to replace it! - } - readHeaderBlock(ctx); - }); + async_file_manager_->unlink( + dispatcher(), filepath_, [ctx = std::move(ctx), this](absl::Status unlink_result) { + if (!unlink_result.ok()) { + ENVOY_LOG(warn, "file_system_http_cache: {} for update cache file {}: {}", + "unlink failed", filepath_, unlink_result); + // But keep going, because unlink might have failed because the file was already + // deleted after we opened it. Worth a try to replace it! + } + readHeaderBlock(std::move(ctx)); + }); } void readHeaderBlock(std::shared_ptr ctx) { auto queued = read_handle_->read( - 0, CacheFileFixedBlock::size(), - [ctx, this](absl::StatusOr read_result) { + dispatcher(), 0, CacheFileFixedBlock::size(), + [ctx = std::move(ctx), this](absl::StatusOr read_result) { if (!read_result.ok() || read_result.value()->length() != CacheFileFixedBlock::size()) { fail("failed to read header block", read_result.status()); return; } header_block_.populateFromStringView(read_result.value()->toString()); - readHeaders(ctx); + readHeaders(std::move(ctx)); }); ASSERT(queued.ok()); } void readHeaders(std::shared_ptr ctx) { auto queued = read_handle_->read( - header_block_.offsetToHeaders(), header_block_.headerSize(), - [ctx, this](absl::StatusOr read_result) { + dispatcher(), header_block_.offsetToHeaders(), header_block_.headerSize(), + [ctx = std::move(ctx), this](absl::StatusOr read_result) { if (!read_result.ok() || read_result.value()->length() != header_block_.headerSize()) { fail("failed to read headers", read_result.status()); return; @@ -207,19 +212,20 @@ class HeaderUpdateContext : public Logger::Loggable { size_t new_header_size = headerProtoSize(header_proto_); header_size_difference_ = header_block_.headerSize() - new_header_size; header_block_.setHeadersSize(new_header_size); - startWriting(ctx); + startWriting(std::move(ctx)); }); ASSERT(queued.ok()); } void startWriting(std::shared_ptr ctx) { async_file_manager_->createAnonymousFile( - cache_path_, [ctx, this](absl::StatusOr create_result) { + dispatcher(), cache_path_, + [ctx = std::move(ctx), this](absl::StatusOr create_result) { if (!create_result.ok()) { fail("failed to open new cache file", create_result.status()); return; } write_handle_ = std::move(create_result.value()); - writeHeaderBlockAndHeaders(ctx); + writeHeaderBlockAndHeaders(std::move(ctx)); }); } void writeHeaderBlockAndHeaders(std::shared_ptr ctx) { @@ -227,13 +233,14 @@ class HeaderUpdateContext : public Logger::Loggable { header_block_.serializeToBuffer(buf); buf.add(bufferFromProto(header_proto_)); auto sz = buf.length(); - auto queued = - write_handle_->write(buf, 0, [ctx, sz, this](absl::StatusOr write_result) { + auto queued = write_handle_->write( + dispatcher(), buf, 0, + [ctx = std::move(ctx), sz, this](absl::StatusOr write_result) { if (!write_result.ok() || write_result.value() != sz) { fail("failed to write header block and headers", write_result.status()); return; } - copyBodyAndTrailers(ctx, header_block_.offsetToBody()); + copyBodyAndTrailers(std::move(ctx), header_block_.offsetToBody()); }); ASSERT(queued.ok()); } @@ -245,33 +252,34 @@ class HeaderUpdateContext : public Logger::Loggable { } sz = std::min(sz, FileSystemHttpCache::max_update_headers_copy_chunk_size_); auto queued = read_handle_->read( - offset + header_size_difference_, sz, - [ctx, offset, sz, this](absl::StatusOr read_result) { + dispatcher(), offset + header_size_difference_, sz, + [ctx = std::move(ctx), offset, sz, this](absl::StatusOr read_result) { if (!read_result.ok() || read_result.value()->length() != sz) { fail("failed to read body chunk", read_result.status()); return; } - auto queued = - write_handle_->write(*read_result.value(), offset, - [ctx, offset, sz, this](absl::StatusOr write_result) { - if (!write_result.ok() || write_result.value() != sz) { - fail("failed to write body chunk", write_result.status()); - return; - } - copyBodyAndTrailers(ctx, offset + sz); - }); + auto queued = write_handle_->write( + dispatcher(), *read_result.value(), offset, + [ctx = std::move(ctx), offset, sz, this](absl::StatusOr write_result) { + if (!write_result.ok() || write_result.value() != sz) { + fail("failed to write body chunk", write_result.status()); + return; + } + copyBodyAndTrailers(std::move(ctx), offset + sz); + }); ASSERT(queued.ok()); }); ASSERT(queued.ok()); } void linkNewFile(std::shared_ptr ctx) { - auto queued = write_handle_->createHardLink(filepath_, [ctx, this](absl::Status link_result) { - if (!link_result.ok()) { - fail("failed to link new cache file", link_result); - return; - } - on_complete_(true); - }); + auto queued = write_handle_->createHardLink( + dispatcher(), filepath_, [ctx = std::move(ctx), this](absl::Status link_result) { + if (!link_result.ok()) { + fail("failed to link new cache file", link_result); + return; + } + on_complete_(true); + }); ASSERT(queued.ok()); } void fail(absl::string_view msg, absl::Status status) { @@ -279,6 +287,8 @@ class HeaderUpdateContext : public Logger::Loggable { status); on_complete_(false); } + Event::Dispatcher* dispatcher() { return &dispatcher_; } + Event::Dispatcher& dispatcher_; std::string filepath_; std::string cache_path_; std::shared_ptr cleanup_; @@ -293,17 +303,19 @@ class HeaderUpdateContext : public Logger::Loggable { std::function on_complete_; }; -void FileSystemHttpCache::updateHeaders(const LookupContext& lookup_context, +void FileSystemHttpCache::updateHeaders(const LookupContext& base_lookup_context, const Http::ResponseHeaderMap& response_headers, const ResponseMetadata& metadata, std::function on_complete) { - const Key& key = dynamic_cast(lookup_context).key(); + const FileLookupContext& lookup_context = + dynamic_cast(base_lookup_context); + const Key& key = lookup_context.key(); auto cleanup = maybeStartWritingEntry(key); if (!cleanup) { return; } - auto ctx = std::make_shared(*this, key, cleanup, response_headers, metadata, - on_complete); + auto ctx = std::make_shared( + *lookup_context.dispatcher(), *this, key, cleanup, response_headers, metadata, on_complete); ctx->begin(ctx); } @@ -326,10 +338,10 @@ std::shared_ptr FileSystemHttpCache::maybeStartWritingEntry(const Key& } std::shared_ptr -FileSystemHttpCache::setCacheEntryToVary(const Key& key, +FileSystemHttpCache::setCacheEntryToVary(Event::Dispatcher& dispatcher, const Key& key, const Http::ResponseHeaderMap& response_headers, const Key& varied_key, std::shared_ptr cleanup) { - writeVaryNodeToDisk(key, response_headers, cleanup); + writeVaryNodeToDisk(dispatcher, key, response_headers, cleanup); return maybeStartWritingEntry(varied_key); } diff --git a/source/extensions/http/cache/file_system_http_cache/file_system_http_cache.h b/source/extensions/http/cache/file_system_http_cache/file_system_http_cache.h index 2c32d110ec..9e81bf0410 100644 --- a/source/extensions/http/cache/file_system_http_cache/file_system_http_cache.h +++ b/source/extensions/http/cache/file_system_http_cache/file_system_http_cache.h @@ -137,9 +137,9 @@ class FileSystemHttpCache : public HttpCache, * if varied_key was added. */ ABSL_MUST_USE_RESULT std::shared_ptr - setCacheEntryToVary(const Key& key, const Http::ResponseHeaderMap& response_headers, - const Key& varied_key, std::shared_ptr cleanup) - ABSL_LOCKS_EXCLUDED(cache_mu_); + setCacheEntryToVary(Event::Dispatcher& dispatcher, const Key& key, + const Http::ResponseHeaderMap& response_headers, const Key& varied_key, + std::shared_ptr cleanup) ABSL_LOCKS_EXCLUDED(cache_mu_); /** * Returns the extension name. @@ -187,6 +187,9 @@ class FileSystemHttpCache : public HttpCache, using PostEvictionCallback = std::function; + // Waits for all queued actions to be completed. + void drainAsyncFileActionsForTest() { async_file_manager_->waitForIdle(); }; + private: /** * Writes a vary node to disk for the given key. A vary node in the cache consists of @@ -196,7 +199,8 @@ class FileSystemHttpCache : public HttpCache, * be extracted. * @param cleanup the cleanup operation to be performed when the write completes. */ - void writeVaryNodeToDisk(const Key& key, const Http::ResponseHeaderMap& response_headers, + void writeVaryNodeToDisk(Event::Dispatcher& dispatcher, const Key& key, + const Http::ResponseHeaderMap& response_headers, std::shared_ptr cleanup); // A shared_ptr to keep the cache singleton alive as long as any of its caches are in use. diff --git a/source/extensions/http/cache/file_system_http_cache/insert_context.cc b/source/extensions/http/cache/file_system_http_cache/insert_context.cc index 53c066b9b0..98e0565773 100644 --- a/source/extensions/http/cache/file_system_http_cache/insert_context.cc +++ b/source/extensions/http/cache/file_system_http_cache/insert_context.cc @@ -31,7 +31,7 @@ FileInsertContext::FileInsertContext(std::shared_ptr cache, void FileInsertContext::insertHeaders(const Http::ResponseHeaderMap& response_headers, const ResponseMetadata& metadata, InsertCallback insert_complete, bool end_stream) { - absl::MutexLock lock(&mu_); + ASSERT(dispatcher()->isThreadSafe()); callback_in_flight_ = insert_complete; const VaryAllowList& vary_allow_list = lookup_context_->lookup().varyAllowList(); const Http::RequestHeaderMap& request_headers = lookup_context_->lookup().requestHeaders(); @@ -47,7 +47,8 @@ void FileInsertContext::insertHeaders(const Http::ResponseHeaderMap& response_he cancelInsert(); return; } - cleanup_ = cache_->setCacheEntryToVary(old_key, response_headers, key_, cleanup_); + cleanup_ = + cache_->setCacheEntryToVary(*dispatcher(), old_key, response_headers, key_, cleanup_); } else { cleanup_ = cache_->maybeStartWritingEntry(key_); } @@ -56,74 +57,98 @@ void FileInsertContext::insertHeaders(const Http::ResponseHeaderMap& response_he cancelInsert(); return; } - auto header_proto = makeCacheFileHeaderProto(key_, response_headers, metadata); - // Open the file. + cache_file_header_proto_ = makeCacheFileHeaderProto(key_, response_headers, metadata); + end_stream_after_headers_ = end_stream; + on_insert_complete_ = std::move(insert_complete); + createFile(); +} + +void FileInsertContext::createFile() { + ASSERT(dispatcher()->isThreadSafe()); + ASSERT(!cancel_action_in_flight_); + ASSERT(callback_in_flight_ != nullptr); cancel_action_in_flight_ = cache_->asyncFileManager()->createAnonymousFile( - cache_->cachePath(), [this, end_stream, header_proto, - insert_complete](absl::StatusOr open_result) { - absl::MutexLock lock(&mu_); + dispatcher(), cache_->cachePath(), [this](absl::StatusOr open_result) { cancel_action_in_flight_ = nullptr; if (!open_result.ok()) { cancelInsert("failed to create anonymous file"); return; } file_handle_ = std::move(open_result.value()); - Buffer::OwnedImpl unset_header; - header_block_.serializeToBuffer(unset_header); - // Write an empty header block. - auto queued = file_handle_->write( - unset_header, 0, [this, end_stream, header_proto](absl::StatusOr write_result) { - absl::MutexLock lock(&mu_); - cancel_action_in_flight_ = nullptr; - if (!write_result.ok() || write_result.value() != CacheFileFixedBlock::size()) { - cancelInsert(writeFailureMessage("empty header block", write_result, - CacheFileFixedBlock::size())); - return; - } - auto buf = bufferFromProto(header_proto); - auto sz = buf.length(); - auto queued = file_handle_->write( - buf, header_block_.offsetToHeaders(), - [this, end_stream, sz](absl::StatusOr write_result) { - absl::MutexLock lock(&mu_); - cancel_action_in_flight_ = nullptr; - if (!write_result.ok() || write_result.value() != sz) { - cancelInsert(writeFailureMessage("headers", write_result, sz)); - return; - } - header_block_.setHeadersSize(sz); - if (end_stream) { - commit(callback_in_flight_); - return; - } - auto cb = callback_in_flight_; - callback_in_flight_ = nullptr; - cb(true); - }); - ASSERT(queued.ok(), queued.status().ToString()); - cancel_action_in_flight_ = queued.value(); - }); - ASSERT(queued.ok(), queued.status().ToString()); - cancel_action_in_flight_ = queued.value(); + writeEmptyHeaderBlock(); }); } +void FileInsertContext::writeEmptyHeaderBlock() { + ASSERT(dispatcher()->isThreadSafe()); + ASSERT(!cancel_action_in_flight_); + ASSERT(callback_in_flight_ != nullptr); + Buffer::OwnedImpl unset_header; + header_block_.serializeToBuffer(unset_header); + // Write an empty header block. + auto queued = file_handle_->write( + dispatcher(), unset_header, 0, [this](absl::StatusOr write_result) { + cancel_action_in_flight_ = nullptr; + if (!write_result.ok() || write_result.value() != CacheFileFixedBlock::size()) { + cancelInsert( + writeFailureMessage("empty header block", write_result, CacheFileFixedBlock::size())); + return; + } + writeHeaderProto(); + }); + ASSERT(queued.ok(), queued.status().ToString()); + cancel_action_in_flight_ = std::move(queued.value()); +} + +void FileInsertContext::succeedCurrentAction() { + ASSERT(!cancel_action_in_flight_); + ASSERT(callback_in_flight_ != nullptr); + auto cb = std::move(callback_in_flight_); + callback_in_flight_ = nullptr; + cb(true); +} + +void FileInsertContext::writeHeaderProto() { + ASSERT(dispatcher()->isThreadSafe()); + ASSERT(!cancel_action_in_flight_); + ASSERT(callback_in_flight_ != nullptr); + auto buf = bufferFromProto(cache_file_header_proto_); + auto sz = buf.length(); + auto queued = + file_handle_->write(dispatcher(), buf, header_block_.offsetToHeaders(), + [this, sz](absl::StatusOr write_result) { + cancel_action_in_flight_ = nullptr; + if (!write_result.ok() || write_result.value() != sz) { + cancelInsert(writeFailureMessage("headers", write_result, sz)); + return; + } + header_block_.setHeadersSize(sz); + if (end_stream_after_headers_) { + commit(); + return; + } + succeedCurrentAction(); + }); + ASSERT(queued.ok(), queued.status().ToString()); + cancel_action_in_flight_ = std::move(queued.value()); +} + void FileInsertContext::insertBody(const Buffer::Instance& fragment, InsertCallback ready_for_next_fragment, bool end_stream) { - absl::MutexLock lock(&mu_); + ASSERT(dispatcher()->isThreadSafe()); + ASSERT(!cancel_action_in_flight_, "should be no actions in flight when receiving new data"); + ASSERT(!callback_in_flight_); if (!cleanup_) { // Already cancelled, do nothing, return failure. ready_for_next_fragment(false); return; } - ASSERT(!cancel_action_in_flight_, "should be no actions in flight when receiving new data"); callback_in_flight_ = ready_for_next_fragment; size_t sz = fragment.length(); Buffer::OwnedImpl consumable_fragment(fragment); auto queued = file_handle_->write( - consumable_fragment, header_block_.offsetToBody() + header_block_.bodySize(), + dispatcher(), consumable_fragment, header_block_.offsetToBody() + header_block_.bodySize(), [this, sz, end_stream](absl::StatusOr write_result) { - absl::MutexLock lock(&mu_); cancel_action_in_flight_ = nullptr; if (!write_result.ok() || write_result.value() != sz) { cancelInsert(writeFailureMessage("body chunk", write_result, sz)); @@ -131,116 +156,121 @@ void FileInsertContext::insertBody(const Buffer::Instance& fragment, } header_block_.setBodySize(header_block_.bodySize() + sz); if (end_stream) { - commit(callback_in_flight_); + commit(); } else { - auto cb = callback_in_flight_; - callback_in_flight_ = nullptr; - cb(true); + succeedCurrentAction(); } }); ASSERT(queued.ok(), queued.status().ToString()); - cancel_action_in_flight_ = queued.value(); + cancel_action_in_flight_ = std::move(queued.value()); } void FileInsertContext::insertTrailers(const Http::ResponseTrailerMap& trailers, InsertCallback insert_complete) { - absl::MutexLock lock(&mu_); + ASSERT(dispatcher()->isThreadSafe()); + ASSERT(!cancel_action_in_flight_, "should be no actions in flight when receiving new data"); + ASSERT(!callback_in_flight_); if (!cleanup_) { // Already cancelled, do nothing, return failure. insert_complete(false); return; } - ASSERT(!cancel_action_in_flight_, "should be no actions in flight when receiving new data"); callback_in_flight_ = insert_complete; CacheFileTrailer file_trailer = makeCacheFileTrailerProto(trailers); Buffer::OwnedImpl consumable_buffer = bufferFromProto(file_trailer); size_t sz = consumable_buffer.length(); auto queued = - file_handle_->write(consumable_buffer, header_block_.offsetToTrailers(), + file_handle_->write(dispatcher(), consumable_buffer, header_block_.offsetToTrailers(), [this, sz](absl::StatusOr write_result) { - absl::MutexLock lock(&mu_); cancel_action_in_flight_ = nullptr; if (!write_result.ok() || write_result.value() != sz) { cancelInsert(writeFailureMessage("trailer chunk", write_result, sz)); return; } header_block_.setTrailersSize(sz); - commit(callback_in_flight_); + commit(); }); ASSERT(queued.ok(), queued.status().ToString()); - cancel_action_in_flight_ = queued.value(); + cancel_action_in_flight_ = std::move(queued.value()); } -void FileInsertContext::onDestroy() { - absl::MutexLock lock(&mu_); - cancelInsert("InsertContext destroyed prematurely"); -} +void FileInsertContext::onDestroy() { cancelInsert("InsertContext destroyed prematurely"); } -void FileInsertContext::commit(InsertCallback callback) { - mu_.AssertHeld(); +void FileInsertContext::commit() { + ASSERT(dispatcher()->isThreadSafe()); + ASSERT(!cancel_action_in_flight_); + ASSERT(callback_in_flight_ != nullptr); // Write the file header block now that we know the sizes of the pieces. Buffer::OwnedImpl block_buffer; - callback_in_flight_ = callback; header_block_.serializeToBuffer(block_buffer); - auto queued = file_handle_->write(block_buffer, 0, [this](absl::StatusOr write_result) { - absl::MutexLock lock(&mu_); - cancel_action_in_flight_ = nullptr; - if (!write_result.ok() || write_result.value() != CacheFileFixedBlock::size()) { - cancelInsert(writeFailureMessage("header block", write_result, CacheFileFixedBlock::size())); - return; - } - // Unlink any existing cache entry with this filename. - cancel_action_in_flight_ = cache_->asyncFileManager()->stat( - absl::StrCat(cache_->cachePath(), cache_->generateFilename(key_)), - [this](absl::StatusOr stat_result) { - absl::MutexLock lock(&mu_); - cancel_action_in_flight_ = nullptr; - size_t file_size = 0; - if (stat_result.ok()) { - file_size = stat_result.value().st_size; - } - cancel_action_in_flight_ = cache_->asyncFileManager()->unlink( - absl::StrCat(cache_->cachePath(), cache_->generateFilename(key_)), - [this, file_size](absl::Status unlink_result) { - if (unlink_result.ok()) { - cache_->trackFileRemoved(file_size); - } - // We can ignore failure of unlink - the file may or may not have previously - // existed. - absl::MutexLock lock(&mu_); - cancel_action_in_flight_ = nullptr; - // Link the file to its filename. - auto queued = file_handle_->createHardLink( - absl::StrCat(cache_->cachePath(), cache_->generateFilename(key_)), - [this](absl::Status link_result) { - absl::MutexLock lock(&mu_); - cancel_action_in_flight_ = nullptr; - if (!link_result.ok()) { - cancelInsert(absl::StrCat("failed to link file (", link_result.ToString(), - "): ", cache_->cachePath(), - cache_->generateFilename(key_))); - return; - } - ENVOY_LOG(debug, "created cache file {}", cache_->generateFilename(key_)); - callback_in_flight_(true); - callback_in_flight_ = nullptr; - uint64_t file_size = - header_block_.offsetToTrailers() + header_block_.trailerSize(); - cache_->trackFileAdded(file_size); - // By clearing cleanup before destructor, we prevent logging an error. - cleanup_ = nullptr; - }); - ASSERT(queued.ok(), queued.status().ToString()); - cancel_action_in_flight_ = queued.value(); - }); - }); - }); + auto queued = file_handle_->write( + dispatcher(), block_buffer, 0, [this](absl::StatusOr write_result) { + cancel_action_in_flight_ = nullptr; + if (!write_result.ok() || write_result.value() != CacheFileFixedBlock::size()) { + cancelInsert( + writeFailureMessage("header block", write_result, CacheFileFixedBlock::size())); + return; + } + commitMeasureExisting(); + }); ASSERT(queued.ok(), queued.status().ToString()); - cancel_action_in_flight_ = queued.value(); + cancel_action_in_flight_ = std::move(queued.value()); +} + +std::string FileInsertContext::pathAndFilename() { + return absl::StrCat(cache_->cachePath(), cache_->generateFilename(key_)); +} + +void FileInsertContext::commitMeasureExisting() { + ASSERT(!cancel_action_in_flight_); + ASSERT(callback_in_flight_ != nullptr); + cancel_action_in_flight_ = cache_->asyncFileManager()->stat( + dispatcher(), pathAndFilename(), [this](absl::StatusOr stat_result) { + cancel_action_in_flight_ = nullptr; + if (stat_result.ok()) { + commitUnlinkExisting(stat_result.value().st_size); + } else { + commitUnlinkExisting(0); + } + }); +} + +void FileInsertContext::commitUnlinkExisting(size_t file_size) { + ASSERT(!cancel_action_in_flight_); + ASSERT(callback_in_flight_ != nullptr); + cancel_action_in_flight_ = cache_->asyncFileManager()->unlink( + dispatcher(), pathAndFilename(), [this, file_size](absl::Status unlink_result) { + cancel_action_in_flight_ = nullptr; + if (unlink_result.ok()) { + cache_->trackFileRemoved(file_size); + } + commitCreateHardLink(); + }); +} + +void FileInsertContext::commitCreateHardLink() { + ASSERT(!cancel_action_in_flight_); + ASSERT(callback_in_flight_ != nullptr); + auto queued = file_handle_->createHardLink( + dispatcher(), pathAndFilename(), [this](absl::Status link_result) { + cancel_action_in_flight_ = nullptr; + if (!link_result.ok()) { + cancelInsert(absl::StrCat("failed to link file (", link_result.ToString(), + "): ", pathAndFilename())); + return; + } + ENVOY_LOG(debug, "created cache file {}", cache_->generateFilename(key_)); + succeedCurrentAction(); + uint64_t file_size = header_block_.offsetToTrailers() + header_block_.trailerSize(); + cache_->trackFileAdded(file_size); + // By clearing cleanup before destructor, we prevent logging an error. + cleanup_ = nullptr; + }); + ASSERT(queued.ok(), queued.status().ToString()); + cancel_action_in_flight_ = std::move(queued.value()); } void FileInsertContext::cancelInsert(absl::string_view error) { - mu_.AssertHeld(); if (cancel_action_in_flight_) { cancel_action_in_flight_(); cancel_action_in_flight_ = nullptr; @@ -256,12 +286,14 @@ void FileInsertContext::cancelInsert(absl::string_view error) { } } if (file_handle_) { - auto close_status = file_handle_->close([](absl::Status) {}); + auto close_status = file_handle_->close(nullptr, [](absl::Status) {}); ASSERT(close_status.ok()); file_handle_ = nullptr; } } +Event::Dispatcher* FileInsertContext::dispatcher() const { return lookup_context_->dispatcher(); } + } // namespace FileSystemHttpCache } // namespace Cache } // namespace HttpFilters diff --git a/source/extensions/http/cache/file_system_http_cache/insert_context.h b/source/extensions/http/cache/file_system_http_cache/insert_context.h index 71e6f4d77b..1f8e666533 100644 --- a/source/extensions/http/cache/file_system_http_cache/insert_context.h +++ b/source/extensions/http/cache/file_system_http_cache/insert_context.h @@ -48,15 +48,55 @@ class FileInsertContext : public InsertContext, public Logger::Loggable lookup_context_; Key key_; std::shared_ptr cache_; - absl::Mutex mu_; // guards file operations - std::shared_ptr cleanup_ ABSL_GUARDED_BY(mu_); - AsyncFileHandle file_handle_ ABSL_GUARDED_BY(mu_); - std::function callback_in_flight_ ABSL_GUARDED_BY(mu_); - CancelFunction cancel_action_in_flight_ ABSL_GUARDED_BY(mu_); - CacheFileFixedBlock header_block_ ABSL_GUARDED_BY(mu_); + std::shared_ptr cleanup_; + AsyncFileHandle file_handle_; + absl::AnyInvocable callback_in_flight_; + CancelFunction cancel_action_in_flight_; + CacheFileFixedBlock header_block_; /** * If seen_end_stream_ is not true (i.e. InsertContext has not yet delivered the @@ -69,19 +109,7 @@ class FileInsertContext : public InsertContext, public Logger::LoggableopenExistingFile( - filepath(), Common::AsyncFiles::AsyncFileManager::Mode::ReadOnly, - [this, cb](absl::StatusOr open_result) { - absl::MutexLock lock(&mu_); + dispatcher(), filepath(), Common::AsyncFiles::AsyncFileManager::Mode::ReadOnly, + [this](absl::StatusOr open_result) { cancel_action_in_flight_ = nullptr; if (!open_result.ok()) { - cache_.stats().cache_miss_.inc(); - cb(LookupResult{}, /* end_stream (ignored) = */ false); - return; + return doCacheMiss(); } ASSERT(!file_handle_); file_handle_ = std::move(open_result.value()); - auto queued = file_handle_->read( - 0, CacheFileFixedBlock::size(), - [this, cb](absl::StatusOr read_result) { - absl::MutexLock lock(&mu_); - cancel_action_in_flight_ = nullptr; - if (!read_result.ok() || - read_result.value()->length() != CacheFileFixedBlock::size()) { - invalidateCacheEntry(); - cache_.stats().cache_miss_.inc(); - cb(LookupResult{}, /* end_stream (ignored) = */ false); - return; - } - header_block_.populateFromStringView(read_result.value()->toString()); - if (!header_block_.isValid()) { - invalidateCacheEntry(); - cache_.stats().cache_miss_.inc(); - cb(LookupResult{}, /* end_stream (ignored) = */ false); - return; - } - auto queued = file_handle_->read( - header_block_.offsetToHeaders(), header_block_.headerSize(), - [this, cb](absl::StatusOr read_result) { - absl::MutexLock lock(&mu_); - cancel_action_in_flight_ = nullptr; - if (!read_result.ok() || - read_result.value()->length() != header_block_.headerSize()) { - invalidateCacheEntry(); - cache_.stats().cache_miss_.inc(); - cb(LookupResult{}, /* end_stream (ignored) = */ false); - return; - } - auto header_proto = makeCacheFileHeaderProto(*read_result.value()); - if (header_proto.headers_size() == 1 && - header_proto.headers().at(0).key() == "vary") { - auto maybe_vary_key = cache_.makeVaryKey( - key_, lookup().varyAllowList(), - absl::StrSplit(header_proto.headers().at(0).value(), ','), - lookup().requestHeaders()); - if (!maybe_vary_key.has_value()) { - cache_.stats().cache_miss_.inc(); - cb(LookupResult{}, /* end_stream (ignored) = */ false); - return; - } - key_ = maybe_vary_key.value(); - auto fh = std::move(file_handle_); - file_handle_ = nullptr; - // It should be possible to cancel close, to make this safe. - // (it should still close the file, but cancel the callback.) - auto queued = fh->close([this, cb](absl::Status) { - absl::MutexLock lock(&mu_); - // Restart getHeaders with the new key. - return getHeadersWithLock(cb); - }); - ASSERT(queued.ok(), queued.ToString()); - return; - } - cache_.stats().cache_hit_.inc(); - cb(lookup().makeLookupResult(headersFromHeaderProto(header_proto), - metadataFromHeaderProto(header_proto), - header_block_.bodySize()), - /* end_stream = */ header_block_.trailerSize() == 0 && - header_block_.bodySize() == 0); - }); - ASSERT(queued.ok(), queued.status().ToString()); - cancel_action_in_flight_ = queued.value(); - }); - ASSERT(queued.ok(), queued.status().ToString()); - cancel_action_in_flight_ = queued.value(); + getHeaderBlockFromFile(); + }); +} + +void FileLookupContext::doCacheMiss() { + cache_.stats().cache_miss_.inc(); + std::move(lookup_headers_callback_)(LookupResult{}, /* end_stream (ignored) = */ false); + lookup_headers_callback_ = nullptr; +} + +void FileLookupContext::doCacheEntryInvalid() { + invalidateCacheEntry(); + doCacheMiss(); +} + +void FileLookupContext::getHeaderBlockFromFile() { + ASSERT(dispatcher()->isThreadSafe()); + auto queued = file_handle_->read( + dispatcher(), 0, CacheFileFixedBlock::size(), + [this](absl::StatusOr read_result) { + ASSERT(dispatcher()->isThreadSafe()); + cancel_action_in_flight_ = nullptr; + if (!read_result.ok() || read_result.value()->length() != CacheFileFixedBlock::size()) { + return doCacheEntryInvalid(); + } + header_block_.populateFromStringView(read_result.value()->toString()); + if (!header_block_.isValid()) { + return doCacheEntryInvalid(); + } + getHeadersFromFile(); + }); + ASSERT(queued.ok(), queued.status().ToString()); + cancel_action_in_flight_ = std::move(queued.value()); +} + +void FileLookupContext::getHeadersFromFile() { + ASSERT(dispatcher()->isThreadSafe()); + auto queued = file_handle_->read( + dispatcher(), header_block_.offsetToHeaders(), header_block_.headerSize(), + [this](absl::StatusOr read_result) { + ASSERT(dispatcher()->isThreadSafe()); + cancel_action_in_flight_ = nullptr; + if (!read_result.ok() || read_result.value()->length() != header_block_.headerSize()) { + return doCacheEntryInvalid(); + } + auto header_proto = makeCacheFileHeaderProto(*read_result.value()); + if (header_proto.headers_size() == 1 && header_proto.headers().at(0).key() == "vary") { + auto maybe_vary_key = cache_.makeVaryKey( + key_, lookup().varyAllowList(), + absl::StrSplit(header_proto.headers().at(0).value(), ','), lookup().requestHeaders()); + if (!maybe_vary_key.has_value()) { + return doCacheMiss(); + } + key_ = maybe_vary_key.value(); + return closeFileAndGetHeadersAgainWithNewVaryKey(); + } + cache_.stats().cache_hit_.inc(); + std::move(lookup_headers_callback_)( + lookup().makeLookupResult(headersFromHeaderProto(header_proto), + metadataFromHeaderProto(header_proto), + header_block_.bodySize()), + /* end_stream = */ header_block_.trailerSize() == 0 && header_block_.bodySize() == 0); }); + ASSERT(queued.ok(), queued.status().ToString()); + cancel_action_in_flight_ = std::move(queued.value()); +} + +void FileLookupContext::closeFileAndGetHeadersAgainWithNewVaryKey() { + ASSERT(dispatcher()->isThreadSafe()); + auto queued = file_handle_->close(dispatcher(), [this](absl::Status) { + ASSERT(dispatcher()->isThreadSafe()); + file_handle_ = nullptr; + // Restart with the new key. + return tryOpenCacheFile(); + }); + ASSERT(queued.ok(), queued.status().ToString()); + cancel_action_in_flight_ = std::move(queued.value()); } void FileLookupContext::invalidateCacheEntry() { + ASSERT(dispatcher()->isThreadSafe()); + // We don't capture the cancel action here because we want these operations to continue even + // if the filter was destroyed in the meantime. For the same reason, we must not capture 'this'. cache_.asyncFileManager()->stat( - filepath(), [file = filepath(), - cache = cache_.shared_from_this()](absl::StatusOr stat_result) { + dispatcher(), filepath(), + [file = filepath(), cache = cache_.shared_from_this(), + dispatcher = dispatcher()](absl::StatusOr stat_result) { + ASSERT(dispatcher->isThreadSafe()); size_t file_size = 0; if (stat_result.ok()) { file_size = stat_result.value().st_size; } - cache->asyncFileManager()->unlink(file, [cache, file_size](absl::Status unlink_result) { - if (unlink_result.ok()) { - cache->trackFileRemoved(file_size); - } - }); + cache->asyncFileManager()->unlink(dispatcher, file, + [cache, file_size](absl::Status unlink_result) { + if (unlink_result.ok()) { + cache->trackFileRemoved(file_size); + } + }); }); } void FileLookupContext::getBody(const AdjustedByteRange& range, LookupBodyCallback&& cb) { - absl::MutexLock lock(&mu_); + ASSERT(dispatcher()->isThreadSafe()); + ASSERT(cb); ASSERT(!cancel_action_in_flight_); + ASSERT(file_handle_); auto queued = file_handle_->read( - header_block_.offsetToBody() + range.begin(), range.length(), - [this, cb, range](absl::StatusOr read_result) { - absl::MutexLock lock(&mu_); + dispatcher(), header_block_.offsetToBody() + range.begin(), range.length(), + [this, cb = std::move(cb), range](absl::StatusOr read_result) { + ASSERT(dispatcher()->isThreadSafe()); cancel_action_in_flight_ = nullptr; if (!read_result.ok() || read_result.value()->length() != range.length()) { invalidateCacheEntry(); // Calling callback with nullptr fails the request. - cb(nullptr, /* end_stream (ignored) = */ false); + std::move(cb)(nullptr, /* end_stream (ignored) = */ false); return; } - cb(std::move(read_result.value()), - /* end_stream = */ range.end() == header_block_.bodySize() && - header_block_.trailerSize() == 0); + std::move(cb)(std::move(read_result.value()), + /* end_stream = */ range.end() == header_block_.bodySize() && + header_block_.trailerSize() == 0); }); ASSERT(queued.ok(), queued.status().ToString()); - cancel_action_in_flight_ = queued.value(); + cancel_action_in_flight_ = std::move(queued.value()); } void FileLookupContext::getTrailers(LookupTrailersCallback&& cb) { + ASSERT(dispatcher()->isThreadSafe()); ASSERT(cb); - absl::MutexLock lock(&mu_); ASSERT(!cancel_action_in_flight_); - auto queued = file_handle_->read(header_block_.offsetToTrailers(), header_block_.trailerSize(), - [this, cb](absl::StatusOr read_result) { - absl::MutexLock lock(&mu_); - cancel_action_in_flight_ = nullptr; - if (!read_result.ok() || read_result.value()->length() != - header_block_.trailerSize()) { - invalidateCacheEntry(); - // There is no failure response for getTrailers, so we just - // say there were no trailers in the event of this failure. - cb(Http::ResponseTrailerMapImpl::create()); - return; - } - CacheFileTrailer trailer; - trailer.ParseFromString(read_result.value()->toString()); - cb(trailersFromTrailerProto(trailer)); - }); + ASSERT(file_handle_); + auto queued = file_handle_->read( + dispatcher(), header_block_.offsetToTrailers(), header_block_.trailerSize(), + [this, cb = std::move(cb)](absl::StatusOr read_result) { + ASSERT(dispatcher()->isThreadSafe()); + cancel_action_in_flight_ = nullptr; + if (!read_result.ok() || read_result.value()->length() != header_block_.trailerSize()) { + invalidateCacheEntry(); + // There is no failure response for getTrailers, so we just + // say there were no trailers in the event of this failure. + std::move(cb)(Http::ResponseTrailerMapImpl::create()); + return; + } + CacheFileTrailer trailer; + trailer.ParseFromString(read_result.value()->toString()); + std::move(cb)(trailersFromTrailerProto(trailer)); + }); ASSERT(queued.ok(), queued.status().ToString()); - cancel_action_in_flight_ = queued.value(); + cancel_action_in_flight_ = std::move(queued.value()); } void FileLookupContext::onDestroy() { - CancelFunction cancel; - { - absl::MutexLock lock(&mu_); - cancel = std::move(cancel_action_in_flight_); + if (cancel_action_in_flight_) { + std::move(cancel_action_in_flight_)(); cancel_action_in_flight_ = nullptr; } - while (cancel) { - // We mustn't hold the lock while calling cancel, as it can potentially wait for - // a callback to complete, and the callback might take the lock. - cancel(); - { - // It's possible that while calling cancel, another action was started - if - // that happened, we must cancel that one too! - absl::MutexLock lock(&mu_); - cancel = std::move(cancel_action_in_flight_); - cancel_action_in_flight_ = nullptr; - } - } - { - absl::MutexLock lock(&mu_); - if (file_handle_) { - auto status = file_handle_->close([](absl::Status) {}); - ASSERT(status.ok(), status.ToString()); - file_handle_ = nullptr; - } + if (file_handle_) { + auto status = file_handle_->close(nullptr, [](absl::Status) {}); + ASSERT(status.ok(), status.status().ToString()); + file_handle_ = nullptr; } } diff --git a/source/extensions/http/cache/file_system_http_cache/lookup_context.h b/source/extensions/http/cache/file_system_http_cache/lookup_context.h index db4668798f..f2454fba5b 100644 --- a/source/extensions/http/cache/file_system_http_cache/lookup_context.h +++ b/source/extensions/http/cache/file_system_http_cache/lookup_context.h @@ -19,8 +19,9 @@ using Envoy::Extensions::Common::AsyncFiles::CancelFunction; class FileLookupContext : public LookupContext { public: - FileLookupContext(FileSystemHttpCache& cache, LookupRequest&& lookup) - : cache_(cache), key_(lookup.key()), lookup_(std::move(lookup)) {} + FileLookupContext(Event::Dispatcher& dispatcher, FileSystemHttpCache& cache, + LookupRequest&& lookup) + : dispatcher_(dispatcher), cache_(cache), key_(lookup.key()), lookup_(std::move(lookup)) {} // From LookupContext void getHeaders(LookupHeadersCallback&& cb) final; @@ -34,28 +35,34 @@ class FileLookupContext : public LookupContext { const LookupRequest& lookup() const { return lookup_; } const Key& key() const { return key_; } bool workInProgress() const; + Event::Dispatcher* dispatcher() const { return &dispatcher_; } private: - void getHeadersWithLock(LookupHeadersCallback cb) ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_); + void tryOpenCacheFile(); + void doCacheMiss(); + void doCacheEntryInvalid(); + void getHeaderBlockFromFile(); + void getHeadersFromFile(); + void closeFileAndGetHeadersAgainWithNewVaryKey(); // In the event that the cache failed to retrieve, remove the cache entry from the // cache so we don't keep repeating the same failure. - void invalidateCacheEntry() ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_); + void invalidateCacheEntry(); - std::string filepath() ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_); + std::string filepath(); + + Event::Dispatcher& dispatcher_; // We can safely use a reference here, because the shared_ptr to a cache is guaranteed to outlive // all filters that use it. FileSystemHttpCache& cache_; - // File actions may be initiated in the file thread or the filter thread, and cancelled or - // completed from either, therefore must be guarded by a mutex. - absl::Mutex mu_; - AsyncFileHandle file_handle_ ABSL_GUARDED_BY(mu_); - CancelFunction cancel_action_in_flight_ ABSL_GUARDED_BY(mu_); - CacheFileFixedBlock header_block_ ABSL_GUARDED_BY(mu_); - Key key_ ABSL_GUARDED_BY(mu_); + AsyncFileHandle file_handle_; + CancelFunction cancel_action_in_flight_; + CacheFileFixedBlock header_block_; + Key key_; + LookupHeadersCallback lookup_headers_callback_; const LookupRequest lookup_; }; diff --git a/test/extensions/common/async_files/async_file_handle_thread_pool_test.cc b/test/extensions/common/async_files/async_file_handle_thread_pool_test.cc index b4e63ed44d..668ae5b98d 100644 --- a/test/extensions/common/async_files/async_file_handle_thread_pool_test.cc +++ b/test/extensions/common/async_files/async_file_handle_thread_pool_test.cc @@ -34,38 +34,48 @@ using ::testing::StrictMock; class AsyncFileHandleHelpers { public: + void resolveFileActions() { + manager_->waitForIdle(); + dispatcher_->run(Event::Dispatcher::RunType::Block); + } void close(AsyncFileHandle& handle) { - std::promise close_result; - EXPECT_OK(handle->close([&](absl::Status status) { close_result.set_value(status); })); - EXPECT_OK(close_result.get_future().get()); + absl::Status close_result; + EXPECT_OK( + handle->close(dispatcher_.get(), [&](absl::Status status) { close_result = status; })); + resolveFileActions(); + EXPECT_OK(close_result); } AsyncFileHandle createAnonymousFile() { - std::promise create_result; - manager_->createAnonymousFile(tmpdir_, [&](absl::StatusOr result) { - create_result.set_value(result.value()); - }); - return create_result.get_future().get(); + AsyncFileHandle create_result; + manager_->createAnonymousFile( + dispatcher_.get(), tmpdir_, + [&](absl::StatusOr result) { create_result = result.value(); }); + resolveFileActions(); + return create_result; } AsyncFileHandle openExistingFile(absl::string_view filename, AsyncFileManager::Mode mode) { - std::promise open_result; - manager_->openExistingFile(filename, mode, [&](absl::StatusOr result) { - open_result.set_value(result.value()); - }); - return open_result.get_future().get(); + AsyncFileHandle open_result; + manager_->openExistingFile( + dispatcher_.get(), filename, mode, + [&](absl::StatusOr result) { open_result = result.value(); }); + resolveFileActions(); + return open_result; } const char* test_tmpdir = std::getenv("TEST_TMPDIR"); std::string tmpdir_ = test_tmpdir ? test_tmpdir : "/tmp"; - std::unique_ptr singleton_manager_; - std::shared_ptr factory_; + std::unique_ptr singleton_manager_ = + std::make_unique(); + std::shared_ptr factory_ = + AsyncFileManagerFactory::singleton(singleton_manager_.get()); std::shared_ptr manager_; + Api::ApiPtr api_ = Api::createApiForTest(); + Event::DispatcherPtr dispatcher_ = api_->allocateDispatcher("test_thread"); }; class AsyncFileHandleTest : public testing::Test, public AsyncFileHandleHelpers { public: void SetUp() override { - singleton_manager_ = std::make_unique(); - factory_ = AsyncFileManagerFactory::singleton(singleton_manager_.get()); envoy::extensions::common::async_files::v3::AsyncFileManagerConfig config; config.mutable_thread_pool()->set_thread_count(1); manager_ = factory_->getAsyncFileManager(config); @@ -77,8 +87,6 @@ class AsyncFileHandleWithMockPosixTest : public testing::Test, public AsyncFileH void SetUp() override { EXPECT_CALL(mock_posix_file_operations_, supportsAllPosixFileOperations()) .WillRepeatedly(Return(true)); - singleton_manager_ = std::make_unique(); - factory_ = AsyncFileManagerFactory::singleton(singleton_manager_.get()); envoy::extensions::common::async_files::v3::AsyncFileManagerConfig config; config.mutable_thread_pool()->set_thread_count(1); manager_ = factory_->getAsyncFileManager(config, &mock_posix_file_operations_); @@ -103,49 +111,41 @@ TEST_F(AsyncFileHandleTest, WriteReadClose) { absl::StatusOr write_status, second_write_status; absl::StatusOr read_status, second_read_status; Buffer::OwnedImpl hello("hello"); - std::promise close_status; - EXPECT_OK(handle->write(hello, 0, [&](absl::StatusOr status) { + ASSERT_OK(handle->write(dispatcher_.get(), hello, 0, [&](absl::StatusOr status) { write_status = std::move(status); - // Make sure writing at an offset works - Buffer::OwnedImpl two_chars("p!"); - EXPECT_OK(handle->write(two_chars, 3, [&](absl::StatusOr status) { - second_write_status = std::move(status); - EXPECT_OK(handle->read(0, 5, [&](absl::StatusOr status) { - read_status = std::move(status); - // Verify reading at an offset. - EXPECT_OK(handle->read(2, 3, [&](absl::StatusOr status) { - second_read_status = std::move(status); - EXPECT_OK(handle->close( - [&](absl::Status status) { close_status.set_value(std::move(status)); })); - })); - })); - })); })); - ASSERT_OK(close_status.get_future().get()); - // The first write was 5 characters. + resolveFileActions(); EXPECT_THAT(write_status, IsOkAndHolds(5U)); - - // The second write was 2 characters. + Buffer::OwnedImpl two_chars("p!"); + ASSERT_OK(handle->write(dispatcher_.get(), two_chars, 3, [&](absl::StatusOr status) { + second_write_status = std::move(status); + })); + resolveFileActions(); EXPECT_THAT(second_write_status, IsOkAndHolds(2U)); - - // This should be "hello" from the first write, with the last two characters replaced with "p!" - // from the second write. - EXPECT_OK(read_status); + ASSERT_OK(handle->read(dispatcher_.get(), 0, 5, [&](absl::StatusOr status) { + read_status = std::move(status); + })); + resolveFileActions(); + ASSERT_OK(read_status); EXPECT_THAT(*read_status.value(), BufferStringEqual("help!")); - - // Second read should have three characters in it. - EXPECT_OK(second_read_status); + ASSERT_OK(handle->read(dispatcher_.get(), 2, 3, [&](absl::StatusOr status) { + second_read_status = std::move(status); + })); + resolveFileActions(); + ASSERT_OK(second_read_status); EXPECT_THAT(*second_read_status.value(), BufferStringEqual("lp!")); + close(handle); } TEST_F(AsyncFileHandleTest, LinkCreatesNamedFile) { auto handle = createAnonymousFile(); - std::promise> write_status_promise; + absl::StatusOr write_status; // Write "hello" to the anonymous file. Buffer::OwnedImpl data("hello"); - EXPECT_OK(handle->write( - data, 0, [&](absl::StatusOr status) { write_status_promise.set_value(status); })); - absl::StatusOr write_status = write_status_promise.get_future().get(); + EXPECT_OK(handle->write(dispatcher_.get(), data, 0, [&](absl::StatusOr status) { + write_status = std::move(status); + })); + resolveFileActions(); ASSERT_THAT(write_status, IsOkAndHolds(5U)); char filename[1024]; snprintf(filename, sizeof(filename), "%s/async_link_test.XXXXXX", tmpdir_.c_str()); @@ -160,12 +160,13 @@ TEST_F(AsyncFileHandleTest, LinkCreatesNamedFile) { posix.unlink(filename); // Link the anonymous file into our tmp file name. - std::promise link_status; + absl::Status link_status = absl::InternalError("not set"); std::cout << "Linking as " << filename << std::endl; - EXPECT_OK(handle->createHardLink(std::string(filename), - [&](absl::Status status) { link_status.set_value(status); })); - ASSERT_OK(link_status.get_future().get()); + EXPECT_OK(handle->createHardLink(dispatcher_.get(), std::string(filename), + [&](absl::Status status) { link_status = status; })); + resolveFileActions(); + ASSERT_OK(link_status); // Read the contents of the linked file back, raw. char fileContents[6]; fileContents[5] = '\0'; @@ -183,11 +184,10 @@ TEST_F(AsyncFileHandleTest, LinkCreatesNamedFile) { TEST_F(AsyncFileHandleTest, LinkReturnsErrorIfLinkFails) { auto handle = createAnonymousFile(); - std::promise link_status_promise; - EXPECT_OK(handle->createHardLink("/some/path/that/does/not/exist", [&](absl::Status status) { - link_status_promise.set_value(status); - })); - absl::Status link_status = link_status_promise.get_future().get(); + absl::Status link_status = absl::InternalError("not set"); + EXPECT_OK(handle->createHardLink(dispatcher_.get(), "/some/path/that/does/not/exist", + [&](absl::Status status) { link_status = std::move(status); })); + resolveFileActions(); ASSERT_EQ(absl::StatusCode::kNotFound, link_status.code()) << link_status; close(handle); } @@ -219,11 +219,11 @@ TEST_F(AsyncFileHandleTest, OpenExistingWriteOnlyFailsOnRead) { TestTmpFile tmpfile(tmpdir_); auto handle = openExistingFile(tmpfile.name(), AsyncFileManager::Mode::WriteOnly); - std::promise> read_status_promise; - EXPECT_OK(handle->read(0, 5, [&](absl::StatusOr status) { - read_status_promise.set_value(std::move(status)); + absl::StatusOr read_status; + EXPECT_OK(handle->read(dispatcher_.get(), 0, 5, [&](absl::StatusOr status) { + read_status = std::move(status); })); - absl::StatusOr read_status = read_status_promise.get_future().get(); + resolveFileActions(); ASSERT_EQ(absl::StatusCode::kFailedPrecondition, read_status.status().code()) << read_status.status(); close(handle); @@ -234,11 +234,14 @@ TEST_F(AsyncFileHandleTest, OpenExistingWriteOnlyCanWrite) { TestTmpFile tmpfile(tmpdir_); auto handle = openExistingFile(tmpfile.name(), AsyncFileManager::Mode::WriteOnly); - std::promise> write_status; + absl::StatusOr write_status; Buffer::OwnedImpl buf("nine char"); - EXPECT_OK(handle->write( - buf, 0, [&](absl::StatusOr status) { write_status.set_value(std::move(status)); })); - ASSERT_EQ(9, write_status.get_future().get().value()); + EXPECT_OK(handle->write(dispatcher_.get(), buf, 0, [&](absl::StatusOr status) { + write_status = std::move(status); + })); + resolveFileActions(); + ASSERT_OK(write_status); + EXPECT_EQ(9, write_status.value()); close(handle); } @@ -247,12 +250,12 @@ TEST_F(AsyncFileHandleTest, OpenExistingReadOnlyFailsOnWrite) { TestTmpFile tmpfile(tmpdir_); auto handle = openExistingFile(tmpfile.name(), AsyncFileManager::Mode::ReadOnly); - std::promise> write_status_promise; + absl::StatusOr write_status; Buffer::OwnedImpl buf("hello"); - EXPECT_OK(handle->write(buf, 0, [&](absl::StatusOr status) { - write_status_promise.set_value(std::move(status)); + EXPECT_OK(handle->write(dispatcher_.get(), buf, 0, [&](absl::StatusOr status) { + write_status = std::move(status); })); - auto write_status = write_status_promise.get_future().get(); + resolveFileActions(); ASSERT_EQ(absl::StatusCode::kFailedPrecondition, write_status.status().code()) << write_status.status(); close(handle); @@ -263,11 +266,13 @@ TEST_F(AsyncFileHandleTest, OpenExistingReadOnlyCanRead) { TestTmpFile tmpfile(tmpdir_); auto handle = openExistingFile(tmpfile.name(), AsyncFileManager::Mode::ReadOnly); - std::promise> read_status; - EXPECT_OK(handle->read(0, 5, [&](absl::StatusOr status) { - read_status.set_value(std::move(status)); + absl::StatusOr read_status; + EXPECT_OK(handle->read(dispatcher_.get(), 0, 5, [&](absl::StatusOr status) { + read_status = std::move(status); })); - ASSERT_EQ("hello", read_status.get_future().get().value()->toString()); + resolveFileActions(); + ASSERT_OK(read_status); + ASSERT_EQ("hello", read_status.value()->toString()); close(handle); } @@ -276,38 +281,40 @@ TEST_F(AsyncFileHandleTest, OpenExistingReadWriteCanReadAndWrite) { TestTmpFile tmpfile(tmpdir_); auto handle = openExistingFile(tmpfile.name(), AsyncFileManager::Mode::ReadWrite); - std::promise> write_status_promise; + absl::StatusOr write_status; Buffer::OwnedImpl buf("p me!"); - EXPECT_OK(handle->write(buf, 3, [&](absl::StatusOr status) { - write_status_promise.set_value(std::move(status)); + EXPECT_OK(handle->write(dispatcher_.get(), buf, 3, [&](absl::StatusOr status) { + write_status = std::move(status); })); - auto write_status = write_status_promise.get_future().get(); + resolveFileActions(); ASSERT_THAT(write_status, IsOkAndHolds(5U)); - std::promise> read_status_promise; - EXPECT_OK(handle->read(0, 8, [&](absl::StatusOr status) { - read_status_promise.set_value(std::move(status)); + absl::StatusOr read_status; + EXPECT_OK(handle->read(dispatcher_.get(), 0, 8, [&](absl::StatusOr status) { + read_status = std::move(status); })); - auto read_status = read_status_promise.get_future().get(); - EXPECT_OK(read_status); + resolveFileActions(); + ASSERT_OK(read_status); EXPECT_THAT(*read_status.value(), BufferStringEqual("help me!")); close(handle); } TEST_F(AsyncFileHandleTest, DuplicateCreatesIndependentHandle) { auto handle = createAnonymousFile(); - std::promise> duplicate_status_promise; - EXPECT_OK(handle->duplicate( - [&](absl::StatusOr status) { duplicate_status_promise.set_value(status); })); - auto duplicate_status = duplicate_status_promise.get_future().get(); + absl::StatusOr duplicate_status; + EXPECT_OK(handle->duplicate(dispatcher_.get(), [&](absl::StatusOr status) { + duplicate_status = std::move(status); + })); + resolveFileActions(); ASSERT_OK(duplicate_status); AsyncFileHandle dup_file = std::move(duplicate_status.value()); // Close the original file. close(handle); - std::promise> write_status_promise; + absl::StatusOr write_status; Buffer::OwnedImpl buf("hello"); - EXPECT_OK(dup_file->write( - buf, 0, [&](absl::StatusOr result) { write_status_promise.set_value(result); })); - auto write_status = write_status_promise.get_future().get(); + EXPECT_OK(dup_file->write(dispatcher_.get(), buf, 0, [&](absl::StatusOr result) { + write_status = std::move(result); + })); + resolveFileActions(); // writing to the duplicate file should still work. EXPECT_THAT(write_status, IsOkAndHolds(5U)); close(dup_file); @@ -320,11 +327,11 @@ TEST_F(AsyncFileHandleWithMockPosixTest, PartialReadReturnsPartialResult) { memcpy(buf, "hel", 3); return Api::SysCallSizeResult{3, 0}; }); - std::promise> read_status_promise; - EXPECT_OK(handle->read(0, 5, [&](absl::StatusOr status) { - read_status_promise.set_value(std::move(status.value())); + absl::StatusOr read_status; + EXPECT_OK(handle->read(dispatcher_.get(), 0, 5, [&](absl::StatusOr status) { + read_status = std::move(status.value()); })); - auto read_status = read_status_promise.get_future().get(); + resolveFileActions(); EXPECT_OK(read_status); EXPECT_THAT(*read_status.value(), BufferStringEqual("hel")); close(handle); @@ -344,11 +351,11 @@ TEST_F(AsyncFileHandleWithMockPosixTest, PartialWriteRetries) { .WillOnce(Return(Api::SysCallSizeResult{3, 0})); EXPECT_CALL(mock_posix_file_operations_, pwrite(_, IsMemoryMatching("lo"), 2, 3)) .WillOnce(Return(Api::SysCallSizeResult{2, 0})); - std::promise> write_status_promise; - EXPECT_OK(handle->write(write_value, 0, [&](absl::StatusOr status) { - write_status_promise.set_value(std::move(status.value())); + absl::StatusOr write_status; + EXPECT_OK(handle->write(dispatcher_.get(), write_value, 0, [&](absl::StatusOr status) { + write_status = std::move(status.value()); })); - auto write_status = write_status_promise.get_future().get(); + resolveFileActions(); EXPECT_THAT(write_status, IsOkAndHolds(5U)); close(handle); } @@ -361,9 +368,8 @@ TEST_F(AsyncFileHandleWithMockPosixTest, CancellingDuplicateInProgressClosesTheF finishing_dup.get_future().wait(); return Api::SysCallSocketResult{4242, 0}; }); - auto cancel_dup = handle->duplicate([](absl::StatusOr) { - // Callback is not called if we cancel (already validated in manager tests) - // so this is unimportant. + auto cancel_dup = handle->duplicate(dispatcher_.get(), [](absl::StatusOr) { + FAIL() << "cancelled callback should not be called"; }); entering_dup.get_future().wait(); cancel_dup.value()(); @@ -386,8 +392,8 @@ TEST_F(AsyncFileHandleWithMockPosixTest, CancellingCreateHardLinkInProgressRemov finishing_hardlink.get_future().wait(); return Api::SysCallIntResult{0, 0}; }); - auto cancel_hardlink = handle->createHardLink(filename, [](absl::Status) { - // Callback is not called if we cancel, so this is unimportant. + auto cancel_hardlink = handle->createHardLink(dispatcher_.get(), filename, [](absl::Status) { + FAIL() << "cancelled callback should not be called"; }); entering_hardlink.get_future().wait(); cancel_hardlink.value()(); @@ -410,8 +416,8 @@ TEST_F(AsyncFileHandleWithMockPosixTest, CancellingFailedCreateHardLinkInProgres finishing_hardlink.get_future().wait(); return Api::SysCallIntResult{-1, EBADF}; }); - auto cancel_hardlink = handle->createHardLink(filename, [](absl::Status) { - // Callback is not called if we cancel, so this is unimportant. + auto cancel_hardlink = handle->createHardLink(dispatcher_.get(), filename, [](absl::Status) { + FAIL() << "cancelled callback should not be called"; }); entering_hardlink.get_future().wait(); cancel_hardlink.value()(); @@ -429,11 +435,11 @@ TEST_F(AsyncFileHandleWithMockPosixTest, StatSuccessReturnsPopulatedStatStruct) *buffer = expected_stat; return Api::SysCallIntResult{0, 0}; }); - std::promise> fstat_status_promise; - EXPECT_OK(handle->stat([&](absl::StatusOr status) { - fstat_status_promise.set_value(std::move(status)); + absl::StatusOr fstat_status; + EXPECT_OK(handle->stat(dispatcher_.get(), [&](absl::StatusOr status) { + fstat_status = std::move(status); })); - auto fstat_status = fstat_status_promise.get_future().get(); + resolveFileActions(); EXPECT_THAT(fstat_status, IsOkAndHolds(testing::Field(&stat::st_size, expected_stat.st_size))); close(handle); } @@ -442,11 +448,11 @@ TEST_F(AsyncFileHandleWithMockPosixTest, StatFailureReportsError) { auto handle = createAnonymousFile(); EXPECT_CALL(mock_posix_file_operations_, fstat(_, _)) .WillOnce(Return(Api::SysCallIntResult{-1, EBADF})); - std::promise> fstat_status_promise; - EXPECT_OK(handle->stat([&](absl::StatusOr status) { - fstat_status_promise.set_value(std::move(status)); + absl::StatusOr fstat_status; + EXPECT_OK(handle->stat(dispatcher_.get(), [&](absl::StatusOr status) { + fstat_status = std::move(status); })); - auto fstat_status = fstat_status_promise.get_future().get(); + resolveFileActions(); EXPECT_THAT(fstat_status, StatusIs(absl::StatusCode::kFailedPrecondition)); close(handle); } @@ -455,9 +461,10 @@ TEST_F(AsyncFileHandleWithMockPosixTest, CloseFailureReportsError) { auto handle = createAnonymousFile(); EXPECT_CALL(mock_posix_file_operations_, close(1)) .WillOnce(Return(Api::SysCallIntResult{-1, EBADF})); - std::promise close_status_promise; - EXPECT_OK(handle->close([&](absl::Status status) { close_status_promise.set_value(status); })); - auto close_status = close_status_promise.get_future().get(); + absl::Status close_status; + EXPECT_OK(handle->close(dispatcher_.get(), + [&](absl::Status status) { close_status = std::move(status); })); + resolveFileActions(); EXPECT_EQ(absl::StatusCode::kFailedPrecondition, close_status.code()) << close_status; } @@ -465,19 +472,20 @@ TEST_F(AsyncFileHandleWithMockPosixTest, DuplicateFailureReportsError) { auto handle = createAnonymousFile(); EXPECT_CALL(mock_posix_file_operations_, duplicate(_)) .WillOnce(Return(Api::SysCallIntResult{-1, EBADF})); - std::promise> dup_status_promise; - EXPECT_OK(handle->duplicate( - [&](absl::StatusOr status) { dup_status_promise.set_value(status); })); - auto dup_status = dup_status_promise.get_future().get(); + absl::StatusOr dup_status; + EXPECT_OK(handle->duplicate(dispatcher_.get(), [&](absl::StatusOr status) { + dup_status = std::move(status); + })); + resolveFileActions(); EXPECT_THAT(dup_status, StatusIs(absl::StatusCode::kFailedPrecondition)); close(handle); } TEST_F(AsyncFileHandleWithMockPosixTest, EnqueuingActionAfterCloseReturnsError) { auto handle = createAnonymousFile(); - EXPECT_OK(handle->close([](absl::Status) {})); - auto failed_status = handle->close([](absl::Status) {}); - EXPECT_EQ(absl::StatusCode::kFailedPrecondition, failed_status.code()) << failed_status; + EXPECT_OK(handle->close(dispatcher_.get(), [](absl::Status) {})); + auto failed_status = handle->close(dispatcher_.get(), [](absl::Status) {}); + EXPECT_THAT(failed_status, StatusIs(absl::StatusCode::kFailedPrecondition)); } } // namespace AsyncFiles diff --git a/test/extensions/common/async_files/async_file_manager_thread_pool_test.cc b/test/extensions/common/async_files/async_file_manager_thread_pool_test.cc index d0c262ddf9..7956b61db2 100644 --- a/test/extensions/common/async_files/async_file_manager_thread_pool_test.cc +++ b/test/extensions/common/async_files/async_file_manager_thread_pool_test.cc @@ -38,82 +38,29 @@ enum class BlockerState { class AsyncFileActionBlockedUntilReleased : public AsyncFileActionWithResult { public: - explicit AsyncFileActionBlockedUntilReleased(std::atomic& state_out) - : AsyncFileActionWithResult([this](bool result) { onComplete(result); }), - state_out_(state_out) { - absl::MutexLock lock(&blocking_mutex_); - state_out_.store(BlockerState::Start); - } - void setState(BlockerState state) ABSL_EXCLUSIVE_LOCKS_REQUIRED(blocking_mutex_) { - stage_ = state; - state_out_.store(state); - } + using AsyncFileActionWithResult::AsyncFileActionWithResult; bool executeImpl() final { - absl::MutexLock lock(&blocking_mutex_); - ASSERT(stage_ == BlockerState::Start); - setState(BlockerState::BlockingDuringExecution); - auto condition = [this]() ABSL_EXCLUSIVE_LOCKS_REQUIRED(blocking_mutex_) { - return stage_ == BlockerState::UnblockedExecution; - }; - blocking_mutex_.Await(absl::Condition(&condition)); - setState(BlockerState::ExecutionFinished); - return true; - } - void onComplete(bool result ABSL_ATTRIBUTE_UNUSED) { - absl::MutexLock lock(&blocking_mutex_); - setState(BlockerState::BlockingDuringCallback); - auto condition = [this]() ABSL_EXCLUSIVE_LOCKS_REQUIRED(blocking_mutex_) { - return stage_ == BlockerState::UnblockedCallback; - }; - blocking_mutex_.Await(absl::Condition(&condition)); + executing_.set_value(); + bool ret = continue_executing_.get_future().wait_for(std::chrono::seconds(1)) == + std::future_status::ready; + return ret; } - bool waitUntilExecutionBlocked() ABSL_LOCKS_EXCLUDED(blocking_mutex_) { - absl::MutexLock lock(&blocking_mutex_); - auto condition = [this]() ABSL_EXCLUSIVE_LOCKS_REQUIRED(blocking_mutex_) { - return stage_ == BlockerState::BlockingDuringExecution; - }; - return blocking_mutex_.AwaitWithTimeout(absl::Condition(&condition), absl::Seconds(1)); + bool waitUntilExecutionBlocked() { + return executing_future_.wait_for(std::chrono::seconds(1)) == std::future_status::ready; } - bool waitUntilCallbackBlocked() ABSL_LOCKS_EXCLUDED(blocking_mutex_) { - absl::MutexLock lock(&blocking_mutex_); - auto condition = [this]() ABSL_EXCLUSIVE_LOCKS_REQUIRED(blocking_mutex_) { - return stage_ == BlockerState::BlockingDuringCallback; - }; - return blocking_mutex_.AwaitWithTimeout(absl::Condition(&condition), absl::Seconds(1)); + bool isStarted() { + return executing_future_.wait_for(std::chrono::milliseconds(1)) == std::future_status::ready; } - bool unblockExecution() ABSL_LOCKS_EXCLUDED(blocking_mutex_) { - absl::MutexLock lock(&blocking_mutex_); - if (stage_ != BlockerState::BlockingDuringExecution) { - return false; - } - setState(BlockerState::UnblockedExecution); + bool unblockExecution() { + continue_executing_.set_value(); return true; } - bool unblockCallback() ABSL_LOCKS_EXCLUDED(blocking_mutex_) { - absl::MutexLock lock(&blocking_mutex_); - if (stage_ != BlockerState::BlockingDuringCallback) { - return false; - } - setState(BlockerState::UnblockedCallback); - return true; - } - bool isStarted() ABSL_LOCKS_EXCLUDED(blocking_mutex_) { - absl::MutexLock lock(&blocking_mutex_); - auto condition = [this]() ABSL_EXCLUSIVE_LOCKS_REQUIRED(blocking_mutex_) { - return stage_ != BlockerState::Start; - }; - // Very short timeout because we can be expecting to fail this. - return blocking_mutex_.AwaitWithTimeout(absl::Condition(&condition), absl::Milliseconds(30)); - } - bool doWholeFlow() ABSL_LOCKS_EXCLUDED(blocking_mutex_) { - return waitUntilExecutionBlocked() && unblockExecution() && waitUntilCallbackBlocked() && - unblockCallback(); - } + bool doWholeFlow() { return waitUntilExecutionBlocked() && unblockExecution(); } private: - absl::Mutex blocking_mutex_; - BlockerState stage_ ABSL_GUARDED_BY(blocking_mutex_) = BlockerState::Start; - std::atomic& state_out_; + std::promise executing_; + std::future executing_future_ = executing_.get_future(); + std::promise continue_executing_; }; class AsyncFileManagerTest : public testing::Test { @@ -123,6 +70,11 @@ class AsyncFileManagerTest : public testing::Test { factory_ = AsyncFileManagerFactory::singleton(singleton_manager_.get()); } + void resolveFileActions() { + manager_->waitForIdle(); + dispatcher_->run(Event::Dispatcher::RunType::Block); + } + protected: std::unique_ptr singleton_manager_; std::shared_ptr factory_; @@ -132,14 +84,16 @@ class AsyncFileManagerTest : public testing::Test { std::shared_ptr manager_; AsyncFileActionBlockedUntilReleased* blocker_[3]; - std::atomic blocker_last_state_[3]; + std::vector blocker_callback_result_ = std::vector(3); // returns the cancellation function. - std::function enqueueBlocker(int index) { - auto blocker = - std::make_shared(blocker_last_state_[index]); + CancelFunction enqueueBlocker(int index) { + auto blocker = std::make_unique( + [this, index](bool result) { blocker_callback_result_[index] = result; }); blocker_[index] = blocker.get(); - return manager_->enqueue(std::move(blocker)); + return manager_->enqueue(dispatcher_.get(), std::move(blocker)); } + Api::ApiPtr api_ = Api::createApiForTest(); + Event::DispatcherPtr dispatcher_ = api_->allocateDispatcher("test_thread"); }; TEST_F(AsyncFileManagerTest, WorksWithThreadPoolSizeZero) { @@ -151,6 +105,7 @@ TEST_F(AsyncFileManagerTest, WorksWithThreadPoolSizeZero) { EXPECT_THAT(manager_->describe(), testing::ContainsRegex("thread_pool_size = [1-9]\\d*")); enqueueBlocker(0); EXPECT_TRUE(blocker_[0]->doWholeFlow()); + resolveFileActions(); factory_.reset(); } @@ -168,9 +123,9 @@ TEST_F(AsyncFileManagerTest, ThreadsBlockAppropriately) { EXPECT_FALSE(blocker_[2]->isStarted()); ASSERT_TRUE(blocker_[0]->doWholeFlow()); // When one of the workers finishes, the third action should be able to start. - EXPECT_TRUE(blocker_[2]->isStarted()); - EXPECT_TRUE(blocker_[1]->doWholeFlow()); EXPECT_TRUE(blocker_[2]->doWholeFlow()); + EXPECT_TRUE(blocker_[1]->doWholeFlow()); + resolveFileActions(); factory_.reset(); } @@ -184,19 +139,23 @@ class AsyncFileManagerSingleThreadTest : public AsyncFileManagerTest { manager_ = factory->getAsyncFileManager(config); } -private: +protected: std::unique_ptr singleton_manager_; }; -TEST_F(AsyncFileManagerSingleThreadTest, AbortingDuringExecutionCancelsTheCallback) { - auto cancelBlocker0 = enqueueBlocker(0); +TEST_F(AsyncFileManagerSingleThreadTest, CancellingDuringExecutionCancelsTheCallback) { + EXPECT_FALSE(blocker_callback_result_[0]); + CancelFunction cancelBlocker0 = enqueueBlocker(0); + EXPECT_FALSE(blocker_callback_result_[0]); ASSERT_TRUE(blocker_[0]->waitUntilExecutionBlocked()); enqueueBlocker(1); ASSERT_FALSE(blocker_[1]->isStarted()); cancelBlocker0(); blocker_[0]->unblockExecution(); ASSERT_TRUE(blocker_[1]->doWholeFlow()); - EXPECT_EQ(BlockerState::ExecutionFinished, blocker_last_state_[0].load()); + resolveFileActions(); + EXPECT_FALSE(blocker_callback_result_[0]); + EXPECT_TRUE(blocker_callback_result_[1]); } TEST_F(AsyncFileManagerSingleThreadTest, AbortingBeforeExecutionCancelsTheExecution) { @@ -208,66 +167,42 @@ TEST_F(AsyncFileManagerSingleThreadTest, AbortingBeforeExecutionCancelsTheExecut // Blocker 1 should never start, having been cancelled before it // was popped from the queue. We can't check its internal value because // it should also have been deleted, so we can only check its output state. - EXPECT_EQ(BlockerState::Start, blocker_last_state_[1].load()); -} - -TEST_F(AsyncFileManagerSingleThreadTest, AbortingDuringCallbackBlocksUntilCallbackCompletes) { - auto cancel = enqueueBlocker(0); - blocker_[0]->waitUntilExecutionBlocked(); - blocker_[0]->unblockExecution(); - blocker_[0]->waitUntilCallbackBlocked(); - std::atomic delayed_action_occurred; - std::thread callback_unblocker([&] { - // Using future::wait_for because lint forbids us from sleeping in - // real-time, but here we're forcing a race to go a specific way, using - // real-time because there's no other practical option here. - std::promise pauser; - pauser.get_future().wait_for(std::chrono::milliseconds(50)); - delayed_action_occurred.store(true); - blocker_[0]->unblockCallback(); - }); - cancel(); - EXPECT_TRUE(delayed_action_occurred.load()); - EXPECT_EQ(BlockerState::UnblockedCallback, blocker_last_state_[0].load()); - callback_unblocker.join(); + resolveFileActions(); + EXPECT_TRUE(blocker_callback_result_[0]); + EXPECT_FALSE(blocker_callback_result_[1]); } TEST_F(AsyncFileManagerSingleThreadTest, AbortingAfterCallbackHasNoObservableEffect) { auto cancel = enqueueBlocker(0); EXPECT_TRUE(blocker_[0]->doWholeFlow()); + resolveFileActions(); cancel(); - EXPECT_EQ(BlockerState::UnblockedCallback, blocker_last_state_[0].load()); } -template class WaitForResult { -public: - std::function callback() { - return [this](T result) { saveResult(result); }; - } - void saveResult(T result) { result_.set_value(std::move(result)); } - T getResult() { return result_.get_future().get(); } - -private: - std::promise result_; -}; - TEST_F(AsyncFileManagerSingleThreadTest, CreateAnonymousFileWorks) { - WaitForResult> handle_blocker; - manager_->createAnonymousFile(tmpdir_, handle_blocker.callback()); - AsyncFileHandle handle = handle_blocker.getResult().value(); + AsyncFileHandle handle; + manager_->createAnonymousFile(dispatcher_.get(), tmpdir_, [&](absl::StatusOr h) { + handle = std::move(h.value()); + }); + resolveFileActions(); // Open a second one, to ensure we get two distinct files // (and for coverage, because the second one doesn't use the once_flag path) - WaitForResult> second_handle_blocker; - manager_->createAnonymousFile(tmpdir_, second_handle_blocker.callback()); - AsyncFileHandle second_handle = second_handle_blocker.getResult().value(); - WaitForResult close_blocker; - EXPECT_OK(handle->close(close_blocker.callback())); - absl::Status status = close_blocker.getResult(); - EXPECT_OK(status); - WaitForResult second_close_blocker; - EXPECT_OK(second_handle->close(second_close_blocker.callback())); - status = second_close_blocker.getResult(); - EXPECT_OK(status); + AsyncFileHandle second_handle; + manager_->createAnonymousFile(dispatcher_.get(), tmpdir_, [&](absl::StatusOr h) { + second_handle = std::move(h.value()); + }); + resolveFileActions(); + EXPECT_THAT(handle, testing::NotNull()); + EXPECT_THAT(second_handle, testing::NotNull()); + EXPECT_NE(handle, second_handle); + absl::Status close_result = absl::InternalError("not set"); + EXPECT_OK(handle->close(dispatcher_.get(), [&](absl::Status s) { close_result = std::move(s); })); + absl::Status second_close_result = absl::InternalError("not set"); + EXPECT_OK(second_handle->close(dispatcher_.get(), + [&](absl::Status s) { second_close_result = std::move(s); })); + resolveFileActions(); + EXPECT_OK(close_result); + EXPECT_OK(second_close_result); } TEST_F(AsyncFileManagerSingleThreadTest, OpenExistingFileStatAndUnlinkWork) { @@ -276,47 +211,53 @@ TEST_F(AsyncFileManagerSingleThreadTest, OpenExistingFileStatAndUnlinkWork) { Api::OsSysCalls& posix = Api::OsSysCallsSingleton().get(); auto fd = posix.mkstemp(filename); posix.close(fd.return_value_); - WaitForResult> handle_blocker; - manager_->openExistingFile(filename, AsyncFileManager::Mode::ReadWrite, - handle_blocker.callback()); - AsyncFileHandle handle = handle_blocker.getResult().value(); - WaitForResult close_blocker; - EXPECT_OK(handle->close(close_blocker.callback())); - absl::Status status = close_blocker.getResult(); - EXPECT_OK(status); - WaitForResult> stat_blocker; - manager_->stat(filename, stat_blocker.callback()); - absl::StatusOr stat_result = stat_blocker.getResult(); + AsyncFileHandle handle; + manager_->openExistingFile( + dispatcher_.get(), filename, AsyncFileManager::Mode::ReadWrite, + [&](absl::StatusOr h) { handle = std::move(h.value()); }); + resolveFileActions(); + absl::Status close_result; + EXPECT_OK(handle->close(dispatcher_.get(), [&](absl::Status s) { close_result = std::move(s); })); + EXPECT_OK(close_result); + absl::StatusOr stat_result; + manager_->stat(dispatcher_.get(), filename, + [&](absl::StatusOr result) { stat_result = std::move(result); }); + resolveFileActions(); EXPECT_OK(stat_result); EXPECT_EQ(0, stat_result.value().st_size); - WaitForResult unlink_blocker; - manager_->unlink(filename, unlink_blocker.callback()); - status = unlink_blocker.getResult(); - EXPECT_OK(status); + absl::Status unlink_result = absl::InternalError("not set"); + manager_->unlink(dispatcher_.get(), filename, + [&](absl::Status s) { unlink_result = std::move(s); }); + resolveFileActions(); + EXPECT_OK(unlink_result); + // Make sure unlink deleted the file. struct stat s; EXPECT_EQ(-1, stat(filename, &s)); } TEST_F(AsyncFileManagerSingleThreadTest, OpenExistingFileFailsForNonexistent) { - WaitForResult> handle_blocker; - manager_->openExistingFile(absl::StrCat(tmpdir_, "/nonexistent_file"), - AsyncFileManager::Mode::ReadWrite, handle_blocker.callback()); - absl::Status status = handle_blocker.getResult().status(); - EXPECT_THAT(status, HasStatusCode(absl::StatusCode::kNotFound)); + absl::StatusOr handle_result; + manager_->openExistingFile(dispatcher_.get(), absl::StrCat(tmpdir_, "/nonexistent_file"), + AsyncFileManager::Mode::ReadWrite, + [&](absl::StatusOr r) { handle_result = r; }); + resolveFileActions(); + EXPECT_THAT(handle_result, HasStatusCode(absl::StatusCode::kNotFound)); } TEST_F(AsyncFileManagerSingleThreadTest, StatFailsForNonexistent) { - WaitForResult> stat_blocker; - manager_->stat(absl::StrCat(tmpdir_, "/nonexistent_file"), stat_blocker.callback()); - absl::StatusOr result = stat_blocker.getResult(); - EXPECT_THAT(result, HasStatusCode(absl::StatusCode::kNotFound)); + absl::StatusOr stat_result; + manager_->stat(dispatcher_.get(), absl::StrCat(tmpdir_, "/nonexistent_file"), + [&](absl::StatusOr r) { stat_result = std::move(r); }); + resolveFileActions(); + EXPECT_THAT(stat_result, HasStatusCode(absl::StatusCode::kNotFound)); } TEST_F(AsyncFileManagerSingleThreadTest, UnlinkFailsForNonexistent) { - WaitForResult handle_blocker; - manager_->unlink(absl::StrCat(tmpdir_, "/nonexistent_file"), handle_blocker.callback()); - absl::Status status = handle_blocker.getResult(); - EXPECT_THAT(status, HasStatusCode(absl::StatusCode::kNotFound)); + absl::Status unlink_result; + manager_->unlink(dispatcher_.get(), absl::StrCat(tmpdir_, "/nonexistent_file"), + [&](absl::Status s) { unlink_result = std::move(s); }); + resolveFileActions(); + EXPECT_THAT(unlink_result, HasStatusCode(absl::StatusCode::kNotFound)); } } // namespace AsyncFiles diff --git a/test/extensions/common/async_files/async_file_manager_thread_pool_with_mocks_test.cc b/test/extensions/common/async_files/async_file_manager_thread_pool_with_mocks_test.cc index 03a854da6b..8e05843621 100644 --- a/test/extensions/common/async_files/async_file_manager_thread_pool_with_mocks_test.cc +++ b/test/extensions/common/async_files/async_file_manager_thread_pool_with_mocks_test.cc @@ -46,68 +46,48 @@ class AsyncFileManagerWithMockFilesTest : public ::testing::Test { manager_ = factory_->getAsyncFileManager(config, &mock_posix_file_operations_); } + void resolveFileActions(int cycles = 1) { + for (int i = 0; i < cycles; i++) { + manager_->waitForIdle(); + dispatcher_->run(Event::Dispatcher::RunType::Block); + } + } + protected: std::unique_ptr singleton_manager_; StrictMock mock_posix_file_operations_; std::shared_ptr factory_; std::shared_ptr manager_; static constexpr absl::string_view tmpdir_{"/mocktmp"}; + Api::ApiPtr api_ = Api::createApiForTest(); + Event::DispatcherPtr dispatcher_ = api_->allocateDispatcher("test_thread"); }; -TEST_F(AsyncFileManagerWithMockFilesTest, ChainedOperationsWorkAndSkipQueue) { - int fd = 1; - std::promise write_blocker; - EXPECT_CALL(mock_posix_file_operations_, open(Eq(tmpdir_), O_TMPFILE | O_RDWR, S_IRUSR | S_IWUSR)) - .WillOnce(Return(Api::SysCallIntResult{fd, 0})); - EXPECT_CALL(mock_posix_file_operations_, pwrite(fd, _, 5, 0)) - .WillOnce([&write_blocker](int, const void*, size_t, off_t) { - write_blocker.get_future().wait(); - return Api::SysCallSizeResult{5, 0}; - }); - // Chain open/write/close. Write will block because of the mock expectation. - manager_->createAnonymousFile(tmpdir_, [&](absl::StatusOr result) { - AsyncFileHandle handle = result.value(); - Buffer::OwnedImpl buf("hello"); - EXPECT_OK(handle->write(buf, 0, [handle](absl::StatusOr result) { - EXPECT_THAT(result, IsOkAndHolds(5U)); - EXPECT_OK(handle->close([](absl::Status result) { EXPECT_OK(result); })); - })); - }); - // Separately queue another action. - std::promise did_second_action; - manager_->whenReady([&](absl::Status) { did_second_action.set_value(); }); - auto second_action_future = did_second_action.get_future(); - // Ensure that the second action didn't get a turn while the file operations are still blocking. - EXPECT_EQ(std::future_status::timeout, - second_action_future.wait_for(std::chrono::milliseconds(1))); - EXPECT_CALL(mock_posix_file_operations_, close(fd)).WillOnce(Return(Api::SysCallIntResult{0, 0})); - // Unblock the write. - write_blocker.set_value(); - // Ensure that the second action does get a turn after the file operations completed. - EXPECT_EQ(std::future_status::ready, second_action_future.wait_for(std::chrono::seconds(1))); -} - TEST_F(AsyncFileManagerWithMockFilesTest, CancellingAQueuedActionPreventsItFromExecuting) { std::promise ready; - // Add a blocking action so we can guarantee cancel is called before unlink begins. - manager_->whenReady([&](absl::Status) { ready.get_future().wait(); }); + EXPECT_CALL(mock_posix_file_operations_, stat(_, _)).WillOnce([&](const char*, struct stat*) { + ready.get_future().wait(); + return Api::SysCallIntResult{0, 0}; + }); + // Queue a blocking action so we can guarantee cancel is called before unlink begins. + manager_->stat(dispatcher_.get(), tmpdir_, [&](absl::StatusOr) {}); // Ensure that unlink doesn't get called. EXPECT_CALL(mock_posix_file_operations_, unlink(_)).Times(0); - auto cancel_unlink = manager_->unlink("irrelevant", [](absl::Status) {}); + auto cancel_unlink = manager_->unlink(dispatcher_.get(), "irrelevant", [](absl::Status) { + FAIL() << "canceled action should not call callback"; + }); cancel_unlink(); - std::promise done; - // Add a notifying action so we can ensure that the unlink action was passed by the time - // the test ends. - manager_->whenReady([&](absl::Status) { done.set_value(); }); ready.set_value(); - done.get_future().wait(); + resolveFileActions(); } TEST_F(AsyncFileManagerWithMockFilesTest, CancellingACompletedActionDoesNothingImportant) { - std::promise ready; - auto cancel = manager_->whenReady([&](absl::Status) { ready.set_value(); }); - ready.get_future().wait(); - std::this_thread::yield(); + EXPECT_CALL(mock_posix_file_operations_, stat(_, _)); + auto cancel = + manager_->stat(dispatcher_.get(), "irrelevant", [&](absl::StatusOr) {}); + resolveFileActions(); + // This is to make sure cancel() doesn't end up with a dangling pointer or something + // when the action is resolved. cancel(); } @@ -122,14 +102,14 @@ TEST_F(AsyncFileManagerWithMockFilesTest, allow_open_to_finish.get_future().wait(); return Api::SysCallIntResult{fd, 0}; }); - std::atomic callback_was_called{false}; - // Queue opening the file, record if the callback was called (it shouldn't be). + EXPECT_CALL(mock_posix_file_operations_, stat(_, _)); auto cancelOpen = manager_->createAnonymousFile( - tmpdir_, - [&callback_was_called](absl::StatusOr) { callback_was_called.store(true); }); + dispatcher_.get(), tmpdir_, + [&](absl::StatusOr) { FAIL() << "callback should not be called"; }); // Separately queue another action. - std::promise did_second_action; - manager_->whenReady([&](absl::Status) { did_second_action.set_value(true); }); + bool did_second_action = false; + manager_->stat(dispatcher_.get(), "", + [&](absl::StatusOr) { did_second_action = true; }); // Wait for the open operation to be entered. wait_for_open_to_be_executing.get_future().wait(); // Cancel the open request (but too late to actually stop it!) @@ -138,12 +118,10 @@ TEST_F(AsyncFileManagerWithMockFilesTest, EXPECT_CALL(mock_posix_file_operations_, close(fd)).WillOnce(Return(Api::SysCallIntResult{0, 0})); // Allow the open operation to complete. allow_open_to_finish.set_value(); + resolveFileActions(); // Ensure that the second action does get a turn after the file operation relinquishes the thread. // (This also ensures that the file operation reached the end, so the file should be closed now.) - ASSERT_EQ(std::future_status::ready, - did_second_action.get_future().wait_for(std::chrono::milliseconds(100))); - // Ensure the callback for the open operation was *not* called, because it was cancelled. - EXPECT_FALSE(callback_was_called.load()); + EXPECT_TRUE(did_second_action); } TEST_F(AsyncFileManagerWithMockFilesTest, @@ -157,14 +135,14 @@ TEST_F(AsyncFileManagerWithMockFilesTest, allow_open_to_finish.get_future().wait(); return Api::SysCallIntResult{fd, 0}; }); - std::atomic callback_was_called{false}; - // Queue opening the file, record if the callback was called (it shouldn't be). + EXPECT_CALL(mock_posix_file_operations_, stat(_, _)); auto cancelOpen = manager_->openExistingFile( - filename, AsyncFileManager::Mode::ReadWrite, - [&callback_was_called](absl::StatusOr) { callback_was_called.store(true); }); + dispatcher_.get(), filename, AsyncFileManager::Mode::ReadWrite, + [&](absl::StatusOr) { FAIL() << "callback should not be called"; }); // Separately queue another action. - std::promise did_second_action; - manager_->whenReady([&](absl::Status) { did_second_action.set_value(true); }); + bool did_second_action; + manager_->stat(dispatcher_.get(), "irrelevant", + [&](absl::StatusOr) { did_second_action = true; }); // Wait for the open operation to be entered. wait_for_open_to_be_executing.get_future().wait(); // Cancel the open request (but too late to actually stop it!) @@ -173,12 +151,57 @@ TEST_F(AsyncFileManagerWithMockFilesTest, EXPECT_CALL(mock_posix_file_operations_, close(fd)).WillOnce(Return(Api::SysCallIntResult{0, 0})); // Allow the open operation to complete. allow_open_to_finish.set_value(); + resolveFileActions(); // Ensure that the second action does get a turn after the file operation relinquishes the thread. // (This also ensures that the file operation reached the end, so the file should be closed now.) - ASSERT_EQ(std::future_status::ready, - did_second_action.get_future().wait_for(std::chrono::milliseconds(100))); - // Ensure the callback for the open operation was *not* called, because it was cancelled. - EXPECT_FALSE(callback_was_called.load()); + EXPECT_TRUE(did_second_action); +} + +TEST_F(AsyncFileManagerWithMockFilesTest, CloseActionExecutesEvenIfCancelled) { + int fd = 1; + // First do a successful open so we have a file handle. + EXPECT_CALL(mock_posix_file_operations_, open(Eq(tmpdir_), O_TMPFILE | O_RDWR, S_IRUSR | S_IWUSR)) + .WillOnce(Return(Api::SysCallIntResult{fd, 0})); + AsyncFileHandle handle; + manager_->createAnonymousFile( + dispatcher_.get(), tmpdir_, + [&](absl::StatusOr result) { handle = std::move(result.value()); }); + resolveFileActions(); + ASSERT_THAT(handle, testing::NotNull()); + EXPECT_CALL(mock_posix_file_operations_, close(fd)); + CancelFunction cancel = handle->close(nullptr, [](absl::Status) {}).value(); + cancel(); + resolveFileActions(); +} + +TEST_F(AsyncFileManagerWithMockFilesTest, CancellingBeforeCallbackUndoesActionsWithSideEffects) { + int fd = 1; + // First do a successful open so we have a file handle. + EXPECT_CALL(mock_posix_file_operations_, open(Eq(tmpdir_), O_TMPFILE | O_RDWR, S_IRUSR | S_IWUSR)) + .WillOnce(Return(Api::SysCallIntResult{fd, 0})); + AsyncFileHandle handle; + manager_->createAnonymousFile( + dispatcher_.get(), tmpdir_, + [&](absl::StatusOr result) { handle = std::move(result.value()); }); + resolveFileActions(); + ASSERT_THAT(handle, testing::NotNull()); + EXPECT_CALL(mock_posix_file_operations_, linkat(fd, _, _, Eq(tmpdir_), _)); + CancelFunction cancel_hard_link = + handle + ->createHardLink( + dispatcher_.get(), tmpdir_, + [&](absl::Status) { FAIL() << "callback should not be called in this test"; }) + .value(); + // wait for the manager to post to the dispatcher, but don't consume it yet. + manager_->waitForIdle(); + // cancel while it's in the dispatcher queue. + cancel_hard_link(); + // Cancellation should remove the link because the callback was not executed. + EXPECT_CALL(mock_posix_file_operations_, unlink(Eq(tmpdir_))); + resolveFileActions(); + EXPECT_CALL(mock_posix_file_operations_, close(fd)).WillOnce(Return(Api::SysCallIntResult{0, 0})); + ASSERT_OK(handle->close(nullptr, [](absl::Status) {})); + resolveFileActions(); } TEST_F(AsyncFileManagerWithMockFilesTest, OpenFailureInCreateAnonymousReturnsAnError) { @@ -188,22 +211,23 @@ TEST_F(AsyncFileManagerWithMockFilesTest, OpenFailureInCreateAnonymousReturnsAnE EXPECT_CALL(mock_posix_file_operations_, open(Eq(tmpdir_), O_TMPFILE | O_RDWR, S_IRUSR | S_IWUSR)) .WillOnce(Return(Api::SysCallIntResult{fd, 0})); EXPECT_CALL(mock_posix_file_operations_, close(fd)).WillOnce(Return(Api::SysCallIntResult{0, 0})); - std::promise first_open_was_called; - manager_->createAnonymousFile(tmpdir_, [&](absl::StatusOr result) { - EXPECT_OK(result.value()->close([](absl::Status) {})); - first_open_was_called.set_value(); - }); - // We have to synchronize on this to avoid racily adding a different matching expectation for the - // first 'open'. - first_open_was_called.get_future().wait(); + AsyncFileHandle handle; + manager_->createAnonymousFile( + dispatcher_.get(), tmpdir_, + [&](absl::StatusOr result) { handle = std::move(result.value()); }); + resolveFileActions(); + ASSERT_THAT(handle, testing::NotNull()); + EXPECT_OK(handle->close(nullptr, [](absl::Status) {})); + resolveFileActions(); EXPECT_CALL(mock_posix_file_operations_, open(Eq(tmpdir_), O_TMPFILE | O_RDWR, S_IRUSR | S_IWUSR)) .WillOnce(Return(Api::SysCallIntResult{-1, EMFILE})); // Capture the result of the second open call, to verify that the error code came through. - std::promise captured_result; - manager_->createAnonymousFile(tmpdir_, [&](absl::StatusOr result) { - captured_result.set_value(result.status()); - }); - EXPECT_EQ(absl::StatusCode::kResourceExhausted, captured_result.get_future().get().code()); + absl::Status captured_result; + manager_->createAnonymousFile( + dispatcher_.get(), tmpdir_, + [&](absl::StatusOr result) { captured_result = result.status(); }); + resolveFileActions(); + EXPECT_EQ(absl::StatusCode::kResourceExhausted, captured_result.code()) << captured_result; } TEST_F(AsyncFileManagerWithMockFilesTest, CreateAnonymousFallbackMkstempReturnsAnErrorOnFailure) { @@ -212,11 +236,12 @@ TEST_F(AsyncFileManagerWithMockFilesTest, CreateAnonymousFallbackMkstempReturnsA EXPECT_CALL(mock_posix_file_operations_, mkstemp(Eq(std::string(tmpdir_) + "/buffer.XXXXXX"))) .WillOnce(Return(Api::SysCallIntResult{-1, EMFILE})); // Capture the result of the open call, to verify that the error code came through. - std::promise captured_result; - manager_->createAnonymousFile(tmpdir_, [&](absl::StatusOr result) { - captured_result.set_value(result.status()); - }); - EXPECT_EQ(absl::StatusCode::kResourceExhausted, captured_result.get_future().get().code()); + absl::Status captured_result; + manager_->createAnonymousFile( + dispatcher_.get(), tmpdir_, + [&](absl::StatusOr result) { captured_result = result.status(); }); + resolveFileActions(); + EXPECT_EQ(absl::StatusCode::kResourceExhausted, captured_result.code()) << captured_result; } TEST_F(AsyncFileManagerWithMockFilesTest, CreateAnonymousFallbackReturnsAnErrorIfPathTooLong) { @@ -228,11 +253,12 @@ TEST_F(AsyncFileManagerWithMockFilesTest, CreateAnonymousFallbackReturnsAnErrorI open(Eq(too_long_tmpdir), O_TMPFILE | O_RDWR, S_IRUSR | S_IWUSR)) .WillOnce(Return(Api::SysCallIntResult{-1, EBADF})); // Capture the result of the open call, to verify that the error code came through. - std::promise captured_result; - manager_->createAnonymousFile(too_long_tmpdir, [&](absl::StatusOr result) { - captured_result.set_value(result.status()); - }); - EXPECT_EQ(absl::StatusCode::kInvalidArgument, captured_result.get_future().get().code()); + absl::Status captured_result; + manager_->createAnonymousFile( + dispatcher_.get(), too_long_tmpdir, + [&](absl::StatusOr result) { captured_result = result.status(); }); + resolveFileActions(); + EXPECT_EQ(absl::StatusCode::kInvalidArgument, captured_result.code()) << captured_result; } TEST_F(AsyncFileManagerWithMockFilesTest, @@ -255,11 +281,12 @@ TEST_F(AsyncFileManagerWithMockFilesTest, EXPECT_CALL(mock_posix_file_operations_, unlink(Eq(absl::StrCat(tmpdir_, "/buffer.ABCDEF")))) .WillOnce(Return(Api::SysCallIntResult{0, 0})); } - std::promise captured_result; - manager_->createAnonymousFile(tmpdir_, [&](absl::StatusOr result) { - captured_result.set_value(result.status()); - }); - EXPECT_EQ(absl::StatusCode::kUnimplemented, captured_result.get_future().get().code()); + absl::Status captured_result; + manager_->createAnonymousFile( + dispatcher_.get(), tmpdir_, + [&](absl::StatusOr result) { captured_result = result.status(); }); + resolveFileActions(); + EXPECT_EQ(absl::StatusCode::kUnimplemented, captured_result.code()) << captured_result; } TEST_F(AsyncFileManagerWithMockFilesTest, @@ -280,15 +307,17 @@ TEST_F(AsyncFileManagerWithMockFilesTest, EXPECT_CALL(mock_posix_file_operations_, close(fd)) .WillOnce(Return(Api::SysCallIntResult{0, 0})); } - std::promise callback_complete; - manager_->createAnonymousFile(tmpdir_, [&](absl::StatusOr result) { - EXPECT_OK(result); - EXPECT_OK(result.value()->close([&](absl::Status result) { - EXPECT_OK(result); - callback_complete.set_value(); - })); - }); - callback_complete.get_future().wait(); + bool callbacks_complete = false; + manager_->createAnonymousFile( + dispatcher_.get(), tmpdir_, [&](absl::StatusOr result) { + EXPECT_OK(result); + EXPECT_OK(result.value()->close(dispatcher_.get(), [&](absl::Status result) { + EXPECT_OK(result); + callbacks_complete = true; + })); + }); + resolveFileActions(2); + EXPECT_TRUE(callbacks_complete); } } // namespace AsyncFiles diff --git a/test/extensions/common/async_files/mocks.cc b/test/extensions/common/async_files/mocks.cc index 347f61af0a..69e60d6d97 100644 --- a/test/extensions/common/async_files/mocks.cc +++ b/test/extensions/common/async_files/mocks.cc @@ -11,69 +11,88 @@ using ::testing::_; MockAsyncFileContext::MockAsyncFileContext(std::shared_ptr manager) : manager_(manager) { - ON_CALL(*this, stat(_)) - .WillByDefault([this](std::function)> on_complete) { - return manager_->enqueue( - std::shared_ptr(new TypedMockAsyncFileAction(on_complete))); + ON_CALL(*this, stat(_, _)) + .WillByDefault([this](Event::Dispatcher* dispatcher, + absl::AnyInvocable)> on_complete) { + return manager_->enqueue(dispatcher, + std::unique_ptr( + new TypedMockAsyncFileAction(std::move(on_complete)))); }); - ON_CALL(*this, createHardLink(_, _)) - .WillByDefault([this](absl::string_view, std::function on_complete) { - return manager_->enqueue( - std::shared_ptr(new TypedMockAsyncFileAction(on_complete))); + ON_CALL(*this, createHardLink(_, _, _)) + .WillByDefault([this](Event::Dispatcher* dispatcher, absl::string_view, + absl::AnyInvocable on_complete) { + return manager_->enqueue(dispatcher, + std::unique_ptr( + new TypedMockAsyncFileAction(std::move(on_complete)))); }); - EXPECT_CALL(*this, close(_)).WillOnce([this](std::function on_complete) { - manager_->enqueue( - std::shared_ptr(new TypedMockAsyncFileAction(on_complete))); - return absl::OkStatus(); - }); - ON_CALL(*this, read(_, _, _)) - .WillByDefault([this](off_t, size_t, - std::function)> on_complete) { - return manager_->enqueue( - std::shared_ptr(new TypedMockAsyncFileAction(on_complete))); + EXPECT_CALL(*this, close(_, _)) + .WillOnce([this](Event::Dispatcher* dispatcher, + absl::AnyInvocable on_complete) mutable { + return manager_->enqueue(dispatcher, + std::unique_ptr( + new TypedMockAsyncFileAction(std::move(on_complete)))); }); - ON_CALL(*this, write(_, _, _)) - .WillByDefault([this](Buffer::Instance&, off_t, - std::function)> on_complete) { - return manager_->enqueue( - std::shared_ptr(new TypedMockAsyncFileAction(on_complete))); + ON_CALL(*this, read(_, _, _, _)) + .WillByDefault( + [this](Event::Dispatcher* dispatcher, off_t, size_t, + absl::AnyInvocable)> on_complete) { + return manager_->enqueue(dispatcher, + std::unique_ptr( + new TypedMockAsyncFileAction(std::move(on_complete)))); + }); + ON_CALL(*this, write(_, _, _, _)) + .WillByDefault([this](Event::Dispatcher* dispatcher, Buffer::Instance&, off_t, + absl::AnyInvocable)> on_complete) { + return manager_->enqueue(dispatcher, + std::unique_ptr( + new TypedMockAsyncFileAction(std::move(on_complete)))); }); - ON_CALL(*this, duplicate(_)) + ON_CALL(*this, duplicate(_, _)) .WillByDefault( - [this]( - std::function>)> on_complete) { - return manager_->enqueue( - std::shared_ptr(new TypedMockAsyncFileAction(on_complete))); + [this](Event::Dispatcher* dispatcher, + absl::AnyInvocable>)> + on_complete) { + return manager_->enqueue(dispatcher, + std::unique_ptr( + new TypedMockAsyncFileAction(std::move(on_complete)))); }); }; MockAsyncFileManager::MockAsyncFileManager() { - ON_CALL(*this, enqueue(_)).WillByDefault([this](const std::shared_ptr action) { - queue_.push_back(std::dynamic_pointer_cast(action)); - return [this]() { mockCancel(); }; - }); - ON_CALL(*this, stat(_, _)) + ON_CALL(*this, enqueue(_, _)) .WillByDefault( - [this](absl::string_view, std::function)> on_complete) { - return enqueue( - std::shared_ptr(new TypedMockAsyncFileAction(on_complete))); + [this](Event::Dispatcher* dispatcher, std::unique_ptr action) { + auto entry = QueuedAction{std::move(action), dispatcher}; + auto cancel_func = [this, state = entry.state_]() { + state->store(QueuedAction::State::Cancelled); + mockCancel(); + }; + queue_.push(std::move(entry)); + return cancel_func; }); - ON_CALL(*this, createAnonymousFile(_, _)) - .WillByDefault([this](absl::string_view, - std::function)> on_complete) { - return enqueue( - std::shared_ptr(new TypedMockAsyncFileAction(on_complete))); + ON_CALL(*this, stat(_, _, _)) + .WillByDefault([this](Event::Dispatcher* dispatcher, absl::string_view, + absl::AnyInvocable)> on_complete) { + return enqueue(dispatcher, std::unique_ptr( + new TypedMockAsyncFileAction(std::move(on_complete)))); + }); + ON_CALL(*this, createAnonymousFile(_, _, _)) + .WillByDefault([this](Event::Dispatcher* dispatcher, absl::string_view, + absl::AnyInvocable)> on_complete) { + return enqueue(dispatcher, std::unique_ptr( + new TypedMockAsyncFileAction(std::move(on_complete)))); }); - ON_CALL(*this, openExistingFile(_, _, _)) - .WillByDefault([this](absl::string_view, Mode, - std::function)> on_complete) { - return enqueue( - std::shared_ptr(new TypedMockAsyncFileAction(on_complete))); + ON_CALL(*this, openExistingFile(_, _, _, _)) + .WillByDefault([this](Event::Dispatcher* dispatcher, absl::string_view, Mode, + absl::AnyInvocable)> on_complete) { + return enqueue(dispatcher, std::unique_ptr( + new TypedMockAsyncFileAction(std::move(on_complete)))); }); - ON_CALL(*this, unlink(_, _)) - .WillByDefault([this](absl::string_view, std::function on_complete) { - return enqueue( - std::shared_ptr(new TypedMockAsyncFileAction(on_complete))); + ON_CALL(*this, unlink(_, _, _)) + .WillByDefault([this](Event::Dispatcher* dispatcher, absl::string_view, + absl::AnyInvocable on_complete) { + return enqueue(dispatcher, std::unique_ptr( + new TypedMockAsyncFileAction(std::move(on_complete)))); }); } diff --git a/test/extensions/common/async_files/mocks.h b/test/extensions/common/async_files/mocks.h index f5f62d6fae..0c890fe95e 100644 --- a/test/extensions/common/async_files/mocks.h +++ b/test/extensions/common/async_files/mocks.h @@ -1,8 +1,11 @@ #pragma once +#include + #include "source/extensions/common/async_files/async_file_handle.h" #include "source/extensions/common/async_files/async_file_manager.h" #include "source/extensions/common/async_files/async_file_manager_factory.h" +#include "source/extensions/common/async_files/async_file_manager_thread_pool.h" #include "gmock/gmock.h" #include "gtest/gtest.h" @@ -23,18 +26,23 @@ class MockAsyncFileContext : public Extensions::Common::AsyncFiles::AsyncFileCon // These can be consumed by calling MockAsyncFileManager::nextActionCompletes // with the desired parameter to the on_complete callback. MOCK_METHOD(absl::StatusOr, stat, - (std::function)> on_complete)); + (Event::Dispatcher * dispatcher, + absl::AnyInvocable)> on_complete)); MOCK_METHOD(absl::StatusOr, createHardLink, - (absl::string_view filename, std::function on_complete)); - MOCK_METHOD(absl::Status, close, (std::function on_complete)); + (Event::Dispatcher * dispatcher, absl::string_view filename, + absl::AnyInvocable on_complete)); + MOCK_METHOD(absl::StatusOr, close, + (Event::Dispatcher * dispatcher, absl::AnyInvocable on_complete)); MOCK_METHOD(absl::StatusOr, read, - (off_t offset, size_t length, - std::function)> on_complete)); + (Event::Dispatcher * dispatcher, off_t offset, size_t length, + absl::AnyInvocable)> on_complete)); MOCK_METHOD(absl::StatusOr, write, - (Buffer::Instance & contents, off_t offset, - std::function)> on_complete)); - MOCK_METHOD(absl::StatusOr, duplicate, - (std::function>)> on_complete)); + (Event::Dispatcher * dispatcher, Buffer::Instance& contents, off_t offset, + absl::AnyInvocable)> on_complete)); + MOCK_METHOD( + absl::StatusOr, duplicate, + (Event::Dispatcher * dispatcher, + absl::AnyInvocable>)> on_complete)); private: std::shared_ptr manager_; @@ -50,7 +58,8 @@ class MockAsyncFileAction : public AsyncFileAction { template class TypedMockAsyncFileAction : public MockAsyncFileAction { public: - explicit TypedMockAsyncFileAction(T on_complete) : on_complete_(on_complete) {} + explicit TypedMockAsyncFileAction(T on_complete) : on_complete_(std::move(on_complete)) {} + void onComplete() override {} T on_complete_; std::string describe() const override { return typeid(T).name(); } }; @@ -60,17 +69,20 @@ class MockAsyncFileManager : public Extensions::Common::AsyncFiles::AsyncFileMan MockAsyncFileManager(); // The default behavior of the methods that would enqueue an action is to enqueue a mock action. MOCK_METHOD(CancelFunction, createAnonymousFile, - (absl::string_view path, - std::function)> on_complete)); + (Event::Dispatcher * dispatcher, absl::string_view path, + absl::AnyInvocable)> on_complete)); MOCK_METHOD(CancelFunction, openExistingFile, - (absl::string_view filename, Mode mode, - std::function)> on_complete)); + (Event::Dispatcher * dispatcher, absl::string_view filename, Mode mode, + absl::AnyInvocable)> on_complete)); MOCK_METHOD(CancelFunction, stat, - (absl::string_view filename, - std::function)> on_complete)); + (Event::Dispatcher * dispatcher, absl::string_view filename, + absl::AnyInvocable)> on_complete)); MOCK_METHOD(CancelFunction, unlink, - (absl::string_view filename, std::function on_complete)); + (Event::Dispatcher * dispatcher, absl::string_view filename, + absl::AnyInvocable on_complete)); MOCK_METHOD(std::string, describe, (), (const)); + MOCK_METHOD(void, waitForIdle, ()); + MOCK_METHOD(void, postCancelledActionForCleanup, (std::unique_ptr action)); // mockCancel is called any time any action queued by mock is cancelled. It isn't overriding // a function from the real class, it's just used for verification. @@ -83,19 +95,29 @@ class MockAsyncFileManager : public Extensions::Common::AsyncFiles::AsyncFileMan // not just a Status or a T. template void nextActionCompletes(T result) { ASSERT_FALSE(queue_.empty()); + auto entry = std::move(queue_.front()); + queue_.pop(); auto action = - std::dynamic_pointer_cast>>(queue_.front()); - ASSERT_TRUE(action.get() != nullptr) - << "mismatched type for nextActionCompletes: action is " << queue_.front()->describe() + dynamic_cast>*>(entry.action_.get()); + ASSERT_TRUE(action != nullptr) + << "mismatched type for nextActionCompletes: action is " << action->describe() << ", nextActionCompletes was given " << typeid(T).name(); - queue_.pop_front(); - action->on_complete_(std::move(result)); + if (entry.dispatcher_) { + entry.dispatcher_->post([action = std::move(entry.action_), state = std::move(entry.state_), + result = std::move(result)]() mutable { + if (state->load() != QueuedAction::State::Cancelled) { + dynamic_cast>*>(action.get()) + ->on_complete_(std::move(result)); + } + }); + } } - std::deque> queue_; + std::queue queue_; private: - MOCK_METHOD(CancelFunction, enqueue, (const std::shared_ptr action)); + MOCK_METHOD(CancelFunction, enqueue, + (Event::Dispatcher * dispatcher, std::unique_ptr action)); friend class MockAsyncFileContext; }; @@ -107,15 +129,16 @@ class MockAsyncFileManagerFactory : public Extensions::Common::AsyncFiles::Async }; // Add deduction guides for comping with the ctad-maybe-unsupported warning -TypedMockAsyncFileAction(std::function) - ->TypedMockAsyncFileAction>; -TypedMockAsyncFileAction(std::function)>) - ->TypedMockAsyncFileAction)>>; -TypedMockAsyncFileAction(std::function)>) - ->TypedMockAsyncFileAction)>>; -TypedMockAsyncFileAction(std::function>)>) +TypedMockAsyncFileAction(absl::AnyInvocable) + ->TypedMockAsyncFileAction>; +TypedMockAsyncFileAction(absl::AnyInvocable)>) + ->TypedMockAsyncFileAction)>>; +TypedMockAsyncFileAction(absl::AnyInvocable)>) + ->TypedMockAsyncFileAction)>>; +TypedMockAsyncFileAction( + absl::AnyInvocable>)>) ->TypedMockAsyncFileAction< - std::function>)>>; + absl::AnyInvocable>)>>; } // namespace AsyncFiles } // namespace Common diff --git a/test/extensions/filters/http/cache/http_cache_implementation_test_common.cc b/test/extensions/filters/http/cache/http_cache_implementation_test_common.cc index e1db6c9d44..c5df0fa728 100644 --- a/test/extensions/filters/http/cache/http_cache_implementation_test_common.cc +++ b/test/extensions/filters/http/cache/http_cache_implementation_test_common.cc @@ -40,6 +40,17 @@ MATCHER(IsOk, "") { return arg.ok(); } } // namespace +void HttpCacheTestDelegate::pumpDispatcher() { + // There may be multiple steps in a cache operation going back and forth with work + // on a cache's thread and work on the filter's thread. So drain both things up to + // 10 times each. This number is arbitrary and could be increased if necessary for + // a cache implementation. + for (int i = 0; i < 10; i++) { + beforePumpingDispatcher(); + dispatcher().run(Event::Dispatcher::RunType::Block); + } +} + HttpCacheImplementationTest::HttpCacheImplementationTest() : delegate_(GetParam()()), vary_allow_list_(getConfig().allowed_vary_headers(), factory_context_) { @@ -47,11 +58,9 @@ HttpCacheImplementationTest::HttpCacheImplementationTest() request_headers_.setHost("example.com"); request_headers_.setScheme("https"); request_headers_.setCopy(Http::CustomHeaders::get().CacheControl, "max-age=3600"); - - EXPECT_CALL(dispatcher_, post(_)).Times(AnyNumber()); - EXPECT_CALL(dispatcher_, isThreadSafe()).Times(AnyNumber()); - - delegate_->setUp(dispatcher_); + ON_CALL(encoder_callbacks_, dispatcher()).WillByDefault(testing::ReturnRef(dispatcher())); + ON_CALL(decoder_callbacks_, dispatcher()).WillByDefault(testing::ReturnRef(dispatcher())); + delegate_->setUp(); } HttpCacheImplementationTest::~HttpCacheImplementationTest() { @@ -64,155 +73,134 @@ bool HttpCacheImplementationTest::updateHeaders( absl::string_view request_path, const Http::TestResponseHeaderMapImpl& response_headers, const ResponseMetadata& metadata) { LookupContextPtr lookup_context = lookup(request_path); - auto update_promise = std::make_shared>(); + bool captured_result = false; + bool seen_result = false; cache()->updateHeaders(*lookup_context, response_headers, metadata, - [update_promise](bool result) { update_promise->set_value(result); }); - auto update_future = update_promise->get_future(); - if (std::future_status::ready != update_future.wait_for(std::chrono::seconds(5))) { - EXPECT_TRUE(false) << "timed out in updateHeaders " << request_path; - return false; - } - return update_future.get(); + [&captured_result, &seen_result](bool result) { + captured_result = result; + seen_result = true; + }); + pumpDispatcher(); + EXPECT_TRUE(seen_result); + return captured_result; } LookupContextPtr HttpCacheImplementationTest::lookup(absl::string_view request_path) { LookupRequest request = makeLookupRequest(request_path); LookupContextPtr context = cache()->makeLookupContext(std::move(request), decoder_callbacks_); - auto headers_promise = std::make_shared>>(); - context->getHeaders([headers_promise](LookupResult&& result, bool end_stream) { - headers_promise->set_value(std::make_pair(std::move(result), end_stream)); + bool seen_result = false; + context->getHeaders([this, &seen_result](LookupResult&& result, bool end_stream) { + lookup_result_ = std::move(result); + lookup_end_stream_after_headers_ = end_stream; + seen_result = true; }); - auto headers_future = headers_promise->get_future(); - if (std::future_status::ready == headers_future.wait_for(std::chrono::seconds(5))) { - auto result_pair = headers_future.get(); - lookup_result_ = std::move(result_pair.first); - lookup_end_stream_after_headers_ = result_pair.second; - } else { - EXPECT_TRUE(false) << "timed out in lookup " << request_path; - } - + pumpDispatcher(); + EXPECT_TRUE(seen_result); return context; } absl::Status HttpCacheImplementationTest::insert(LookupContextPtr lookup, const Http::TestResponseHeaderMapImpl& headers, - const absl::string_view body, - std::chrono::milliseconds timeout) { - return insert(std::move(lookup), headers, body, absl::nullopt, timeout); + const absl::string_view body) { + return insert(std::move(lookup), headers, body, absl::nullopt); } absl::Status HttpCacheImplementationTest::insert( LookupContextPtr lookup, const Http::TestResponseHeaderMapImpl& headers, - const absl::string_view body, const absl::optional trailers, - std::chrono::milliseconds timeout) { + const absl::string_view body, const absl::optional trailers) { // For responses with body, we must wait for insertBody's callback before // calling insertTrailers or completing. Note, in a multipart body test this // would need to check for the callback having been called for *every* body part, // but since the test only uses single-part bodies, inserting trailers or // completing in direct response to the callback works. - std::shared_ptr> insert_promise; - auto make_insert_callback = [&insert_promise]() { - insert_promise = std::make_shared>(); - return [insert_promise](bool success_ready_for_more) { - insert_promise->set_value(success_ready_for_more); - }; - }; - auto wait_for_insert = [&insert_promise, timeout](absl::string_view fn) { - auto future = insert_promise->get_future(); - auto result = future.wait_for(timeout); - if (result == std::future_status::timeout) { - return absl::DeadlineExceededError(absl::StrCat("Timed out waiting for ", fn)); - } - if (!future.get()) { - return absl::UnknownError(absl::StrCat("Insert was aborted by cache in ", fn)); - } - return absl::OkStatus(); - }; - + bool inserted_headers = false; + bool inserted_body = false; + bool inserted_trailers = false; InsertContextPtr inserter = cache()->makeInsertContext(std::move(lookup), encoder_callbacks_); absl::Cleanup destroy_inserter{[&inserter] { inserter->onDestroy(); }}; const ResponseMetadata metadata{time_system_.systemTime()}; bool headers_end_stream = body.empty() && !trailers.has_value(); - inserter->insertHeaders(headers, metadata, make_insert_callback(), headers_end_stream); - auto status = wait_for_insert("insertHeaders()"); - if (!status.ok()) { - return status; + inserter->insertHeaders( + headers, metadata, [&inserted_headers](bool result) { inserted_headers = result; }, + headers_end_stream); + pumpDispatcher(); + if (!inserted_headers) { + return absl::InternalError("headers were not inserted"); } if (headers_end_stream) { return absl::OkStatus(); } if (!body.empty()) { - inserter->insertBody(Buffer::OwnedImpl(body), make_insert_callback(), - /*end_stream=*/!trailers.has_value()); - auto status = wait_for_insert("insertBody()"); - if (!status.ok()) { - return status; + inserter->insertBody( + Buffer::OwnedImpl(body), [&inserted_body](bool result) { inserted_body = result; }, + /*end_stream=*/!trailers.has_value()); + pumpDispatcher(); + if (!inserted_body) { + return absl::InternalError("body was not inserted"); } } - - if (trailers.has_value()) { - inserter->insertTrailers(trailers.value(), make_insert_callback()); - auto status = wait_for_insert("insertTrailers()"); - if (!status.ok()) { - return status; - } + if (!trailers.has_value()) { + return absl::OkStatus(); + } + inserter->insertTrailers(trailers.value(), + [&inserted_trailers](bool result) { inserted_trailers = result; }); + pumpDispatcher(); + if (!inserted_trailers) { + return absl::InternalError("trailers were not inserted"); } return absl::OkStatus(); } absl::Status HttpCacheImplementationTest::insert(absl::string_view request_path, const Http::TestResponseHeaderMapImpl& headers, - const absl::string_view body, - std::chrono::milliseconds timeout) { - return insert(lookup(request_path), headers, body, timeout); + const absl::string_view body) { + return insert(lookup(request_path), headers, body); } std::pair HttpCacheImplementationTest::getHeaders(LookupContext& context) { - Http::ResponseHeaderMapPtr response_headers_ptr; - auto headers_promise = - std::make_shared>>(); - context.getHeaders([headers_promise](LookupResult&& lookup_result, bool end_stream) { + std::pair returned_pair; + bool seen_result = false; + context.getHeaders([&returned_pair, &seen_result](LookupResult&& lookup_result, bool end_stream) { EXPECT_NE(lookup_result.cache_entry_status_, CacheEntryStatus::Unusable); EXPECT_NE(lookup_result.headers_, nullptr); - headers_promise->set_value(std::make_pair(std::move(lookup_result.headers_), end_stream)); + returned_pair.first = std::move(lookup_result.headers_); + returned_pair.second = end_stream; + seen_result = true; }); - auto future = headers_promise->get_future(); - EXPECT_EQ(std::future_status::ready, future.wait_for(std::chrono::seconds(5))); - return future.get(); + pumpDispatcher(); + EXPECT_TRUE(seen_result); + return returned_pair; } std::pair HttpCacheImplementationTest::getBody(LookupContext& context, uint64_t start, uint64_t end) { AdjustedByteRange range(start, end); - auto body_promise = std::make_shared>>(); - context.getBody(range, [body_promise](Buffer::InstancePtr&& data, bool end_stream) { - EXPECT_NE(data, nullptr); - body_promise->set_value(data ? std::make_pair(data->toString(), end_stream) - : std::make_pair("", end_stream)); - }); - auto future = body_promise->get_future(); - EXPECT_EQ(std::future_status::ready, future.wait_for(std::chrono::seconds(5))); - return future.get(); + std::pair returned_pair; + bool seen_result = false; + context.getBody(range, + [&returned_pair, &seen_result](Buffer::InstancePtr&& data, bool end_stream) { + EXPECT_NE(data, nullptr); + returned_pair = std::make_pair(data->toString(), end_stream); + seen_result = true; + }); + pumpDispatcher(); + EXPECT_TRUE(seen_result); + return returned_pair; } Http::TestResponseTrailerMapImpl HttpCacheImplementationTest::getTrailers(LookupContext& context) { - auto trailers_promise = - std::make_shared>>(); - context.getTrailers([trailers_promise](Http::ResponseTrailerMapPtr&& data) { + Http::ResponseTrailerMapPtr trailers; + context.getTrailers([&trailers](Http::ResponseTrailerMapPtr&& data) { if (data) { - trailers_promise->set_value(std::move(data)); + trailers = std::move(data); } }); - auto future = trailers_promise->get_future(); - EXPECT_EQ(std::future_status::ready, future.wait_for(std::chrono::seconds(5))); - Http::TestResponseTrailerMapImpl trailers; - if (std::future_status::ready == future.wait_for(std::chrono::seconds(5))) { - trailers = *future.get(); - } - return trailers; + pumpDispatcher(); + EXPECT_THAT(trailers, testing::NotNull()); + return *trailers; } LookupRequest HttpCacheImplementationTest::makeLookupRequest(absl::string_view request_path) { @@ -423,30 +411,23 @@ TEST_P(HttpCacheImplementationTest, StreamingPut) { InsertContextPtr inserter = cache()->makeInsertContext(lookup(request_path), encoder_callbacks_); absl::Cleanup destroy_inserter{[&inserter] { inserter->onDestroy(); }}; ResponseMetadata metadata{time_system_.systemTime()}; - std::promise insert_headers_promise; - std::promise insert_body1_promise; - std::promise insert_body2_promise; + bool inserted_headers = false; + bool inserted_body1 = false; + bool inserted_body2 = false; inserter->insertHeaders( - response_headers, metadata, - [&insert_headers_promise](bool ready) { insert_headers_promise.set_value(ready); }, false); - auto insert_future = insert_headers_promise.get_future(); - ASSERT_EQ(std::future_status::ready, insert_future.wait_for(std::chrono::seconds(5))) - << "timed out waiting for inserts to complete"; - ASSERT_TRUE(insert_future.get()); + response_headers, metadata, [&inserted_headers](bool ready) { inserted_headers = ready; }, + false); + pumpDispatcher(); + ASSERT_TRUE(inserted_headers); inserter->insertBody( - Buffer::OwnedImpl("Hello, "), - [&insert_body1_promise](bool ready) { insert_body1_promise.set_value(ready); }, false); - insert_future = insert_body1_promise.get_future(); - ASSERT_EQ(std::future_status::ready, insert_future.wait_for(std::chrono::seconds(5))) - << "timed out waiting for inserts to complete"; - ASSERT_TRUE(insert_future.get()); + Buffer::OwnedImpl("Hello, "), [&inserted_body1](bool ready) { inserted_body1 = ready; }, + false); + pumpDispatcher(); + ASSERT_TRUE(inserted_body1); inserter->insertBody( - Buffer::OwnedImpl("World!"), - [&insert_body2_promise](bool ready) { insert_body2_promise.set_value(ready); }, true); - insert_future = insert_body2_promise.get_future(); - ASSERT_EQ(std::future_status::ready, insert_future.wait_for(std::chrono::seconds(5))) - << "timed out waiting for inserts to complete"; - ASSERT_TRUE(insert_future.get()); + Buffer::OwnedImpl("World!"), [&inserted_body2](bool ready) { inserted_body2 = ready; }, true); + pumpDispatcher(); + ASSERT_TRUE(inserted_body2); LookupContextPtr name_lookup = lookup(request_path); ASSERT_EQ(CacheEntryStatus::Ok, lookup_result_.cache_entry_status_); diff --git a/test/extensions/filters/http/cache/http_cache_implementation_test_common.h b/test/extensions/filters/http/cache/http_cache_implementation_test_common.h index d172f95fab..497bfcad81 100644 --- a/test/extensions/filters/http/cache/http_cache_implementation_test_common.h +++ b/test/extensions/filters/http/cache/http_cache_implementation_test_common.h @@ -28,8 +28,9 @@ class HttpCacheTestDelegate { public: virtual ~HttpCacheTestDelegate() = default; - virtual void setUp(Event::MockDispatcher& dispatcher) { dispatcher_ = &dispatcher; } + virtual void setUp() {} virtual void tearDown() {} + virtual std::shared_ptr cache() = 0; // Specifies whether or not the cache supports validating stale cache entries @@ -38,14 +39,21 @@ class HttpCacheTestDelegate { // RequiresValidation. virtual bool validationEnabled() const = 0; - Event::MockDispatcher& dispatcher() { return *dispatcher_; } + // May be overridden to, for example, also drain other threads into the dispatcher + // before draining the dispatcher. + virtual void beforePumpingDispatcher(){}; + void pumpDispatcher(); + + Event::Dispatcher& dispatcher() { return *dispatcher_; } private: - Event::MockDispatcher* dispatcher_ = nullptr; + Api::ApiPtr api_ = Api::createApiForTest(); + Event::DispatcherPtr dispatcher_ = api_->allocateDispatcher("test_thread"); }; class HttpCacheImplementationTest - : public testing::TestWithParam()>> { + : public Event::TestUsingSimulatedTime, + public testing::TestWithParam()>> { public: static constexpr absl::Duration kLastValidUpdateMinInterval = absl::Seconds(10); @@ -55,21 +63,19 @@ class HttpCacheImplementationTest std::shared_ptr cache() const { return delegate_->cache(); } bool validationEnabled() const { return delegate_->validationEnabled(); } + void pumpDispatcher() { delegate_->pumpDispatcher(); } LookupContextPtr lookup(absl::string_view request_path); absl::Status insert(LookupContextPtr lookup, const Http::TestResponseHeaderMapImpl& headers, - const absl::string_view body, - std::chrono::milliseconds timeout = std::chrono::seconds(1)); + const absl::string_view body); virtual absl::Status insert(LookupContextPtr lookup, const Http::TestResponseHeaderMapImpl& headers, const absl::string_view body, - const absl::optional trailers, - std::chrono::milliseconds timeout = std::chrono::seconds(1)); + const absl::optional trailers); absl::Status insert(absl::string_view request_path, - const Http::TestResponseHeaderMapImpl& headers, const absl::string_view body, - std::chrono::milliseconds timeout = std::chrono::seconds(1)); + const Http::TestResponseHeaderMapImpl& headers, const absl::string_view body); // Returns the headers and a bool for end_stream. std::pair getHeaders(LookupContext& context); @@ -99,7 +105,7 @@ class HttpCacheImplementationTest bool lookup_end_stream_after_headers_; Http::TestRequestHeaderMapImpl request_headers_; Event::SimulatedTimeSystem time_system_; - Event::MockDispatcher dispatcher_; + Event::Dispatcher& dispatcher() { return delegate_->dispatcher(); } DateFormatter formatter_{"%a, %d %b %Y %H:%M:%S GMT"}; NiceMock decoder_callbacks_; NiceMock encoder_callbacks_; diff --git a/test/extensions/filters/http/file_system_buffer/filter_test.cc b/test/extensions/filters/http/file_system_buffer/filter_test.cc index 78541b92b3..cf3bd20171 100644 --- a/test/extensions/filters/http/file_system_buffer/filter_test.cc +++ b/test/extensions/filters/http/file_system_buffer/filter_test.cc @@ -23,6 +23,7 @@ using Extensions::Common::AsyncFiles::MockAsyncFileManager; using Extensions::Common::AsyncFiles::MockAsyncFileManagerFactory; using ::testing::NiceMock; using ::testing::Return; +using ::testing::ReturnRef; class FileSystemBufferFilterTest : public testing::Test { public: @@ -42,8 +43,9 @@ class FileSystemBufferFilterTest : public testing::Test { protected: void expectAsyncFileCreated() { - EXPECT_CALL(*mock_async_file_manager_, createAnonymousFile(_, _)); + EXPECT_CALL(*mock_async_file_manager_, createAnonymousFile(_, _, _)); } + void pumpDispatcher() { dispatcher_->run(Event::Dispatcher::RunType::Block); } // A file is only opened by the filter if it's going to chain a write immediately afterwards, // so we combine completing the open and expecting the write, which allows for simplified control // of the handle. @@ -56,13 +58,13 @@ class FileSystemBufferFilterTest : public testing::Test { } void expectWriteWithPosition(MockAsyncFileHandle handle, absl::string_view content, off_t offset) { - EXPECT_CALL(*handle, write(BufferStringEqual(std::string(content)), offset, _)); + EXPECT_CALL(*handle, write(_, BufferStringEqual(std::string(content)), offset, _)); } void completeWriteOfSize(size_t length) { mock_async_file_manager_->nextActionCompletes(absl::StatusOr{length}); } void expectRead(MockAsyncFileHandle handle, off_t offset, size_t size) { - EXPECT_CALL(*handle, read(offset, size, _)); + EXPECT_CALL(*handle, read(_, offset, size, _)); } void completeRead(absl::string_view content) { mock_async_file_manager_->nextActionCompletes(absl::StatusOr>{ @@ -86,6 +88,10 @@ class FileSystemBufferFilterTest : public testing::Test { proto_config); } + void useDeferredDispatcher() { + EXPECT_CALL(decoder_callbacks_, dispatcher()).WillRepeatedly(ReturnRef(*dispatcher_)); + } + void createFilterFromYaml(absl::string_view yaml) { auto config = configFromYaml(yaml); filter_ = std::make_shared(config); @@ -105,14 +111,6 @@ class FileSystemBufferFilterTest : public testing::Test { ASSERT_FALSE(continued_encoding_); continued_encoding_ = true; }); - // Using EXPECT_CALL rather than ON_CALL because this one was set up in Envoy code and - // isn't a NiceMock. Using EXPECT reduces log noise. - // For simplicity's sake the dispatcher just runs the function immediately - // - since the mock is capturing callbacks, we're effectively triggering - // the dispatcher when we resolve the callback. - EXPECT_CALL(decoder_callbacks_.dispatcher_, post(_)).WillRepeatedly([](Event::PostCb fn) { - fn(); - }); filter_->setDecoderFilterCallbacks(decoder_callbacks_); filter_->setEncoderFilterCallbacks(encoder_callbacks_); EXPECT_CALL(decoder_callbacks_, onDecoderFilterAboveWriteBufferHighWatermark()) @@ -154,6 +152,8 @@ class FileSystemBufferFilterTest : public testing::Test { bool continued_encoding_ = false; int request_source_watermark_ = 0; int response_source_watermark_ = 0; + Api::ApiPtr api_ = Api::createApiForTest(); + Event::DispatcherPtr dispatcher_ = api_->allocateDispatcher("test_thread"); LogLevelSetter log_level_setter_ = LogLevelSetter(ENVOY_SPDLOG_LEVEL(debug)); }; @@ -738,26 +738,23 @@ TEST_F(FileSystemBufferFilterTest, FilterDestroyedWhileFileActionIsInDispatcherI behavior: fully_buffer: {} )"); + useDeferredDispatcher(); EXPECT_EQ(Http::FilterHeadersStatus::StopIteration, filter_->decodeHeaders(request_headers_, false)); + pumpDispatcher(); expectAsyncFileCreated(); Buffer::OwnedImpl request_body{"12345678901234567890"}; EXPECT_EQ(Http::FilterDataStatus::StopIterationNoBuffer, filter_->decodeData(request_body, false)); + pumpDispatcher(); completeCreateFileAndExpectWrite("1234567890"); - Event::PostCb intercepted_dispatcher_callback; - // Our default mock dispatcher behavior calls the callback immediately - here we intercept - // one so we can call it after a 'realistic' delay during which something else happened to - // destroy the filter. - EXPECT_CALL(decoder_callbacks_.dispatcher_, post(_)) - .WillOnce([&intercepted_dispatcher_callback](Event::PostCb fn) { - intercepted_dispatcher_callback = std::move(fn); - }); + pumpDispatcher(); + // Action completes in file system manager. Don't consume the dispatched callback yet. completeWriteOfSize(10); + // Action is cancelled before callback; async file manager prevents the callback after this. + EXPECT_CALL(*mock_async_file_manager_, mockCancel()); destroyFilter(); - // Callback called from dispatcher after filter was destroyed and its pointer invalidated, - // should not cause a crash. - intercepted_dispatcher_callback(); + pumpDispatcher(); } TEST_F(FileSystemBufferFilterTest, MergesRouteConfig) { diff --git a/test/extensions/filters/http/file_system_buffer/fragment_test.cc b/test/extensions/filters/http/file_system_buffer/fragment_test.cc index 662173729c..59e1644fca 100644 --- a/test/extensions/filters/http/file_system_buffer/fragment_test.cc +++ b/test/extensions/filters/http/file_system_buffer/fragment_test.cc @@ -22,33 +22,33 @@ using StatusHelpers::HasStatusMessage; using ::testing::_; using ::testing::Eq; using ::testing::HasSubstr; +using ::testing::MockFunction; using ::testing::StrictMock; -std::function storageSuccessCallback() { - return [](absl::Status status) { ASSERT_OK(status); }; -} - -template -std::function storageFailureCallback(MatcherT matcher) { - return [matcher](absl::Status status) { EXPECT_THAT(status, matcher); }; -} - -void dispatchImmediately(std::function callback) { callback(); } - class FileSystemBufferFilterFragmentTest : public ::testing::Test { public: + void resolveFileActions() { dispatcher_->run(Event::Dispatcher::RunType::Block); } + protected: MockAsyncFileHandle handle_ = std::make_shared>(); void moveFragmentToStorage(Fragment* frag) { - EXPECT_CALL(*handle_, write(_, _, _)) - .WillOnce( - [frag](Buffer::Instance&, off_t, std::function)> callback) { - callback(frag->size()); - return []() {}; - }); - EXPECT_OK(frag->toStorage(handle_, 123, &dispatchImmediately, storageSuccessCallback())); + EXPECT_CALL(*handle_, write(_, _, _, _)) + .WillOnce([frag](Event::Dispatcher* dispatcher, Buffer::Instance&, off_t, + absl::AnyInvocable)> callback) { + dispatcher->post([frag, callback = std::move(callback)]() mutable { + std::move(callback)(frag->size()); + }); + return []() {}; + }); + MockFunction callback; + EXPECT_OK(frag->toStorage(handle_, 123, *dispatcher_, callback.AsStdFunction())); + EXPECT_CALL(callback, Call(absl::OkStatus())); + resolveFileActions(); } + + Api::ApiPtr api_ = Api::createApiForTest(); + Event::DispatcherPtr dispatcher_ = api_->allocateDispatcher("test_thread"); }; TEST_F(FileSystemBufferFilterFragmentTest, CreatesAndExtractsWithoutCopying) { @@ -77,39 +77,42 @@ TEST_F(FileSystemBufferFilterFragmentTest, CreatesFragmentFromPartialBufferAndCo TEST_F(FileSystemBufferFilterFragmentTest, WritesAndReadsBack) { Buffer::OwnedImpl input("hello"); Fragment frag(input); - std::function)> captured_write_callback; - EXPECT_CALL(*handle_, write(BufferStringEqual("hello"), 123, _)) - .WillOnce([&captured_write_callback](Buffer::Instance&, off_t, - std::function)> callback) { - captured_write_callback = std::move(callback); + EXPECT_CALL(*handle_, write(_, BufferStringEqual("hello"), 123, _)) + .WillOnce([](Event::Dispatcher* dispatcher, Buffer::Instance&, off_t, + absl::AnyInvocable)> callback) { + dispatcher->post([callback = std::move(callback)]() mutable { std::move(callback)(5); }); return []() {}; }); // Request the fragment be moved to storage. - EXPECT_OK(frag.toStorage(handle_, 123, &dispatchImmediately, storageSuccessCallback())); + MockFunction write_callback; + EXPECT_OK(frag.toStorage(handle_, 123, *dispatcher_, write_callback.AsStdFunction())); // Before the file confirms written, the state should be neither in memory nor in storage. EXPECT_FALSE(frag.isMemory()); EXPECT_FALSE(frag.isStorage()); // Fake the file thread confirming 5 bytes were written. - captured_write_callback(5); + EXPECT_CALL(write_callback, Call(absl::OkStatus())); + resolveFileActions(); // Now the fragment should be tagged as being in storage. EXPECT_TRUE(frag.isStorage()); EXPECT_FALSE(frag.isMemory()); - std::function>)> captured_read_callback; - EXPECT_CALL(*handle_, read(123, 5, _)) + EXPECT_CALL(*handle_, read(_, 123, 5, _)) .WillOnce( - [&captured_read_callback]( - off_t, size_t, - std::function>)> callback) { - captured_read_callback = std::move(callback); + [](Event::Dispatcher* dispatcher, off_t, size_t, + absl::AnyInvocable>)> callback) { + dispatcher->post([callback = std::move(callback)]() mutable { + std::move(callback)(std::make_unique("hello")); + }); return []() {}; }); // Request the fragment be moved from storage. - EXPECT_OK(frag.fromStorage(handle_, &dispatchImmediately, storageSuccessCallback())); + MockFunction read_callback; + EXPECT_OK(frag.fromStorage(handle_, *dispatcher_, read_callback.AsStdFunction())); // Before the file confirms read, the state should be neither in memory nor storage. EXPECT_FALSE(frag.isMemory()); EXPECT_FALSE(frag.isStorage()); // Fake the file thread completing read. - captured_read_callback(std::make_unique("hello")); + EXPECT_CALL(read_callback, Call(absl::OkStatus())); + resolveFileActions(); // Now the fragment should be tagged as being in memory. EXPECT_TRUE(frag.isMemory()); EXPECT_FALSE(frag.isStorage()); @@ -121,86 +124,81 @@ TEST_F(FileSystemBufferFilterFragmentTest, WritesAndReadsBack) { TEST_F(FileSystemBufferFilterFragmentTest, ReturnsErrorOnWriteError) { Buffer::OwnedImpl input("hello"); Fragment frag(input); - auto write_error = absl::UnknownError("write error"); - std::function)> captured_write_callback; - EXPECT_CALL(*handle_, write(BufferStringEqual("hello"), 123, _)) - .WillOnce([&captured_write_callback](Buffer::Instance&, off_t, - std::function)> callback) { - captured_write_callback = std::move(callback); + EXPECT_CALL(*handle_, write(_, BufferStringEqual("hello"), 123, _)) + .WillOnce([](Event::Dispatcher* dispatcher, Buffer::Instance&, off_t, + absl::AnyInvocable)> callback) { + dispatcher->post([callback = std::move(callback)]() mutable { + std::move(callback)(absl::UnknownError("write error")); + }); return []() {}; }); // Request the fragment be moved to storage. - EXPECT_OK( - frag.toStorage(handle_, 123, &dispatchImmediately, storageFailureCallback(Eq(write_error)))); - - // Fake file system declares a write error. This should - // provoke the expected error in the callback above. - captured_write_callback(write_error); + MockFunction callback; + EXPECT_OK(frag.toStorage(handle_, 123, *dispatcher_, callback.AsStdFunction())); + EXPECT_CALL(callback, Call(Eq(absl::UnknownError("write error")))); + resolveFileActions(); } TEST_F(FileSystemBufferFilterFragmentTest, ReturnsErrorOnWriteIncomplete) { Buffer::OwnedImpl input("hello"); Fragment frag(input); - std::function)> captured_write_callback; - EXPECT_CALL(*handle_, write(BufferStringEqual("hello"), 123, _)) - .WillOnce([&captured_write_callback](Buffer::Instance&, off_t, - std::function)> callback) { - captured_write_callback = std::move(callback); + EXPECT_CALL(*handle_, write(_, BufferStringEqual("hello"), 123, _)) + .WillOnce([](Event::Dispatcher* dispatcher, Buffer::Instance&, off_t, + absl::AnyInvocable)> callback) { + dispatcher->post([callback = std::move(callback)]() mutable { std::move(callback)(2); }); return []() {}; }); // Request the fragment be moved to storage. - EXPECT_OK(frag.toStorage( - handle_, 123, &dispatchImmediately, - storageFailureCallback(HasStatusMessage(HasSubstr("wrote 2 bytes, wanted 5"))))); - + MockFunction callback; + EXPECT_OK(frag.toStorage(handle_, 123, *dispatcher_, callback.AsStdFunction())); // Fake file says it wrote 2 bytes when the fragment was of size 5 - this should // provoke the expected error in the callback above. - captured_write_callback(2); + EXPECT_CALL(callback, Call(HasStatusMessage(HasSubstr("wrote 2 bytes, wanted 5")))); + resolveFileActions(); } TEST_F(FileSystemBufferFilterFragmentTest, ReturnsErrorOnReadError) { Buffer::OwnedImpl input("hello"); Fragment frag(input); moveFragmentToStorage(&frag); - auto read_error = absl::UnknownError("read error"); - std::function>)> captured_read_callback; - EXPECT_CALL(*handle_, read(123, 5, _)) + EXPECT_CALL(*handle_, read(_, 123, 5, _)) .WillOnce( - [&captured_read_callback]( - off_t, size_t, - std::function>)> callback) { - captured_read_callback = std::move(callback); + [](Event::Dispatcher* dispatcher, off_t, size_t, + absl::AnyInvocable>)> callback) { + dispatcher->post([callback = std::move(callback)]() mutable { + std::move(callback)(absl::UnknownError("read error")); + }); return []() {}; }); // Request the fragment be moved from storage. - EXPECT_OK( - frag.fromStorage(handle_, &dispatchImmediately, storageFailureCallback(Eq(read_error)))); - // Fake file system declares a read error. This should - // provoke the expected error in the callback above. - captured_read_callback(read_error); + MockFunction callback; + EXPECT_OK(frag.fromStorage(handle_, *dispatcher_, callback.AsStdFunction())); + EXPECT_CALL(callback, Call(Eq(absl::UnknownError("read error")))); + resolveFileActions(); } TEST_F(FileSystemBufferFilterFragmentTest, ReturnsErrorOnReadIncomplete) { Buffer::OwnedImpl input("hello"); Fragment frag(input); moveFragmentToStorage(&frag); - std::function>)> captured_read_callback; - EXPECT_CALL(*handle_, read(123, 5, _)) + absl::AnyInvocable>)> + captured_read_callback; + EXPECT_CALL(*handle_, read(_, 123, 5, _)) .WillOnce( - [&captured_read_callback]( - off_t, size_t, - std::function>)> callback) { - captured_read_callback = std::move(callback); + [](Event::Dispatcher* dispatcher, off_t, size_t, + absl::AnyInvocable>)> callback) { + dispatcher->post([callback = std::move(callback)]() mutable { + std::move(callback)(std::make_unique("he")); + }); return []() {}; }); + MockFunction callback; // Request the fragment be moved from storage. - EXPECT_OK(frag.fromStorage( - handle_, &dispatchImmediately, - storageFailureCallback(HasStatusMessage(HasSubstr("read got 2 bytes, wanted 5"))))); - - // Fake file system declares a read error. This should + EXPECT_OK(frag.fromStorage(handle_, *dispatcher_, callback.AsStdFunction())); + // Mock file system declares a read error. This should // provoke the expected error in the callback above. - captured_read_callback(std::make_unique("he")); + EXPECT_CALL(callback, Call(HasStatusMessage(HasSubstr("read got 2 bytes, wanted 5")))); + resolveFileActions(); } } // namespace FileSystemBuffer diff --git a/test/extensions/http/cache/file_system_http_cache/file_system_http_cache_test.cc b/test/extensions/http/cache/file_system_http_cache/file_system_http_cache_test.cc index 208163fb91..29c87ea43a 100644 --- a/test/extensions/http/cache/file_system_http_cache/file_system_http_cache_test.cc +++ b/test/extensions/http/cache/file_system_http_cache/file_system_http_cache_test.cc @@ -335,6 +335,8 @@ class FileSystemHttpCacheTestWithMockFiles : public FileSystemHttpCacheTest { return ret; } + void pumpDispatcher() { dispatcher_->run(Event::Dispatcher::RunType::Block); } + protected: ::testing::NiceMock mock_singleton_manager_; std::shared_ptr mock_async_file_manager_factory_ = @@ -364,6 +366,8 @@ class FileSystemHttpCacheTestWithMockFiles : public FileSystemHttpCacheTest { std::function expect_true_callback_; size_t headers_size_; size_t trailers_size_; + Api::ApiPtr api_ = Api::createApiForTest(); + Event::DispatcherPtr dispatcher_ = api_->allocateDispatcher("test_thread"); }; TEST_F(FileSystemHttpCacheTestWithMockFiles, WriteVaryNodeFailingToCreateFileJustAborts) { @@ -375,19 +379,21 @@ TEST_F(FileSystemHttpCacheTestWithMockFiles, WriteVaryNodeFailingToCreateFileJus {"cache-control", "public,max-age=3600"}, {"vary", "accept"}}; // one file created for the vary node, one for the actual write. - EXPECT_CALL(*mock_async_file_manager_, createAnonymousFile(_, _)).Times(2); + EXPECT_CALL(*mock_async_file_manager_, createAnonymousFile(_, _, _)).Times(2); inserter->insertHeaders( response_headers, metadata_, [&](bool result) { EXPECT_FALSE(result); }, true); // File handle for the vary node. // (This is the failure under test, we expect write to *not* be called.) mock_async_file_manager_->nextActionCompletes( absl::StatusOr{absl::UnknownError("create failure for vary node")}); + pumpDispatcher(); // Fail to create file for the cache entry node. // (This provokes the false callback to insertHeaders.) mock_async_file_manager_->nextActionCompletes( absl::StatusOr{absl::UnknownError("open failure")}); + pumpDispatcher(); // File handle was not used and is expected to be closed. - EXPECT_OK(mock_async_file_handle_->close([](absl::Status) {})); + EXPECT_OK(mock_async_file_handle_->close(nullptr, [](absl::Status) {})); } TEST_F(FileSystemHttpCacheTestWithMockFiles, WriteVaryNodeFailingToWriteJustClosesTheFile) { @@ -399,28 +405,31 @@ TEST_F(FileSystemHttpCacheTestWithMockFiles, WriteVaryNodeFailingToWriteJustClos {"cache-control", "public,max-age=3600"}, {"vary", "accept"}}; // one file created for the vary node, one for the actual write. - EXPECT_CALL(*mock_async_file_manager_, createAnonymousFile(_, _)).Times(2); + EXPECT_CALL(*mock_async_file_manager_, createAnonymousFile(_, _, _)).Times(2); inserter->insertHeaders( response_headers, metadata_, [&](bool result) { EXPECT_FALSE(result); }, true); - EXPECT_CALL(*mock_async_file_handle_, write(_, _, _)); + EXPECT_CALL(*mock_async_file_handle_, write(_, _, _, _)); // File handle for the vary node. // (This triggers the expected write call.) mock_async_file_manager_->nextActionCompletes( absl::StatusOr{mock_async_file_handle_}); + pumpDispatcher(); // Fail to create file for the cache entry node. // (This provokes the false callback to insertHeaders.) mock_async_file_manager_->nextActionCompletes( absl::StatusOr{absl::UnknownError("open failure")}); + pumpDispatcher(); // Fail to write for the vary node. mock_async_file_manager_->nextActionCompletes( absl::StatusOr(absl::UnknownError("write failure"))); + pumpDispatcher(); } TEST_F(FileSystemHttpCacheTestWithMockFiles, LookupDuringAnotherInsertPreventsInserts) { auto inserter = testInserter(); absl::Cleanup destroy_inserter{[&inserter]() { inserter->onDestroy(); }}; // First inserter will try to create a file. - EXPECT_CALL(*mock_async_file_manager_, createAnonymousFile(_, _)); + EXPECT_CALL(*mock_async_file_manager_, createAnonymousFile(_, _, _)); inserter->insertHeaders( response_headers_, metadata_, [&](bool result) { EXPECT_FALSE(result); }, false); @@ -429,12 +438,13 @@ TEST_F(FileSystemHttpCacheTestWithMockFiles, LookupDuringAnotherInsertPreventsIn // Allow the first inserter to complete after the second lookup was made. mock_async_file_manager_->nextActionCompletes( absl::StatusOr{absl::UnknownError("intentionally failed to open file")}); + pumpDispatcher(); inserter2->insertHeaders(response_headers_, metadata_, expect_false_callback_, false); inserter2->insertBody(Buffer::OwnedImpl("boop"), expect_false_callback_, false); inserter2->insertTrailers(response_trailers_, expect_false_callback_); EXPECT_EQ(false_callbacks_called_, 3); // The file handle didn't actually get used in this test, but is expected to be closed. - EXPECT_OK(mock_async_file_handle_->close([](absl::Status) {})); + EXPECT_OK(mock_async_file_handle_->close(nullptr, [](absl::Status) {})); } TEST_F(FileSystemHttpCacheTestWithMockFiles, DuplicateInsertWhileInsertInProgressIsPrevented) { @@ -443,29 +453,31 @@ TEST_F(FileSystemHttpCacheTestWithMockFiles, DuplicateInsertWhileInsertInProgres auto inserter2 = testInserter(); absl::Cleanup destroy_inserter2{[&inserter2]() { inserter2->onDestroy(); }}; // First inserter will try to create a file. - EXPECT_CALL(*mock_async_file_manager_, createAnonymousFile(_, _)); + EXPECT_CALL(*mock_async_file_manager_, createAnonymousFile(_, _, _)); inserter->insertHeaders(response_headers_, metadata_, expect_false_callback_, false); inserter2->insertHeaders(response_headers_, metadata_, expect_false_callback_, false); // Allow the first inserter to complete after the second insert was called. mock_async_file_manager_->nextActionCompletes( absl::StatusOr{absl::UnknownError("intentionally failed to open file")}); + pumpDispatcher(); inserter2->insertBody(Buffer::OwnedImpl("boop"), expect_false_callback_, false); inserter2->insertTrailers(response_trailers_, expect_false_callback_); EXPECT_EQ(false_callbacks_called_, 4); // The file handle didn't actually get used in this test, but is expected to be closed. - EXPECT_OK(mock_async_file_handle_->close([](absl::Status) {})); + EXPECT_OK(mock_async_file_handle_->close(nullptr, [](absl::Status) {})); } TEST_F(FileSystemHttpCacheTestWithMockFiles, FailedOpenForReadReturnsMiss) { auto lookup = testLookupContext(); absl::Cleanup destroy_lookup([&lookup]() { lookup->onDestroy(); }); LookupResult result; - EXPECT_CALL(*mock_async_file_manager_, openExistingFile(_, _, _)); + EXPECT_CALL(*mock_async_file_manager_, openExistingFile(_, _, _, _)); lookup->getHeaders([&](LookupResult&& r, bool /*end_stream*/) { result = std::move(r); }); mock_async_file_manager_->nextActionCompletes( absl::StatusOr(absl::UnknownError("Intentionally failed to open file"))); + pumpDispatcher(); // File handle didn't get used but is expected to be closed. - EXPECT_OK(mock_async_file_handle_->close([](absl::Status) {})); + EXPECT_OK(mock_async_file_handle_->close(nullptr, [](absl::Status) {})); EXPECT_EQ(result.cache_entry_status_, CacheEntryStatus::Unusable); EXPECT_EQ(cache_->stats().cache_miss_.value(), 1); EXPECT_EQ(cache_->stats().cache_hit_.value(), 0); @@ -480,21 +492,25 @@ TEST_F(FileSystemHttpCacheTestWithMockFiles, FailedReadOfHeaderBlockInvalidatesT auto lookup = testLookupContext(); absl::Cleanup destroy_lookup([&lookup]() { lookup->onDestroy(); }); LookupResult result; - EXPECT_CALL(*mock_async_file_manager_, openExistingFile(_, _, _)); - EXPECT_CALL(*mock_async_file_handle_, read(0, CacheFileFixedBlock::size(), _)); + EXPECT_CALL(*mock_async_file_manager_, openExistingFile(_, _, _, _)); + EXPECT_CALL(*mock_async_file_handle_, read(_, 0, CacheFileFixedBlock::size(), _)); lookup->getHeaders([&](LookupResult&& r, bool /*end_stream*/) { result = std::move(r); }); mock_async_file_manager_->nextActionCompletes( absl::StatusOr(mock_async_file_handle_)); - EXPECT_CALL(*mock_async_file_manager_, stat(_, _)); - EXPECT_CALL(*mock_async_file_manager_, unlink(_, _)); + pumpDispatcher(); + EXPECT_CALL(*mock_async_file_manager_, stat(_, _, _)); + EXPECT_CALL(*mock_async_file_manager_, unlink(_, _, _)); mock_async_file_manager_->nextActionCompletes( absl::StatusOr(absl::UnknownError("intentional failure to read"))); + pumpDispatcher(); struct stat stat_result = {}; stat_result.st_size = 12345; // stat mock_async_file_manager_->nextActionCompletes(absl::StatusOr{stat_result}); + pumpDispatcher(); // unlink mock_async_file_manager_->nextActionCompletes(absl::OkStatus()); + pumpDispatcher(); EXPECT_EQ(result.cache_entry_status_, CacheEntryStatus::Unusable); waitForEvictionThreadIdle(); // Should have deducted the size of the file that got deleted. Since we started at 2 * 12345, @@ -519,19 +535,23 @@ TEST_F(FileSystemHttpCacheTestWithMockFiles, ReadWithInvalidHeaderBlockInvalidat auto lookup = testLookupContext(); absl::Cleanup destroy_lookup([&lookup]() { lookup->onDestroy(); }); LookupResult result; - EXPECT_CALL(*mock_async_file_manager_, openExistingFile(_, _, _)); - EXPECT_CALL(*mock_async_file_handle_, read(0, CacheFileFixedBlock::size(), _)); + EXPECT_CALL(*mock_async_file_manager_, openExistingFile(_, _, _, _)); + EXPECT_CALL(*mock_async_file_handle_, read(_, 0, CacheFileFixedBlock::size(), _)); lookup->getHeaders([&](LookupResult&& r, bool /*end_stream*/) { result = std::move(r); }); mock_async_file_manager_->nextActionCompletes( absl::StatusOr(mock_async_file_handle_)); - EXPECT_CALL(*mock_async_file_manager_, stat(_, _)); - EXPECT_CALL(*mock_async_file_manager_, unlink(_, _)); + pumpDispatcher(); + EXPECT_CALL(*mock_async_file_manager_, stat(_, _, _)); + EXPECT_CALL(*mock_async_file_manager_, unlink(_, _, _)); mock_async_file_manager_->nextActionCompletes( absl::StatusOr(invalidHeaderBlock())); + pumpDispatcher(); mock_async_file_manager_->nextActionCompletes(absl::StatusOr{ absl::UnknownError("intentionally failed to stat, for coverage")}); + pumpDispatcher(); mock_async_file_manager_->nextActionCompletes( absl::UnknownError("intentionally failed to unlink, for coverage")); + pumpDispatcher(); EXPECT_EQ(result.cache_entry_status_, CacheEntryStatus::Unusable); } @@ -539,22 +559,27 @@ TEST_F(FileSystemHttpCacheTestWithMockFiles, FailedReadOfHeaderProtoInvalidatesT auto lookup = testLookupContext(); absl::Cleanup destroy_lookup([&lookup]() { lookup->onDestroy(); }); LookupResult result; - EXPECT_CALL(*mock_async_file_manager_, openExistingFile(_, _, _)); - EXPECT_CALL(*mock_async_file_handle_, read(0, CacheFileFixedBlock::size(), _)); - EXPECT_CALL(*mock_async_file_handle_, read(CacheFileFixedBlock::size(), headers_size_, _)); + EXPECT_CALL(*mock_async_file_manager_, openExistingFile(_, _, _, _)); + EXPECT_CALL(*mock_async_file_handle_, read(_, 0, CacheFileFixedBlock::size(), _)); + EXPECT_CALL(*mock_async_file_handle_, read(_, CacheFileFixedBlock::size(), headers_size_, _)); lookup->getHeaders([&](LookupResult&& r, bool /*end_stream*/) { result = std::move(r); }); mock_async_file_manager_->nextActionCompletes( absl::StatusOr(mock_async_file_handle_)); + pumpDispatcher(); mock_async_file_manager_->nextActionCompletes( absl::StatusOr(testHeaderBlock(0))); - EXPECT_CALL(*mock_async_file_manager_, stat(_, _)); - EXPECT_CALL(*mock_async_file_manager_, unlink(_, _)); + pumpDispatcher(); + EXPECT_CALL(*mock_async_file_manager_, stat(_, _, _)); + EXPECT_CALL(*mock_async_file_manager_, unlink(_, _, _)); mock_async_file_manager_->nextActionCompletes( absl::StatusOr(absl::UnknownError("intentional failure to read"))); + pumpDispatcher(); mock_async_file_manager_->nextActionCompletes(absl::StatusOr{ absl::UnknownError("intentionally failed to stat, for coverage")}); + pumpDispatcher(); mock_async_file_manager_->nextActionCompletes( absl::UnknownError("intentionally failed to unlink, for coverage")); + pumpDispatcher(); EXPECT_EQ(result.cache_entry_status_, CacheEntryStatus::Unusable); } @@ -563,34 +588,40 @@ TEST_F(FileSystemHttpCacheTestWithMockFiles, FailedReadOfBodyInvalidatesTheCache absl::Cleanup destroy_lookup([&lookup]() { lookup->onDestroy(); }); LookupResult result; bool end_stream_after_headers = true; // initialized wrong to ensure it's set. - EXPECT_CALL(*mock_async_file_manager_, openExistingFile(_, _, _)); - EXPECT_CALL(*mock_async_file_handle_, read(0, CacheFileFixedBlock::size(), _)); - EXPECT_CALL(*mock_async_file_handle_, read(CacheFileFixedBlock::size(), headers_size_, _)); + EXPECT_CALL(*mock_async_file_manager_, openExistingFile(_, _, _, _)); + EXPECT_CALL(*mock_async_file_handle_, read(_, 0, CacheFileFixedBlock::size(), _)); + EXPECT_CALL(*mock_async_file_handle_, read(_, CacheFileFixedBlock::size(), headers_size_, _)); lookup->getHeaders([&](LookupResult&& r, bool es) { result = std::move(r); end_stream_after_headers = es; }); mock_async_file_manager_->nextActionCompletes( absl::StatusOr(mock_async_file_handle_)); + pumpDispatcher(); mock_async_file_manager_->nextActionCompletes( absl::StatusOr(testHeaderBlock(0))); + pumpDispatcher(); mock_async_file_manager_->nextActionCompletes( absl::StatusOr(testHeaderBuffer())); + pumpDispatcher(); // result should be populated. EXPECT_NE(result.cache_entry_status_, CacheEntryStatus::Unusable); EXPECT_FALSE(end_stream_after_headers); - EXPECT_CALL(*mock_async_file_handle_, read(_, _, _)); + EXPECT_CALL(*mock_async_file_handle_, read(_, _, _, _)); lookup->getBody(AdjustedByteRange(0, 8), [&](Buffer::InstancePtr body, bool /*end_stream*/) { EXPECT_EQ(body.get(), nullptr); }); - EXPECT_CALL(*mock_async_file_manager_, stat(_, _)); - EXPECT_CALL(*mock_async_file_manager_, unlink(_, _)); + EXPECT_CALL(*mock_async_file_manager_, stat(_, _, _)); + EXPECT_CALL(*mock_async_file_manager_, unlink(_, _, _)); mock_async_file_manager_->nextActionCompletes( absl::StatusOr(absl::UnknownError("intentional failure to read"))); + pumpDispatcher(); mock_async_file_manager_->nextActionCompletes(absl::StatusOr{ absl::UnknownError("intentionally failed to stat, for coverage")}); + pumpDispatcher(); mock_async_file_manager_->nextActionCompletes( absl::UnknownError("intentionally failed to unlink, for coverage")); + pumpDispatcher(); } TEST_F(FileSystemHttpCacheTestWithMockFiles, FailedReadOfTrailersInvalidatesTheCacheEntry) { @@ -598,230 +629,268 @@ TEST_F(FileSystemHttpCacheTestWithMockFiles, FailedReadOfTrailersInvalidatesTheC absl::Cleanup destroy_lookup([&lookup]() { lookup->onDestroy(); }); LookupResult result; bool end_stream_after_headers = true; - EXPECT_CALL(*mock_async_file_manager_, openExistingFile(_, _, _)); - EXPECT_CALL(*mock_async_file_handle_, read(0, CacheFileFixedBlock::size(), _)); - EXPECT_CALL(*mock_async_file_handle_, read(CacheFileFixedBlock::size(), headers_size_, _)); + EXPECT_CALL(*mock_async_file_manager_, openExistingFile(_, _, _, _)); + EXPECT_CALL(*mock_async_file_handle_, read(_, 0, CacheFileFixedBlock::size(), _)); + EXPECT_CALL(*mock_async_file_handle_, read(_, CacheFileFixedBlock::size(), headers_size_, _)); lookup->getHeaders([&](LookupResult&& r, bool es) { result = std::move(r); end_stream_after_headers = es; }); mock_async_file_manager_->nextActionCompletes( absl::StatusOr(mock_async_file_handle_)); + pumpDispatcher(); mock_async_file_manager_->nextActionCompletes( absl::StatusOr(testHeaderBlock(0))); + pumpDispatcher(); mock_async_file_manager_->nextActionCompletes( absl::StatusOr(testHeaderBuffer())); + pumpDispatcher(); // result should be populated. EXPECT_NE(result.cache_entry_status_, CacheEntryStatus::Unusable); EXPECT_FALSE(end_stream_after_headers); - EXPECT_CALL(*mock_async_file_handle_, read(_, 8, _)); + EXPECT_CALL(*mock_async_file_handle_, read(_, _, 8, _)); lookup->getBody(AdjustedByteRange(0, 8), [&](Buffer::InstancePtr body, bool end_stream) { EXPECT_EQ(body->toString(), "beepbeep"); EXPECT_FALSE(end_stream); }); mock_async_file_manager_->nextActionCompletes( absl::StatusOr(std::make_unique("beepbeep"))); - EXPECT_CALL(*mock_async_file_handle_, read(_, _, _)); + pumpDispatcher(); + EXPECT_CALL(*mock_async_file_handle_, read(_, _, _, _)); // No point validating that the trailers are empty since that's not even particularly // desirable behavior - it's a quirk of the filter that we can't properly signify an error. lookup->getTrailers([&](Http::ResponseTrailerMapPtr) {}); - EXPECT_CALL(*mock_async_file_manager_, stat(_, _)); - EXPECT_CALL(*mock_async_file_manager_, unlink(_, _)); + EXPECT_CALL(*mock_async_file_manager_, stat(_, _, _)); + EXPECT_CALL(*mock_async_file_manager_, unlink(_, _, _)); mock_async_file_manager_->nextActionCompletes(absl::StatusOr( absl::UnknownError("intentional failure to read trailers"))); + pumpDispatcher(); mock_async_file_manager_->nextActionCompletes(absl::StatusOr{ absl::UnknownError("intentionally failed to stat, for coverage")}); + pumpDispatcher(); mock_async_file_manager_->nextActionCompletes( absl::UnknownError("intentionally failed to unlink, for coverage")); + pumpDispatcher(); } TEST_F(FileSystemHttpCacheTestWithMockFiles, ReadWithMultipleBlocksWorksCorrectly) { trailers_size_ = 0; auto lookup = testLookupContext(); LookupResult result; - EXPECT_CALL(*mock_async_file_manager_, openExistingFile(_, _, _)); - EXPECT_CALL(*mock_async_file_handle_, read(0, CacheFileFixedBlock::size(), _)); + EXPECT_CALL(*mock_async_file_manager_, openExistingFile(_, _, _, _)); + EXPECT_CALL(*mock_async_file_handle_, read(_, 0, CacheFileFixedBlock::size(), _)); EXPECT_CALL(*mock_async_file_handle_, - read(CacheFileFixedBlock::offsetToHeaders(), headers_size_, _)); + read(_, CacheFileFixedBlock::offsetToHeaders(), headers_size_, _)); lookup->getHeaders([&](LookupResult&& r, bool end_stream) { result = std::move(r); EXPECT_FALSE(end_stream) << "in headers"; }); mock_async_file_manager_->nextActionCompletes( absl::StatusOr(mock_async_file_handle_)); + pumpDispatcher(); mock_async_file_manager_->nextActionCompletes( absl::StatusOr(testHeaderBlock(8))); + pumpDispatcher(); mock_async_file_manager_->nextActionCompletes( absl::StatusOr(testHeaderBuffer())); + pumpDispatcher(); EXPECT_CALL(*mock_async_file_handle_, - read(CacheFileFixedBlock::offsetToHeaders() + headers_size_, 4, _)); + read(_, CacheFileFixedBlock::offsetToHeaders() + headers_size_, 4, _)); EXPECT_CALL(*mock_async_file_handle_, - read(CacheFileFixedBlock::offsetToHeaders() + headers_size_ + 4, 4, _)); + read(_, CacheFileFixedBlock::offsetToHeaders() + headers_size_ + 4, 4, _)); lookup->getBody(AdjustedByteRange(0, 4), [&](Buffer::InstancePtr body, bool end_stream) { EXPECT_EQ(body->toString(), "beep"); EXPECT_FALSE(end_stream) << "in body part 1"; }); mock_async_file_manager_->nextActionCompletes( absl::StatusOr(std::make_unique("beep"))); + pumpDispatcher(); lookup->getBody(AdjustedByteRange(4, 8), [&](Buffer::InstancePtr body, bool end_stream) { EXPECT_EQ(body->toString(), "boop"); EXPECT_TRUE(end_stream) << "in body part 2"; }); mock_async_file_manager_->nextActionCompletes( absl::StatusOr(std::make_unique("boop"))); + pumpDispatcher(); // While we're here, incidentally test the behavior of aborting a lookup in progress // while no file actions are in flight. lookup->onDestroy(); lookup.reset(); // There should be a file-close in the queue. mock_async_file_manager_->nextActionCompletes(absl::OkStatus()); + pumpDispatcher(); } TEST_F(FileSystemHttpCacheTestWithMockFiles, DestroyingALookupWithFileActionInFlightCancelsAction) { auto lookup = testLookupContext(); absl::Cleanup destroy_lookup([&lookup]() { lookup->onDestroy(); }); LookupResult result; - EXPECT_CALL(*mock_async_file_manager_, openExistingFile(_, _, _)); - EXPECT_CALL(*mock_async_file_manager_, mockCancel()).WillOnce([this]() { - mock_async_file_manager_->queue_.pop_front(); - }); + EXPECT_CALL(*mock_async_file_manager_, openExistingFile(_, _, _, _)); + EXPECT_CALL(*mock_async_file_manager_, mockCancel()); lookup->getHeaders([&](LookupResult&& r, bool /*end_stream*/) { result = std::move(r); }); // File wasn't used in this test but is expected to be closed. - EXPECT_OK(mock_async_file_handle_->close([](absl::Status) {})); + EXPECT_OK(mock_async_file_handle_->close(nullptr, [](absl::Status) {})); } TEST_F(FileSystemHttpCacheTestWithMockFiles, DestroyingInsertContextWithFileActionInFlightCancelsAction) { auto inserter = testInserter(); absl::Cleanup destroy_inserter([&inserter]() { inserter->onDestroy(); }); - EXPECT_CALL(*mock_async_file_manager_, createAnonymousFile(_, _)); - EXPECT_CALL(*mock_async_file_manager_, mockCancel()).WillOnce([this]() { - mock_async_file_manager_->queue_.pop_front(); - }); + EXPECT_CALL(*mock_async_file_manager_, createAnonymousFile(_, _, _)); + EXPECT_CALL(*mock_async_file_manager_, mockCancel()); inserter->insertHeaders(response_headers_, metadata_, expect_false_callback_, false); // File wasn't used in this test but is expected to be closed. - EXPECT_OK(mock_async_file_handle_->close([](absl::Status) {})); + EXPECT_OK(mock_async_file_handle_->close(nullptr, [](absl::Status) {})); } TEST_F(FileSystemHttpCacheTestWithMockFiles, InsertAbortsOnFailureToWriteEmptyHeaderBlock) { auto inserter = testInserter(); absl::Cleanup destroy_inserter([&inserter]() { inserter->onDestroy(); }); - EXPECT_CALL(*mock_async_file_manager_, createAnonymousFile(_, _)); - EXPECT_CALL(*mock_async_file_handle_, write(_, _, _)); + EXPECT_CALL(*mock_async_file_manager_, createAnonymousFile(_, _, _)); + EXPECT_CALL(*mock_async_file_handle_, write(_, _, _, _)); inserter->insertHeaders(response_headers_, metadata_, expect_false_callback_, false); mock_async_file_manager_->nextActionCompletes( absl::StatusOr(mock_async_file_handle_)); + pumpDispatcher(); mock_async_file_manager_->nextActionCompletes(absl::StatusOr( absl::UnknownError("intentionally failed write to empty header block"))); + pumpDispatcher(); EXPECT_EQ(false_callbacks_called_, 1); } TEST_F(FileSystemHttpCacheTestWithMockFiles, InsertAbortsOnFailureToWriteHeaderChunk) { auto inserter = testInserter(); absl::Cleanup destroy_inserter([&inserter]() { inserter->onDestroy(); }); - EXPECT_CALL(*mock_async_file_manager_, createAnonymousFile(_, _)); - EXPECT_CALL(*mock_async_file_handle_, write(_, _, _)).Times(2); + EXPECT_CALL(*mock_async_file_manager_, createAnonymousFile(_, _, _)); + EXPECT_CALL(*mock_async_file_handle_, write(_, _, _, _)).Times(2); inserter->insertHeaders(response_headers_, metadata_, expect_false_callback_, false); mock_async_file_manager_->nextActionCompletes( absl::StatusOr(mock_async_file_handle_)); + pumpDispatcher(); mock_async_file_manager_->nextActionCompletes( absl::StatusOr(CacheFileFixedBlock::size())); + pumpDispatcher(); mock_async_file_manager_->nextActionCompletes( absl::StatusOr(absl::UnknownError("intentionally failed write of header chunk"))); + pumpDispatcher(); EXPECT_EQ(false_callbacks_called_, 1); } TEST_F(FileSystemHttpCacheTestWithMockFiles, InsertAbortsOnFailureToWriteBodyChunk) { auto inserter = testInserter(); absl::Cleanup destroy_inserter([&inserter]() { inserter->onDestroy(); }); - EXPECT_CALL(*mock_async_file_manager_, createAnonymousFile(_, _)); - EXPECT_CALL(*mock_async_file_handle_, write(_, _, _)).Times(3); + EXPECT_CALL(*mock_async_file_manager_, createAnonymousFile(_, _, _)); + EXPECT_CALL(*mock_async_file_handle_, write(_, _, _, _)).Times(3); inserter->insertHeaders(response_headers_, metadata_, expect_true_callback_, false); mock_async_file_manager_->nextActionCompletes( absl::StatusOr(mock_async_file_handle_)); + pumpDispatcher(); mock_async_file_manager_->nextActionCompletes( absl::StatusOr(CacheFileFixedBlock::size())); + pumpDispatcher(); mock_async_file_manager_->nextActionCompletes(absl::StatusOr(headers_size_)); + pumpDispatcher(); EXPECT_EQ(true_callbacks_called_, 1); inserter->insertBody(Buffer::OwnedImpl("woop"), expect_false_callback_, false); // Intentionally undersized write of body chunk. mock_async_file_manager_->nextActionCompletes(absl::StatusOr(1)); + pumpDispatcher(); EXPECT_EQ(false_callbacks_called_, 1); } TEST_F(FileSystemHttpCacheTestWithMockFiles, InsertAbortsOnFailureToWriteTrailerChunk) { auto inserter = testInserter(); absl::Cleanup destroy_inserter([&inserter]() { inserter->onDestroy(); }); - EXPECT_CALL(*mock_async_file_manager_, createAnonymousFile(_, _)); - EXPECT_CALL(*mock_async_file_handle_, write(_, _, _)).Times(4); + EXPECT_CALL(*mock_async_file_manager_, createAnonymousFile(_, _, _)); + EXPECT_CALL(*mock_async_file_handle_, write(_, _, _, _)).Times(4); inserter->insertHeaders(response_headers_, metadata_, expect_true_callback_, false); const absl::string_view body = "woop"; mock_async_file_manager_->nextActionCompletes( absl::StatusOr(mock_async_file_handle_)); + pumpDispatcher(); mock_async_file_manager_->nextActionCompletes( absl::StatusOr(CacheFileFixedBlock::size())); + pumpDispatcher(); mock_async_file_manager_->nextActionCompletes(absl::StatusOr(headers_size_)); + pumpDispatcher(); EXPECT_EQ(true_callbacks_called_, 1); inserter->insertBody(Buffer::OwnedImpl(body), expect_true_callback_, false); mock_async_file_manager_->nextActionCompletes(absl::StatusOr(body.size())); + pumpDispatcher(); EXPECT_EQ(true_callbacks_called_, 2); inserter->insertTrailers(response_trailers_, expect_false_callback_); mock_async_file_manager_->nextActionCompletes( absl::StatusOr(absl::UnknownError("intentionally failed write of trailer chunk"))); + pumpDispatcher(); EXPECT_EQ(false_callbacks_called_, 1); } TEST_F(FileSystemHttpCacheTestWithMockFiles, InsertAbortsOnFailureToWriteUpdatedHeaderBlock) { auto inserter = testInserter(); absl::Cleanup destroy_inserter([&inserter]() { inserter->onDestroy(); }); - EXPECT_CALL(*mock_async_file_manager_, createAnonymousFile(_, _)); - EXPECT_CALL(*mock_async_file_handle_, write(_, _, _)).Times(5); + EXPECT_CALL(*mock_async_file_manager_, createAnonymousFile(_, _, _)); + EXPECT_CALL(*mock_async_file_handle_, write(_, _, _, _)).Times(5); inserter->insertHeaders(response_headers_, metadata_, expect_true_callback_, false); mock_async_file_manager_->nextActionCompletes( absl::StatusOr(mock_async_file_handle_)); + pumpDispatcher(); mock_async_file_manager_->nextActionCompletes( absl::StatusOr(CacheFileFixedBlock::size())); + pumpDispatcher(); mock_async_file_manager_->nextActionCompletes(absl::StatusOr(headers_size_)); + pumpDispatcher(); EXPECT_EQ(true_callbacks_called_, 1); const absl::string_view body = "woop"; inserter->insertBody(Buffer::OwnedImpl(body), expect_true_callback_, false); mock_async_file_manager_->nextActionCompletes(absl::StatusOr(body.size())); + pumpDispatcher(); EXPECT_EQ(true_callbacks_called_, 2); inserter->insertTrailers(response_trailers_, expect_false_callback_); mock_async_file_manager_->nextActionCompletes(absl::StatusOr(trailers_size_)); + pumpDispatcher(); mock_async_file_manager_->nextActionCompletes(absl::StatusOr( absl::UnknownError("intentionally failed write of updated header block"))); + pumpDispatcher(); EXPECT_EQ(false_callbacks_called_, 1); } TEST_F(FileSystemHttpCacheTestWithMockFiles, InsertAbortsOnFailureToLinkFile) { auto inserter = testInserter(); absl::Cleanup destroy_inserter([&inserter]() { inserter->onDestroy(); }); - EXPECT_CALL(*mock_async_file_manager_, createAnonymousFile(_, _)); - EXPECT_CALL(*mock_async_file_handle_, write(_, _, _)).Times(5); - EXPECT_CALL(*mock_async_file_manager_, stat(_, _)); - EXPECT_CALL(*mock_async_file_manager_, unlink(_, _)); - EXPECT_CALL(*mock_async_file_handle_, createHardLink(_, _)); + EXPECT_CALL(*mock_async_file_manager_, createAnonymousFile(_, _, _)); + EXPECT_CALL(*mock_async_file_handle_, write(_, _, _, _)).Times(5); + EXPECT_CALL(*mock_async_file_manager_, stat(_, _, _)); + EXPECT_CALL(*mock_async_file_manager_, unlink(_, _, _)); + EXPECT_CALL(*mock_async_file_handle_, createHardLink(_, _, _)); inserter->insertHeaders(response_headers_, metadata_, expect_true_callback_, false); mock_async_file_manager_->nextActionCompletes( absl::StatusOr(mock_async_file_handle_)); + pumpDispatcher(); mock_async_file_manager_->nextActionCompletes( absl::StatusOr(CacheFileFixedBlock::size())); + pumpDispatcher(); mock_async_file_manager_->nextActionCompletes(absl::StatusOr(headers_size_)); + pumpDispatcher(); EXPECT_EQ(true_callbacks_called_, 1); const absl::string_view body = "woop"; inserter->insertBody(Buffer::OwnedImpl(body), expect_true_callback_, false); mock_async_file_manager_->nextActionCompletes(absl::StatusOr(body.size())); + pumpDispatcher(); EXPECT_EQ(true_callbacks_called_, 2); inserter->insertTrailers(response_trailers_, expect_false_callback_); mock_async_file_manager_->nextActionCompletes(absl::StatusOr(trailers_size_)); + pumpDispatcher(); mock_async_file_manager_->nextActionCompletes( absl::StatusOr(CacheFileFixedBlock::size())); + pumpDispatcher(); mock_async_file_manager_->nextActionCompletes(absl::StatusOr{ absl::UnknownError("intentionally failed to stat, for coverage")}); + pumpDispatcher(); mock_async_file_manager_->nextActionCompletes(absl::OkStatus()); + pumpDispatcher(); mock_async_file_manager_->nextActionCompletes( absl::UnknownError("intentionally failed to link cache file")); + pumpDispatcher(); EXPECT_EQ(false_callbacks_called_, 1); } @@ -834,16 +903,17 @@ TEST_F(FileSystemHttpCacheTestWithMockFiles, UpdateHeadersAbortsIfFileOpenFailed {"cache-control", "public,max-age=3600"}, }; auto lookup_context = testLookupContext(); - EXPECT_CALL(*mock_async_file_manager_, openExistingFile(_, _, _)); + EXPECT_CALL(*mock_async_file_manager_, openExistingFile(_, _, _, _)); bool update_success; cache_->updateHeaders(*lookup_context, response_headers, {time_system_.systemTime()}, [&update_success](bool success) { update_success = success; }); mock_async_file_manager_->nextActionCompletes( absl::StatusOr(absl::UnknownError("Intentionally failed to open file"))); + pumpDispatcher(); lookup_context->onDestroy(); EXPECT_FALSE(update_success); // File is not used in this test, but is expected to be closed. - EXPECT_OK(mock_async_file_handle_->close([](absl::Status) {})); + EXPECT_OK(mock_async_file_handle_->close(nullptr, [](absl::Status) {})); } TEST_F(FileSystemHttpCacheTestWithMockFiles, UpdateHeadersKeepsTryingIfUnlinkOriginalFails) { @@ -855,19 +925,23 @@ TEST_F(FileSystemHttpCacheTestWithMockFiles, UpdateHeadersKeepsTryingIfUnlinkOri {"cache-control", "public,max-age=3600"}, }; auto lookup_context = testLookupContext(); - EXPECT_CALL(*mock_async_file_manager_, openExistingFile(_, _, _)); - EXPECT_CALL(*mock_async_file_manager_, unlink(_, _)); - EXPECT_CALL(*mock_async_file_handle_, read(0, CacheFileFixedBlock::size(), _)); + EXPECT_CALL(*mock_async_file_manager_, openExistingFile(_, _, _, _)); + EXPECT_CALL(*mock_async_file_manager_, unlink(_, _, _)); + EXPECT_CALL(*mock_async_file_handle_, read(_, 0, CacheFileFixedBlock::size(), _)); bool update_success; cache_->updateHeaders(*lookup_context, response_headers, {time_system_.systemTime()}, [&update_success](bool success) { update_success = success; }); mock_async_file_manager_->nextActionCompletes( absl::StatusOr(mock_async_file_handle_)); + pumpDispatcher(); mock_async_file_manager_->nextActionCompletes( absl::UnknownError("Intentionally failed to unlink")); + pumpDispatcher(); mock_async_file_manager_->nextActionCompletes(absl::StatusOr( absl::UnknownError("Intentionally failed to read header block"))); + pumpDispatcher(); mock_async_file_manager_->nextActionCompletes(absl::OkStatus()); // close read handle + pumpDispatcher(); lookup_context->onDestroy(); EXPECT_FALSE(update_success); } @@ -881,21 +955,26 @@ TEST_F(FileSystemHttpCacheTestWithMockFiles, UpdateHeadersAbortsIfReadHeadersFai {"cache-control", "public,max-age=3600"}, }; auto lookup_context = testLookupContext(); - EXPECT_CALL(*mock_async_file_manager_, openExistingFile(_, _, _)); - EXPECT_CALL(*mock_async_file_manager_, unlink(_, _)); - EXPECT_CALL(*mock_async_file_handle_, read(0, CacheFileFixedBlock::size(), _)); - EXPECT_CALL(*mock_async_file_handle_, read(CacheFileFixedBlock::size(), headers_size_, _)); + EXPECT_CALL(*mock_async_file_manager_, openExistingFile(_, _, _, _)); + EXPECT_CALL(*mock_async_file_manager_, unlink(_, _, _)); + EXPECT_CALL(*mock_async_file_handle_, read(_, 0, CacheFileFixedBlock::size(), _)); + EXPECT_CALL(*mock_async_file_handle_, read(_, CacheFileFixedBlock::size(), headers_size_, _)); bool update_success; cache_->updateHeaders(*lookup_context, response_headers, {time_system_.systemTime()}, [&update_success](bool success) { update_success = success; }); mock_async_file_manager_->nextActionCompletes( absl::StatusOr(mock_async_file_handle_)); + pumpDispatcher(); mock_async_file_manager_->nextActionCompletes(absl::OkStatus()); + pumpDispatcher(); mock_async_file_manager_->nextActionCompletes( absl::StatusOr(testHeaderBlock(0))); + pumpDispatcher(); mock_async_file_manager_->nextActionCompletes(absl::StatusOr( absl::UnknownError("Intentionally failed to read headers block"))); + pumpDispatcher(); mock_async_file_manager_->nextActionCompletes(absl::OkStatus()); // close read handle + pumpDispatcher(); lookup_context->onDestroy(); EXPECT_FALSE(update_success); } @@ -918,22 +997,27 @@ TEST_F(FileSystemHttpCacheTestWithMockFiles, UpdateHeadersAbortsIfReadHeadersFin {"cache-control", "public,max-age=3600"}, }; auto lookup_context = testLookupContext(); - EXPECT_CALL(*mock_async_file_manager_, openExistingFile(_, _, _)); - EXPECT_CALL(*mock_async_file_manager_, unlink(_, _)); - EXPECT_CALL(*mock_async_file_handle_, read(0, CacheFileFixedBlock::size(), _)); + EXPECT_CALL(*mock_async_file_manager_, openExistingFile(_, _, _, _)); + EXPECT_CALL(*mock_async_file_manager_, unlink(_, _, _)); + EXPECT_CALL(*mock_async_file_handle_, read(_, 0, CacheFileFixedBlock::size(), _)); EXPECT_CALL(*mock_async_file_handle_, - read(CacheFileFixedBlock::size(), vary_headers_buffer->length(), _)); + read(_, CacheFileFixedBlock::size(), vary_headers_buffer->length(), _)); bool update_success; cache_->updateHeaders(*lookup_context, response_headers, {time_system_.systemTime()}, [&update_success](bool success) { update_success = success; }); mock_async_file_manager_->nextActionCompletes( absl::StatusOr(mock_async_file_handle_)); + pumpDispatcher(); mock_async_file_manager_->nextActionCompletes(absl::OkStatus()); + pumpDispatcher(); mock_async_file_manager_->nextActionCompletes( absl::StatusOr(std::move(vary_block_buffer))); + pumpDispatcher(); mock_async_file_manager_->nextActionCompletes( absl::StatusOr(std::move(vary_headers_buffer))); + pumpDispatcher(); mock_async_file_manager_->nextActionCompletes(absl::OkStatus()); // close read handle + pumpDispatcher(); lookup_context->onDestroy(); EXPECT_FALSE(update_success); } @@ -947,24 +1031,30 @@ TEST_F(FileSystemHttpCacheTestWithMockFiles, UpdateHeadersAbortsIfOpenForWriteFa {"cache-control", "public,max-age=3600"}, }; auto lookup_context = testLookupContext(); - EXPECT_CALL(*mock_async_file_manager_, openExistingFile(_, _, _)); - EXPECT_CALL(*mock_async_file_manager_, unlink(_, _)); - EXPECT_CALL(*mock_async_file_handle_, read(0, CacheFileFixedBlock::size(), _)); - EXPECT_CALL(*mock_async_file_handle_, read(CacheFileFixedBlock::size(), headers_size_, _)); - EXPECT_CALL(*mock_async_file_manager_, createAnonymousFile(_, _)); + EXPECT_CALL(*mock_async_file_manager_, openExistingFile(_, _, _, _)); + EXPECT_CALL(*mock_async_file_manager_, unlink(_, _, _)); + EXPECT_CALL(*mock_async_file_handle_, read(_, 0, CacheFileFixedBlock::size(), _)); + EXPECT_CALL(*mock_async_file_handle_, read(_, CacheFileFixedBlock::size(), headers_size_, _)); + EXPECT_CALL(*mock_async_file_manager_, createAnonymousFile(_, _, _)); bool update_success; cache_->updateHeaders(*lookup_context, response_headers, {time_system_.systemTime()}, [&update_success](bool success) { update_success = success; }); mock_async_file_manager_->nextActionCompletes( absl::StatusOr(mock_async_file_handle_)); + pumpDispatcher(); mock_async_file_manager_->nextActionCompletes(absl::OkStatus()); + pumpDispatcher(); mock_async_file_manager_->nextActionCompletes( absl::StatusOr(testHeaderBlock(0))); + pumpDispatcher(); mock_async_file_manager_->nextActionCompletes( absl::StatusOr(testHeaderBuffer())); + pumpDispatcher(); mock_async_file_manager_->nextActionCompletes(absl::StatusOr( absl::UnknownError("Intentionally failed to create file for write"))); + pumpDispatcher(); mock_async_file_manager_->nextActionCompletes(absl::OkStatus()); // close read handle + pumpDispatcher(); lookup_context->onDestroy(); EXPECT_FALSE(update_success); } @@ -980,27 +1070,35 @@ TEST_F(FileSystemHttpCacheTestWithMockFiles, UpdateHeadersAbortsIfWriteHeaderBlo auto lookup_context = testLookupContext(); MockAsyncFileHandle write_handle = std::make_shared>(mock_async_file_manager_); - EXPECT_CALL(*mock_async_file_manager_, openExistingFile(_, _, _)); - EXPECT_CALL(*mock_async_file_manager_, unlink(_, _)); - EXPECT_CALL(*mock_async_file_handle_, read(0, CacheFileFixedBlock::size(), _)); - EXPECT_CALL(*mock_async_file_handle_, read(CacheFileFixedBlock::size(), headers_size_, _)); - EXPECT_CALL(*mock_async_file_manager_, createAnonymousFile(_, _)); - EXPECT_CALL(*write_handle, write(_, 0, _)); + EXPECT_CALL(*mock_async_file_manager_, openExistingFile(_, _, _, _)); + EXPECT_CALL(*mock_async_file_manager_, unlink(_, _, _)); + EXPECT_CALL(*mock_async_file_handle_, read(_, 0, CacheFileFixedBlock::size(), _)); + EXPECT_CALL(*mock_async_file_handle_, read(_, CacheFileFixedBlock::size(), headers_size_, _)); + EXPECT_CALL(*mock_async_file_manager_, createAnonymousFile(_, _, _)); + EXPECT_CALL(*write_handle, write(_, _, 0, _)); bool update_success; cache_->updateHeaders(*lookup_context, response_headers, {time_system_.systemTime()}, [&update_success](bool success) { update_success = success; }); mock_async_file_manager_->nextActionCompletes( absl::StatusOr(mock_async_file_handle_)); + pumpDispatcher(); mock_async_file_manager_->nextActionCompletes(absl::OkStatus()); + pumpDispatcher(); mock_async_file_manager_->nextActionCompletes( absl::StatusOr(testHeaderBlock(0))); + pumpDispatcher(); mock_async_file_manager_->nextActionCompletes( absl::StatusOr(testHeaderBuffer())); + pumpDispatcher(); mock_async_file_manager_->nextActionCompletes(absl::StatusOr(write_handle)); + pumpDispatcher(); mock_async_file_manager_->nextActionCompletes( absl::StatusOr(absl::UnknownError("Intentionally failed to write header block"))); + pumpDispatcher(); mock_async_file_manager_->nextActionCompletes(absl::OkStatus()); // close read handle + pumpDispatcher(); mock_async_file_manager_->nextActionCompletes(absl::OkStatus()); // close write handle + pumpDispatcher(); lookup_context->onDestroy(); EXPECT_FALSE(update_success); } @@ -1019,31 +1117,40 @@ TEST_F(FileSystemHttpCacheTestWithMockFiles, UpdateHeadersAbortsIfReadBodyFails) auto lookup_context = testLookupContext(); MockAsyncFileHandle write_handle = std::make_shared>(mock_async_file_manager_); - EXPECT_CALL(*mock_async_file_manager_, openExistingFile(_, _, _)); - EXPECT_CALL(*mock_async_file_manager_, unlink(_, _)); - EXPECT_CALL(*mock_async_file_handle_, read(0, CacheFileFixedBlock::size(), _)); - EXPECT_CALL(*mock_async_file_handle_, read(CacheFileFixedBlock::size(), headers_size_, _)); - EXPECT_CALL(*mock_async_file_manager_, createAnonymousFile(_, _)); - EXPECT_CALL(*write_handle, write(_, 0, _)); + EXPECT_CALL(*mock_async_file_manager_, openExistingFile(_, _, _, _)); + EXPECT_CALL(*mock_async_file_manager_, unlink(_, _, _)); + EXPECT_CALL(*mock_async_file_handle_, read(_, 0, CacheFileFixedBlock::size(), _)); + EXPECT_CALL(*mock_async_file_handle_, read(_, CacheFileFixedBlock::size(), headers_size_, _)); + EXPECT_CALL(*mock_async_file_manager_, createAnonymousFile(_, _, _)); + EXPECT_CALL(*write_handle, write(_, _, 0, _)); EXPECT_CALL(*mock_async_file_handle_, - read(CacheFileFixedBlock::size() + headers_size_, body_size + trailers_size_, _)); + read(_, CacheFileFixedBlock::size() + headers_size_, body_size + trailers_size_, _)); bool update_success; cache_->updateHeaders(*lookup_context, response_headers, {time_system_.systemTime()}, [&update_success](bool success) { update_success = success; }); mock_async_file_manager_->nextActionCompletes( absl::StatusOr(mock_async_file_handle_)); + pumpDispatcher(); mock_async_file_manager_->nextActionCompletes(absl::OkStatus()); + pumpDispatcher(); mock_async_file_manager_->nextActionCompletes( absl::StatusOr(testHeaderBlock(body_size))); + pumpDispatcher(); mock_async_file_manager_->nextActionCompletes( absl::StatusOr(testHeaderBuffer())); + pumpDispatcher(); mock_async_file_manager_->nextActionCompletes(absl::StatusOr(write_handle)); + pumpDispatcher(); mock_async_file_manager_->nextActionCompletes( absl::StatusOr(updated_headers_size + CacheFileFixedBlock::size())); + pumpDispatcher(); mock_async_file_manager_->nextActionCompletes( absl::StatusOr(absl::UnknownError("intentionally failed body read"))); + pumpDispatcher(); mock_async_file_manager_->nextActionCompletes(absl::OkStatus()); // close read handle + pumpDispatcher(); mock_async_file_manager_->nextActionCompletes(absl::OkStatus()); // close write handle + pumpDispatcher(); lookup_context->onDestroy(); EXPECT_FALSE(update_success); } @@ -1062,36 +1169,46 @@ TEST_F(FileSystemHttpCacheTestWithMockFiles, UpdateHeadersAbortsIfWriteBodyFails auto lookup_context = testLookupContext(); MockAsyncFileHandle write_handle = std::make_shared>(mock_async_file_manager_); - EXPECT_CALL(*mock_async_file_manager_, openExistingFile(_, _, _)); - EXPECT_CALL(*mock_async_file_manager_, unlink(_, _)); - EXPECT_CALL(*mock_async_file_handle_, read(0, CacheFileFixedBlock::size(), _)); - EXPECT_CALL(*mock_async_file_handle_, read(CacheFileFixedBlock::size(), headers_size_, _)); - EXPECT_CALL(*mock_async_file_manager_, createAnonymousFile(_, _)); - EXPECT_CALL(*write_handle, write(_, 0, _)); + EXPECT_CALL(*mock_async_file_manager_, openExistingFile(_, _, _, _)); + EXPECT_CALL(*mock_async_file_manager_, unlink(_, _, _)); + EXPECT_CALL(*mock_async_file_handle_, read(_, 0, CacheFileFixedBlock::size(), _)); + EXPECT_CALL(*mock_async_file_handle_, read(_, CacheFileFixedBlock::size(), headers_size_, _)); + EXPECT_CALL(*mock_async_file_manager_, createAnonymousFile(_, _, _)); + EXPECT_CALL(*write_handle, write(_, _, 0, _)); EXPECT_CALL(*mock_async_file_handle_, - read(CacheFileFixedBlock::size() + headers_size_, body_size + trailers_size_, _)); - EXPECT_CALL(*write_handle, write(_, CacheFileFixedBlock::size() + updated_headers_size, _)); + read(_, CacheFileFixedBlock::size() + headers_size_, body_size + trailers_size_, _)); + EXPECT_CALL(*write_handle, write(_, _, CacheFileFixedBlock::size() + updated_headers_size, _)); bool update_success; cache_->updateHeaders(*lookup_context, response_headers, {time_system_.systemTime()}, [&update_success](bool success) { update_success = success; }); mock_async_file_manager_->nextActionCompletes( absl::StatusOr(mock_async_file_handle_)); + pumpDispatcher(); mock_async_file_manager_->nextActionCompletes(absl::OkStatus()); + pumpDispatcher(); mock_async_file_manager_->nextActionCompletes( absl::StatusOr(testHeaderBlock(body_size))); + pumpDispatcher(); mock_async_file_manager_->nextActionCompletes( absl::StatusOr(testHeaderBuffer())); + pumpDispatcher(); mock_async_file_manager_->nextActionCompletes(absl::StatusOr(write_handle)); + pumpDispatcher(); mock_async_file_manager_->nextActionCompletes( absl::StatusOr(updated_headers_size + CacheFileFixedBlock::size())); + pumpDispatcher(); std::string body_and_trailers; body_and_trailers.resize(body_size + trailers_size_); mock_async_file_manager_->nextActionCompletes( absl::StatusOr(std::make_unique(body_and_trailers))); + pumpDispatcher(); mock_async_file_manager_->nextActionCompletes( absl::StatusOr(absl::UnknownError("intentionally failed body write"))); + pumpDispatcher(); mock_async_file_manager_->nextActionCompletes(absl::OkStatus()); // close read handle + pumpDispatcher(); mock_async_file_manager_->nextActionCompletes(absl::OkStatus()); // close write handle + pumpDispatcher(); lookup_context->onDestroy(); EXPECT_FALSE(update_success); } @@ -1110,19 +1227,20 @@ TEST_F(FileSystemHttpCacheTestWithMockFiles, UpdateHeadersCopiesInChunksIfBodySi auto lookup_context = testLookupContext(); MockAsyncFileHandle write_handle = std::make_shared>(mock_async_file_manager_); - EXPECT_CALL(*mock_async_file_manager_, openExistingFile(_, _, _)); - EXPECT_CALL(*mock_async_file_manager_, unlink(_, _)); - EXPECT_CALL(*mock_async_file_handle_, read(0, CacheFileFixedBlock::size(), _)); - EXPECT_CALL(*mock_async_file_handle_, read(CacheFileFixedBlock::size(), headers_size_, _)); - EXPECT_CALL(*mock_async_file_manager_, createAnonymousFile(_, _)); - EXPECT_CALL(*write_handle, write(_, 0, _)); + EXPECT_CALL(*mock_async_file_manager_, openExistingFile(_, _, _, _)); + EXPECT_CALL(*mock_async_file_manager_, unlink(_, _, _)); + EXPECT_CALL(*mock_async_file_handle_, read(_, 0, CacheFileFixedBlock::size(), _)); + EXPECT_CALL(*mock_async_file_handle_, read(_, CacheFileFixedBlock::size(), headers_size_, _)); + EXPECT_CALL(*mock_async_file_manager_, createAnonymousFile(_, _, _)); + EXPECT_CALL(*write_handle, write(_, _, 0, _)); EXPECT_CALL(*mock_async_file_handle_, - read(CacheFileFixedBlock::size() + headers_size_, + read(_, CacheFileFixedBlock::size() + headers_size_, FileSystemHttpCache::max_update_headers_copy_chunk_size_, _)); - EXPECT_CALL(*write_handle, write(_, CacheFileFixedBlock::size() + updated_headers_size, _)); + EXPECT_CALL(*write_handle, write(_, _, CacheFileFixedBlock::size() + updated_headers_size, _)); EXPECT_CALL( *mock_async_file_handle_, - read(CacheFileFixedBlock::size() + headers_size_ + + read(_, + CacheFileFixedBlock::size() + headers_size_ + FileSystemHttpCache::max_update_headers_copy_chunk_size_, body_size + trailers_size_ - FileSystemHttpCache::max_update_headers_copy_chunk_size_, _)); @@ -1131,24 +1249,35 @@ TEST_F(FileSystemHttpCacheTestWithMockFiles, UpdateHeadersCopiesInChunksIfBodySi [&update_success](bool success) { update_success = success; }); mock_async_file_manager_->nextActionCompletes( absl::StatusOr(mock_async_file_handle_)); + pumpDispatcher(); mock_async_file_manager_->nextActionCompletes(absl::OkStatus()); + pumpDispatcher(); mock_async_file_manager_->nextActionCompletes( absl::StatusOr(testHeaderBlock(body_size))); + pumpDispatcher(); mock_async_file_manager_->nextActionCompletes( absl::StatusOr(testHeaderBuffer())); + pumpDispatcher(); mock_async_file_manager_->nextActionCompletes(absl::StatusOr(write_handle)); + pumpDispatcher(); mock_async_file_manager_->nextActionCompletes( absl::StatusOr(updated_headers_size + CacheFileFixedBlock::size())); + pumpDispatcher(); std::string body_chunk; body_chunk.resize(FileSystemHttpCache::max_update_headers_copy_chunk_size_); mock_async_file_manager_->nextActionCompletes( absl::StatusOr(std::make_unique(body_chunk))); + pumpDispatcher(); mock_async_file_manager_->nextActionCompletes( absl::StatusOr(FileSystemHttpCache::max_update_headers_copy_chunk_size_)); + pumpDispatcher(); mock_async_file_manager_->nextActionCompletes(absl::StatusOr( absl::UnknownError("intentionally failed second body read"))); + pumpDispatcher(); mock_async_file_manager_->nextActionCompletes(absl::OkStatus()); // close read handle + pumpDispatcher(); mock_async_file_manager_->nextActionCompletes(absl::OkStatus()); // close write handle + pumpDispatcher(); lookup_context->onDestroy(); EXPECT_FALSE(update_success); } @@ -1167,37 +1296,48 @@ TEST_F(FileSystemHttpCacheTestWithMockFiles, UpdateHeadersAbortsIfLinkFails) { auto lookup_context = testLookupContext(); MockAsyncFileHandle write_handle = std::make_shared>(mock_async_file_manager_); - EXPECT_CALL(*mock_async_file_manager_, openExistingFile(_, _, _)); - EXPECT_CALL(*mock_async_file_manager_, unlink(_, _)); - EXPECT_CALL(*mock_async_file_handle_, read(0, CacheFileFixedBlock::size(), _)); - EXPECT_CALL(*mock_async_file_handle_, read(CacheFileFixedBlock::size(), headers_size_, _)); - EXPECT_CALL(*mock_async_file_manager_, createAnonymousFile(_, _)); - EXPECT_CALL(*write_handle, write(_, 0, _)); + EXPECT_CALL(*mock_async_file_manager_, openExistingFile(_, _, _, _)); + EXPECT_CALL(*mock_async_file_manager_, unlink(_, _, _)); + EXPECT_CALL(*mock_async_file_handle_, read(_, 0, CacheFileFixedBlock::size(), _)); + EXPECT_CALL(*mock_async_file_handle_, read(_, CacheFileFixedBlock::size(), headers_size_, _)); + EXPECT_CALL(*mock_async_file_manager_, createAnonymousFile(_, _, _)); + EXPECT_CALL(*write_handle, write(_, _, 0, _)); EXPECT_CALL(*mock_async_file_handle_, - read(CacheFileFixedBlock::size() + headers_size_, body_size + trailers_size_, _)); - EXPECT_CALL(*write_handle, write(_, CacheFileFixedBlock::size() + updated_headers_size, _)); - EXPECT_CALL(*write_handle, createHardLink(_, _)); + read(_, CacheFileFixedBlock::size() + headers_size_, body_size + trailers_size_, _)); + EXPECT_CALL(*write_handle, write(_, _, CacheFileFixedBlock::size() + updated_headers_size, _)); + EXPECT_CALL(*write_handle, createHardLink(_, _, _)); bool update_success; cache_->updateHeaders(*lookup_context, response_headers, {time_system_.systemTime()}, [&update_success](bool success) { update_success = success; }); mock_async_file_manager_->nextActionCompletes( absl::StatusOr(mock_async_file_handle_)); + pumpDispatcher(); mock_async_file_manager_->nextActionCompletes(absl::OkStatus()); + pumpDispatcher(); mock_async_file_manager_->nextActionCompletes( absl::StatusOr(testHeaderBlock(body_size))); + pumpDispatcher(); mock_async_file_manager_->nextActionCompletes( absl::StatusOr(testHeaderBuffer())); + pumpDispatcher(); mock_async_file_manager_->nextActionCompletes(absl::StatusOr(write_handle)); + pumpDispatcher(); mock_async_file_manager_->nextActionCompletes( absl::StatusOr(updated_headers_size + CacheFileFixedBlock::size())); + pumpDispatcher(); std::string body_and_trailers; body_and_trailers.resize(body_size + trailers_size_); mock_async_file_manager_->nextActionCompletes( absl::StatusOr(std::make_unique(body_and_trailers))); + pumpDispatcher(); mock_async_file_manager_->nextActionCompletes(absl::StatusOr(body_and_trailers.size())); + pumpDispatcher(); mock_async_file_manager_->nextActionCompletes(absl::UnknownError("intentionally failed to link")); + pumpDispatcher(); mock_async_file_manager_->nextActionCompletes(absl::OkStatus()); // close read handle + pumpDispatcher(); mock_async_file_manager_->nextActionCompletes(absl::OkStatus()); // close write handle + pumpDispatcher(); lookup_context->onDestroy(); EXPECT_FALSE(update_success); } @@ -1210,7 +1350,7 @@ TEST_F(FileSystemHttpCacheTestWithMockFiles, UpdateHeadersAbortsEarlyIfCacheEntr {"x-whatever", "updated"}, {"cache-control", "public,max-age=3600"}, }; - EXPECT_CALL(*mock_async_file_manager_, openExistingFile(_, _, _)); + EXPECT_CALL(*mock_async_file_manager_, openExistingFile(_, _, _, _)); bool update_success; cache_->updateHeaders(*lookup_context, response_headers, {time_system_.systemTime()}, [&update_success](bool success) { update_success = success; }); @@ -1221,10 +1361,11 @@ TEST_F(FileSystemHttpCacheTestWithMockFiles, UpdateHeadersAbortsEarlyIfCacheEntr [&update_success](bool success) { update_success = success; }); mock_async_file_manager_->nextActionCompletes( absl::StatusOr(absl::UnknownError("intentionally failed to open file"))); + pumpDispatcher(); lookup_context->onDestroy(); lookup_context_2->onDestroy(); // The file handle didn't actually get used in this test, but is expected to be closed. - EXPECT_OK(mock_async_file_handle_->close([](absl::Status) {})); + EXPECT_OK(mock_async_file_handle_->close(nullptr, [](absl::Status) {})); } // For the standard cache tests from http_cache_implementation_test_common.cc @@ -1236,6 +1377,7 @@ class FileSystemHttpCacheTestDelegate : public HttpCacheTestDelegate, FileSystemHttpCacheTestDelegate() { initCache(); } std::shared_ptr cache() override { return cache_; } bool validationEnabled() const override { return true; } + void beforePumpingDispatcher() override { cache_->drainAsyncFileActionsForTest(); } }; // For the standard cache tests from http_cache_implementation_test_common.cc From 975a005b5722be0ad81dadcf97964038514c45f3 Mon Sep 17 00:00:00 2001 From: "dependency-envoy[bot]" <148525496+dependency-envoy[bot]@users.noreply.github.com> Date: Wed, 18 Sep 2024 17:50:41 +0100 Subject: [PATCH 12/65] deps: Bump `rules_rust` -> 0.50.1 (#36194) Fix #36087 Signed-off-by: dependency-envoy[bot] <148525496+dependency-envoy[bot]@users.noreply.github.com> Signed-off-by: Ryan Northey --- bazel/repository_locations.bzl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/bazel/repository_locations.bzl b/bazel/repository_locations.bzl index 94f70cfb36..3ed519854c 100644 --- a/bazel/repository_locations.bzl +++ b/bazel/repository_locations.bzl @@ -1452,9 +1452,9 @@ REPOSITORY_LOCATIONS_SPEC = dict( project_name = "Bazel rust rules", project_desc = "Bazel rust rules (used by Wasm)", project_url = "https://github.com/bazelbuild/rules_rust", - version = "0.48.0", + version = "0.50.1", strip_prefix = "rules_rust-{version}", - sha256 = "a4b8ede7723088dff1e909632c4282e51ddbe0e44c38eea013ee0f12d348b1c7", + sha256 = "ddfc0210b19498086d09c458672ef2a6fb7790103dbb1b2da73c54677c330ed1", urls = ["https://github.com/bazelbuild/rules_rust/archive/{version}.tar.gz"], use_category = [ "controlplane", @@ -1463,7 +1463,7 @@ REPOSITORY_LOCATIONS_SPEC = dict( ], implied_untracked_deps = ["rules_cc"], extensions = ["envoy.wasm.runtime.wasmtime"], - release_date = "2024-07-19", + release_date = "2024-09-11", cpe = "N/A", license = "Apache-2.0", license_url = "https://github.com/bazelbuild/rules_rust/blob/{version}/LICENSE.txt", From c6aa25c0dfc17a8f8df4fd52fc7665e1799aa142 Mon Sep 17 00:00:00 2001 From: alyssawilk Date: Wed, 18 Sep 2024 17:05:34 -0400 Subject: [PATCH 13/65] tooling: narrowing exception checks (#36185) I reviewed a PR adding exceptions to a previously exception free path without realizing it. Narrowing the checks so we're more likely to catch this in CI. Risk Level: n/a (tooling only) Testing: ci Docs Changes: n/a Release Notes: n/a part of https://github.com/envoyproxy/envoy/issues/27412 Signed-off-by: Alyssa Wilk --- tools/code_format/config.yaml | 86 +++++++++++++++++++++++++++-------- 1 file changed, 68 insertions(+), 18 deletions(-) diff --git a/tools/code_format/config.yaml b/tools/code_format/config.yaml index bbc5d3f81d..5b1d73eda6 100644 --- a/tools/code_format/config.yaml +++ b/tools/code_format/config.yaml @@ -160,36 +160,86 @@ paths: # Extensions can exempt entire directories but new extensions # points should ideally use StatusOr - source/extensions/access_loggers - - source/extensions/bootstrap - - source/extensions/clusters + - source/extensions/bootstrap/wasm/config.cc + - source/extensions/clusters/eds/ + - source/extensions/clusters/logical_dns + - source/extensions/clusters/original_dst + - source/extensions/clusters/redis + - source/extensions/clusters/static + - source/extensions/clusters/strict_dns - source/extensions/common - - source/extensions/config + - source/extensions/config/validators/minimum_clusters/minimum_clusters_validator.cc - source/extensions/config_subscription - - source/extensions/compression/zstd/common - - source/extensions/early_data - - source/extensions/filters + - source/extensions/compression/zstd/common/dictionary_manager.h + - source/extensions/filters/http/adaptive_concurrency/controller + - source/extensions/filters/http/admission_control + - source/extensions/filters/http/aws_lambda + - source/extensions/filters/http/aws_request_signing + - source/extensions/filters/http/bandwidth_limit + - source/extensions/filters/http/basic_auth + - source/extensions/filters/http/cache + - source/extensions/filters/http/cdn_loop + - source/extensions/filters/http/common + - source/extensions/filters/http/composite + - source/extensions/filters/http/ext_authz + - source/extensions/filters/http/ext_proc + - source/extensions/filters/http/file_system_buffer + - source/extensions/filters/http/gcp_authn + - source/extensions/filters/http/grpc_field_extraction + - source/extensions/filters/http/grpc_json_transcoder + - source/extensions/filters/http/grpc_stats + - source/extensions/filters/http/header_mutation + - source/extensions/filters/http/header_to_metadata + - source/extensions/filters/http/health_check + - source/extensions/filters/http/ip_tagging + - source/extensions/filters/http/json_to_metadata + - source/extensions/filters/http/jwt_authn + - source/extensions/filters/http/local_ratelimit + - source/extensions/filters/http/oauth2 + - source/extensions/filters/http/file_system_buffer + - source/extensions/filters/http/header_to_metadata + - source/extensions/filters/http/on_demand + - source/extensions/filters/http/json_to_metadata + - source/extensions/filters/http/json_to_metadata + - source/extensions/filters/http/thrift_to_metadata + - source/extensions/filters/http/lua + - source/extensions/filters/http/proto_message_extraction + - source/extensions/filters/http/rate_limit_quota + - source/extensions/filters/http/ratelimit + - source/extensions/filters/http/oauth2 + - source/extensions/filters/http/wasm + - source/extensions/filters/network + - source/extensions/filters/common + - source/extensions/filters/udp + - source/extensions/filters/listener - source/extensions/formatter - - source/extensions/geoip_providers + - source/extensions/geoip_providers/maxmind/geoip_provider.cc - source/extensions/grpc_credentials - - source/extensions/health_check + - source/extensions/health_check/event_sinks/file/file_sink_impl.h - source/extensions/health_checkers - - source/extensions/http - - source/extensions/io_socket + - source/extensions/http/cache/file_system_http_cache/config.cc + - source/extensions/http/custom_response + - source/extensions/http/early_header_mutation + - source/extensions/http/injected_credentials + - source/extensions/http/original_ip_detection + - source/extensions/http/stateful_session + - source/extensions/io_socket/user_space - source/extensions/key_value - - source/extensions/listener_managers - - source/extensions/load_balancing_policies + - source/extensions/load_balancing_policies/maglev + - source/extensions/load_balancing_policies/ring_hash + - source/extensions/load_balancing_policies/subset - source/extensions/matching - - source/extensions/network - - source/extensions/path + - source/extensions/network/dns_resolver/cares/ - source/extensions/quic/server_preferred_address - source/extensions/rate_limit_descriptors - source/extensions/resource_monitors - - source/extensions/retry - - source/extensions/router + - source/extensions/router/cluster_specifiers/lua/lua_cluster_specifier.cc - source/extensions/stat_sinks - - source/extensions/string_matcher + - source/extensions/string_matcher/lua/match.cc - source/extensions/tracers - - source/extensions/transport_sockets + - source/extensions/transport_sockets/internal_upstream + - source/extensions/transport_sockets/tls/cert_validator + - source/extensions/transport_sockets/tcp_stats/config.cc # Only one C++ file should instantiate grpc_init grpc_init: From a2d9eba9188e14d6238e779755b1f2bec73463d6 Mon Sep 17 00:00:00 2001 From: Adam Kotwasinski Date: Wed, 18 Sep 2024 16:03:15 -0700 Subject: [PATCH 14/65] kafka: upgrade to 3.8, add support for more requests (#36166) Commit Message: kafka: upgrade to 3.8, add support for more requests Additional Description: upgrade kafka dependency to 3.8, add necessary parsing code and deserializer to process new stuff present in 3.8 (nullable struct) Risk Level: low Testing: automated suite + manual with [envoy-kafka-tests](https://github.com/adamkotwasinski/envoy-kafka-tests/pull/13) Docs Changes: readme updates due to version bump Release Notes: n/a Platform Specific Features: n/a --------- Signed-off-by: Adam Kotwasinski --- bazel/repository_locations.bzl | 12 +- .../network/source/protocol/generator.py | 69 +++++++----- .../filters/network/source/serialization.h | 104 ++++++++++++++++++ .../network/test/serialization_test.cc | 16 +++ .../network_filters/kafka_broker_filter.rst | 5 +- .../network_filters/kafka_mesh_filter.rst | 2 +- 6 files changed, 172 insertions(+), 36 deletions(-) diff --git a/bazel/repository_locations.bzl b/bazel/repository_locations.bzl index 3ed519854c..6752ec066c 100644 --- a/bazel/repository_locations.bzl +++ b/bazel/repository_locations.bzl @@ -1333,13 +1333,13 @@ REPOSITORY_LOCATIONS_SPEC = dict( project_name = "Kafka (source)", project_desc = "Open-source distributed event streaming platform", project_url = "https://kafka.apache.org", - version = "3.5.1", - sha256 = "9715589a02148fb21bc80d79f29763dbd371457bedcbbeab3db4f5c7fdd2d29c", + version = "3.8.0", + sha256 = "8761a0c22738201d3049f11f78c8e6c0f201203ba799157e498ef7eb04c259f3", strip_prefix = "kafka-{version}/clients/src/main/resources/common/message", urls = ["https://github.com/apache/kafka/archive/{version}.zip"], use_category = ["dataplane_ext"], extensions = ["envoy.filters.network.kafka_broker", "envoy.filters.network.kafka_mesh"], - release_date = "2023-07-14", + release_date = "2024-07-23", cpe = "cpe:2.3:a:apache:kafka:*", license = "Apache-2.0", license_url = "https://github.com/apache/kafka/blob/{version}/LICENSE", @@ -1363,11 +1363,11 @@ REPOSITORY_LOCATIONS_SPEC = dict( project_name = "Kafka (server binary)", project_desc = "Open-source distributed event streaming platform", project_url = "https://kafka.apache.org", - version = "3.5.1", - sha256 = "f7b74d544023f2c0ec52a179de59975cb64e34ea03650d829328b407b560e4da", + version = "3.8.0", + sha256 = "e0297cc6fdb09ef9d9905751b25d2b629c17528f8629b60561eeff87ce29099c", strip_prefix = "kafka_2.13-{version}", urls = ["https://archive.apache.org/dist/kafka/{version}/kafka_2.13-{version}.tgz"], - release_date = "2023-07-21", + release_date = "2024-07-23", use_category = ["test_only"], ), proxy_wasm_cpp_sdk = dict( diff --git a/contrib/kafka/filters/network/source/protocol/generator.py b/contrib/kafka/filters/network/source/protocol/generator.py index 31762b1757..656856219d 100755 --- a/contrib/kafka/filters/network/source/protocol/generator.py +++ b/contrib/kafka/filters/network/source/protocol/generator.py @@ -153,9 +153,8 @@ def parse_messages(self, input_files): amended = re.sub(r'-2147483648', 'INT32_MIN', without_empty_newlines) message_spec = json.loads(amended) api_key = message_spec['apiKey'] - # (adam.kotwasinski) Higher API keys in the future versions of Kafka need - # some more changes to parse. - if api_key < 68 or api_key == 69: + # (adam.kotwasinski) Telemetry is not supported for now. + if api_key not in [71, 72]: message = self.parse_top_level_element(message_spec) messages.append(message) except Exception as e: @@ -224,8 +223,9 @@ def parse_complex_type(self, type_name, field_spec, versions): fields.append(child) # Some structures share the same name, use request/response as prefix. - if cpp_name in ['EntityData', 'EntryData', 'PartitionData', 'PartitionSnapshot', - 'SnapshotId', 'TopicData', 'TopicPartitions', 'TopicSnapshot']: + if cpp_name in ['Cursor', 'DirectoryData', 'EntityData', 'EntryData', 'PartitionData', + 'PartitionSnapshot', 'SnapshotId', 'TopicData', 'TopicPartitions', + 'TopicSnapshot']: cpp_name = self.type.capitalize() + type_name # Some of the types repeat multiple times (e.g. AlterableConfig). @@ -370,9 +370,9 @@ def example_value(self): class FieldSpec: """ - Represents a field present in a structure (request, or child structure thereof). - Contains name, type, and versions when it is used (nullable or not). - """ + Represents a field present in a structure (request, or child structure thereof). + Contains name, type, and versions when it is used (nullable or not). + """ def __init__(self, name, type, version_usage, version_usage_as_nullable): import re @@ -387,10 +387,10 @@ def is_nullable(self): def is_nullable_in_version(self, version): """ - Whether the field is nullable in given version. - Fields can be non-nullable in earlier versions. - See https://github.com/apache/kafka/tree/2.2.0-rc0/clients/src/main/resources/common/message#nullable-fields - """ + Whether the field is nullable in given version. + Fields can be non-nullable in earlier versions. + See https://github.com/apache/kafka/tree/3.8.0/clients/src/main/resources/common/message#nullable-fields + """ return version in self.version_usage_as_nullable def used_in_version(self, version): @@ -428,13 +428,21 @@ def example_value_for_test(self, version): def deserializer_name_in_version(self, version, compact): if self.is_nullable_in_version(version): - return 'Nullable%s' % self.type.deserializer_name_in_version(version, compact) + underlying_deserializer = self.type.deserializer_name_in_version(version, compact) + # Handles KAFKA-14425 - structs (complex types) can now be nullable. + if isinstance(self.type, Complex): + return 'NullableStructDeserializer<%s>' % underlying_deserializer + else: + return 'Nullable%s' % underlying_deserializer else: return self.type.deserializer_name_in_version(version, compact) def is_printable(self): return self.type.is_printable() + def __str__(self): + return '%s(%s)' % (self.name, self.type) + class TypeSpecification: @@ -471,10 +479,10 @@ def is_printable(self): class Array(TypeSpecification): """ - Represents array complex type. - To use instance of this type, it is necessary to declare structures required by self.underlying - (e.g. to use Array, we need to have `struct Foo {...}`). - """ + Represents array complex type. + To use instance of this type, it is necessary to declare structures required by self.underlying + (e.g. to use Array, we need to have `struct Foo {...}`). + """ def __init__(self, underlying): self.underlying = underlying @@ -505,6 +513,9 @@ def example_value_for_test(self, version): def is_printable(self): return self.underlying.is_printable() + def __str__(self): + return self.name + class Primitive(TypeSpecification): """ @@ -643,6 +654,9 @@ def example_value_for_test(self, version): def is_printable(self): return self.name not in ['Bytes'] + def __str__(self): + return self.name + class FieldSerializationSpec(): @@ -679,9 +693,9 @@ def register_flexible_versions(self, flexible_versions): def compute_declaration_chain(self): """ - Computes all dependencies, what means all non-primitive types used by this type. - They need to be declared before this struct is declared. - """ + Computes all dependencies, what means all non-primitive types used by this type. + They need to be declared before this struct is declared. + """ result = [] for field in self.fields: field_dependencies = field.type.compute_declaration_chain() @@ -700,10 +714,10 @@ def get_extra(self, key): def compute_constructors(self): """ - Field lists for different versions may not differ (as Kafka can bump version without any - changes). But constructors need to be unique, so we need to remove duplicates if the signatures - match. - """ + Field lists for different versions may not differ (as Kafka can bump version without any + changes). But constructors need to be unique, so we need to remove duplicates + if the signatures match. + """ signature_to_constructor = {} for field_list in self.compute_field_lists(): signature = field_list.constructor_signature() @@ -724,8 +738,8 @@ def compute_constructors(self): def compute_field_lists(self): """ - Return field lists representing each of structure versions. - """ + Return field lists representing each of structure versions. + """ field_lists = [] for version in self.versions: field_list = FieldList(version, version in self.flexible_versions, self.fields) @@ -772,6 +786,9 @@ def example_value_for_test(self, version): def is_printable(self): return True + def __str__(self): + return self.name + class RenderingHelper: """ diff --git a/contrib/kafka/filters/network/source/serialization.h b/contrib/kafka/filters/network/source/serialization.h index 902fbd9c00..f2ea6a7545 100644 --- a/contrib/kafka/filters/network/source/serialization.h +++ b/contrib/kafka/filters/network/source/serialization.h @@ -918,6 +918,72 @@ class NullableCompactArrayDeserializer bool ready_{false}; }; +/** + * Nullable objects are sent as single byte and following data. + * Reference: https://issues.apache.org/jira/browse/KAFKA-14425 + */ +template +class NullableStructDeserializer + : public Deserializer> { +public: + using ResponseType = absl::optional; + + uint32_t feed(absl::string_view& data) override { + + if (data.empty()) { + return 0; + } + + uint32_t bytes_read = 0; + + if (!marker_consumed_) { + // Read marker byte from input. + int8_t marker; + safeMemcpy(&marker, data.data()); + data = {data.data() + 1, data.size() - 1}; + bytes_read += 1; + marker_consumed_ = true; + + if (marker >= 0) { + data_buf_ = absl::make_optional(DeserializerType()); + } else { + return bytes_read; + } + } + + if (data_buf_) { + bytes_read += data_buf_->feed(data); + } + + return bytes_read; + } + + bool ready() const override { + if (marker_consumed_) { + if (data_buf_) { + return data_buf_->ready(); + } else { + return true; // It's an empty optional. + } + } else { + return false; + } + } + + ResponseType get() const override { + if (data_buf_) { + const typename ResponseType::value_type deserialized_form = data_buf_->get(); + return absl::make_optional(deserialized_form); + } else { + return absl::nullopt; + } + } + +private: + bool marker_consumed_{false}; + absl::optional data_buf_; // Present if marker was consumed and was 0 or more. +}; + /** * Kafka UUID is basically two longs, so we are going to keep model them the same way. * Reference: @@ -996,6 +1062,12 @@ class EncodingContext { */ template uint32_t computeSize(const NullableArray& arg) const; + /** + * Compute size of given nullable object, if it were to be encoded. + * @return serialized size of argument. + */ + template uint32_t computeSize(const absl::optional& arg) const; + /** * Compute size of given reference, if it were to be compactly encoded. * @return serialized size of argument. @@ -1032,6 +1104,12 @@ class EncodingContext { */ template uint32_t encode(const NullableArray& arg, Buffer::Instance& dst); + /** + * Encode given nullable object in a buffer. + * @return bytes written + */ + template uint32_t encode(const absl::optional& arg, Buffer::Instance& dst); + /** * Compactly encode given reference in a buffer. * @return bytes written. @@ -1135,6 +1213,15 @@ inline uint32_t EncodingContext::computeSize(const NullableArray& arg) const return arg ? computeSize(*arg) : sizeof(int32_t); } +/** + * Template overload for nullable T. + * The size of nullable object is 1 (for market byte) and the size of real object (if any). + */ +template +inline uint32_t EncodingContext::computeSize(const absl::optional& arg) const { + return 1 + (arg ? computeSize(*arg) : 0); +} + /** * Template overload for Uuid. */ @@ -1388,6 +1475,23 @@ uint32_t EncodingContext::encode(const NullableArray& arg, Buffer::Instance& } } +/** + * Encode nullable object as marker byte (1 if present, -1 otherwise), then if object is present, + * have it serialise itself. + */ +template +uint32_t EncodingContext::encode(const absl::optional& arg, Buffer::Instance& dst) { + if (arg) { + const int8_t marker = 1; + encode(marker, dst); + const uint32_t written = encode(*arg, dst); + return 1 + written; + } else { + const int8_t marker = -1; + return encode(marker, dst); + } +} + /** * Template overload for Uuid. */ diff --git a/contrib/kafka/filters/network/test/serialization_test.cc b/contrib/kafka/filters/network/test/serialization_test.cc index 59aa0e567b..bbb80c3bd8 100644 --- a/contrib/kafka/filters/network/test/serialization_test.cc +++ b/contrib/kafka/filters/network/test/serialization_test.cc @@ -41,6 +41,8 @@ TEST_EmptyDeserializerShouldNotBeReady(BytesDeserializer); TEST_EmptyDeserializerShouldNotBeReady(CompactBytesDeserializer); TEST_EmptyDeserializerShouldNotBeReady(NullableBytesDeserializer); TEST_EmptyDeserializerShouldNotBeReady(NullableCompactBytesDeserializer); +using ExampleNullableStructDeserializer = NullableStructDeserializer; +TEST_EmptyDeserializerShouldNotBeReady(ExampleNullableStructDeserializer); TEST_EmptyDeserializerShouldNotBeReady(UuidDeserializer); TEST(ArrayDeserializer, EmptyBufferShouldNotBeReady) { @@ -544,6 +546,20 @@ TEST(NullableCompactArrayDeserializer, ShouldConsumeCorrectAmountOfDataForLargeI NullableCompactArrayDeserializer>(value); } +// Nullable struct. + +using ExampleNSD = NullableStructDeserializer; + +TEST(NullableStructDeserializer, ShouldConsumeCorrectAmountOfData) { + const ExampleNSD::ResponseType value = {42}; + serializeThenDeserializeAndCheckEquality(value); +} + +TEST(NullableStructDeserializer, ShouldConsumeNullStruct) { + const ExampleNSD::ResponseType value = absl::nullopt; + serializeThenDeserializeAndCheckEquality(value); +} + // UUID. TEST(UuidDeserializer, ShouldDeserialize) { diff --git a/docs/root/configuration/listeners/network_filters/kafka_broker_filter.rst b/docs/root/configuration/listeners/network_filters/kafka_broker_filter.rst index b8d0302796..2025137c17 100644 --- a/docs/root/configuration/listeners/network_filters/kafka_broker_filter.rst +++ b/docs/root/configuration/listeners/network_filters/kafka_broker_filter.rst @@ -5,9 +5,8 @@ Kafka Broker filter The Apache Kafka broker filter decodes the client protocol for `Apache Kafka `_, both the requests and responses in the payload. -The message versions in `Kafka 3.5.1 `_ -are supported (apart from ConsumerGroupHeartbeat - what means consumers configured with -``group.protocol=consumer``). +The message versions in `Kafka 3.8.0 `_ +are supported. By default the filter attempts not to influence the communication between client and brokers, so the messages that could not be decoded (due to Kafka client or broker running a newer version than diff --git a/docs/root/configuration/listeners/network_filters/kafka_mesh_filter.rst b/docs/root/configuration/listeners/network_filters/kafka_mesh_filter.rst index 4729473489..6da435ad83 100644 --- a/docs/root/configuration/listeners/network_filters/kafka_mesh_filter.rst +++ b/docs/root/configuration/listeners/network_filters/kafka_mesh_filter.rst @@ -12,7 +12,7 @@ clients. The requests received by this filter instance can be forwarded to one of multiple clusters, depending on the configured forwarding rules. -Corresponding message versions from Kafka 3.5.1 are supported. +Corresponding message versions from Kafka 3.8.0 are supported. * This filter should be configured with the type URL ``type.googleapis.com/envoy.extensions.filters.network.kafka_mesh.v3alpha.KafkaMesh``. * :ref:`v3 API reference ` From 596beacc826b4d0d1ec57c112ce965a070a9d92c Mon Sep 17 00:00:00 2001 From: phlax Date: Thu, 19 Sep 2024 00:04:56 +0100 Subject: [PATCH 15/65] python/deps: Update `cryptography` to resolve vulnerabilities (#36180) Signed-off-by: Ryan Northey --- tools/base/requirements.in | 3 +- tools/base/requirements.txt | 68 +++++++++++++++++-------------------- 2 files changed, 34 insertions(+), 37 deletions(-) diff --git a/tools/base/requirements.in b/tools/base/requirements.in index 608947efed..0cd07a89d4 100644 --- a/tools/base/requirements.in +++ b/tools/base/requirements.in @@ -10,7 +10,7 @@ clang-format==14.0.6 clang-tidy==14.0.6 colorama coloredlogs -cryptography>=42.0.0 +cryptography>=43.0.1 dependatool>=0.2.2 envoy.base.utils>=0.5.0 envoy.code.check>=0.5.12 @@ -36,6 +36,7 @@ ply # `MessageFactory class is deprecated. Please use GetMessageClass() instead of MessageFactory.GetPrototype` protobuf<5.29.0 pygithub +pyopenssl>=24.2.1 pyreadline pyyaml setuptools diff --git a/tools/base/requirements.txt b/tools/base/requirements.txt index 354b0da3c7..7d8dd8884d 100644 --- a/tools/base/requirements.txt +++ b/tools/base/requirements.txt @@ -458,39 +458,34 @@ coloredlogs==15.0.1 \ crcmod==1.7 \ --hash=sha256:dc7051a0db5f2bd48665a990d3ec1cc305a466a77358ca4492826f41f283601e # via gsutil -cryptography==42.0.8 \ - --hash=sha256:013629ae70b40af70c9a7a5db40abe5d9054e6f4380e50ce769947b73bf3caad \ - --hash=sha256:2346b911eb349ab547076f47f2e035fc8ff2c02380a7cbbf8d87114fa0f1c583 \ - --hash=sha256:2f66d9cd9147ee495a8374a45ca445819f8929a3efcd2e3df6428e46c3cbb10b \ - --hash=sha256:2f88d197e66c65be5e42cd72e5c18afbfae3f741742070e3019ac8f4ac57262c \ - --hash=sha256:31f721658a29331f895a5a54e7e82075554ccfb8b163a18719d342f5ffe5ecb1 \ - --hash=sha256:343728aac38decfdeecf55ecab3264b015be68fc2816ca800db649607aeee648 \ - --hash=sha256:5226d5d21ab681f432a9c1cf8b658c0cb02533eece706b155e5fbd8a0cdd3949 \ - --hash=sha256:57080dee41209e556a9a4ce60d229244f7a66ef52750f813bfbe18959770cfba \ - --hash=sha256:5a94eccb2a81a309806027e1670a358b99b8fe8bfe9f8d329f27d72c094dde8c \ - --hash=sha256:6b7c4f03ce01afd3b76cf69a5455caa9cfa3de8c8f493e0d3ab7d20611c8dae9 \ - --hash=sha256:7016f837e15b0a1c119d27ecd89b3515f01f90a8615ed5e9427e30d9cdbfed3d \ - --hash=sha256:81884c4d096c272f00aeb1f11cf62ccd39763581645b0812e99a91505fa48e0c \ - --hash=sha256:81d8a521705787afe7a18d5bfb47ea9d9cc068206270aad0b96a725022e18d2e \ - --hash=sha256:8d09d05439ce7baa8e9e95b07ec5b6c886f548deb7e0f69ef25f64b3bce842f2 \ - --hash=sha256:961e61cefdcb06e0c6d7e3a1b22ebe8b996eb2bf50614e89384be54c48c6b63d \ - --hash=sha256:9c0c1716c8447ee7dbf08d6db2e5c41c688544c61074b54fc4564196f55c25a7 \ - --hash=sha256:a0608251135d0e03111152e41f0cc2392d1e74e35703960d4190b2e0f4ca9c70 \ - --hash=sha256:a0c5b2b0585b6af82d7e385f55a8bc568abff8923af147ee3c07bd8b42cda8b2 \ - --hash=sha256:ad803773e9df0b92e0a817d22fd8a3675493f690b96130a5e24f1b8fabbea9c7 \ - --hash=sha256:b297f90c5723d04bcc8265fc2a0f86d4ea2e0f7ab4b6994459548d3a6b992a14 \ - --hash=sha256:ba4f0a211697362e89ad822e667d8d340b4d8d55fae72cdd619389fb5912eefe \ - --hash=sha256:c4783183f7cb757b73b2ae9aed6599b96338eb957233c58ca8f49a49cc32fd5e \ - --hash=sha256:c9bb2ae11bfbab395bdd072985abde58ea9860ed84e59dbc0463a5d0159f5b71 \ - --hash=sha256:cafb92b2bc622cd1aa6a1dce4b93307792633f4c5fe1f46c6b97cf67073ec961 \ - --hash=sha256:d45b940883a03e19e944456a558b67a41160e367a719833c53de6911cabba2b7 \ - --hash=sha256:dc0fdf6787f37b1c6b08e6dfc892d9d068b5bdb671198c72072828b80bd5fe4c \ - --hash=sha256:dea567d1b0e8bc5764b9443858b673b734100c2871dc93163f58c46a97a83d28 \ - --hash=sha256:dec9b018df185f08483f294cae6ccac29e7a6e0678996587363dc352dc65c842 \ - --hash=sha256:e3ec3672626e1b9e55afd0df6d774ff0e953452886e06e0f1eb7eb0c832e8902 \ - --hash=sha256:e599b53fd95357d92304510fb7bda8523ed1f79ca98dce2f43c115950aa78801 \ - --hash=sha256:fa76fbb7596cc5839320000cdd5d0955313696d9511debab7ee7278fc8b5c84a \ - --hash=sha256:fff12c88a672ab9c9c1cf7b0c80e3ad9e2ebd9d828d955c126be4fd3e5578c9e +cryptography==43.0.1 \ + --hash=sha256:014f58110f53237ace6a408b5beb6c427b64e084eb451ef25a28308270086494 \ + --hash=sha256:1bbcce1a551e262dfbafb6e6252f1ae36a248e615ca44ba302df077a846a8806 \ + --hash=sha256:203e92a75716d8cfb491dc47c79e17d0d9207ccffcbcb35f598fbe463ae3444d \ + --hash=sha256:27e613d7077ac613e399270253259d9d53872aaf657471473ebfc9a52935c062 \ + --hash=sha256:2bd51274dcd59f09dd952afb696bf9c61a7a49dfc764c04dd33ef7a6b502a1e2 \ + --hash=sha256:38926c50cff6f533f8a2dae3d7f19541432610d114a70808f0926d5aaa7121e4 \ + --hash=sha256:511f4273808ab590912a93ddb4e3914dfd8a388fed883361b02dea3791f292e1 \ + --hash=sha256:58d4e9129985185a06d849aa6df265bdd5a74ca6e1b736a77959b498e0505b85 \ + --hash=sha256:5b43d1ea6b378b54a1dc99dd8a2b5be47658fe9a7ce0a58ff0b55f4b43ef2b84 \ + --hash=sha256:61ec41068b7b74268fa86e3e9e12b9f0c21fcf65434571dbb13d954bceb08042 \ + --hash=sha256:666ae11966643886c2987b3b721899d250855718d6d9ce41b521252a17985f4d \ + --hash=sha256:68aaecc4178e90719e95298515979814bda0cbada1256a4485414860bd7ab962 \ + --hash=sha256:7c05650fe8023c5ed0d46793d4b7d7e6cd9c04e68eabe5b0aeea836e37bdcec2 \ + --hash=sha256:80eda8b3e173f0f247f711eef62be51b599b5d425c429b5d4ca6a05e9e856baa \ + --hash=sha256:8385d98f6a3bf8bb2d65a73e17ed87a3ba84f6991c155691c51112075f9ffc5d \ + --hash=sha256:88cce104c36870d70c49c7c8fd22885875d950d9ee6ab54df2745f83ba0dc365 \ + --hash=sha256:9d3cdb25fa98afdd3d0892d132b8d7139e2c087da1712041f6b762e4f807cc96 \ + --hash=sha256:a575913fb06e05e6b4b814d7f7468c2c660e8bb16d8d5a1faf9b33ccc569dd47 \ + --hash=sha256:ac119bb76b9faa00f48128b7f5679e1d8d437365c5d26f1c2c3f0da4ce1b553d \ + --hash=sha256:c1332724be35d23a854994ff0b66530119500b6053d0bd3363265f7e5e77288d \ + --hash=sha256:d03a475165f3134f773d1388aeb19c2d25ba88b6a9733c5c590b9ff7bbfa2e0c \ + --hash=sha256:d75601ad10b059ec832e78823b348bfa1a59f6b8d545db3a24fd44362a1564cb \ + --hash=sha256:de41fd81a41e53267cb020bb3a7212861da53a7d39f863585d13ea11049cf277 \ + --hash=sha256:e710bf40870f4db63c3d7d929aa9e09e4e7ee219e703f949ec4073b4294f6172 \ + --hash=sha256:ea25acb556320250756e53f9e20a4177515f012c9eaea17eb7587a8c4d8ae034 \ + --hash=sha256:f98bf604c82c416bc829e490c700ca1553eafdf2912a91e23a79d97d9801372a \ + --hash=sha256:fba1007b3ef89946dbbb515aeeb41e30203b004f0b4b00e5e16078b518563289 # via # -r requirements.in # aioquic @@ -1152,10 +1147,11 @@ pynacl==1.5.0 \ --hash=sha256:a422368fc821589c228f4c49438a368831cb5bbc0eab5ebe1d7fac9dded6567b \ --hash=sha256:e46dae94e34b085175f8abb3b0aaa7da40767865ac82c928eeb9e57e1ea8a543 # via pygithub -pyopenssl==24.1.0 \ - --hash=sha256:17ed5be5936449c5418d1cd269a1a9e9081bc54c17aed272b45856a3d3dc86ad \ - --hash=sha256:cabed4bfaa5df9f1a16c0ef64a0cb65318b5cd077a7eda7d6970131ca2f41a6f +pyopenssl==24.2.1 \ + --hash=sha256:4247f0dbe3748d560dcbb2ff3ea01af0f9a1a001ef5f7c4c647956ed8cbf0e95 \ + --hash=sha256:967d5719b12b243588573f39b0c677637145c7a1ffedcd495a487e58177fbb8d # via + # -r requirements.in # aioquic # gcs-oauth2-boto-plugin # gsutil From 6069f86c529d9ee3712cdd5f7cb738d3f4fb1acf Mon Sep 17 00:00:00 2001 From: yanjunxiang-google <78807980+yanjunxiang-google@users.noreply.github.com> Date: Wed, 18 Sep 2024 21:50:39 -0400 Subject: [PATCH 16/65] Using drop_overload category in EDS to report drop_overload stats in LRS (#36047) Using drop_overload category in EDS to report drop_overload stats in LRS. This is a follow up PR to support drop_overload load report service: https://github.com/envoyproxy/envoy/pull/31384 Currently it is reporting with a fixed category "drop_overload". This PR changes it into the category passed in by cluster or EDS policy configuration. --------- Signed-off-by: Yanjun Xiang --- changelogs/current.yaml | 5 ++++ envoy/upstream/thread_local_cluster.h | 10 ++++++++ envoy/upstream/upstream.h | 10 ++++++++ .../common/upstream/cluster_manager_impl.cc | 25 +++++++++++-------- source/common/upstream/cluster_manager_impl.h | 13 +++++++--- .../upstream/health_discovery_service.h | 6 ++++- source/common/upstream/load_stats_reporter.cc | 2 +- source/common/upstream/upstream_impl.cc | 1 + source/common/upstream/upstream_impl.h | 3 +++ source/server/admin/config_dump_handler.cc | 2 +- test/common/upstream/upstream_impl_test.cc | 4 ++- test/mocks/upstream/cluster.cc | 6 +++++ test/mocks/upstream/cluster.h | 3 +++ test/mocks/upstream/thread_local_cluster.cc | 5 ++++ test/mocks/upstream/thread_local_cluster.h | 2 ++ test/server/admin/config_dump_handler_test.cc | 3 ++- 16 files changed, 82 insertions(+), 18 deletions(-) diff --git a/changelogs/current.yaml b/changelogs/current.yaml index e60a462af2..bfc2be2fc5 100644 --- a/changelogs/current.yaml +++ b/changelogs/current.yaml @@ -128,6 +128,11 @@ bug_fixes: the number of requests per I/O cycle is configured and an HTTP decoder filter that pauses filter chain is present. This behavior can be reverted by setting the runtime guard ``envoy.reloadable_features.use_filter_manager_state_for_downstream_end_stream`` to false. +- area: upstream + change: | + Fixed a bug using hard coded drop category when reporting drop_overload stats to the load report service. + It is changed to use drop category that is set in + :ref:`category `. - area: proxy_filter change: | Fixed a bug in the ``CONNECT`` implementation that would cause the ``CONNECT`` request created to be invalid when the diff --git a/envoy/upstream/thread_local_cluster.h b/envoy/upstream/thread_local_cluster.h index cb97bc55ef..69a42751c0 100644 --- a/envoy/upstream/thread_local_cluster.h +++ b/envoy/upstream/thread_local_cluster.h @@ -157,10 +157,20 @@ class ThreadLocalCluster { */ virtual UnitFloat dropOverload() const PURE; + /** + * @return the thread local cluster drop_category configuration. + */ + virtual const std::string& dropCategory() const PURE; + /** * Set up the drop_overload value for the thread local cluster. */ virtual void setDropOverload(UnitFloat drop_overload) PURE; + + /** + * Set up the drop_category value for the thread local cluster. + */ + virtual void setDropCategory(absl::string_view drop_category) PURE; }; using ThreadLocalClusterOptRef = absl::optional>; diff --git a/envoy/upstream/upstream.h b/envoy/upstream/upstream.h index a4c6c2b889..e307de9471 100644 --- a/envoy/upstream/upstream.h +++ b/envoy/upstream/upstream.h @@ -1315,10 +1315,20 @@ class Cluster { */ virtual UnitFloat dropOverload() const PURE; + /** + * @return the cluster drop_category_ configuration. + */ + virtual const std::string& dropCategory() const PURE; + /** * Set up the drop_overload value for the cluster. */ virtual void setDropOverload(UnitFloat drop_overload) PURE; + + /** + * Set up the drop_category value for the thread local cluster. + */ + virtual void setDropCategory(absl::string_view drop_category) PURE; }; using ClusterSharedPtr = std::shared_ptr; diff --git a/source/common/upstream/cluster_manager_impl.cc b/source/common/upstream/cluster_manager_impl.cc index fcdef2ad85..c65cdb5f15 100644 --- a/source/common/upstream/cluster_manager_impl.cc +++ b/source/common/upstream/cluster_manager_impl.cc @@ -1236,15 +1236,18 @@ void ClusterManagerImpl::postThreadLocalClusterUpdate(ClusterManagerCluster& cm_ pending_cluster_creations_.erase(cm_cluster.cluster().info()->name()); const UnitFloat drop_overload = cm_cluster.cluster().dropOverload(); + const std::string drop_category = cm_cluster.cluster().dropCategory(); // Populate the cluster initialization object based on this update. ClusterInitializationObjectConstSharedPtr cluster_initialization_object = - addOrUpdateClusterInitializationObjectIfSupported( - params, cm_cluster.cluster().info(), load_balancer_factory, host_map, drop_overload); + addOrUpdateClusterInitializationObjectIfSupported(params, cm_cluster.cluster().info(), + load_balancer_factory, host_map, + drop_overload, drop_category); tls_.runOnAllThreads([info = cm_cluster.cluster().info(), params = std::move(params), add_or_update_cluster, load_balancer_factory, map = std::move(host_map), cluster_initialization_object = std::move(cluster_initialization_object), - drop_overload](OptRef cluster_manager) { + drop_overload, drop_category = std::move(drop_category)]( + OptRef cluster_manager) { ASSERT(cluster_manager.has_value(), "Expected the ThreadLocalClusterManager to be set during ClusterManagerImpl creation."); @@ -1302,6 +1305,7 @@ void ClusterManagerImpl::postThreadLocalClusterUpdate(ClusterManagerCluster& cm_ if (cluster_manager->thread_local_clusters_[info->name()]) { cluster_manager->thread_local_clusters_[info->name()]->setDropOverload(drop_overload); + cluster_manager->thread_local_clusters_[info->name()]->setDropCategory(drop_category); } for (const auto& per_priority : params.per_priority_update_params_) { cluster_manager->updateClusterMembership( @@ -1338,7 +1342,7 @@ ClusterManagerImpl::ClusterInitializationObjectConstSharedPtr ClusterManagerImpl::addOrUpdateClusterInitializationObjectIfSupported( const ThreadLocalClusterUpdateParams& params, ClusterInfoConstSharedPtr cluster_info, LoadBalancerFactorySharedPtr load_balancer_factory, HostMapConstSharedPtr map, - UnitFloat drop_overload) { + UnitFloat drop_overload, absl::string_view drop_category) { if (!deferralIsSupportedForCluster(cluster_info)) { return nullptr; } @@ -1369,13 +1373,13 @@ ClusterManagerImpl::addOrUpdateClusterInitializationObjectIfSupported( entry->second->per_priority_state_, params, std::move(cluster_info), load_balancer_factory == nullptr ? entry->second->load_balancer_factory_ : load_balancer_factory, - map, drop_overload); + map, drop_overload, drop_category); cluster_initialization_map_[cluster_name] = new_initialization_object; return new_initialization_object; } else { // We need to create a fresh Cluster Initialization Object. auto new_initialization_object = std::make_shared( - params, std::move(cluster_info), load_balancer_factory, map, drop_overload); + params, std::move(cluster_info), load_balancer_factory, map, drop_overload, drop_category); cluster_initialization_map_[cluster_name] = new_initialization_object; return new_initialization_object; } @@ -1409,6 +1413,7 @@ ClusterManagerImpl::ThreadLocalClusterManagerImpl::initializeClusterInlineIfExis initialization_object->cross_priority_host_map_); } thread_local_clusters_[cluster]->setDropOverload(initialization_object->drop_overload_); + thread_local_clusters_[cluster]->setDropCategory(initialization_object->drop_category_); // Remove the CIO as we've initialized the cluster. thread_local_deferred_clusters_.erase(entry); @@ -1419,9 +1424,9 @@ ClusterManagerImpl::ThreadLocalClusterManagerImpl::initializeClusterInlineIfExis ClusterManagerImpl::ClusterInitializationObject::ClusterInitializationObject( const ThreadLocalClusterUpdateParams& params, ClusterInfoConstSharedPtr cluster_info, LoadBalancerFactorySharedPtr load_balancer_factory, HostMapConstSharedPtr map, - UnitFloat drop_overload) + UnitFloat drop_overload, absl::string_view drop_category) : cluster_info_(std::move(cluster_info)), load_balancer_factory_(load_balancer_factory), - cross_priority_host_map_(map), drop_overload_(drop_overload) { + cross_priority_host_map_(map), drop_overload_(drop_overload), drop_category_(drop_category) { // Copy the update since the map is empty. for (const auto& update : params.per_priority_update_params_) { per_priority_state_.emplace(update.priority_, update); @@ -1432,10 +1437,10 @@ ClusterManagerImpl::ClusterInitializationObject::ClusterInitializationObject( const absl::flat_hash_map& per_priority_state, const ThreadLocalClusterUpdateParams& update_params, ClusterInfoConstSharedPtr cluster_info, LoadBalancerFactorySharedPtr load_balancer_factory, HostMapConstSharedPtr map, - UnitFloat drop_overload) + UnitFloat drop_overload, absl::string_view drop_category) : per_priority_state_(per_priority_state), cluster_info_(std::move(cluster_info)), load_balancer_factory_(load_balancer_factory), cross_priority_host_map_(map), - drop_overload_(drop_overload) { + drop_overload_(drop_overload), drop_category_(drop_category) { // Because EDS Clusters receive the entire ClusterLoadAssignment but only // provides the delta we must process the hosts_added and hosts_removed and diff --git a/source/common/upstream/cluster_manager_impl.h b/source/common/upstream/cluster_manager_impl.h index da8e2eda75..3d4bfa1656 100644 --- a/source/common/upstream/cluster_manager_impl.h +++ b/source/common/upstream/cluster_manager_impl.h @@ -427,20 +427,22 @@ class ClusterManagerImpl : public ClusterManager, ClusterInitializationObject(const ThreadLocalClusterUpdateParams& params, ClusterInfoConstSharedPtr cluster_info, LoadBalancerFactorySharedPtr load_balancer_factory, - HostMapConstSharedPtr map, UnitFloat drop_overload); + HostMapConstSharedPtr map, UnitFloat drop_overload, + absl::string_view drop_category); ClusterInitializationObject( const absl::flat_hash_map& per_priority_state, const ThreadLocalClusterUpdateParams& update_params, ClusterInfoConstSharedPtr cluster_info, LoadBalancerFactorySharedPtr load_balancer_factory, HostMapConstSharedPtr map, - UnitFloat drop_overload); + UnitFloat drop_overload, absl::string_view drop_category); absl::flat_hash_map per_priority_state_; const ClusterInfoConstSharedPtr cluster_info_; const LoadBalancerFactorySharedPtr load_balancer_factory_; const HostMapConstSharedPtr cross_priority_host_map_; UnitFloat drop_overload_{0}; + const std::string drop_category_; }; using ClusterInitializationObjectConstSharedPtr = @@ -610,7 +612,11 @@ class ClusterManagerImpl : public ClusterManager, void drainConnPools(DrainConnectionsHostPredicate predicate, ConnectionPool::DrainBehavior behavior); UnitFloat dropOverload() const override { return drop_overload_; } + const std::string& dropCategory() const override { return drop_category_; } void setDropOverload(UnitFloat drop_overload) override { drop_overload_ = drop_overload; } + void setDropCategory(absl::string_view drop_category) override { + drop_category_ = drop_category; + } private: Http::ConnectionPool::Instance* @@ -627,6 +633,7 @@ class ClusterManagerImpl : public ClusterManager, ThreadLocalClusterManagerImpl& parent_; PrioritySetImpl priority_set_; UnitFloat drop_overload_{0}; + std::string drop_category_; // Don't change the order of cluster_info_ and lb_factory_/lb_ as the the lb_factory_/lb_ // may keep a reference to the cluster_info_. @@ -889,7 +896,7 @@ class ClusterManagerImpl : public ClusterManager, ClusterInitializationObjectConstSharedPtr addOrUpdateClusterInitializationObjectIfSupported( const ThreadLocalClusterUpdateParams& params, ClusterInfoConstSharedPtr cluster_info, LoadBalancerFactorySharedPtr load_balancer_factory, HostMapConstSharedPtr map, - UnitFloat drop_overload); + UnitFloat drop_overload, absl::string_view drop_category); bool deferralIsSupportedForCluster(const ClusterInfoConstSharedPtr& info) const; diff --git a/source/common/upstream/health_discovery_service.h b/source/common/upstream/health_discovery_service.h index 2cd21b06da..f2e1d539e4 100644 --- a/source/common/upstream/health_discovery_service.h +++ b/source/common/upstream/health_discovery_service.h @@ -72,8 +72,10 @@ class HdsCluster : public Cluster, Logger::Loggable { std::vector healthCheckers() { return health_checkers_; }; std::vector hosts() { return *hosts_; }; - UnitFloat dropOverload() const override { return UnitFloat(0); } + UnitFloat dropOverload() const override { return drop_overload_; } + const std::string& dropCategory() const override { return drop_category_; } void setDropOverload(UnitFloat) override {} + void setDropCategory(absl::string_view) override {} protected: PrioritySetImpl priority_set_; @@ -99,6 +101,8 @@ class HdsCluster : public Cluster, Logger::Loggable { std::vector health_checkers_; HealthCheckerMap health_checkers_map_; TimeSource& time_source_; + UnitFloat drop_overload_{0}; + const std::string drop_category_; absl::Status updateHealthchecks( const Protobuf::RepeatedPtrField& health_checks); diff --git a/source/common/upstream/load_stats_reporter.cc b/source/common/upstream/load_stats_reporter.cc index a06d85c40d..0e64bf7e88 100644 --- a/source/common/upstream/load_stats_reporter.cc +++ b/source/common/upstream/load_stats_reporter.cc @@ -127,7 +127,7 @@ void LoadStatsReporter::sendLoadStatsRequest() { cluster.info()->loadReportStats().upstream_rq_drop_overload_.latch(); if (drop_overload_count > 0) { auto* dropped_request = cluster_stats->add_dropped_requests(); - dropped_request->set_category("drop_overload"); + dropped_request->set_category(cluster.dropCategory()); dropped_request->set_dropped_count(drop_overload_count); } diff --git a/source/common/upstream/upstream_impl.cc b/source/common/upstream/upstream_impl.cc index a336aa2689..bfee8e6b2b 100644 --- a/source/common/upstream/upstream_impl.cc +++ b/source/common/upstream/upstream_impl.cc @@ -1832,6 +1832,7 @@ absl::Status ClusterImplBase::parseDropOverloadConfig( drop_ratio = std::min(drop_ratio, float(drop_ratio_runtime) / float(MAX_DROP_OVERLOAD_RUNTIME)); drop_overload_ = UnitFloat(drop_ratio); + drop_category_ = policy.drop_overloads(0).category(); return absl::OkStatus(); } diff --git a/source/common/upstream/upstream_impl.h b/source/common/upstream/upstream_impl.h index 4ce4791a01..47d3246857 100644 --- a/source/common/upstream/upstream_impl.h +++ b/source/common/upstream/upstream_impl.h @@ -1200,7 +1200,9 @@ class ClusterImplBase : public Cluster, protected Logger::Loggable callback) override; UnitFloat dropOverload() const override { return drop_overload_; } + const std::string& dropCategory() const override { return drop_category_; } void setDropOverload(UnitFloat drop_overload) override { drop_overload_ = drop_overload; } + void setDropCategory(absl::string_view drop_category) override { drop_category_ = drop_category; } protected: ClusterImplBase(const envoy::config::cluster::v3::Cluster& cluster, @@ -1271,6 +1273,7 @@ class ClusterImplBase : public Cluster, protected Logger::Loggable 0) { auto* drop_overload = policy.add_drop_overloads(); - drop_overload->set_category("drop_overload"); + drop_overload->set_category(cluster.dropCategory()); auto* percent = drop_overload->mutable_drop_percentage(); percent->set_denominator(envoy::type::v3::FractionalPercent::MILLION); percent->set_numerator(uint32_t(value)); diff --git a/test/common/upstream/upstream_impl_test.cc b/test/common/upstream/upstream_impl_test.cc index 3ef5cef66f..be63bcf58d 100644 --- a/test/common/upstream/upstream_impl_test.cc +++ b/test/common/upstream/upstream_impl_test.cc @@ -275,6 +275,7 @@ TEST_P(StrictDnsParamTest, DropOverLoadConfigTestBasicMillion) { false); auto cluster = *StrictDnsClusterImpl::create(cluster_config, factory_context, dns_resolver); EXPECT_EQ(0.000035f, cluster->dropOverload().value()); + EXPECT_EQ("test", cluster->dropCategory()); } TEST_P(StrictDnsParamTest, DropOverLoadConfigTestBasicTenThousand) { @@ -290,7 +291,7 @@ TEST_P(StrictDnsParamTest, DropOverLoadConfigTestBasicTenThousand) { load_assignment: policy: drop_overloads: - category: test + category: foo drop_percentage: numerator: 1000 denominator: TEN_THOUSAND @@ -301,6 +302,7 @@ TEST_P(StrictDnsParamTest, DropOverLoadConfigTestBasicTenThousand) { false); auto cluster = *StrictDnsClusterImpl::create(cluster_config, factory_context, dns_resolver); EXPECT_EQ(0.1f, cluster->dropOverload().value()); + EXPECT_EQ("foo", cluster->dropCategory()); } TEST_P(StrictDnsParamTest, DropOverLoadConfigTestBadDenominator) { diff --git a/test/mocks/upstream/cluster.cc b/test/mocks/upstream/cluster.cc index 39c2bd4e77..e1cb719069 100644 --- a/test/mocks/upstream/cluster.cc +++ b/test/mocks/upstream/cluster.cc @@ -8,6 +8,8 @@ namespace Upstream { using ::testing::_; using ::testing::Invoke; using ::testing::Return; +using ::testing::ReturnRef; + MockCluster::MockCluster() { ON_CALL(*this, info()).WillByDefault(Return(info_)); ON_CALL(*this, initialize(_)) @@ -16,9 +18,13 @@ MockCluster::MockCluster() { initialize_callback_ = callback; })); ON_CALL(*this, dropOverload()).WillByDefault(Return(drop_overload_)); + ON_CALL(*this, dropCategory()).WillByDefault(ReturnRef(drop_category_)); ON_CALL(*this, setDropOverload(_)).WillByDefault(Invoke([this](UnitFloat drop_overload) -> void { drop_overload_ = drop_overload; })); + ON_CALL(*this, setDropCategory(_)) + .WillByDefault(Invoke( + [this](absl::string_view drop_category) -> void { drop_category_ = drop_category; })); } MockCluster::~MockCluster() = default; diff --git a/test/mocks/upstream/cluster.h b/test/mocks/upstream/cluster.h index f2fe2bad99..cb90626596 100644 --- a/test/mocks/upstream/cluster.h +++ b/test/mocks/upstream/cluster.h @@ -26,12 +26,15 @@ class MockCluster : public Cluster { MOCK_METHOD(PrioritySet&, prioritySet, ()); MOCK_METHOD(const PrioritySet&, prioritySet, (), (const)); MOCK_METHOD(UnitFloat, dropOverload, (), (const)); + MOCK_METHOD(const std::string&, dropCategory, (), (const)); MOCK_METHOD(void, setDropOverload, (UnitFloat)); + MOCK_METHOD(void, setDropCategory, (absl::string_view)); std::shared_ptr info_{new ::testing::NiceMock()}; std::function initialize_callback_; Network::Address::InstanceConstSharedPtr source_address_; UnitFloat drop_overload_{0}; + std::string drop_category_{"drop_overload"}; }; } // namespace Upstream } // namespace Envoy diff --git a/test/mocks/upstream/thread_local_cluster.cc b/test/mocks/upstream/thread_local_cluster.cc index 2e4951d461..bc1024331b 100644 --- a/test/mocks/upstream/thread_local_cluster.cc +++ b/test/mocks/upstream/thread_local_cluster.cc @@ -19,9 +19,14 @@ MockThreadLocalCluster::MockThreadLocalCluster() { .WillByDefault(Return(Upstream::TcpPoolData([]() {}, &tcp_conn_pool_))); ON_CALL(*this, httpAsyncClient()).WillByDefault(ReturnRef(async_client_)); ON_CALL(*this, dropOverload()).WillByDefault(Return(cluster_.drop_overload_)); + ON_CALL(*this, dropCategory()).WillByDefault(ReturnRef(cluster_.drop_category_)); ON_CALL(*this, setDropOverload(_)).WillByDefault(Invoke([this](UnitFloat drop_overload) -> void { cluster_.drop_overload_ = drop_overload; })); + ON_CALL(*this, setDropCategory(_)) + .WillByDefault(Invoke([this](absl::string_view drop_category) -> void { + cluster_.drop_category_ = drop_category; + })); } MockThreadLocalCluster::~MockThreadLocalCluster() = default; diff --git a/test/mocks/upstream/thread_local_cluster.h b/test/mocks/upstream/thread_local_cluster.h index 0efb100c20..266aa94c99 100644 --- a/test/mocks/upstream/thread_local_cluster.h +++ b/test/mocks/upstream/thread_local_cluster.h @@ -40,7 +40,9 @@ class MockThreadLocalCluster : public ThreadLocalCluster { MOCK_METHOD(Tcp::AsyncTcpClientPtr, tcpAsyncClient, (LoadBalancerContext * context, Tcp::AsyncTcpClientOptionsConstSharedPtr options)); MOCK_METHOD(UnitFloat, dropOverload, (), (const)); + MOCK_METHOD(const std::string&, dropCategory, (), (const)); MOCK_METHOD(void, setDropOverload, (UnitFloat)); + MOCK_METHOD(void, setDropCategory, (absl::string_view)); NiceMock cluster_; NiceMock lb_; diff --git a/test/server/admin/config_dump_handler_test.cc b/test/server/admin/config_dump_handler_test.cc index eb2718e0c8..4606be607e 100644 --- a/test/server/admin/config_dump_handler_test.cc +++ b/test/server/admin/config_dump_handler_test.cc @@ -151,7 +151,8 @@ TEST_P(AdminInstanceTest, ConfigDumpWithEndpoint) { hostname_for_healthcheck, "tcp://1.2.3.5:90", 5, 6); // Adding drop_overload config. ON_CALL(cluster, dropOverload()).WillByDefault(Return(UnitFloat(0.00035))); - + const std::string drop_overload = "drop_overload"; + ON_CALL(cluster, dropCategory()).WillByDefault(ReturnRef(drop_overload)); Buffer::OwnedImpl response; Http::TestResponseHeaderMapImpl header_map; EXPECT_EQ(Http::Code::OK, getCallback("/config_dump?include_eds", header_map, response)); From fdfdad004bc71f6db1fab2360546362bc1c2880a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 19 Sep 2024 08:54:37 +0100 Subject: [PATCH 17/65] build(deps): bump distroless/base-nossl-debian12 from `fb10a97` to `4cc93c5` in /ci (#36206) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- ci/Dockerfile-envoy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci/Dockerfile-envoy b/ci/Dockerfile-envoy index 826b3e869f..134511d212 100644 --- a/ci/Dockerfile-envoy +++ b/ci/Dockerfile-envoy @@ -58,7 +58,7 @@ COPY --chown=0:0 --chmod=755 \ # STAGE: envoy-distroless -FROM gcr.io/distroless/base-nossl-debian12:nonroot@sha256:fb10a979880367004a93467d9dad87eea1af67c6adda0a0060d2e785a8c1a0e6 AS envoy-distroless +FROM gcr.io/distroless/base-nossl-debian12:nonroot@sha256:4cc93c5b247e24470905bf3cdf8285aeac176bb0e7c62ee2b748a95c0c4123b5 AS envoy-distroless EXPOSE 10000 ENTRYPOINT ["/usr/local/bin/envoy"] CMD ["-c", "/etc/envoy/envoy.yaml"] From 8d74446c8a3d219572380731bae42ab328426996 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20R=2E=20Sede=C3=B1o?= Date: Thu, 19 Sep 2024 05:35:10 -0400 Subject: [PATCH 18/65] Fewer external deps (#36187) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit Message: Remove the native.bind entries for the following libraries: - libcircllhist - uring - ares - xxhash - sqlparser - tclap - fmtlib - spdlog - benchmark - libsxg - yaml_cpp - event - colm - ragel - zlib - brotlienc - brotlidec - zstd - msgpack - opentelemetry_api - dd_trace_cpp - cpp2sky - json - http_parser - hessian2_codec_object_codec_lib - hessian2_codec_codec_impl - su-exec - googletest - protoc - opencensus_trace - opencensus_trace_b3 - opencensus_trace_cloud_trace_context - opencensus_trace_grpc_trace_bin - opencensus_trace_trace_context - opencensus_exporter_ocagent - opencensus_exporter_stdout - opencensus_exporter_stackdriver - opencensus_exporter_zipkin - quiche_common_platform - quiche_http2_adapter - quiche_http2_protocol - quiche_http2_test_tools - quiche_quic_platform - quiche_quic_platform_base - quiche_http2_hpack - quiche_http2_hpack_decoder - jwt_verify_lib - simple_lru_cache_lib - luajit - tcmalloc - tcmalloc_profile_marshaler - tcmalloc_malloc_extension - gperftools - librdkafka Update `external_deps` that used them to `deps` of their actual locations. Some examples: - `zlib` ā†’ `//bazel/foreign_cc:zlib` - `json` ā†’ `@com_github_nlohmann_json//:json` The bindings that remain are either used by dependencies that need to be updated or have uses in some envoy bazel rules that make removing them trickier. These are the easy ones. Risk Level: low Testing: Building envoy and running integration test suites. Existing tests pass. --------- Signed-off-by: Alejandro R SedeƱo --- bazel/EXTERNAL_DEPS.md | 4 +- bazel/envoy_build_system.bzl | 4 +- bazel/envoy_internal.bzl | 18 +- bazel/envoy_library.bzl | 26 +- bazel/envoy_pch.bzl | 2 +- bazel/envoy_test.bzl | 5 +- bazel/external/json.BUILD | 19 -- bazel/external/quiche.BUILD | 20 +- bazel/foreign_cc/BUILD | 2 +- bazel/protobuf.patch | 4 +- bazel/repositories.bzl | 237 +----------------- ci/do_ci.sh | 2 +- contrib/common/sqlutils/source/BUILD | 2 +- contrib/common/sqlutils/test/BUILD | 2 +- .../cryptomb/private_key_providers/test/BUILD | 6 +- .../matching/input_matchers/source/BUILD | 8 +- .../matching/input_matchers/test/BUILD | 4 +- .../kafka/filters/network/source/mesh/BUILD | 5 +- contrib/kafka/filters/network/test/mesh/BUILD | 6 +- .../mysql_proxy/filters/network/test/BUILD | 2 +- .../qatzstd/compressor/source/BUILD | 2 +- .../qat/private_key_providers/source/BUILD | 4 +- contrib/sxg/filters/http/source/BUILD | 2 +- distribution/binary/BUILD | 2 +- distribution/binary/compiler.bzl | 2 +- envoy/grpc/BUILD | 4 +- mobile/bazel/protobuf.patch | 4 +- source/common/common/BUILD | 18 +- source/common/compression/zstd/common/BUILD | 2 +- source/common/crypto/BUILD | 4 +- source/common/event/BUILD | 14 +- source/common/filesystem/BUILD | 4 +- source/common/grpc/BUILD | 8 +- source/common/http/BUILD | 12 +- source/common/http/http1/BUILD | 2 +- source/common/http/http2/BUILD | 12 +- source/common/io/BUILD | 2 +- source/common/json/BUILD | 4 +- source/common/orca/BUILD | 8 +- source/common/protobuf/BUILD | 20 +- source/common/quic/BUILD | 30 +-- source/common/stats/BUILD | 4 +- source/common/tls/BUILD | 28 +-- source/common/tls/cert_validator/BUILD | 4 +- source/common/upstream/BUILD | 4 +- .../extensions/access_loggers/fluentd/BUILD | 4 +- source/extensions/common/dubbo/BUILD | 6 +- source/extensions/common/wasm/BUILD | 2 +- source/extensions/common/wasm/ext/BUILD | 2 +- .../compression/brotli/compressor/BUILD | 2 +- .../compression/brotli/decompressor/BUILD | 2 +- .../extensions/compression/gzip/common/BUILD | 2 +- .../compression/gzip/compressor/BUILD | 2 +- .../compression/gzip/decompressor/BUILD | 2 +- .../extensions/compression/zstd/common/BUILD | 2 +- .../extensions/config_subscription/rest/BUILD | 4 +- source/extensions/filters/common/lua/BUILD | 4 +- .../adaptive_concurrency/controller/BUILD | 4 +- source/extensions/filters/http/common/BUILD | 4 +- .../extensions/filters/http/gcp_authn/BUILD | 6 +- .../filters/http/grpc_field_extraction/BUILD | 8 +- .../filters/http/grpc_json_transcoder/BUILD | 4 +- .../extensions/filters/http/jwt_authn/BUILD | 18 +- source/extensions/filters/http/oauth2/BUILD | 4 +- .../filters/listener/http_inspector/BUILD | 2 +- .../filters/network/dubbo_proxy/BUILD | 6 +- .../extensions/filters/udp/dns_filter/BUILD | 2 +- source/extensions/health_checkers/grpc/BUILD | 4 +- .../network/dns_resolver/cares/BUILD | 2 +- source/extensions/tracers/datadog/BUILD | 4 +- source/extensions/tracers/opencensus/BUILD | 20 +- source/extensions/tracers/opentelemetry/BUILD | 4 +- source/extensions/tracers/skywalking/BUILD | 8 +- source/extensions/tracers/xray/BUILD | 1 - .../extensions/transport_sockets/alts/BUILD | 16 +- .../transport_sockets/starttls/BUILD | 4 +- .../tls/cert_validator/spiffe/BUILD | 4 +- source/server/BUILD | 4 +- test/BUILD | 6 +- test/benchmark/BUILD | 6 +- test/common/buffer/BUILD | 4 +- test/common/common/BUILD | 22 +- test/common/crypto/BUILD | 4 +- test/common/formatter/BUILD | 4 +- test/common/grpc/BUILD | 4 +- test/common/http/BUILD | 8 +- test/common/http/http2/BUILD | 26 +- test/common/listener_manager/BUILD | 8 +- test/common/network/BUILD | 8 +- test/common/orca/BUILD | 8 +- test/common/protobuf/BUILD | 2 +- test/common/quic/BUILD | 8 +- test/common/quic/platform/BUILD | 2 +- test/common/router/BUILD | 12 +- test/common/stats/BUILD | 24 +- test/common/tls/BUILD | 6 +- test/common/upstream/BUILD | 4 +- test/dependencies/BUILD | 4 +- test/extensions/access_loggers/fluentd/BUILD | 4 +- .../access_loggers/open_telemetry/BUILD | 4 +- test/extensions/bootstrap/wasm/BUILD | 4 +- test/extensions/clusters/eds/BUILD | 4 +- test/extensions/common/wasm/BUILD | 4 +- test/extensions/filters/http/compressor/BUILD | 6 +- test/extensions/filters/http/ext_proc/BUILD | 2 - .../message_converter/BUILD | 2 - .../extraction_util/BUILD | 1 - .../filters/listener/tls_inspector/BUILD | 4 +- .../filters/network/redis_proxy/BUILD | 8 +- test/extensions/filters/udp/dns_filter/BUILD | 2 +- .../load_balancing_policies/common/BUILD | 4 +- .../load_balancing_policies/subset/BUILD | 4 +- test/extensions/tracers/datadog/BUILD | 4 +- test/extensions/tracers/opentelemetry/BUILD | 4 +- test/extensions/tracers/skywalking/BUILD | 4 +- test/extensions/transport_sockets/alts/BUILD | 8 +- test/fuzz/BUILD | 4 +- test/server/BUILD | 4 +- test/test_common/BUILD | 4 +- test/tools/router_check/BUILD | 2 +- test/tools/schema_validator/BUILD | 2 +- test/tools/wee8_compile/BUILD | 4 +- 122 files changed, 259 insertions(+), 745 deletions(-) delete mode 100644 bazel/external/json.BUILD diff --git a/bazel/EXTERNAL_DEPS.md b/bazel/EXTERNAL_DEPS.md index b7919b5b06..2694e7cc05 100644 --- a/bazel/EXTERNAL_DEPS.md +++ b/bazel/EXTERNAL_DEPS.md @@ -16,7 +16,7 @@ build process. 1. Define a new Bazel repository in [`bazel/repositories.bzl`](repositories.bzl), in the `envoy_dependencies()` function. 2. Reference your new external dependency in some `envoy_cc_library` via the - `external_deps` attribute. + `deps` attribute. 3. `bazel test //test/...` ## External CMake (preferred) @@ -28,7 +28,7 @@ This is the preferred style of adding dependencies that use CMake for their buil 2. Add an `envoy_cmake` rule to [`bazel/foreign_cc/BUILD`](foreign_cc/BUILD). This will reference the source repository in step 1. 3. Reference your new external dependency in some `envoy_cc_library` via the name bound in step 1 - `external_deps` attribute. + `deps` attribute. 4. `bazel test //test/...` # Adding external dependencies to Envoy (Python) diff --git a/bazel/envoy_build_system.bzl b/bazel/envoy_build_system.bzl index f6492e18d2..5d7f8654fa 100644 --- a/bazel/envoy_build_system.bzl +++ b/bazel/envoy_build_system.bzl @@ -211,13 +211,13 @@ def envoy_proto_descriptor(name, out, srcs = [], external_deps = []): options.extend(["-I" + include_path for include_path in include_paths]) options.append("--descriptor_set_out=$@") - cmd = "$(location //external:protoc) " + " ".join(options + input_files) + cmd = "$(location @com_google_protobuf//:protoc) " + " ".join(options + input_files) native.genrule( name = name, srcs = srcs, outs = [out], cmd = cmd, - tools = ["//external:protoc"], + tools = ["@com_google_protobuf//:protoc"], ) # Dependencies on Google grpc should be wrapped with this function. diff --git a/bazel/envoy_internal.bzl b/bazel/envoy_internal.bzl index 45c6acb8ec..b84d93ef7a 100644 --- a/bazel/envoy_internal.bzl +++ b/bazel/envoy_internal.bzl @@ -166,15 +166,15 @@ def tcmalloc_external_dep(repository): repository + "//bazel:disable_tcmalloc": None, repository + "//bazel:disable_tcmalloc_on_linux_x86_64": None, repository + "//bazel:disable_tcmalloc_on_linux_aarch64": None, - repository + "//bazel:debug_tcmalloc": envoy_external_dep_path("gperftools"), - repository + "//bazel:debug_tcmalloc_on_linux_x86_64": envoy_external_dep_path("gperftools"), - repository + "//bazel:debug_tcmalloc_on_linux_aarch64": envoy_external_dep_path("gperftools"), - repository + "//bazel:gperftools_tcmalloc": envoy_external_dep_path("gperftools"), - repository + "//bazel:gperftools_tcmalloc_on_linux_x86_64": envoy_external_dep_path("gperftools"), - repository + "//bazel:gperftools_tcmalloc_on_linux_aarch64": envoy_external_dep_path("gperftools"), - repository + "//bazel:linux_x86_64": envoy_external_dep_path("tcmalloc"), - repository + "//bazel:linux_aarch64": envoy_external_dep_path("tcmalloc"), - "//conditions:default": envoy_external_dep_path("gperftools"), + repository + "//bazel:debug_tcmalloc": repository + "//bazel/foreign_cc:gperftools", + repository + "//bazel:debug_tcmalloc_on_linux_x86_64": repository + "//bazel/foreign_cc:gperftools", + repository + "//bazel:debug_tcmalloc_on_linux_aarch64": repository + "//bazel/foreign_cc:gperftools", + repository + "//bazel:gperftools_tcmalloc": repository + "//bazel/foreign_cc:gperftools", + repository + "//bazel:gperftools_tcmalloc_on_linux_x86_64": repository + "//bazel/foreign_cc:gperftools", + repository + "//bazel:gperftools_tcmalloc_on_linux_aarch64": repository + "//bazel/foreign_cc:gperftools", + repository + "//bazel:linux_x86_64": "@com_github_google_tcmalloc//tcmalloc", + repository + "//bazel:linux_aarch64": "@com_github_google_tcmalloc//tcmalloc", + "//conditions:default": repository + "//bazel/foreign_cc:gperftools", }) # Select the given values if default path normalization is on in the current build. diff --git a/bazel/envoy_library.bzl b/bazel/envoy_library.bzl index c1266770d7..d5ed602b2f 100644 --- a/bazel/envoy_library.bzl +++ b/bazel/envoy_library.bzl @@ -24,23 +24,23 @@ def tcmalloc_external_deps(repository): repository + "//bazel:disable_tcmalloc": [], repository + "//bazel:disable_tcmalloc_on_linux_x86_64": [], repository + "//bazel:disable_tcmalloc_on_linux_aarch64": [], - repository + "//bazel:debug_tcmalloc": [envoy_external_dep_path("gperftools")], - repository + "//bazel:debug_tcmalloc_on_linux_x86_64": [envoy_external_dep_path("gperftools")], - repository + "//bazel:debug_tcmalloc_on_linux_aarch64": [envoy_external_dep_path("gperftools")], - repository + "//bazel:gperftools_tcmalloc": [envoy_external_dep_path("gperftools")], - repository + "//bazel:gperftools_tcmalloc_on_linux_x86_64": [envoy_external_dep_path("gperftools")], - repository + "//bazel:gperftools_tcmalloc_on_linux_aarch64": [envoy_external_dep_path("gperftools")], + repository + "//bazel:debug_tcmalloc": [repository + "//bazel/foreign_cc:gperftools"], + repository + "//bazel:debug_tcmalloc_on_linux_x86_64": [repository + "//bazel/foreign_cc:gperftools"], + repository + "//bazel:debug_tcmalloc_on_linux_aarch64": [repository + "//bazel/foreign_cc:gperftools"], + repository + "//bazel:gperftools_tcmalloc": [repository + "//bazel/foreign_cc:gperftools"], + repository + "//bazel:gperftools_tcmalloc_on_linux_x86_64": [repository + "//bazel/foreign_cc:gperftools"], + repository + "//bazel:gperftools_tcmalloc_on_linux_aarch64": [repository + "//bazel/foreign_cc:gperftools"], repository + "//bazel:linux_x86_64": [ - envoy_external_dep_path("tcmalloc"), - envoy_external_dep_path("tcmalloc_profile_marshaler"), - envoy_external_dep_path("tcmalloc_malloc_extension"), + "@com_github_google_tcmalloc//tcmalloc", + "@com_github_google_tcmalloc//tcmalloc:profile_marshaler", + "@com_github_google_tcmalloc//tcmalloc:malloc_extension", ], repository + "//bazel:linux_aarch64": [ - envoy_external_dep_path("tcmalloc"), - envoy_external_dep_path("tcmalloc_profile_marshaler"), - envoy_external_dep_path("tcmalloc_malloc_extension"), + "@com_github_google_tcmalloc//tcmalloc", + "@com_github_google_tcmalloc//tcmalloc:profile_marshaler", + "@com_github_google_tcmalloc//tcmalloc:malloc_extension", ], - "//conditions:default": [envoy_external_dep_path("gperftools")], + "//conditions:default": [repository + "//bazel/foreign_cc:gperftools"], }) # Envoy C++ library targets that need no transformations or additional dependencies before being diff --git a/bazel/envoy_pch.bzl b/bazel/envoy_pch.bzl index 843937d8dc..1e9766b680 100644 --- a/bazel/envoy_pch.bzl +++ b/bazel/envoy_pch.bzl @@ -27,8 +27,8 @@ def envoy_pch_library( name, includes, deps, - external_deps, visibility, + external_deps = [], testonly = False, repository = ""): native.cc_library( diff --git a/bazel/envoy_test.bzl b/bazel/envoy_test.bzl index 0bdfc36c51..c9a4266603 100644 --- a/bazel/envoy_test.bzl +++ b/bazel/envoy_test.bzl @@ -40,7 +40,7 @@ def _envoy_cc_test_infrastructure_library( extra_deps = [] pch_copts = [] if disable_pch: - extra_deps = [envoy_external_dep_path("googletest")] + extra_deps = ["@com_google_googletest//:gtest"] else: extra_deps = envoy_pch_deps(repository, "//test:test_pch") pch_copts = envoy_pch_copts(repository, "//test:test_pch") @@ -175,9 +175,10 @@ def envoy_cc_test( linkopts = _envoy_test_linkopts() + linkopts, linkstatic = envoy_linkstatic(), malloc = tcmalloc_external_dep(repository), - deps = envoy_stdlib_deps() + deps + [envoy_external_dep_path(dep) for dep in external_deps + ["googletest"]] + [ + deps = envoy_stdlib_deps() + deps + [envoy_external_dep_path(dep) for dep in external_deps] + [ repository + "//test:main", repository + "//test/test_common:test_version_linkstamp", + "@com_google_googletest//:gtest", ] + envoy_pch_deps(repository, "//test:test_pch"), # from https://github.com/google/googletest/blob/6e1970e2376c14bf658eb88f655a054030353f9f/googlemock/src/gmock.cc#L51 # 2 - by default, mocks act as StrictMocks. diff --git a/bazel/external/json.BUILD b/bazel/external/json.BUILD deleted file mode 100644 index cc19af32bf..0000000000 --- a/bazel/external/json.BUILD +++ /dev/null @@ -1,19 +0,0 @@ -licenses(["notice"]) # Apache 2 - -cc_library( - name = "nlohmann_json_lib", - hdrs = glob([ - "include/nlohmann/*.hpp", - "include/nlohmann/**/*.hpp", - "include/nlohmann/*/*/*.hpp", - ]), - includes = ["external/nlohmann_json_lib"], - visibility = ["//visibility:public"], -) - -cc_library( - name = "json", - includes = ["include"], - visibility = ["//visibility:public"], - deps = [":nlohmann_json_lib"], -) diff --git a/bazel/external/quiche.BUILD b/bazel/external/quiche.BUILD index 950f9426a6..3923966229 100644 --- a/bazel/external/quiche.BUILD +++ b/bazel/external/quiche.BUILD @@ -2460,10 +2460,7 @@ envoy_quic_cc_library( "quiche/quic/core/crypto/quic_compressed_certs_cache.h", "quiche/quic/core/crypto/transport_parameters.h", ], - external_deps = [ - "ssl", - "zlib", - ], + external_deps = ["ssl"], tags = [ "pg3", ], @@ -2489,6 +2486,7 @@ envoy_quic_cc_library( ":quic_core_utils_lib", ":quic_core_versions_lib", ":quic_platform", + "@envoy//bazel/foreign_cc:zlib", ], ) @@ -2502,9 +2500,6 @@ envoy_quic_cc_library( "quiche/quic/core/crypto/quic_client_session_cache.h", "quiche/quic/core/crypto/quic_crypto_client_config.h", ], - external_deps = [ - "zlib", - ], tags = [ "pg3", ], @@ -2513,6 +2508,7 @@ envoy_quic_cc_library( ":quic_core_crypto_client_proof_source_lib", ":quic_core_crypto_crypto_handshake_lib", ":quiche_common_platform_client_stats", + "@envoy//bazel/foreign_cc:zlib", ], ) @@ -2524,10 +2520,7 @@ envoy_quic_cc_library( hdrs = [ "quiche/quic/core/crypto/quic_crypto_server_config.h", ], - external_deps = [ - "ssl", - "zlib", - ], + external_deps = ["ssl"], tags = [ "pg3", ], @@ -2536,6 +2529,7 @@ envoy_quic_cc_library( ":quic_core_proto_crypto_server_config_proto_header", ":quic_core_server_id_lib", ":quic_server_crypto_tls_handshake_lib", + "@envoy//bazel/foreign_cc:zlib", ], ) @@ -2658,9 +2652,7 @@ envoy_quic_cc_library( name = "quic_core_crypto_proof_source_x509_lib", srcs = ["quiche/quic/core/crypto/proof_source_x509.cc"], hdrs = ["quiche/quic/core/crypto/proof_source_x509.h"], - external_deps = [ - "ssl", - ], + external_deps = ["ssl"], deps = [ ":quic_core_crypto_certificate_view_lib", ":quic_core_crypto_crypto_handshake_lib", diff --git a/bazel/foreign_cc/BUILD b/bazel/foreign_cc/BUILD index 81f04ab3d5..60271a4925 100644 --- a/bazel/foreign_cc/BUILD +++ b/bazel/foreign_cc/BUILD @@ -310,8 +310,8 @@ envoy_cmake( deps = [ ":ares", ":nghttp2", + ":zlib", "//external:ssl", - "//external:zlib", ], ) diff --git a/bazel/protobuf.patch b/bazel/protobuf.patch index 833b4aa9b7..c07b5ce9d8 100644 --- a/bazel/protobuf.patch +++ b/bazel/protobuf.patch @@ -101,12 +101,12 @@ index e7555ee10..a93beb1c5 100644 diff --git a/src/google/protobuf/io/BUILD.bazel b/src/google/protobuf/io/BUILD.bazel --- a/src/google/protobuf/io/BUILD.bazel +++ b/src/google/protobuf/io/BUILD.bazel -@@ -138,7 +138,7 @@ cc_library( +@@ -138,6 +138,6 @@ cc_library( "@com_google_absl//absl/log:absl_log", ] + select({ "//build_defs:config_msvc": [], - "//conditions:default": ["@zlib"], -+ "//conditions:default": ["//external:zlib"], ++ "//conditions:default": ["@envoy//bazel/foreign_cc:zlib"], }), ) diff --git a/bazel/repositories.bzl b/bazel/repositories.bzl index f0fed861ee..99f1d57d6c 100644 --- a/bazel/repositories.bzl +++ b/bazel/repositories.bzl @@ -165,7 +165,6 @@ def envoy_dependencies(skip_targets = []): _com_github_nghttp2_nghttp2() _com_github_msgpack_cpp() _com_github_skyapm_cpp2sky() - _com_github_nodejs_http_parser() _com_github_alibaba_hessian2_codec() _com_github_tencent_rapidjson() _com_github_nlohmann_json() @@ -267,20 +266,12 @@ def _com_github_openhistogram_libcircllhist(): name = "com_github_openhistogram_libcircllhist", build_file = "@envoy//bazel/external:libcircllhist.BUILD", ) - native.bind( - name = "libcircllhist", - actual = "@com_github_openhistogram_libcircllhist//:libcircllhist", - ) def _com_github_axboe_liburing(): external_http_archive( name = "com_github_axboe_liburing", build_file_content = BUILD_ALL_CONTENT, ) - native.bind( - name = "uring", - actual = "@envoy//bazel/foreign_cc:liburing_linux", - ) def _com_github_bazel_buildtools(): # TODO(phlax): Add binary download @@ -294,30 +285,18 @@ def _com_github_c_ares_c_ares(): name = "com_github_c_ares_c_ares", build_file_content = BUILD_ALL_CONTENT, ) - native.bind( - name = "ares", - actual = "@envoy//bazel/foreign_cc:ares", - ) def _com_github_cyan4973_xxhash(): external_http_archive( name = "com_github_cyan4973_xxhash", build_file = "@envoy//bazel/external:xxhash.BUILD", ) - native.bind( - name = "xxhash", - actual = "@com_github_cyan4973_xxhash//:xxhash", - ) def _com_github_envoyproxy_sqlparser(): external_http_archive( name = "com_github_envoyproxy_sqlparser", build_file = "@envoy//bazel/external:sqlparser.BUILD", ) - native.bind( - name = "sqlparser", - actual = "@com_github_envoyproxy_sqlparser//:sqlparser", - ) def _com_github_mirror_tclap(): external_http_archive( @@ -325,30 +304,18 @@ def _com_github_mirror_tclap(): build_file = "@envoy//bazel/external:tclap.BUILD", patch_args = ["-p1"], ) - native.bind( - name = "tclap", - actual = "@com_github_mirror_tclap//:tclap", - ) def _com_github_fmtlib_fmt(): external_http_archive( name = "com_github_fmtlib_fmt", build_file = "@envoy//bazel/external:fmtlib.BUILD", ) - native.bind( - name = "fmtlib", - actual = "@com_github_fmtlib_fmt//:fmtlib", - ) def _com_github_gabime_spdlog(): external_http_archive( name = "com_github_gabime_spdlog", build_file = "@envoy//bazel/external:spdlog.BUILD", ) - native.bind( - name = "spdlog", - actual = "@com_github_gabime_spdlog//:spdlog", - ) def _com_github_google_benchmark(): external_http_archive( @@ -358,10 +325,6 @@ def _com_github_google_benchmark(): name = "libpfm", build_file = "@com_github_google_benchmark//tools:libpfm.BUILD.bazel", ) - native.bind( - name = "benchmark", - actual = "@com_github_google_benchmark//:benchmark", - ) def _com_github_google_libprotobuf_mutator(): external_http_archive( @@ -375,11 +338,6 @@ def _com_github_google_libsxg(): build_file_content = BUILD_ALL_CONTENT, ) - native.bind( - name = "libsxg", - actual = "@envoy//bazel/foreign_cc:libsxg", - ) - def _com_github_unicode_org_icu(): external_http_archive( name = "com_github_unicode_org_icu", @@ -437,40 +395,24 @@ def _com_github_jbeder_yaml_cpp(): external_http_archive( name = "com_github_jbeder_yaml_cpp", ) - native.bind( - name = "yaml_cpp", - actual = "@com_github_jbeder_yaml_cpp//:yaml-cpp", - ) def _com_github_libevent_libevent(): external_http_archive( name = "com_github_libevent_libevent", build_file_content = BUILD_ALL_CONTENT, ) - native.bind( - name = "event", - actual = "@envoy//bazel/foreign_cc:event", - ) def _net_colm_open_source_colm(): external_http_archive( name = "net_colm_open_source_colm", build_file_content = BUILD_ALL_CONTENT, ) - native.bind( - name = "colm", - actual = "@envoy//bazel/foreign_cc:colm", - ) def _net_colm_open_source_ragel(): external_http_archive( name = "net_colm_open_source_ragel", build_file_content = BUILD_ALL_CONTENT, ) - native.bind( - name = "ragel", - actual = "@envoy//bazel/foreign_cc:ragel", - ) def _net_zlib(): external_http_archive( @@ -480,11 +422,6 @@ def _net_zlib(): patches = ["@envoy//bazel/foreign_cc:zlib.patch"], ) - native.bind( - name = "zlib", - actual = "@envoy//bazel/foreign_cc:zlib", - ) - # Bind for grpc. native.bind( name = "madler_zlib", @@ -524,14 +461,6 @@ def _org_brotli(): external_http_archive( name = "org_brotli", ) - native.bind( - name = "brotlienc", - actual = "@org_brotli//:brotlienc", - ) - native.bind( - name = "brotlidec", - actual = "@org_brotli//:brotlidec", - ) def _com_github_facebook_zstd(): external_http_archive( @@ -539,11 +468,6 @@ def _com_github_facebook_zstd(): build_file_content = BUILD_ALL_CONTENT, ) - native.bind( - name = "zstd", - actual = "@envoy//bazel/foreign_cc:zstd", - ) - def _com_google_cel_cpp(): external_http_archive( "com_google_cel_cpp", @@ -584,10 +508,6 @@ def _com_github_msgpack_cpp(): name = "com_github_msgpack_cpp", build_file = "@envoy//bazel/external:msgpack.BUILD", ) - native.bind( - name = "msgpack", - actual = "@com_github_msgpack_cpp//:msgpack", - ) def _io_hyperscan(): external_http_archive( @@ -608,17 +528,9 @@ def _io_vectorscan(): def _io_opentelemetry_api_cpp(): external_http_archive(name = "io_opentelemetry_cpp") - native.bind( - name = "opentelemetry_api", - actual = "@io_opentelemetry_cpp//api:api", - ) def _com_github_datadog_dd_trace_cpp(): external_http_archive("com_github_datadog_dd_trace_cpp") - native.bind( - name = "dd_trace_cpp", - actual = "@com_github_datadog_dd_trace_cpp//:dd_trace_cpp", - ) def _com_github_skyapm_cpp2sky(): external_http_archive( @@ -627,10 +539,6 @@ def _com_github_skyapm_cpp2sky(): external_http_archive( name = "skywalking_data_collect_protocol", ) - native.bind( - name = "cpp2sky", - actual = "@com_github_skyapm_cpp2sky//source:cpp2sky_data_lib", - ) def _com_github_tencent_rapidjson(): external_http_archive( @@ -641,39 +549,16 @@ def _com_github_tencent_rapidjson(): def _com_github_nlohmann_json(): external_http_archive( name = "com_github_nlohmann_json", - build_file = "@envoy//bazel/external:json.BUILD", - ) - native.bind( - name = "json", - actual = "@com_github_nlohmann_json//:json", - ) - -def _com_github_nodejs_http_parser(): - native.bind( - name = "http_parser", - actual = "@envoy//bazel/external/http_parser", ) def _com_github_alibaba_hessian2_codec(): external_http_archive("com_github_alibaba_hessian2_codec") - native.bind( - name = "hessian2_codec_object_codec_lib", - actual = "@com_github_alibaba_hessian2_codec//hessian2/basic_codec:object_codec_lib", - ) - native.bind( - name = "hessian2_codec_codec_impl", - actual = "@com_github_alibaba_hessian2_codec//hessian2:codec_impl_lib", - ) def _com_github_ncopa_suexec(): external_http_archive( name = "com_github_ncopa_suexec", build_file = "@envoy//bazel/external:su-exec.BUILD", ) - native.bind( - name = "su-exec", - actual = "@com_github_ncopa_suexec//:su-exec", - ) def _com_google_googletest(): external_http_archive( @@ -681,10 +566,6 @@ def _com_google_googletest(): patches = ["@envoy//bazel:googletest.patch"], patch_args = ["-p1"], ) - native.bind( - name = "googletest", - actual = "@com_google_googletest//:gtest", - ) # TODO(jmarantz): replace the use of bind and external_deps with just # the direct Bazel path at all sites. This will make it easier to @@ -736,6 +617,7 @@ def _com_google_protobuf(): patch_args = ["-p1"], ) + # Needed by grpc, jwt_verify_lib, maybe others. native.bind( name = "protobuf", actual = "@com_google_protobuf//:protobuf", @@ -748,10 +630,6 @@ def _com_google_protobuf(): name = "protocol_compiler", actual = "@com_google_protobuf//:protoc", ) - native.bind( - name = "protoc", - actual = "@com_google_protobuf//:protoc", - ) # Needed for `bazel fetch` to work with @com_google_protobuf # https://github.com/google/protobuf/blob/v3.6.1/util/python/BUILD#L6-L9 @@ -759,6 +637,8 @@ def _com_google_protobuf(): name = "python_headers", actual = "//bazel:python_headers", ) + + # Needed by grpc until we update again. native.bind( name = "upb_base_lib", actual = "@com_google_protobuf//upb:base", @@ -788,42 +668,6 @@ def _io_opencensus_cpp(): external_http_archive( name = "io_opencensus_cpp", ) - native.bind( - name = "opencensus_trace", - actual = "@io_opencensus_cpp//opencensus/trace", - ) - native.bind( - name = "opencensus_trace_b3", - actual = "@io_opencensus_cpp//opencensus/trace:b3", - ) - native.bind( - name = "opencensus_trace_cloud_trace_context", - actual = "@io_opencensus_cpp//opencensus/trace:cloud_trace_context", - ) - native.bind( - name = "opencensus_trace_grpc_trace_bin", - actual = "@io_opencensus_cpp//opencensus/trace:grpc_trace_bin", - ) - native.bind( - name = "opencensus_trace_trace_context", - actual = "@io_opencensus_cpp//opencensus/trace:trace_context", - ) - native.bind( - name = "opencensus_exporter_ocagent", - actual = "@io_opencensus_cpp//opencensus/exporters/trace/ocagent:ocagent_exporter", - ) - native.bind( - name = "opencensus_exporter_stdout", - actual = "@io_opencensus_cpp//opencensus/exporters/trace/stdout:stdout_exporter", - ) - native.bind( - name = "opencensus_exporter_stackdriver", - actual = "@io_opencensus_cpp//opencensus/exporters/trace/stackdriver:stackdriver_exporter", - ) - native.bind( - name = "opencensus_exporter_zipkin", - actual = "@io_opencensus_cpp//opencensus/exporters/trace/zipkin:zipkin_exporter", - ) def _com_github_curl(): # The usage by AWS extensions common utilities is deprecated and will be removed by Q3 2024 after @@ -857,6 +701,8 @@ def _v8(): ], patch_args = ["-p1"], ) + + # Needed by proxy_wasm_cpp_host. native.bind( name = "wee8", actual = "@v8//:wee8", @@ -867,6 +713,8 @@ def _com_googlesource_chromium_base_trace_event_common(): name = "com_googlesource_chromium_base_trace_event_common", build_file = "@v8//:bazel/BUILD.trace_event_common", ) + + # Needed by v8. native.bind( name = "base_trace_event_common", actual = "@com_googlesource_chromium_base_trace_event_common//:trace_event_common", @@ -878,38 +726,6 @@ def _com_github_google_quiche(): patch_cmds = ["find quiche/ -type f -name \"*.bazel\" -delete"], build_file = "@envoy//bazel/external:quiche.BUILD", ) - native.bind( - name = "quiche_common_platform", - actual = "@com_github_google_quiche//:quiche_common_platform", - ) - native.bind( - name = "quiche_http2_adapter", - actual = "@com_github_google_quiche//:http2_adapter", - ) - native.bind( - name = "quiche_http2_protocol", - actual = "@com_github_google_quiche//:http2_adapter_http2_protocol", - ) - native.bind( - name = "quiche_http2_test_tools", - actual = "@com_github_google_quiche//:http2_adapter_mock_http2_visitor", - ) - native.bind( - name = "quiche_quic_platform", - actual = "@com_github_google_quiche//:quic_platform", - ) - native.bind( - name = "quiche_quic_platform_base", - actual = "@com_github_google_quiche//:quic_platform_base", - ) - native.bind( - name = "quiche_http2_hpack", - actual = "@com_github_google_quiche//:http2_hpack_hpack_lib", - ) - native.bind( - name = "quiche_http2_hpack_decoder", - actual = "@com_github_google_quiche//:http2_hpack_decoder_hpack_decoder_lib", - ) def _com_googlesource_googleurl(): external_http_archive( @@ -949,7 +765,7 @@ def _com_github_grpc_grpc(): ) native.bind( name = "cares", - actual = "//external:ares", + actual = "@envoy//bazel/foreign_cc:ares", ) native.bind( @@ -983,6 +799,7 @@ def _rules_proto_grpc(): def _re2(): external_http_archive("com_googlesource_code_re2") + # Needed by grpc. native.bind( name = "re2", actual = "@com_googlesource_code_re2//:re2", @@ -1016,16 +833,6 @@ def _emsdk(): def _com_github_google_jwt_verify(): external_http_archive("com_github_google_jwt_verify") - native.bind( - name = "jwt_verify_lib", - actual = "@com_github_google_jwt_verify//:jwt_verify_lib", - ) - - native.bind( - name = "simple_lru_cache_lib", - actual = "@com_github_google_jwt_verify//:simple_lru_cache_lib", - ) - def _com_github_luajit_luajit(): external_http_archive( name = "com_github_luajit_luajit", @@ -1035,38 +842,16 @@ def _com_github_luajit_luajit(): patch_cmds = ["chmod u+x build.py"], ) - native.bind( - name = "luajit", - actual = "@envoy//bazel/foreign_cc:luajit", - ) - def _com_github_google_tcmalloc(): external_http_archive( name = "com_github_google_tcmalloc", ) - native.bind( - name = "tcmalloc", - actual = "@com_github_google_tcmalloc//tcmalloc", - ) - native.bind( - name = "tcmalloc_profile_marshaler", - actual = "@com_github_google_tcmalloc//tcmalloc:profile_marshaler", - ) - native.bind( - name = "tcmalloc_malloc_extension", - actual = "@com_github_google_tcmalloc//tcmalloc:malloc_extension", - ) - def _com_github_gperftools_gperftools(): external_http_archive( name = "com_github_gperftools_gperftools", build_file_content = BUILD_ALL_CONTENT, ) - native.bind( - name = "gperftools", - actual = "@envoy//bazel/foreign_cc:gperftools", - ) def _com_github_wamr(): external_http_archive( @@ -1157,10 +942,6 @@ filegroup( patches = ["@envoy//bazel/foreign_cc:librdkafka.patch"], patch_args = ["-p1"], ) - native.bind( - name = "librdkafka", - actual = "@envoy//bazel/foreign_cc:librdkafka", - ) # This archive provides Kafka (and Zookeeper) binaries, that are used during Kafka integration # tests. diff --git a/ci/do_ci.sh b/ci/do_ci.sh index 3258e8aad1..6d4295b53b 100755 --- a/ci/do_ci.sh +++ b/ci/do_ci.sh @@ -225,7 +225,7 @@ function bazel_binary_build() { //test/tools/router_check:router_check_tool "${CONFIG_ARGS[@]}" # Build su-exec utility - bazel build "${BAZEL_BUILD_OPTIONS[@]}" --remote_download_toplevel -c "${COMPILE_TYPE}" external:su-exec + bazel build "${BAZEL_BUILD_OPTIONS[@]}" --remote_download_toplevel -c "${COMPILE_TYPE}" @com_github_ncopa_suexec//:su-exec cp_binary_for_image_build "${BINARY_TYPE}" "${COMPILE_TYPE}" "${EXE_NAME}" } diff --git a/contrib/common/sqlutils/source/BUILD b/contrib/common/sqlutils/source/BUILD index c100c39ae9..fb660bbee5 100644 --- a/contrib/common/sqlutils/source/BUILD +++ b/contrib/common/sqlutils/source/BUILD @@ -12,8 +12,8 @@ envoy_cc_library( name = "sqlutils_lib", srcs = ["sqlutils.cc"], hdrs = ["sqlutils.h"], - external_deps = ["sqlparser"], deps = [ "//source/common/protobuf:utility_lib", + "@com_github_envoyproxy_sqlparser//:sqlparser", ], ) diff --git a/contrib/common/sqlutils/test/BUILD b/contrib/common/sqlutils/test/BUILD index e89cb0138b..087e44dcdb 100644 --- a/contrib/common/sqlutils/test/BUILD +++ b/contrib/common/sqlutils/test/BUILD @@ -13,8 +13,8 @@ envoy_cc_test( srcs = [ "sqlutils_test.cc", ], - external_deps = ["sqlparser"], deps = [ "//contrib/common/sqlutils/source:sqlutils_lib", + "@com_github_envoyproxy_sqlparser//:sqlparser", ], ) diff --git a/contrib/cryptomb/private_key_providers/test/BUILD b/contrib/cryptomb/private_key_providers/test/BUILD index 2940695756..777cc49f89 100644 --- a/contrib/cryptomb/private_key_providers/test/BUILD +++ b/contrib/cryptomb/private_key_providers/test/BUILD @@ -87,13 +87,11 @@ envoy_cc_test( envoy_cc_benchmark_binary( name = "speed_test", srcs = ["speed_test.cc"], - external_deps = [ - "benchmark", - "ssl", - ], + external_deps = ["ssl"], deps = [ "//contrib/cryptomb/private_key_providers/source:ipp_crypto_wrapper_lib", "//source/common/common:assert_lib", "//source/common/common:utility_lib", + "@com_github_google_benchmark//:benchmark", ], ) diff --git a/contrib/hyperscan/matching/input_matchers/source/BUILD b/contrib/hyperscan/matching/input_matchers/source/BUILD index ee3ce33489..8f00c2bdfa 100644 --- a/contrib/hyperscan/matching/input_matchers/source/BUILD +++ b/contrib/hyperscan/matching/input_matchers/source/BUILD @@ -5,10 +5,6 @@ load( "envoy_cmake", "envoy_contrib_package", ) -load( - "//bazel:envoy_internal.bzl", - "envoy_external_dep_path", -) load( "//contrib:all_contrib_extensions.bzl", "envoy_contrib_linux_aarch64_constraints", @@ -38,7 +34,7 @@ envoy_cmake( tags = ["skip_on_windows"], target_compatible_with = envoy_contrib_linux_x86_64_constraints(), deps = [ - envoy_external_dep_path("ragel"), + "//bazel/foreign_cc:ragel", ], ) @@ -64,7 +60,7 @@ envoy_cmake( tags = ["skip_on_windows"], target_compatible_with = envoy_contrib_linux_aarch64_constraints(), deps = [ - envoy_external_dep_path("ragel"), + "//bazel/foreign_cc:ragel", ], ) diff --git a/contrib/hyperscan/matching/input_matchers/test/BUILD b/contrib/hyperscan/matching/input_matchers/test/BUILD index aa1ebb140f..3be84e8b8c 100644 --- a/contrib/hyperscan/matching/input_matchers/test/BUILD +++ b/contrib/hyperscan/matching/input_matchers/test/BUILD @@ -39,10 +39,10 @@ envoy_cc_test( envoy_cc_benchmark_binary( name = "hyperscan_speed_test", srcs = ["hyperscan_speed_test.cc"], - external_deps = ["benchmark"], deps = [ "//source/common/common:assert_lib", "//source/common/common:utility_lib", + "@com_github_google_benchmark//:benchmark", "@com_googlesource_code_re2//:re2", ] + select({ "//bazel:linux_x86_64": [ @@ -57,13 +57,13 @@ envoy_cc_benchmark_binary( envoy_cc_benchmark_binary( name = "matcher_speed_test", srcs = ["matcher_speed_test.cc"], - external_deps = ["benchmark"], deps = [ "//source/common/common:assert_lib", "//source/common/common:regex_lib", "//source/common/common:utility_lib", "//source/common/thread_local:thread_local_lib", "//test/mocks/event:event_mocks", + "@com_github_google_benchmark//:benchmark", ] + select({ "//bazel:linux_x86_64": [ "//contrib/hyperscan/matching/input_matchers/source:hyperscan_matcher_lib", diff --git a/contrib/kafka/filters/network/source/mesh/BUILD b/contrib/kafka/filters/network/source/mesh/BUILD index b52c41fa5f..69f6e35ff2 100644 --- a/contrib/kafka/filters/network/source/mesh/BUILD +++ b/contrib/kafka/filters/network/source/mesh/BUILD @@ -4,7 +4,6 @@ load( "envoy_cc_library", "envoy_contrib_package", ) -load("//bazel:envoy_internal.bzl", "envoy_external_dep_path") licenses(["notice"]) # Apache 2 @@ -253,9 +252,9 @@ envoy_cc_library( ], tags = ["skip_on_windows"], deps = [ + "//bazel/foreign_cc:librdkafka", "//envoy/common:pure_lib", "@com_google_absl//absl/strings", - envoy_external_dep_path("librdkafka"), ], ) @@ -270,7 +269,7 @@ envoy_cc_library( tags = ["skip_on_windows"], deps = [ ":librdkafka_utils_lib", - envoy_external_dep_path("librdkafka"), + "//bazel/foreign_cc:librdkafka", "//source/common/common:macros", ], ) diff --git a/contrib/kafka/filters/network/test/mesh/BUILD b/contrib/kafka/filters/network/test/mesh/BUILD index 06a76c4afe..184e5623c6 100644 --- a/contrib/kafka/filters/network/test/mesh/BUILD +++ b/contrib/kafka/filters/network/test/mesh/BUILD @@ -4,10 +4,6 @@ load( "envoy_cc_test_library", "envoy_contrib_package", ) -load( - "//bazel:envoy_internal.bzl", - "envoy_external_dep_path", -) licenses(["notice"]) # Apache 2 @@ -104,7 +100,7 @@ envoy_cc_test_library( hdrs = ["kafka_mocks.h"], tags = ["skip_on_windows"], deps = [ - envoy_external_dep_path("librdkafka"), + "//bazel/foreign_cc:librdkafka", "//contrib/kafka/filters/network/source/mesh:librdkafka_utils_lib", ], ) diff --git a/contrib/mysql_proxy/filters/network/test/BUILD b/contrib/mysql_proxy/filters/network/test/BUILD index 1a7e65a434..bb6bfecf23 100644 --- a/contrib/mysql_proxy/filters/network/test/BUILD +++ b/contrib/mysql_proxy/filters/network/test/BUILD @@ -109,7 +109,6 @@ envoy_cc_test( "mysql_command_test.cc", ], data = ["mysql_test_config.yaml"], - external_deps = ["sqlparser"], deps = [ ":mysql_test_utils_lib", "//contrib/mysql_proxy/filters/network/source:codec_lib", @@ -117,5 +116,6 @@ envoy_cc_test( "//source/common/tcp_proxy", "//source/extensions/filters/network/tcp_proxy:config", "//test/integration:integration_lib", + "@com_github_envoyproxy_sqlparser//:sqlparser", ], ) diff --git a/contrib/qat/compression/qatzstd/compressor/source/BUILD b/contrib/qat/compression/qatzstd/compressor/source/BUILD index 960fa2b9b5..f1d7caa3a3 100644 --- a/contrib/qat/compression/qatzstd/compressor/source/BUILD +++ b/contrib/qat/compression/qatzstd/compressor/source/BUILD @@ -34,8 +34,8 @@ make( "install", ], deps = [ + "//bazel/foreign_cc:zstd", "//contrib/qat:qatlib", - "//external:zstd", ], ) diff --git a/contrib/qat/private_key_providers/source/BUILD b/contrib/qat/private_key_providers/source/BUILD index e6dfb8ac26..76757e972f 100644 --- a/contrib/qat/private_key_providers/source/BUILD +++ b/contrib/qat/private_key_providers/source/BUILD @@ -32,9 +32,7 @@ envoy_cc_library( "qat.h", "qat_private_key_provider.h", ], - external_deps = [ - "ssl", - ], + external_deps = ["ssl"], deps = [ ":libqat_wrapper_lib", "//envoy/api:api_interface", diff --git a/contrib/sxg/filters/http/source/BUILD b/contrib/sxg/filters/http/source/BUILD index 1d3b5b9231..83a1f04817 100644 --- a/contrib/sxg/filters/http/source/BUILD +++ b/contrib/sxg/filters/http/source/BUILD @@ -21,7 +21,6 @@ envoy_cc_library( "filter.h", "filter_config.h", ], - external_deps = ["libsxg"], deps = [ "//envoy/server:filter_config_interface", "//source/common/config:datasource_lib", @@ -31,6 +30,7 @@ envoy_cc_library( "//source/common/secret:secret_provider_impl_lib", "//source/extensions/filters/http/common:pass_through_filter_lib", "@envoy_api//contrib/envoy/extensions/filters/http/sxg/v3alpha:pkg_cc_proto", + "//bazel/foreign_cc:libsxg", # use boringssl alias to select fips vs non-fips version. "//bazel:boringssl", ], diff --git a/distribution/binary/BUILD b/distribution/binary/BUILD index 5d610f0d07..4f72887530 100644 --- a/distribution/binary/BUILD +++ b/distribution/binary/BUILD @@ -18,7 +18,7 @@ bundled( "//distribution:envoy-dwarf": "dbg/envoy.dwp", "//distribution:envoy-contrib-binary": "dbg/envoy-contrib", "//distribution:envoy-contrib-dwarf": "dbg/envoy-contrib.dwp", - "//external:su-exec": "utils/su-exec", + "@com_github_ncopa_suexec//:su-exec": "utils/su-exec", }, ) diff --git a/distribution/binary/compiler.bzl b/distribution/binary/compiler.bzl index 1506be1260..aa4a287371 100644 --- a/distribution/binary/compiler.bzl +++ b/distribution/binary/compiler.bzl @@ -32,7 +32,7 @@ # targets = { # "//distribution:envoy-binary": "envoy", # "//distribution:envoy-contrib-binary": "envoy-contrib", -# "//external:su-exec": "utils/su-exec", +# "@com_github_ncopa_suexec//:su-exec": "utils/su-exec", # }, # ) # diff --git a/envoy/grpc/BUILD b/envoy/grpc/BUILD index 47b9631194..50ae15b205 100644 --- a/envoy/grpc/BUILD +++ b/envoy/grpc/BUILD @@ -46,9 +46,7 @@ envoy_cc_library( envoy_cc_library( name = "google_grpc_creds_interface", hdrs = ["google_grpc_creds.h"], - external_deps = [ - "grpc", - ], + external_deps = ["grpc"], deps = [ "//envoy/api:api_interface", "//envoy/config:typed_config_interface", diff --git a/mobile/bazel/protobuf.patch b/mobile/bazel/protobuf.patch index e786c7ebe1..d3bb997483 100644 --- a/mobile/bazel/protobuf.patch +++ b/mobile/bazel/protobuf.patch @@ -12,12 +12,12 @@ diff --git a/BUILD b/BUILD index efc3d8e7f..746ad4851 100644 --- a/BUILD +++ b/BUILD -@@ -24,7 +24,7 @@ config_setting( +@@ -24,4 +24,4 @@ config_setting( # ZLIB configuration ################################################################################ -ZLIB_DEPS = ["@zlib//:zlib"] -+ZLIB_DEPS = ["//external:zlib"] ++ZLIB_DEPS = ["@envoy//bazel/foreign_cc:zlib"] ################################################################################ # Protobuf Runtime Library diff --git a/source/common/common/BUILD b/source/common/common/BUILD index 415b71d4c2..e2f26a09a2 100644 --- a/source/common/common/BUILD +++ b/source/common/common/BUILD @@ -127,11 +127,9 @@ envoy_cc_library( envoy_basic_cc_library( name = "fmt_lib", hdrs = ["fmt.h"], - external_deps = [ - "fmtlib", - ], deps = [ "//envoy/common:base_includes", + "@com_github_fmtlib_fmt//:fmtlib", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", ], @@ -141,11 +139,11 @@ envoy_cc_library( name = "hash_lib", srcs = ["hash.cc"], hdrs = ["hash.h"], - external_deps = ["xxhash"], deps = [ ":macros", ":safe_memcpy_lib", "//envoy/common:base_includes", + "@com_github_cyan4973_xxhash//:xxhash", "@com_google_absl//absl/container:flat_hash_map", "@com_google_absl//absl/container:flat_hash_set", ], @@ -167,14 +165,12 @@ envoy_cc_library( name = "key_value_store_lib", srcs = ["key_value_store_base.cc"], hdrs = ["key_value_store_base.h"], - external_deps = [ - "quiche_quic_platform", - ], deps = [ "//envoy/common:key_value_store_interface", "//envoy/event:dispatcher_interface", "//envoy/filesystem:filesystem_interface", "//source/common/config:ttl_lib", + "@com_github_google_quiche//:quic_platform", "@com_github_google_quiche//:quiche_common_lib", "@com_google_absl//absl/cleanup", ], @@ -229,10 +225,8 @@ envoy_cc_library( name = "base_logger_lib", srcs = ["base_logger.cc"], hdrs = ["base_logger.h"], - external_deps = [ - "spdlog", - ], deps = [ + "@com_github_gabime_spdlog//:spdlog", "@com_google_absl//absl/strings", ], ) @@ -585,9 +579,6 @@ envoy_cc_library( envoy_pch_library( name = "common_pch", - external_deps = [ - "spdlog", - ], includes = [ "envoy/config/bootstrap/v3/bootstrap.pb.h", "envoy/config/cluster/v3/cluster.pb.h", @@ -598,6 +589,7 @@ envoy_pch_library( "envoy/service/discovery/v3/discovery.pb.h", "spdlog/sinks/android_sink.h", "spdlog/spdlog.h", + "@com_github_gabime_spdlog//:spdlog", ], visibility = ["//visibility:public"], deps = [ diff --git a/source/common/compression/zstd/common/BUILD b/source/common/compression/zstd/common/BUILD index e9ecaa5338..523ef652ef 100644 --- a/source/common/compression/zstd/common/BUILD +++ b/source/common/compression/zstd/common/BUILD @@ -12,8 +12,8 @@ envoy_cc_library( name = "zstd_base_lib", srcs = ["base.cc"], hdrs = ["base.h"], - external_deps = ["zstd"], deps = [ + "//bazel/foreign_cc:zstd", "//source/common/buffer:buffer_lib", ], ) diff --git a/source/common/crypto/BUILD b/source/common/crypto/BUILD index 1baf0903f6..3f52f93003 100644 --- a/source/common/crypto/BUILD +++ b/source/common/crypto/BUILD @@ -19,9 +19,7 @@ envoy_cc_library( "utility.h", "utility_impl.h", ], - external_deps = [ - "ssl", - ], + external_deps = ["ssl"], deps = [ "//envoy/buffer:buffer_interface", "//envoy/common/crypto:crypto_interface", diff --git a/source/common/event/BUILD b/source/common/event/BUILD index 659d8e76b0..0bcc005674 100644 --- a/source/common/event/BUILD +++ b/source/common/event/BUILD @@ -88,8 +88,8 @@ envoy_cc_library( name = "event_impl_base_lib", srcs = ["event_impl_base.cc"], hdrs = ["event_impl_base.h"], - external_deps = [ - "event", + deps = [ + "//bazel/foreign_cc:event", ], ) @@ -133,10 +133,8 @@ envoy_cc_library( name = "libevent_lib", srcs = ["libevent.cc"], hdrs = ["libevent.h"], - external_deps = [ - "event", - ], deps = [ + "//bazel/foreign_cc:event", "//source/common/common:assert_lib", "//source/common/common:c_smart_ptr_lib", ], @@ -146,11 +144,11 @@ envoy_cc_library( name = "libevent_scheduler_lib", srcs = ["libevent_scheduler.cc"], hdrs = ["libevent_scheduler.h"], - external_deps = ["event"], deps = [ ":libevent_lib", ":schedulable_cb_lib", ":timer_lib", + "//bazel/foreign_cc:event", "//envoy/event:dispatcher_interface", "//envoy/event:timer_interface", "//source/common/common:assert_lib", @@ -161,10 +159,10 @@ envoy_cc_library( name = "schedulable_cb_lib", srcs = ["schedulable_cb_impl.cc"], hdrs = ["schedulable_cb_impl.h"], - external_deps = ["event"], deps = [ ":event_impl_base_lib", ":libevent_lib", + "//bazel/foreign_cc:event", "//envoy/event:schedulable_cb_interface", ], ) @@ -173,10 +171,10 @@ envoy_cc_library( name = "timer_lib", srcs = ["timer_impl.cc"], hdrs = ["timer_impl.h"], - external_deps = ["event"], deps = [ ":event_impl_base_lib", ":libevent_lib", + "//bazel/foreign_cc:event", "//envoy/event:timer_interface", "//source/common/common:scope_tracker", "//source/common/common:utility_lib", diff --git a/source/common/filesystem/BUILD b/source/common/filesystem/BUILD index 65f8e0c87b..783882d695 100644 --- a/source/common/filesystem/BUILD +++ b/source/common/filesystem/BUILD @@ -106,9 +106,6 @@ envoy_cc_library( "inotify/watcher_impl.h", ], }), - external_deps = [ - "event", - ], include_prefix = "source/common/filesystem", strip_include_prefix = select({ "//bazel:apple": "kqueue", @@ -116,6 +113,7 @@ envoy_cc_library( "//conditions:default": "inotify", }), deps = [ + "//bazel/foreign_cc:event", "//envoy/api:api_interface", "//envoy/event:dispatcher_interface", "//source/common/buffer:buffer_lib", diff --git a/source/common/grpc/BUILD b/source/common/grpc/BUILD index 3e183c19e2..200d365aec 100644 --- a/source/common/grpc/BUILD +++ b/source/common/grpc/BUILD @@ -133,9 +133,7 @@ envoy_cc_library( name = "google_grpc_utils_lib", srcs = ["google_grpc_utils.cc"], hdrs = ["google_grpc_utils.h"], - external_deps = [ - "grpc", - ], + external_deps = ["grpc"], deps = [ ":google_grpc_creds_lib", "//envoy/api:api_interface", @@ -166,9 +164,7 @@ envoy_cc_library( name = "google_async_client_lib", srcs = ["google_async_client_impl.cc"], hdrs = ["google_async_client_impl.h"], - external_deps = [ - "grpc", - ], + external_deps = ["grpc"], deps = [ ":context_lib", ":google_grpc_context_lib", diff --git a/source/common/http/BUILD b/source/common/http/BUILD index c9d337388d..f0dc9190b8 100644 --- a/source/common/http/BUILD +++ b/source/common/http/BUILD @@ -240,7 +240,6 @@ envoy_cc_library( "http_server_properties_cache_impl.h", "http_server_properties_cache_manager_impl.h", ], - external_deps = ["quiche_quic_platform"], deps = [ ":http3_status_tracker_impl_lib", "//envoy/common:time_interface", @@ -253,6 +252,7 @@ envoy_cc_library( "//source/common/common:logger_lib", "//source/common/config:utility_lib", "@com_github_google_quiche//:http2_core_alt_svc_wire_format_lib", + "@com_github_google_quiche//:quic_platform", "@envoy_api//envoy/config/common/key_value/v3:pkg_cc_proto", "@envoy_api//envoy/config/core/v3:pkg_cc_proto", ], @@ -519,10 +519,6 @@ envoy_cc_library( name = "utility_lib", srcs = ["utility.cc"], hdrs = ["utility.h"], - external_deps = [ - "http_parser", - "quiche_http2_protocol", - ], deps = [ ":character_set_validation_lib", ":exception_lib", @@ -530,6 +526,7 @@ envoy_cc_library( ":headers_lib", ":http_option_limits_lib", ":message_lib", + "//bazel/external/http_parser", "//envoy/common:regex_interface", "//envoy/http:codes_interface", "//envoy/http:filter_interface", @@ -545,6 +542,7 @@ envoy_cc_library( "//source/common/network:utility_lib", "//source/common/protobuf:utility_lib", "//source/common/runtime:runtime_features_lib", + "@com_github_google_quiche//:http2_adapter_http2_protocol", "@com_google_absl//absl/container:node_hash_set", "@com_google_absl//absl/types:optional", "@envoy_api//envoy/config/core/v3:pkg_cc_proto", @@ -556,9 +554,6 @@ envoy_cc_library( name = "header_utility_lib", srcs = ["header_utility.cc"], hdrs = ["header_utility.h"], - external_deps = [ - "quiche_http2_adapter", - ], deps = [ ":character_set_validation_lib", ":header_map_lib", @@ -574,6 +569,7 @@ envoy_cc_library( "//source/common/common:utility_lib", "//source/common/protobuf:utility_lib", "//source/common/runtime:runtime_features_lib", + "@com_github_google_quiche//:http2_adapter", "@envoy_api//envoy/config/core/v3:pkg_cc_proto", "@envoy_api//envoy/config/route/v3:pkg_cc_proto", "@envoy_api//envoy/type/v3:pkg_cc_proto", diff --git a/source/common/http/http1/BUILD b/source/common/http/http1/BUILD index 84f8e2d7c3..0e31c65919 100644 --- a/source/common/http/http1/BUILD +++ b/source/common/http/http1/BUILD @@ -115,9 +115,9 @@ envoy_cc_library( name = "legacy_parser_lib", srcs = ["legacy_parser_impl.cc"], hdrs = ["legacy_parser_impl.h"], - external_deps = ["http_parser"], deps = [ ":parser_interface", + "//bazel/external/http_parser", "//source/common/common:assert_lib", ], ) diff --git a/source/common/http/http2/BUILD b/source/common/http/http2/BUILD index 26fa680b9f..281377db83 100644 --- a/source/common/http/http2/BUILD +++ b/source/common/http/http2/BUILD @@ -28,9 +28,6 @@ envoy_cc_library( name = "codec_lib", srcs = ["codec_impl.cc"], hdrs = ["codec_impl.h"], - external_deps = [ - "quiche_http2_adapter", - ], deps = [ ":codec_stats_lib", ":metadata_decoder_lib", @@ -61,6 +58,7 @@ envoy_cc_library( "//source/common/http:utility_lib", "//source/common/network:common_connection_filter_states_lib", "//source/common/runtime:runtime_features_lib", + "@com_github_google_quiche//:http2_adapter", "@com_google_absl//absl/algorithm", "@com_google_absl//absl/cleanup", "@com_google_absl//absl/container:inlined_vector", @@ -97,14 +95,12 @@ envoy_cc_library( name = "metadata_encoder_lib", srcs = ["metadata_encoder.cc"], hdrs = ["metadata_encoder.h"], - external_deps = [ - "quiche_http2_adapter", - ], deps = [ "//envoy/http:codec_interface", "//source/common/buffer:buffer_lib", "//source/common/common:assert_lib", "//source/common/common:minimal_logger_lib", + "@com_github_google_quiche//:http2_adapter", ], ) @@ -112,15 +108,13 @@ envoy_cc_library( name = "metadata_decoder_lib", srcs = ["metadata_decoder.cc"], hdrs = ["metadata_decoder.h"], - external_deps = [ - "quiche_http2_hpack_decoder", - ], deps = [ "//envoy/http:codec_interface", "//source/common/buffer:buffer_lib", "//source/common/common:assert_lib", "//source/common/common:minimal_logger_lib", "//source/common/runtime:runtime_features_lib", + "@com_github_google_quiche//:http2_hpack_decoder_hpack_decoder_lib", ] + envoy_select_nghttp2([envoy_external_dep_path("nghttp2")]), ) diff --git a/source/common/io/BUILD b/source/common/io/BUILD index c3d8166152..2b6c2b029f 100644 --- a/source/common/io/BUILD +++ b/source/common/io/BUILD @@ -17,9 +17,9 @@ envoy_cc_library( hdrs = [ "io_uring_impl.h", ], - external_deps = ["uring"], tags = ["nocompdb"], deps = [ + "//bazel/foreign_cc:liburing_linux", "//envoy/common/io:io_uring_interface", "//envoy/thread_local:thread_local_interface", ], diff --git a/source/common/json/BUILD b/source/common/json/BUILD index 1ca1e30c9d..02ae19bfab 100644 --- a/source/common/json/BUILD +++ b/source/common/json/BUILD @@ -12,15 +12,13 @@ envoy_cc_library( name = "json_internal_lib", srcs = ["json_internal.cc"], hdrs = ["json_internal.h"], - external_deps = [ - "json", - ], deps = [ "//envoy/json:json_object_interface", "//source/common/common:assert_lib", "//source/common/common:hash_lib", "//source/common/common:utility_lib", "//source/common/protobuf:utility_lib", + "@com_github_nlohmann_json//:json", ], ) diff --git a/source/common/orca/BUILD b/source/common/orca/BUILD index c558cee04e..79aa433408 100644 --- a/source/common/orca/BUILD +++ b/source/common/orca/BUILD @@ -12,13 +12,11 @@ envoy_cc_library( name = "orca_parser", srcs = ["orca_parser.cc"], hdrs = ["orca_parser.h"], - external_deps = [ - "fmtlib", - ], deps = [ "//envoy/http:header_map_interface", "//source/common/common:base64_lib", "@com_github_cncf_xds//xds/data/orca/v3:pkg_cc_proto", + "@com_github_fmtlib_fmt//:fmtlib", "@com_google_absl//absl/status:statusor", "@com_google_absl//absl/strings", ], @@ -28,15 +26,13 @@ envoy_cc_library( name = "orca_load_metrics_lib", srcs = ["orca_load_metrics.cc"], hdrs = ["orca_load_metrics.h"], - external_deps = [ - "fmtlib", - ], deps = [ ":orca_parser", "//envoy/http:header_map_interface", "//source/common/http:header_utility_lib", "//source/common/protobuf:utility_lib_header", "@com_github_cncf_xds//xds/data/orca/v3:pkg_cc_proto", + "@com_github_fmtlib_fmt//:fmtlib", "@com_google_absl//absl/container:flat_hash_map", "@com_google_absl//absl/status", "@com_google_absl//absl/status:statusor", diff --git a/source/common/protobuf/BUILD b/source/common/protobuf/BUILD index fa252699ff..8c60668ca2 100644 --- a/source/common/protobuf/BUILD +++ b/source/common/protobuf/BUILD @@ -34,7 +34,6 @@ envoy_cc_library( name = "message_validator_lib", srcs = ["message_validator_impl.cc"], hdrs = ["message_validator_impl.h"], - external_deps = ["protobuf"], deps = [ "//envoy/protobuf:message_validator_interface", "//envoy/stats:stats_interface", @@ -42,18 +41,17 @@ envoy_cc_library( "//source/common/common:hash_lib", "//source/common/common:logger_lib", "//source/common/common:macros", + "@com_google_protobuf//:protobuf", ], ) envoy_cc_library( name = "protobuf", hdrs = ["protobuf.h"], - external_deps = [ - "protobuf", - ], deps = [ ":cc_wkt_protos", "//envoy/common:base_includes", + "@com_google_protobuf//:protobuf", ], ) @@ -72,10 +70,6 @@ envoy_cc_library( envoy_cc_library( name = "yaml_utility_lib", srcs = envoy_select_enable_yaml(["yaml_utility.cc"]), - external_deps = [ - "protobuf", - "yaml_cpp", - ], deps = [ ":message_validator_lib", ":protobuf", @@ -88,6 +82,8 @@ envoy_cc_library( "//source/common/protobuf:visitor_lib", "//source/common/runtime:runtime_features_lib", "@com_github_cncf_xds//udpa/annotations:pkg_cc_proto", + "@com_github_jbeder_yaml_cpp//:yaml-cpp", + "@com_google_protobuf//:protobuf", "@envoy_api//envoy/annotations:pkg_cc_proto", "@envoy_api//envoy/type/v3:pkg_cc_proto", "@utf8_range//:utf8_validity", @@ -99,11 +95,9 @@ envoy_cc_library( srcs = [ "create_reflectable_message.cc", ], - external_deps = [ - "protobuf", - ], deps = [ "utility_lib_header", + "@com_google_protobuf//:protobuf", ] + envoy_select_enable_lite_protos([ "@envoy_api//bazel/cc_proto_descriptor_library:create_dynamic_message", "@envoy_api//bazel/cc_proto_descriptor_library:text_format_transcoder", @@ -213,9 +207,6 @@ envoy_cc_library( envoy_cc_library( name = "utility_lib", srcs = ["utility.cc"], - external_deps = [ - "protobuf", - ], deps = [ ":deterministic_hash_lib", ":message_validator_lib", @@ -229,6 +220,7 @@ envoy_cc_library( "//source/common/protobuf:visitor_lib", "//source/common/runtime:runtime_features_lib", "@com_github_cncf_xds//udpa/annotations:pkg_cc_proto", + "@com_google_protobuf//:protobuf", "@envoy_api//envoy/annotations:pkg_cc_proto", "@envoy_api//envoy/type/v3:pkg_cc_proto", ] + envoy_select_enable_yaml(["yaml_utility_lib"]), diff --git a/source/common/quic/BUILD b/source/common/quic/BUILD index 62a54d13e6..2186c5f600 100644 --- a/source/common/quic/BUILD +++ b/source/common/quic/BUILD @@ -21,13 +21,13 @@ envoy_cc_library( name = "envoy_quic_alarm_lib", srcs = ["envoy_quic_alarm.cc"], hdrs = ["envoy_quic_alarm.h"], - external_deps = ["quiche_quic_platform"], tags = ["nofips"], deps = [ "//envoy/event:dispatcher_interface", "//envoy/event:timer_interface", "@com_github_google_quiche//:quic_core_alarm_lib", "@com_github_google_quiche//:quic_core_clock_lib", + "@com_github_google_quiche//:quic_platform", ], ) @@ -35,13 +35,13 @@ envoy_cc_library( name = "envoy_quic_alarm_factory_lib", srcs = ["envoy_quic_alarm_factory.cc"], hdrs = ["envoy_quic_alarm_factory.h"], - external_deps = ["quiche_quic_platform"], tags = ["nofips"], deps = [ ":envoy_quic_alarm_lib", "@com_github_google_quiche//:quic_core_alarm_factory_lib", "@com_github_google_quiche//:quic_core_arena_scoped_ptr_lib", "@com_github_google_quiche//:quic_core_one_block_arena_lib", + "@com_github_google_quiche//:quic_platform", ], ) @@ -100,7 +100,6 @@ envoy_cc_library( name = "envoy_quic_proof_source_base_lib", srcs = ["envoy_quic_proof_source_base.cc"], hdrs = ["envoy_quic_proof_source_base.h"], - external_deps = ["quiche_quic_platform"], tags = ["nofips"], deps = [ ":envoy_quic_utils_lib", @@ -109,6 +108,7 @@ envoy_cc_library( "@com_github_google_quiche//:quic_core_crypto_proof_source_lib", "@com_github_google_quiche//:quic_core_data_lib", "@com_github_google_quiche//:quic_core_versions_lib", + "@com_github_google_quiche//:quic_platform", ], ) @@ -116,9 +116,7 @@ envoy_cc_library( name = "envoy_quic_proof_source_lib", srcs = ["envoy_quic_proof_source.cc"], hdrs = ["envoy_quic_proof_source.h"], - external_deps = [ - "ssl", - ], + external_deps = ["ssl"], tags = ["nofips"], deps = [ ":envoy_quic_proof_source_base_lib", @@ -138,13 +136,13 @@ envoy_cc_library( name = "envoy_quic_proof_verifier_base_lib", srcs = ["envoy_quic_proof_verifier_base.cc"], hdrs = ["envoy_quic_proof_verifier_base.h"], - external_deps = ["quiche_quic_platform"], tags = ["nofips"], deps = [ ":envoy_quic_utils_lib", "@com_github_google_quiche//:quic_core_crypto_certificate_view_lib", "@com_github_google_quiche//:quic_core_crypto_crypto_handshake_lib", "@com_github_google_quiche//:quic_core_versions_lib", + "@com_github_google_quiche//:quic_platform", ], ) @@ -152,13 +150,13 @@ envoy_cc_library( name = "envoy_quic_proof_verifier_lib", srcs = ["envoy_quic_proof_verifier.cc"], hdrs = ["envoy_quic_proof_verifier.h"], - external_deps = ["quiche_quic_platform"], tags = ["nofips"], deps = [ ":envoy_quic_proof_verifier_base_lib", ":envoy_quic_utils_lib", ":quic_ssl_connection_info_lib", "//source/common/tls:context_lib", + "@com_github_google_quiche//:quic_platform", ], ) @@ -462,10 +460,7 @@ envoy_cc_library( name = "envoy_quic_utils_lib", srcs = ["envoy_quic_utils.cc"], hdrs = ["envoy_quic_utils.h"], - external_deps = [ - "quiche_quic_platform", - "ssl", - ], + external_deps = ["ssl"], tags = ["nofips"], deps = [ "//envoy/http:codec_interface", @@ -478,6 +473,7 @@ envoy_cc_library( "//source/common/quic:quic_io_handle_wrapper_lib", "@com_github_google_quiche//:quic_core_config_lib", "@com_github_google_quiche//:quic_core_http_header_list_lib", + "@com_github_google_quiche//:quic_platform", "@envoy_api//envoy/config/core/v3:pkg_cc_proto", "@envoy_api//envoy/config/listener/v3:pkg_cc_proto", ], @@ -591,11 +587,11 @@ envoy_cc_library( name = "envoy_quic_packet_writer_lib", srcs = ["envoy_quic_packet_writer.cc"], hdrs = ["envoy_quic_packet_writer.h"], - external_deps = ["quiche_quic_platform"], tags = ["nofips"], deps = [ ":envoy_quic_utils_lib", "@com_github_google_quiche//:quic_core_packet_writer_lib", + "@com_github_google_quiche//:quic_platform", ], ) @@ -606,7 +602,6 @@ envoy_cc_library( "//conditions:default": [], }), hdrs = ["udp_gso_batch_writer.h"], - external_deps = ["quiche_quic_platform"], tags = ["nofips"], deps = [ ":envoy_quic_utils_lib", @@ -614,6 +609,7 @@ envoy_cc_library( "//source/common/network:io_socket_error_lib", "//source/common/protobuf:utility_lib", "//source/common/runtime:runtime_lib", + "@com_github_google_quiche//:quic_platform", ] + select({ "//bazel:linux": ["@com_github_google_quiche//:quic_core_batch_writer_gso_batch_writer_lib"], "//conditions:default": [], @@ -721,11 +717,9 @@ envoy_cc_library( name = "cert_compression_lib", srcs = ["cert_compression.cc"], hdrs = ["cert_compression.h"], - external_deps = [ - "ssl", - "zlib", - ], + external_deps = ["ssl"], deps = [ + "//bazel/foreign_cc:zlib", "//source/common/common:assert_lib", "//source/common/common:logger_lib", "//source/common/runtime:runtime_lib", diff --git a/source/common/stats/BUILD b/source/common/stats/BUILD index b2852de43a..4e01a6e007 100644 --- a/source/common/stats/BUILD +++ b/source/common/stats/BUILD @@ -54,15 +54,13 @@ envoy_cc_library( name = "histogram_lib", srcs = ["histogram_impl.cc"], hdrs = ["histogram_impl.h"], - external_deps = [ - "libcircllhist", - ], deps = [ ":metric_impl_lib", "//source/common/common:assert_lib", "//source/common/common:hash_lib", "//source/common/common:matchers_lib", "//source/common/common:utility_lib", + "@com_github_openhistogram_libcircllhist//:libcircllhist", "@envoy_api//envoy/config/metrics/v3:pkg_cc_proto", ], ) diff --git a/source/common/tls/BUILD b/source/common/tls/BUILD index 4a0b1b3b71..ea7576b8c2 100644 --- a/source/common/tls/BUILD +++ b/source/common/tls/BUILD @@ -63,9 +63,7 @@ envoy_cc_library( name = "ssl_socket_base", srcs = ["ssl_socket.cc"], hdrs = ["ssl_socket.h"], - external_deps = [ - "ssl", - ], + external_deps = ["ssl"], # TLS is core functionality. visibility = ["//visibility:public"], deps = [ @@ -98,9 +96,7 @@ envoy_cc_library( name = "client_ssl_socket_lib", srcs = ["client_ssl_socket.cc"], hdrs = ["client_ssl_socket.h"], - external_deps = [ - "ssl", - ], + external_deps = ["ssl"], deps = [ ":ssl_socket_base", "@com_google_absl//absl/container:node_hash_set", @@ -114,9 +110,7 @@ envoy_cc_library( name = "server_ssl_socket_lib", srcs = ["server_ssl_socket.cc"], hdrs = ["server_ssl_socket.h"], - external_deps = [ - "ssl", - ], + external_deps = ["ssl"], deps = [ ":ssl_socket_base", "@com_google_absl//absl/container:node_hash_set", @@ -138,9 +132,7 @@ envoy_cc_library( name = "context_config_lib", srcs = ["context_config_impl.cc"], hdrs = ["context_config_impl.h"], - external_deps = [ - "ssl", - ], + external_deps = ["ssl"], # TLS is core functionality. visibility = ["//visibility:public"], deps = [ @@ -185,9 +177,7 @@ envoy_cc_library( "context_impl.h", "context_manager_impl.h", ], - external_deps = [ - "ssl", - ], + external_deps = ["ssl"], # TLS is core functionality. visibility = ["//visibility:public"], deps = [ @@ -243,9 +233,7 @@ envoy_cc_library( name = "stats_lib", srcs = ["stats.cc"], hdrs = ["stats.h"], - external_deps = [ - "ssl", - ], + external_deps = ["ssl"], deps = [ "//envoy/stats:stats_interface", "//envoy/stats:stats_macros", @@ -258,9 +246,7 @@ envoy_cc_library( name = "utility_lib", srcs = ["utility.cc"], hdrs = ["utility.h"], - external_deps = [ - "ssl", - ], + external_deps = ["ssl"], deps = [ "//source/common/common:assert_lib", "//source/common/common:empty_string", diff --git a/source/common/tls/cert_validator/BUILD b/source/common/tls/cert_validator/BUILD index ed1619c6d5..63fbe3df35 100644 --- a/source/common/tls/cert_validator/BUILD +++ b/source/common/tls/cert_validator/BUILD @@ -23,9 +23,7 @@ envoy_cc_library( "san_matcher.h", "utility.h", ], - external_deps = [ - "ssl", - ], + external_deps = ["ssl"], visibility = ["//visibility:public"], deps = [ "//envoy/config:typed_config_interface", diff --git a/source/common/upstream/BUILD b/source/common/upstream/BUILD index e96b08a318..f974321a7b 100644 --- a/source/common/upstream/BUILD +++ b/source/common/upstream/BUILD @@ -227,9 +227,7 @@ envoy_cc_library( name = "health_checker_lib", srcs = ["health_checker_impl.cc"], hdrs = ["health_checker_impl.h"], - external_deps = [ - "grpc_health_proto", - ], + external_deps = ["grpc_health_proto"], deps = [ ":health_checker_event_logger_lib", "@envoy_api//envoy/config/core/v3:pkg_cc_proto", diff --git a/source/extensions/access_loggers/fluentd/BUILD b/source/extensions/access_loggers/fluentd/BUILD index 3a7151731b..73da28b991 100644 --- a/source/extensions/access_loggers/fluentd/BUILD +++ b/source/extensions/access_loggers/fluentd/BUILD @@ -23,14 +23,12 @@ envoy_cc_library( name = "fluentd_access_log_lib", srcs = ["fluentd_access_log_impl.cc"], hdrs = ["fluentd_access_log_impl.h"], - external_deps = [ - "msgpack", - ], deps = [ ":substitution_formatter_lib", "//envoy/access_log:access_log_interface", "//source/common/access_log:access_log_lib", "//source/extensions/access_loggers/common:access_log_base", + "@com_github_msgpack_cpp//:msgpack", "@envoy_api//envoy/extensions/access_loggers/fluentd/v3:pkg_cc_proto", ], ) diff --git a/source/extensions/common/dubbo/BUILD b/source/extensions/common/dubbo/BUILD index ec22a68ea7..e3e114a4e1 100644 --- a/source/extensions/common/dubbo/BUILD +++ b/source/extensions/common/dubbo/BUILD @@ -12,13 +12,11 @@ envoy_cc_library( name = "hessian2_utils_lib", srcs = ["hessian2_utils.cc"], hdrs = ["hessian2_utils.h"], - external_deps = [ - "hessian2_codec_codec_impl", - "hessian2_codec_object_codec_lib", - ], deps = [ "//envoy/buffer:buffer_interface", "//source/common/singleton:const_singleton", + "@com_github_alibaba_hessian2_codec//hessian2:codec_impl_lib", + "@com_github_alibaba_hessian2_codec//hessian2/basic_codec:object_codec_lib", ], ) diff --git a/source/extensions/common/wasm/BUILD b/source/extensions/common/wasm/BUILD index c45b87e200..1931b851d5 100644 --- a/source/extensions/common/wasm/BUILD +++ b/source/extensions/common/wasm/BUILD @@ -97,8 +97,8 @@ envoy_cc_extension( deps = [ ":wasm_hdr", ":wasm_runtime_factory_interface", + "//bazel/foreign_cc:zlib", "//envoy/server:lifecycle_notifier_interface", - "//external:zlib", "//source/common/buffer:buffer_lib", "//source/common/common:enum_to_int", "//source/common/common:safe_memcpy_lib", diff --git a/source/extensions/common/wasm/ext/BUILD b/source/extensions/common/wasm/ext/BUILD index 3523551306..254f4b1276 100644 --- a/source/extensions/common/wasm/ext/BUILD +++ b/source/extensions/common/wasm/ext/BUILD @@ -97,7 +97,7 @@ cc_proto_library( name = "node_subset_cc_proto", deps = [ ":node_subset_proto", - # "//external:protobuf_clib", + # "@com_google_protobuf//:protoc_lib", ], ) diff --git a/source/extensions/compression/brotli/compressor/BUILD b/source/extensions/compression/brotli/compressor/BUILD index c8e6e3a8a4..6eb824ae6d 100644 --- a/source/extensions/compression/brotli/compressor/BUILD +++ b/source/extensions/compression/brotli/compressor/BUILD @@ -13,11 +13,11 @@ envoy_cc_library( name = "compressor_lib", srcs = ["brotli_compressor_impl.cc"], hdrs = ["brotli_compressor_impl.h"], - external_deps = ["brotlienc"], deps = [ "//envoy/compression/compressor:compressor_interface", "//source/common/buffer:buffer_lib", "//source/extensions/compression/brotli/common:brotli_base_lib", + "@org_brotli//:brotlienc", ], ) diff --git a/source/extensions/compression/brotli/decompressor/BUILD b/source/extensions/compression/brotli/decompressor/BUILD index 18155bfaae..c5239f0df1 100644 --- a/source/extensions/compression/brotli/decompressor/BUILD +++ b/source/extensions/compression/brotli/decompressor/BUILD @@ -13,7 +13,6 @@ envoy_cc_library( name = "decompressor_lib", srcs = ["brotli_decompressor_impl.cc"], hdrs = ["brotli_decompressor_impl.h"], - external_deps = ["brotlidec"], deps = [ "//envoy/compression/decompressor:decompressor_interface", "//envoy/stats:stats_interface", @@ -21,6 +20,7 @@ envoy_cc_library( "//source/common/buffer:buffer_lib", "//source/common/runtime:runtime_features_lib", "//source/extensions/compression/brotli/common:brotli_base_lib", + "@org_brotli//:brotlidec", ], ) diff --git a/source/extensions/compression/gzip/common/BUILD b/source/extensions/compression/gzip/common/BUILD index 5c301a6a9a..c843301dd6 100644 --- a/source/extensions/compression/gzip/common/BUILD +++ b/source/extensions/compression/gzip/common/BUILD @@ -12,8 +12,8 @@ envoy_cc_library( name = "zlib_base_lib", srcs = ["base.cc"], hdrs = ["base.h"], - external_deps = ["zlib"], deps = [ + "//bazel/foreign_cc:zlib", "//source/common/buffer:buffer_lib", ], ) diff --git a/source/extensions/compression/gzip/compressor/BUILD b/source/extensions/compression/gzip/compressor/BUILD index c138afe6ac..a7d38764f3 100644 --- a/source/extensions/compression/gzip/compressor/BUILD +++ b/source/extensions/compression/gzip/compressor/BUILD @@ -13,8 +13,8 @@ envoy_cc_library( name = "compressor_lib", srcs = ["zlib_compressor_impl.cc"], hdrs = ["zlib_compressor_impl.h"], - external_deps = ["zlib"], deps = [ + "//bazel/foreign_cc:zlib", "//envoy/compression/compressor:compressor_interface", "//source/common/buffer:buffer_lib", "//source/common/common:assert_lib", diff --git a/source/extensions/compression/gzip/decompressor/BUILD b/source/extensions/compression/gzip/decompressor/BUILD index 2090f49bcd..4904d33ac4 100644 --- a/source/extensions/compression/gzip/decompressor/BUILD +++ b/source/extensions/compression/gzip/decompressor/BUILD @@ -13,8 +13,8 @@ envoy_cc_library( name = "zlib_decompressor_impl_lib", srcs = ["zlib_decompressor_impl.cc"], hdrs = ["zlib_decompressor_impl.h"], - external_deps = ["zlib"], deps = [ + "//bazel/foreign_cc:zlib", "//envoy/compression/decompressor:decompressor_interface", "//envoy/stats:stats_interface", "//envoy/stats:stats_macros", diff --git a/source/extensions/compression/zstd/common/BUILD b/source/extensions/compression/zstd/common/BUILD index a0aa945564..eb8f90fb83 100644 --- a/source/extensions/compression/zstd/common/BUILD +++ b/source/extensions/compression/zstd/common/BUILD @@ -11,8 +11,8 @@ envoy_extension_package() envoy_cc_library( name = "zstd_dictionary_manager_lib", hdrs = ["dictionary_manager.h"], - external_deps = ["zstd"], deps = [ + "//bazel/foreign_cc:zstd", "//envoy/event:dispatcher_interface", "//envoy/thread_local:thread_local_interface", "//source/common/config:datasource_lib", diff --git a/source/extensions/config_subscription/rest/BUILD b/source/extensions/config_subscription/rest/BUILD index 360ed0cdac..e7f8051ddf 100644 --- a/source/extensions/config_subscription/rest/BUILD +++ b/source/extensions/config_subscription/rest/BUILD @@ -13,9 +13,7 @@ envoy_cc_extension( name = "http_subscription_lib", srcs = ["http_subscription_impl.cc"], hdrs = ["http_subscription_impl.h"], - external_deps = [ - "http_api_protos", - ], + external_deps = ["http_api_protos"], extra_visibility = [ # previously considered core code. "//test:__subpackages__", diff --git a/source/extensions/filters/common/lua/BUILD b/source/extensions/filters/common/lua/BUILD index 12d7d0554a..207abbac99 100644 --- a/source/extensions/filters/common/lua/BUILD +++ b/source/extensions/filters/common/lua/BUILD @@ -12,10 +12,8 @@ envoy_cc_library( name = "lua_lib", srcs = ["lua.cc"], hdrs = ["lua.h"], - external_deps = [ - "luajit", - ], deps = [ + "//bazel/foreign_cc:luajit", "//envoy/thread_local:thread_local_interface", "//source/common/common:assert_lib", "//source/common/common:c_smart_ptr_lib", diff --git a/source/extensions/filters/http/adaptive_concurrency/controller/BUILD b/source/extensions/filters/http/adaptive_concurrency/controller/BUILD index 60cb03dd31..abceffc527 100644 --- a/source/extensions/filters/http/adaptive_concurrency/controller/BUILD +++ b/source/extensions/filters/http/adaptive_concurrency/controller/BUILD @@ -19,9 +19,6 @@ envoy_cc_library( "controller.h", "gradient_controller.h", ], - external_deps = [ - "libcircllhist", - ], deps = [ "//envoy/common:time_interface", "//source/common/common:thread_synchronizer_lib", @@ -30,6 +27,7 @@ envoy_cc_library( "//source/common/runtime:runtime_lib", "//source/common/stats:isolated_store_lib", "//source/common/stats:stats_lib", + "@com_github_openhistogram_libcircllhist//:libcircllhist", "@envoy_api//envoy/extensions/filters/http/adaptive_concurrency/v3:pkg_cc_proto", ], ) diff --git a/source/extensions/filters/http/common/BUILD b/source/extensions/filters/http/common/BUILD index 7bc4eea7f4..73d4be20fb 100644 --- a/source/extensions/filters/http/common/BUILD +++ b/source/extensions/filters/http/common/BUILD @@ -31,12 +31,10 @@ envoy_cc_library( name = "jwks_fetcher_lib", srcs = ["jwks_fetcher.cc"], hdrs = ["jwks_fetcher.h"], - external_deps = [ - "jwt_verify_lib", - ], deps = [ "//envoy/upstream:cluster_manager_interface", "//source/common/http:utility_lib", + "@com_github_google_jwt_verify//:jwt_verify_lib", "@envoy_api//envoy/config/core/v3:pkg_cc_proto", "@envoy_api//envoy/extensions/filters/http/jwt_authn/v3:pkg_cc_proto", ], diff --git a/source/extensions/filters/http/gcp_authn/BUILD b/source/extensions/filters/http/gcp_authn/BUILD index ecb021ee00..2dd2e7daa0 100644 --- a/source/extensions/filters/http/gcp_authn/BUILD +++ b/source/extensions/filters/http/gcp_authn/BUILD @@ -44,16 +44,14 @@ envoy_cc_library( envoy_cc_library( name = "token_cache", hdrs = ["token_cache.h"], - external_deps = [ - "jwt_verify_lib", - "simple_lru_cache_lib", - ], deps = [ "//source/common/http:headers_lib", "//source/common/http:message_lib", "//source/common/http:utility_lib", "//source/extensions/filters/http/common:factory_base_lib", "//source/extensions/filters/http/common:pass_through_filter_lib", + "@com_github_google_jwt_verify//:jwt_verify_lib", + "@com_github_google_jwt_verify//:simple_lru_cache_lib", "@envoy_api//envoy/extensions/filters/http/gcp_authn/v3:pkg_cc_proto", ], ) diff --git a/source/extensions/filters/http/grpc_field_extraction/BUILD b/source/extensions/filters/http/grpc_field_extraction/BUILD index 929124b0a6..ae910dc834 100644 --- a/source/extensions/filters/http/grpc_field_extraction/BUILD +++ b/source/extensions/filters/http/grpc_field_extraction/BUILD @@ -24,9 +24,7 @@ envoy_cc_library( name = "extractor_impl", srcs = ["extractor_impl.cc"], hdrs = ["extractor_impl.h"], - external_deps = [ - "grpc_transcoding", - ], + external_deps = ["grpc_transcoding"], deps = [ "extractor", "//source/common/common:minimal_logger_lib", @@ -52,9 +50,7 @@ envoy_cc_library( name = "filter", srcs = ["filter.cc"], hdrs = ["filter.h"], - external_deps = [ - "grpc_transcoding", - ], + external_deps = ["grpc_transcoding"], deps = [ "extractor_impl", "filter_config", diff --git a/source/extensions/filters/http/grpc_json_transcoder/BUILD b/source/extensions/filters/http/grpc_json_transcoder/BUILD index 7a8455a241..fa88fe00db 100644 --- a/source/extensions/filters/http/grpc_json_transcoder/BUILD +++ b/source/extensions/filters/http/grpc_json_transcoder/BUILD @@ -43,9 +43,7 @@ envoy_cc_library( name = "http_body_utils_lib", srcs = ["http_body_utils.cc"], hdrs = ["http_body_utils.h"], - external_deps = [ - "api_httpbody_protos", - ], + external_deps = ["api_httpbody_protos"], deps = [ "//source/common/grpc:codec_lib", "//source/common/protobuf", diff --git a/source/extensions/filters/http/jwt_authn/BUILD b/source/extensions/filters/http/jwt_authn/BUILD index ccf0af7f35..c01f977750 100644 --- a/source/extensions/filters/http/jwt_authn/BUILD +++ b/source/extensions/filters/http/jwt_authn/BUILD @@ -34,9 +34,6 @@ envoy_cc_library( name = "jwks_async_fetcher_lib", srcs = ["jwks_async_fetcher.cc"], hdrs = ["jwks_async_fetcher.h"], - external_deps = [ - "jwt_verify_lib", - ], deps = [ ":stats_lib", "//envoy/server:factory_context_interface", @@ -45,6 +42,7 @@ envoy_cc_library( "//source/common/protobuf:utility_lib", "//source/common/tracing:http_tracer_lib", "//source/extensions/filters/http/common:jwks_fetcher_lib", + "@com_github_google_jwt_verify//:jwt_verify_lib", "@envoy_api//envoy/extensions/filters/http/jwt_authn/v3:pkg_cc_proto", ], ) @@ -53,13 +51,11 @@ envoy_cc_library( name = "jwks_cache_lib", srcs = ["jwks_cache.cc"], hdrs = ["jwks_cache.h"], - external_deps = [ - "jwt_verify_lib", - ], deps = [ "jwks_async_fetcher_lib", ":jwt_cache_lib", "//source/common/config:datasource_lib", + "@com_github_google_jwt_verify//:jwt_verify_lib", "@envoy_api//envoy/extensions/filters/http/jwt_authn/v3:pkg_cc_proto", ], ) @@ -83,14 +79,12 @@ envoy_cc_library( name = "filter_lib", srcs = ["filter.cc"], hdrs = ["filter.h"], - external_deps = [ - "jwt_verify_lib", - ], deps = [ ":filter_config_lib", ":matchers_lib", "//envoy/http:filter_interface", "//source/common/http:headers_lib", + "@com_github_google_jwt_verify//:jwt_verify_lib", ], ) @@ -151,12 +145,10 @@ envoy_cc_library( name = "jwt_cache_lib", srcs = ["jwt_cache.cc"], hdrs = ["jwt_cache.h"], - external_deps = [ - "jwt_verify_lib", - "simple_lru_cache_lib", - ], deps = [ "//source/common/protobuf:utility_lib", + "@com_github_google_jwt_verify//:jwt_verify_lib", + "@com_github_google_jwt_verify//:simple_lru_cache_lib", "@envoy_api//envoy/extensions/filters/http/jwt_authn/v3:pkg_cc_proto", ], ) diff --git a/source/extensions/filters/http/oauth2/BUILD b/source/extensions/filters/http/oauth2/BUILD index 5438db7cb9..5874d69036 100644 --- a/source/extensions/filters/http/oauth2/BUILD +++ b/source/extensions/filters/http/oauth2/BUILD @@ -44,9 +44,6 @@ envoy_cc_library( name = "oauth_lib", srcs = ["filter.cc"], hdrs = ["filter.h"], - external_deps = [ - "jwt_verify_lib", - ], deps = [ ":oauth_client", "//envoy/server:filter_config_interface", @@ -59,6 +56,7 @@ envoy_cc_library( "//source/common/protobuf:utility_lib", "//source/common/secret:secret_provider_impl_lib", "//source/extensions/filters/http/common:pass_through_filter_lib", + "@com_github_google_jwt_verify//:jwt_verify_lib", "@envoy_api//envoy/config/core/v3:pkg_cc_proto", "@envoy_api//envoy/extensions/filters/http/oauth2/v3:pkg_cc_proto", ], diff --git a/source/extensions/filters/listener/http_inspector/BUILD b/source/extensions/filters/listener/http_inspector/BUILD index a0fc9a0bfd..fc5dec01f9 100644 --- a/source/extensions/filters/listener/http_inspector/BUILD +++ b/source/extensions/filters/listener/http_inspector/BUILD @@ -15,8 +15,8 @@ envoy_cc_library( name = "http_inspector_lib", srcs = ["http_inspector.cc"], hdrs = ["http_inspector.h"], - external_deps = ["http_parser"], deps = [ + "//bazel/external/http_parser", "//envoy/event:dispatcher_interface", "//envoy/event:timer_interface", "//envoy/network:filter_interface", diff --git a/source/extensions/filters/network/dubbo_proxy/BUILD b/source/extensions/filters/network/dubbo_proxy/BUILD index 909bb29b7f..09edc7e358 100644 --- a/source/extensions/filters/network/dubbo_proxy/BUILD +++ b/source/extensions/filters/network/dubbo_proxy/BUILD @@ -13,13 +13,11 @@ envoy_cc_library( name = "hessian_utils_lib", srcs = ["hessian_utils.cc"], hdrs = ["hessian_utils.h"], - external_deps = [ - "hessian2_codec_codec_impl", - "hessian2_codec_object_codec_lib", - ], deps = [ "//envoy/buffer:buffer_interface", "//source/common/singleton:const_singleton", + "@com_github_alibaba_hessian2_codec//hessian2:codec_impl_lib", + "@com_github_alibaba_hessian2_codec//hessian2/basic_codec:object_codec_lib", ], ) diff --git a/source/extensions/filters/udp/dns_filter/BUILD b/source/extensions/filters/udp/dns_filter/BUILD index ebb9bff329..e4315f1acc 100644 --- a/source/extensions/filters/udp/dns_filter/BUILD +++ b/source/extensions/filters/udp/dns_filter/BUILD @@ -24,8 +24,8 @@ envoy_cc_library( "dns_filter_utils.h", "dns_parser.h", ], - external_deps = ["ares"], deps = [ + "//bazel/foreign_cc:ares", "//envoy/buffer:buffer_interface", "//envoy/event:dispatcher_interface", "//envoy/network:address_interface", diff --git a/source/extensions/health_checkers/grpc/BUILD b/source/extensions/health_checkers/grpc/BUILD index 8507c82777..c06822d4e7 100644 --- a/source/extensions/health_checkers/grpc/BUILD +++ b/source/extensions/health_checkers/grpc/BUILD @@ -12,9 +12,7 @@ envoy_cc_extension( name = "health_checker_lib", srcs = ["health_checker_impl.cc"], hdrs = ["health_checker_impl.h"], - external_deps = [ - "grpc_health_proto", - ], + external_deps = ["grpc_health_proto"], extra_visibility = [ # previously considered core code. "//test:__subpackages__", diff --git a/source/extensions/network/dns_resolver/cares/BUILD b/source/extensions/network/dns_resolver/cares/BUILD index bb9c3a94f7..7a8a92fa61 100644 --- a/source/extensions/network/dns_resolver/cares/BUILD +++ b/source/extensions/network/dns_resolver/cares/BUILD @@ -12,9 +12,9 @@ envoy_cc_extension( name = "config", srcs = ["dns_impl.cc"], hdrs = ["dns_impl.h"], - external_deps = ["ares"], visibility = ["//visibility:public"], deps = [ + "//bazel/foreign_cc:ares", "//envoy/event:dispatcher_interface", "//envoy/event:file_event_interface", "//envoy/network:dns_interface", diff --git a/source/extensions/tracers/datadog/BUILD b/source/extensions/tracers/datadog/BUILD index cd7327a67d..85dfb3d1d0 100644 --- a/source/extensions/tracers/datadog/BUILD +++ b/source/extensions/tracers/datadog/BUILD @@ -37,9 +37,6 @@ envoy_cc_library( # equivalents of std::string_view and std::optional. "-DDD_USE_ABSEIL_FOR_ENVOY", ], - external_deps = [ - "dd_trace_cpp", - ], deps = [ "//source/common/config:utility_lib", "//source/common/http:async_client_utility_lib", @@ -51,6 +48,7 @@ envoy_cc_library( "//source/common/upstream:cluster_update_tracker_lib", "//source/common/version:version_lib", "//source/extensions/tracers/common:factory_base_lib", + "@com_github_datadog_dd_trace_cpp//:dd_trace_cpp", ], ) diff --git a/source/extensions/tracers/opencensus/BUILD b/source/extensions/tracers/opencensus/BUILD index f661bed6dd..51c454f51c 100644 --- a/source/extensions/tracers/opencensus/BUILD +++ b/source/extensions/tracers/opencensus/BUILD @@ -28,20 +28,18 @@ envoy_cc_library( srcs = ["opencensus_tracer_impl.cc"], hdrs = ["opencensus_tracer_impl.h"], copts = ["-Wno-unused-parameter"], - external_deps = [ - "opencensus_trace", - "opencensus_trace_b3", - "opencensus_trace_cloud_trace_context", - "opencensus_trace_grpc_trace_bin", - "opencensus_trace_trace_context", - "opencensus_exporter_ocagent", - "opencensus_exporter_stdout", - "opencensus_exporter_stackdriver", - "opencensus_exporter_zipkin", - ], deps = [ "//source/common/config:utility_lib", "//source/common/tracing:http_tracer_lib", "@envoy_api//envoy/config/trace/v3:pkg_cc_proto", + "@io_opencensus_cpp//opencensus/exporters/trace/ocagent:ocagent_exporter", + "@io_opencensus_cpp//opencensus/exporters/trace/stackdriver:stackdriver_exporter", + "@io_opencensus_cpp//opencensus/exporters/trace/stdout:stdout_exporter", + "@io_opencensus_cpp//opencensus/exporters/trace/zipkin:zipkin_exporter", + "@io_opencensus_cpp//opencensus/trace", + "@io_opencensus_cpp//opencensus/trace:b3", + "@io_opencensus_cpp//opencensus/trace:cloud_trace_context", + "@io_opencensus_cpp//opencensus/trace:grpc_trace_bin", + "@io_opencensus_cpp//opencensus/trace:trace_context", ] + envoy_select_google_grpc(["//source/common/grpc:google_async_client_lib"]), ) diff --git a/source/extensions/tracers/opentelemetry/BUILD b/source/extensions/tracers/opentelemetry/BUILD index bcc2e7526a..0b6e75abea 100644 --- a/source/extensions/tracers/opentelemetry/BUILD +++ b/source/extensions/tracers/opentelemetry/BUILD @@ -40,7 +40,6 @@ envoy_cc_library( # https://github.com/open-telemetry/opentelemetry-cpp/blob/v1.14.0/api/BUILD#L32 "-DHAVE_ABSEIL", ], - external_deps = ["opentelemetry_api"], deps = [ ":trace_exporter", "//envoy/thread_local:thread_local_interface", @@ -50,6 +49,7 @@ envoy_cc_library( "//source/extensions/tracers/opentelemetry/resource_detectors:resource_detector_lib", "//source/extensions/tracers/opentelemetry/samplers:sampler_lib", "@envoy_api//envoy/config/trace/v3:pkg_cc_proto", + "@io_opentelemetry_cpp//api", "@opentelemetry_proto//:trace_cc_proto", ], ) @@ -67,7 +67,6 @@ envoy_cc_library( "otlp_utils.h", "trace_exporter.h", ], - external_deps = ["opentelemetry_api"], deps = [ "//envoy/grpc:async_client_manager_interface", "//envoy/upstream:cluster_manager_interface", @@ -80,6 +79,7 @@ envoy_cc_library( "//source/common/tracing:trace_context_lib", "//source/common/version:version_lib", "@envoy_api//envoy/config/core/v3:pkg_cc_proto", + "@io_opentelemetry_cpp//api", "@opentelemetry_proto//:trace_cc_proto", ], ) diff --git a/source/extensions/tracers/skywalking/BUILD b/source/extensions/tracers/skywalking/BUILD index b4c33f8786..2c376371a7 100644 --- a/source/extensions/tracers/skywalking/BUILD +++ b/source/extensions/tracers/skywalking/BUILD @@ -15,14 +15,12 @@ envoy_cc_library( name = "trace_segment_reporter_lib", srcs = ["trace_segment_reporter.cc"], hdrs = ["trace_segment_reporter.h"], - external_deps = [ - "cpp2sky", - ], deps = [ ":skywalking_stats_lib", "//envoy/grpc:async_client_manager_interface", "//source/common/common:backoff_lib", "//source/common/grpc:async_client_lib", + "@com_github_skyapm_cpp2sky//source:cpp2sky_data_lib", "@envoy_api//envoy/config/trace/v3:pkg_cc_proto", ], ) @@ -37,9 +35,6 @@ envoy_cc_library( "skywalking_tracer_impl.h", "tracer.h", ], - external_deps = [ - "cpp2sky", - ], deps = [ ":trace_segment_reporter_lib", "//envoy/common:time_interface", @@ -49,6 +44,7 @@ envoy_cc_library( "//source/common/http:header_map_lib", "//source/common/runtime:runtime_lib", "//source/common/tracing:http_tracer_lib", + "@com_github_skyapm_cpp2sky//source:cpp2sky_data_lib", "@envoy_api//envoy/config/trace/v3:pkg_cc_proto", ], ) diff --git a/source/extensions/tracers/xray/BUILD b/source/extensions/tracers/xray/BUILD index e13753344d..78cfd6c785 100644 --- a/source/extensions/tracers/xray/BUILD +++ b/source/extensions/tracers/xray/BUILD @@ -36,7 +36,6 @@ envoy_cc_library( "xray_configuration.h", "xray_tracer_impl.h", ], - external_deps = [], deps = [ ":daemon_cc_proto", "//envoy/common:time_interface", diff --git a/source/extensions/transport_sockets/alts/BUILD b/source/extensions/transport_sockets/alts/BUILD index 7d66d8dd9b..cd32ac0ca8 100644 --- a/source/extensions/transport_sockets/alts/BUILD +++ b/source/extensions/transport_sockets/alts/BUILD @@ -18,9 +18,7 @@ envoy_cc_library( hdrs = [ "grpc_tsi.h", ], - external_deps = [ - "grpc", - ], + external_deps = ["grpc"], visibility = ["//visibility:private"], deps = [ "//source/common/common:c_smart_ptr_lib", @@ -115,9 +113,7 @@ envoy_cc_library( name = "alts_channel_pool", srcs = ["alts_channel_pool.cc"], hdrs = ["alts_channel_pool.h"], - external_deps = [ - "grpc", - ], + external_deps = ["grpc"], deps = [ "@com_google_absl//absl/random", ], @@ -132,9 +128,7 @@ envoy_cc_library( name = "alts_proxy", srcs = ["alts_proxy.cc"], hdrs = ["alts_proxy.h"], - external_deps = [ - "grpc", - ], + external_deps = ["grpc"], deps = [ ":handshaker_cc_grpc", "@com_google_absl//absl/memory", @@ -147,9 +141,7 @@ envoy_cc_library( name = "alts_tsi_handshaker", srcs = ["alts_tsi_handshaker.cc"], hdrs = ["alts_tsi_handshaker.h"], - external_deps = [ - "grpc", - ], + external_deps = ["grpc"], deps = [ ":alts_proxy", ":handshaker_cc_grpc", diff --git a/source/extensions/transport_sockets/starttls/BUILD b/source/extensions/transport_sockets/starttls/BUILD index 1117a147ab..ec4bbbe5d5 100644 --- a/source/extensions/transport_sockets/starttls/BUILD +++ b/source/extensions/transport_sockets/starttls/BUILD @@ -29,9 +29,7 @@ envoy_cc_library( name = "starttls_socket_lib", srcs = ["starttls_socket.cc"], hdrs = ["starttls_socket.h"], - external_deps = [ - "ssl", - ], + external_deps = ["ssl"], deps = [ "//envoy/network:connection_interface", "//envoy/network:transport_socket_interface", diff --git a/source/extensions/transport_sockets/tls/cert_validator/spiffe/BUILD b/source/extensions/transport_sockets/tls/cert_validator/spiffe/BUILD index 150928e553..0de73d027e 100644 --- a/source/extensions/transport_sockets/tls/cert_validator/spiffe/BUILD +++ b/source/extensions/transport_sockets/tls/cert_validator/spiffe/BUILD @@ -16,9 +16,7 @@ envoy_cc_extension( hdrs = [ "spiffe_validator.h", ], - external_deps = [ - "ssl", - ], + external_deps = ["ssl"], deps = [ "//envoy/ssl:context_config_interface", "//envoy/ssl:ssl_socket_extended_info_interface", diff --git a/source/server/BUILD b/source/server/BUILD index 7420331d1f..300b859024 100644 --- a/source/server/BUILD +++ b/source/server/BUILD @@ -267,11 +267,10 @@ envoy_cc_library( envoy_cc_library( name = "options_lib", - # TCLAP command line parser needs this to support int64_t/uint64_t in several build environments. srcs = ["options_impl.cc"], hdrs = ["options_impl.h"], + # TCLAP command line parser needs this to support int64_t/uint64_t in several build environments. copts = ["-DHAVE_LONG_LONG"], - external_deps = ["tclap"], deps = [ ":options_base", "//envoy/network:address_interface", @@ -285,6 +284,7 @@ envoy_cc_library( "//source/common/stats:stats_lib", "//source/common/stats:tag_utility_lib", "//source/common/version:version_lib", + "@com_github_mirror_tclap//:tclap", "@envoy_api//envoy/admin/v3:pkg_cc_proto", "@envoy_api//envoy/config/bootstrap/v3:pkg_cc_proto", ], diff --git a/test/BUILD b/test/BUILD index d8ad1e080c..b4711e6551 100644 --- a/test/BUILD +++ b/test/BUILD @@ -56,10 +56,6 @@ envoy_cc_test_library( envoy_pch_library( name = "test_pch", testonly = True, - external_deps = [ - "googletest", - "spdlog", - ], includes = [ "envoy/config/bootstrap/v3/bootstrap.pb.h", "envoy/config/cluster/v3/cluster.pb.h", @@ -93,6 +89,8 @@ envoy_pch_library( "//test/mocks/server:factory_context_mocks", "//test/mocks/server:instance_mocks", "//test/mocks/stats:stats_mocks", + "@com_github_gabime_spdlog//:spdlog", + "@com_google_googletest//:gtest", "@envoy_api//envoy/config/bootstrap/v3:pkg_cc_proto", "@envoy_api//envoy/config/cluster/v3:pkg_cc_proto", "@envoy_api//envoy/config/core/v3:pkg_cc_proto", diff --git a/test/benchmark/BUILD b/test/benchmark/BUILD index 7d14fd5f4c..73b358abb3 100644 --- a/test/benchmark/BUILD +++ b/test/benchmark/BUILD @@ -12,15 +12,13 @@ envoy_cc_test_library( name = "main", srcs = ["main.cc"], hdrs = ["main.h"], - external_deps = [ - "benchmark", - "tclap", - ], deps = [ "//source/common/common:minimal_logger_lib", "//source/common/common:thread_lib", "//test/test_common:environment_lib", "//test/test_common:printers_lib", "//test/test_common:test_runtime_lib", + "@com_github_google_benchmark//:benchmark", + "@com_github_mirror_tclap//:tclap", ], ) diff --git a/test/common/buffer/BUILD b/test/common/buffer/BUILD index 1a6841bb67..027e7aaf6d 100644 --- a/test/common/buffer/BUILD +++ b/test/common/buffer/BUILD @@ -117,12 +117,10 @@ envoy_cc_test( envoy_cc_benchmark_binary( name = "buffer_speed_test", srcs = ["buffer_speed_test.cc"], - external_deps = [ - "benchmark", - ], deps = [ "//source/common/buffer:buffer_lib", "//source/common/buffer:watermark_buffer_lib", + "@com_github_google_benchmark//:benchmark", "@envoy_api//envoy/config/overload/v3:pkg_cc_proto", ], ) diff --git a/test/common/common/BUILD b/test/common/common/BUILD index cac07a646a..96ad095dab 100644 --- a/test/common/common/BUILD +++ b/test/common/common/BUILD @@ -197,8 +197,10 @@ envoy_cc_test( envoy_cc_benchmark_binary( name = "logger_speed_test", srcs = ["logger_speed_test.cc"], - external_deps = ["benchmark"], - deps = ["//source/common/common:minimal_logger_lib"], + deps = [ + "//source/common/common:minimal_logger_lib", + "@com_github_google_benchmark//:benchmark", + ], ) envoy_benchmark_test( @@ -371,10 +373,10 @@ envoy_cc_test( envoy_cc_benchmark_binary( name = "re_speed_test", srcs = ["re_speed_test.cc"], - external_deps = ["benchmark"], deps = [ "//source/common/common:assert_lib", "//source/common/common:utility_lib", + "@com_github_google_benchmark//:benchmark", "@com_googlesource_code_re2//:re2", ], ) @@ -382,12 +384,10 @@ envoy_cc_benchmark_binary( envoy_cc_benchmark_binary( name = "utility_speed_test", srcs = ["utility_speed_test.cc"], - external_deps = [ - "benchmark", - ], deps = [ "//source/common/common:assert_lib", "//source/common/common:utility_lib", + "@com_github_google_benchmark//:benchmark", "@com_google_absl//absl/strings", ], ) @@ -400,11 +400,9 @@ envoy_benchmark_test( envoy_cc_benchmark_binary( name = "trie_lookup_table_speed_test", srcs = ["trie_lookup_table_speed_test.cc"], - external_deps = [ - "benchmark", - ], deps = [ "//source/common/common:trie_lookup_table_lib", + "@com_github_google_benchmark//:benchmark", "@com_google_absl//absl/strings", ], ) @@ -529,8 +527,10 @@ envoy_cc_test( envoy_cc_benchmark_binary( name = "inline_map_speed_test", srcs = ["inline_map_speed_test.cc"], - external_deps = ["benchmark"], - deps = ["//source/common/common:inline_map"], + deps = [ + "//source/common/common:inline_map", + "@com_github_google_benchmark//:benchmark", + ], ) envoy_benchmark_test( diff --git a/test/common/crypto/BUILD b/test/common/crypto/BUILD index a3d8272da2..d85fe7c034 100644 --- a/test/common/crypto/BUILD +++ b/test/common/crypto/BUILD @@ -15,9 +15,7 @@ envoy_cc_test( srcs = [ "utility_test.cc", ], - external_deps = [ - "ssl", - ], + external_deps = ["ssl"], deps = [ "//source/common/buffer:buffer_lib", "//source/common/common:hex_lib", diff --git a/test/common/formatter/BUILD b/test/common/formatter/BUILD index 661e19a6af..544346222f 100644 --- a/test/common/formatter/BUILD +++ b/test/common/formatter/BUILD @@ -92,9 +92,6 @@ envoy_cc_test( envoy_cc_benchmark_binary( name = "substitution_formatter_speed_test", srcs = ["substitution_formatter_speed_test.cc"], - external_deps = [ - "benchmark", - ], deps = [ "//source/common/formatter:formatter_extension_lib", "//source/common/formatter:substitution_formatter_lib", @@ -104,6 +101,7 @@ envoy_cc_benchmark_binary( "//test/mocks/http:http_mocks", "//test/mocks/stream_info:stream_info_mocks", "//test/test_common:printers_lib", + "@com_github_google_benchmark//:benchmark", ], ) diff --git a/test/common/grpc/BUILD b/test/common/grpc/BUILD index ac4ebe2684..40934f3e5e 100644 --- a/test/common/grpc/BUILD +++ b/test/common/grpc/BUILD @@ -225,9 +225,6 @@ envoy_cc_test( envoy_cc_benchmark_binary( name = "async_client_manager_benchmark", srcs = ["async_client_manager_benchmark.cc"], - external_deps = [ - "benchmark", - ], deps = [ "//source/common/api:api_lib", "//source/common/grpc:async_client_manager_lib", @@ -238,6 +235,7 @@ envoy_cc_benchmark_binary( "//test/mocks/upstream:cluster_priority_set_mocks", "//test/test_common:test_runtime_lib", "//test/test_common:utility_lib", + "@com_github_google_benchmark//:benchmark", "@envoy_api//envoy/config/bootstrap/v3:pkg_cc_proto", "@envoy_api//envoy/config/core/v3:pkg_cc_proto", ], diff --git a/test/common/http/BUILD b/test/common/http/BUILD index 98b1e1be8a..565dbfddf8 100644 --- a/test/common/http/BUILD +++ b/test/common/http/BUILD @@ -164,13 +164,11 @@ envoy_cc_test( envoy_cc_benchmark_binary( name = "codes_speed_test", srcs = ["codes_speed_test.cc"], - external_deps = [ - "benchmark", - ], deps = [ "//source/common/http:codes_lib", "//source/common/stats:isolated_store_lib", "//source/common/stats:stats_lib", + "@com_github_google_benchmark//:benchmark", ], ) @@ -333,11 +331,9 @@ envoy_cc_test( envoy_cc_benchmark_binary( name = "header_map_impl_speed_test", srcs = ["header_map_impl_speed_test.cc"], - external_deps = [ - "benchmark", - ], deps = [ "//source/common/http:header_map_lib", + "@com_github_google_benchmark//:benchmark", ], ) diff --git a/test/common/http/http2/BUILD b/test/common/http/http2/BUILD index f6a8835d42..04b9c8a8c2 100644 --- a/test/common/http/http2/BUILD +++ b/test/common/http/http2/BUILD @@ -15,9 +15,6 @@ envoy_cc_test( name = "codec_impl_test", size = "large", srcs = ["codec_impl_test.cc"], - external_deps = [ - "quiche_http2_adapter", - ], shard_count = 5, deps = [ ":codec_impl_test_util", @@ -46,19 +43,18 @@ envoy_cc_test( "//test/test_common:registry_lib", "//test/test_common:test_runtime_lib", "//test/test_common:utility_lib", + "@com_github_google_quiche//:http2_adapter", ], ) envoy_cc_test_library( name = "codec_impl_test_util", hdrs = ["codec_impl_test_util.h"], - external_deps = [ - "quiche_http2_adapter", - ], deps = [ "//source/common/http/http2:codec_lib", "//test/mocks:common_lib", "//test/mocks/server:overload_manager_mocks", + "@com_github_google_quiche//:http2_adapter", "@com_google_absl//absl/types:optional", ], ) @@ -89,15 +85,13 @@ envoy_cc_test_library( name = "http2_frame", srcs = ["http2_frame.cc"], hdrs = ["http2_frame.h"], - external_deps = [ - "quiche_http2_hpack", - ], deps = [ "//envoy/http:metadata_interface_with_external_headers", "//source/common/buffer:buffer_lib", "//source/common/common:assert_lib", "//source/common/common:hex_lib", "//source/common/common:macros", + "@com_github_google_quiche//:http2_hpack_hpack_lib", ], ) @@ -137,10 +131,6 @@ envoy_cc_test( envoy_cc_test( name = "metadata_encoder_test", srcs = ["metadata_encoder_test.cc"], - external_deps = [ - "quiche_http2_adapter", - "quiche_http2_test_tools", - ], deps = [ "//source/common/buffer:buffer_lib", "//source/common/common:random_generator_lib", @@ -151,6 +141,8 @@ envoy_cc_test( "//test/test_common:logging_lib", "//test/test_common:test_runtime_lib", "//test/test_common:utility_lib", + "@com_github_google_quiche//:http2_adapter", + "@com_github_google_quiche//:http2_adapter_mock_http2_visitor", ], ) @@ -207,9 +199,7 @@ envoy_cc_fuzz_test( name = "hpack_fuzz_test", srcs = ["hpack_fuzz_test.cc"], corpus = "hpack_corpus", - external_deps = [ - "nghttp2", - ], + external_deps = ["nghttp2"], deps = [ ":hpack_fuzz_proto_cc_proto", "//test/test_common:utility_lib", @@ -226,9 +216,7 @@ envoy_cc_fuzz_test( name = "http2_connection_fuzz_test", srcs = ["http2_connection_fuzz_test.cc"], corpus = "http2_connection_corpus", - external_deps = [ - "nghttp2", - ], + external_deps = ["nghttp2"], deps = [ ":http2_connection_proto_cc_proto", "//source/common/http/http2:codec_lib", diff --git a/test/common/listener_manager/BUILD b/test/common/listener_manager/BUILD index 35780b1bfa..484a147a49 100644 --- a/test/common/listener_manager/BUILD +++ b/test/common/listener_manager/BUILD @@ -184,12 +184,7 @@ envoy_cc_test( envoy_cc_benchmark_binary( name = "filter_chain_benchmark_test", srcs = ["filter_chain_benchmark_test.cc"], - external_deps = [ - "benchmark", - "googletest", - ], deps = [ - "@envoy_api//envoy/config/listener/v3:pkg_cc_proto", "//source/common/listener_manager:filter_chain_manager_lib", "//test/test_common:environment_lib", "//test/mocks/network:network_mocks", @@ -197,6 +192,9 @@ envoy_cc_benchmark_binary( "//test/mocks/stream_info:stream_info_mocks", # tranport socket config registration "//source/extensions/transport_sockets/tls:config", + "@com_github_google_benchmark//:benchmark", + "@com_google_googletest//:gtest", + "@envoy_api//envoy/config/listener/v3:pkg_cc_proto", ], ) diff --git a/test/common/network/BUILD b/test/common/network/BUILD index 8c7e54a689..036c23c15d 100644 --- a/test/common/network/BUILD +++ b/test/common/network/BUILD @@ -50,11 +50,9 @@ envoy_cc_test( envoy_cc_benchmark_binary( name = "address_impl_speed_test", srcs = ["address_impl_speed_test.cc"], - external_deps = [ - "benchmark", - ], deps = [ "//source/common/network:address_lib", + "@com_github_google_benchmark//:benchmark", ], ) @@ -408,12 +406,10 @@ envoy_cc_fuzz_test( envoy_cc_benchmark_binary( name = "lc_trie_speed_test", srcs = ["lc_trie_speed_test.cc"], - external_deps = [ - "benchmark", - ], deps = [ "//source/common/network:lc_trie_lib", "//source/common/network:utility_lib", + "@com_github_google_benchmark//:benchmark", ], ) diff --git a/test/common/orca/BUILD b/test/common/orca/BUILD index c63c06cd9e..35e25fc6b3 100644 --- a/test/common/orca/BUILD +++ b/test/common/orca/BUILD @@ -11,15 +11,13 @@ envoy_package() envoy_cc_test( name = "orca_load_metrics_test", srcs = ["orca_load_metrics_test.cc"], - external_deps = [ - "fmtlib", - ], deps = [ "//source/common/orca:orca_load_metrics_lib", "//source/common/upstream:upstream_lib", "//test/test_common:status_utility_lib", "//test/test_common:utility_lib", "@com_github_cncf_xds//xds/data/orca/v3:pkg_cc_proto", + "@com_github_fmtlib_fmt//:fmtlib", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", ], @@ -28,15 +26,13 @@ envoy_cc_test( envoy_cc_test( name = "orca_parser_test", srcs = ["orca_parser_test.cc"], - external_deps = [ - "fmtlib", - ], deps = [ "//source/common/common:base64_lib", "//source/common/orca:orca_parser", "//test/test_common:status_utility_lib", "//test/test_common:utility_lib", "@com_github_cncf_xds//xds/data/orca/v3:pkg_cc_proto", + "@com_github_fmtlib_fmt//:fmtlib", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", ], diff --git a/test/common/protobuf/BUILD b/test/common/protobuf/BUILD index befefa24b6..c1fe7afdeb 100644 --- a/test/common/protobuf/BUILD +++ b/test/common/protobuf/BUILD @@ -102,11 +102,11 @@ envoy_cc_fuzz_test( envoy_cc_benchmark_binary( name = "utility_speed_test", srcs = ["utility_speed_test.cc"], - external_deps = ["benchmark"], deps = [ ":deterministic_hash_test_proto_cc_proto", "//source/common/protobuf:utility_lib", "//test/test_common:test_runtime_lib", + "@com_github_google_benchmark//:benchmark", ], ) diff --git a/test/common/quic/BUILD b/test/common/quic/BUILD index 938238aafd..71fa7de681 100644 --- a/test/common/quic/BUILD +++ b/test/common/quic/BUILD @@ -15,7 +15,6 @@ envoy_package() envoy_cc_test( name = "envoy_quic_alarm_test", srcs = ["envoy_quic_alarm_test.cc"], - external_deps = ["quiche_quic_platform"], tags = ["nofips"], deps = [ "//source/common/quic:envoy_quic_alarm_factory_lib", @@ -23,6 +22,7 @@ envoy_cc_test( "//source/common/quic:envoy_quic_clock_lib", "//test/test_common:simulated_time_system_lib", "//test/test_common:utility_lib", + "@com_github_google_quiche//:quic_platform", ], ) @@ -41,7 +41,6 @@ envoy_cc_test( envoy_cc_test( name = "envoy_quic_writer_test", srcs = ["envoy_quic_writer_test.cc"], - external_deps = ["quiche_quic_platform"], tags = ["nofips"], deps = [ "//source/common/network:io_socket_error_lib", @@ -50,13 +49,13 @@ envoy_cc_test( "//test/mocks/api:api_mocks", "//test/mocks/network:network_mocks", "//test/test_common:threadsafe_singleton_injector_lib", + "@com_github_google_quiche//:quic_platform", ], ) envoy_cc_test( name = "envoy_quic_proof_source_test", srcs = ["envoy_quic_proof_source_test.cc"], - external_deps = ["quiche_quic_platform"], tags = ["nofips"], deps = [ ":test_utils_lib", @@ -69,6 +68,7 @@ envoy_cc_test( "//test/mocks/ssl:ssl_mocks", "//test/test_common:test_runtime_lib", "@com_github_google_quiche//:quic_core_versions_lib", + "@com_github_google_quiche//:quic_platform", "@com_github_google_quiche//:quic_test_tools_test_certificates_lib", ], ) @@ -101,7 +101,6 @@ envoy_cc_test( envoy_cc_test( name = "envoy_quic_proof_verifier_test", srcs = ["envoy_quic_proof_verifier_test.cc"], - external_deps = ["quiche_quic_platform"], tags = ["nofips"], deps = [ ":test_utils_lib", @@ -112,6 +111,7 @@ envoy_cc_test( "//test/mocks/event:event_mocks", "//test/mocks/server:server_factory_context_mocks", "//test/mocks/ssl:ssl_mocks", + "@com_github_google_quiche//:quic_platform", "@com_github_google_quiche//:quic_test_tools_test_certificates_lib", ], ) diff --git a/test/common/quic/platform/BUILD b/test/common/quic/platform/BUILD index ef8fc42c98..dca484cd50 100644 --- a/test/common/quic/platform/BUILD +++ b/test/common/quic/platform/BUILD @@ -23,7 +23,6 @@ envoy_cc_test( "//conditions:default": ["-Wno-unused-parameter"], }), data = ["//test/common/tls/test_data:certs"], - external_deps = ["quiche_quic_platform"], tags = ["nofips"], deps = [ "//source/common/memory:stats_lib", @@ -37,6 +36,7 @@ envoy_cc_test( "//test/test_common:utility_lib", "@com_github_google_quiche//:quic_core_error_codes_lib", "@com_github_google_quiche//:quic_core_types_lib", + "@com_github_google_quiche//:quic_platform", "@com_github_google_quiche//:quic_platform_expect_bug", "@com_github_google_quiche//:quic_platform_test", "@com_github_google_quiche//:quic_platform_test_output", diff --git a/test/common/router/BUILD b/test/common/router/BUILD index 414d769202..af12e529b7 100644 --- a/test/common/router/BUILD +++ b/test/common/router/BUILD @@ -65,14 +65,12 @@ envoy_cc_test( envoy_cc_benchmark_binary( name = "config_impl_headermap_benchmark_test", srcs = ["config_impl_headermap_benchmark_test.cc"], - external_deps = [ - "benchmark", - ], deps = [ "//source/common/http:header_map_lib", "//source/common/router:config_lib", "//test/mocks/server:server_mocks", "//test/test_common:utility_lib", + "@com_github_google_benchmark//:benchmark", "@envoy_api//envoy/config/route/v3:pkg_cc_proto", ], ) @@ -519,15 +517,13 @@ envoy_proto_library( envoy_cc_benchmark_binary( name = "config_impl_speed_test", srcs = ["config_impl_speed_test.cc"], - external_deps = [ - "benchmark", - ], deps = [ "//source/common/common:assert_lib", "//source/common/router:config_lib", "//test/mocks/server:instance_mocks", "//test/mocks/stream_info:stream_info_mocks", "//test/test_common:utility_lib", + "@com_github_google_benchmark//:benchmark", "@envoy_api//envoy/config/route/v3:pkg_cc_proto", ], ) @@ -540,12 +536,10 @@ envoy_benchmark_test( envoy_cc_benchmark_binary( name = "header_formatter_speed_test", srcs = ["header_formatter_speed_test.cc"], - external_deps = [ - "benchmark", - ], deps = [ "//source/common/router:router_lib", "//test/common/stream_info:test_util", + "@com_github_google_benchmark//:benchmark", ], ) diff --git a/test/common/stats/BUILD b/test/common/stats/BUILD index 95ccb0e0e0..7218abb28a 100644 --- a/test/common/stats/BUILD +++ b/test/common/stats/BUILD @@ -72,14 +72,12 @@ envoy_cc_test( envoy_cc_benchmark_binary( name = "recent_lookups_benchmark", srcs = ["recent_lookups_speed_test.cc"], - external_deps = [ - "benchmark", - ], deps = [ "//source/common/common:random_generator_lib", "//source/common/common:utility_lib", "//source/common/runtime:runtime_lib", "//source/common/stats:recent_lookups_lib", + "@com_github_google_benchmark//:benchmark", ], ) @@ -215,9 +213,6 @@ envoy_cc_benchmark_binary( "make_elements_helper.cc", "symbol_table_speed_test.cc", ], - external_deps = [ - "benchmark", - ], deps = [ ":make_elements_helper_lib", ":stat_test_utility_lib", @@ -229,6 +224,7 @@ envoy_cc_benchmark_binary( "//test/mocks/stats:stats_mocks", "//test/test_common:logging_lib", "//test/test_common:utility_lib", + "@com_github_google_benchmark//:benchmark", "@com_google_absl//absl/strings", ], ) @@ -248,9 +244,6 @@ envoy_cc_test( envoy_cc_benchmark_binary( name = "deferred_creation_stats_benchmark", srcs = ["deferred_creation_stats_speed_test.cc"], - external_deps = [ - "benchmark", - ], deps = [ ":real_thread_test_base", "//source/common/common:random_generator_lib", @@ -260,6 +253,7 @@ envoy_cc_benchmark_binary( "//source/common/stats:isolated_store_lib", "//source/common/stats:symbol_table_lib", "//source/exe:process_wide_lib", + "@com_github_google_benchmark//:benchmark", ], ) @@ -279,15 +273,13 @@ envoy_cc_benchmark_binary( srcs = [ "stats_matcher_impl_speed_test.cc", ], - external_deps = [ - "benchmark", - ], deps = [ "//source/common/memory:stats_lib", "//source/common/stats:stats_matcher_lib", "//test/mocks/server:server_factory_context_mocks", "//test/test_common:logging_lib", "//test/test_common:utility_lib", + "@com_github_google_benchmark//:benchmark", "@com_google_absl//absl/strings", "@envoy_api//envoy/config/metrics/v3:pkg_cc_proto", "@envoy_api//envoy/type/matcher/v3:pkg_cc_proto", @@ -325,11 +317,9 @@ envoy_cc_benchmark_binary( srcs = [ "tag_extractor_impl_speed_test.cc", ], - external_deps = [ - "benchmark", - ], deps = [ "//source/common/stats:tag_producer_lib", + "@com_github_google_benchmark//:benchmark", "@envoy_api//envoy/config/metrics/v3:pkg_cc_proto", ], ) @@ -366,9 +356,6 @@ envoy_cc_test( envoy_cc_benchmark_binary( name = "thread_local_store_speed_test", srcs = ["thread_local_store_speed_test.cc"], - external_deps = [ - "benchmark", - ], deps = [ ":stat_test_utility_lib", "//source/common/common:thread_lib", @@ -380,6 +367,7 @@ envoy_cc_benchmark_binary( "//test/test_common:simulated_time_system_lib", "//test/test_common:test_time_lib", "//test/test_common:utility_lib", + "@com_github_google_benchmark//:benchmark", "@com_google_absl//absl/strings", "@envoy_api//envoy/config/metrics/v3:pkg_cc_proto", ], diff --git a/test/common/tls/BUILD b/test/common/tls/BUILD index 055c56ab68..6e2dc3207d 100644 --- a/test/common/tls/BUILD +++ b/test/common/tls/BUILD @@ -282,14 +282,12 @@ envoy_cc_benchmark_binary( data = [ "//test/common/tls/test_data:certs", ], - external_deps = [ - "benchmark", - "ssl", - ], + external_deps = ["ssl"], # Uses raw POSIX syscalls, does not build on Windows. tags = ["skip_on_windows"], deps = [ "//source/common/buffer:buffer_lib", + "@com_github_google_benchmark//:benchmark", ], ) diff --git a/test/common/upstream/BUILD b/test/common/upstream/BUILD index 97fdd20407..216aca1bac 100644 --- a/test/common/upstream/BUILD +++ b/test/common/upstream/BUILD @@ -604,12 +604,10 @@ envoy_cc_fuzz_test( envoy_cc_benchmark_binary( name = "scheduler_benchmark", srcs = ["scheduler_benchmark.cc"], - external_deps = [ - "benchmark", - ], deps = [ "//source/common/common:random_generator_lib", "//source/common/upstream:scheduler_lib", + "@com_github_google_benchmark//:benchmark", ], ) diff --git a/test/dependencies/BUILD b/test/dependencies/BUILD index 1ef365b90f..688fedc331 100644 --- a/test/dependencies/BUILD +++ b/test/dependencies/BUILD @@ -11,7 +11,5 @@ envoy_package() envoy_cc_test( name = "curl_test", srcs = ["curl_test.cc"], - external_deps = [ - "curl", - ], + external_deps = ["curl"], ) diff --git a/test/extensions/access_loggers/fluentd/BUILD b/test/extensions/access_loggers/fluentd/BUILD index 0c6e832be6..a8a4d9acad 100644 --- a/test/extensions/access_loggers/fluentd/BUILD +++ b/test/extensions/access_loggers/fluentd/BUILD @@ -15,14 +15,12 @@ envoy_extension_cc_test( name = "fluentd_access_log_impl_test", srcs = ["fluentd_access_log_impl_test.cc"], extension_names = ["envoy.access_loggers.fluentd"], - external_deps = [ - "msgpack", - ], deps = [ "//source/extensions/access_loggers/fluentd:config", "//test/mocks/server:factory_context_mocks", "//test/test_common:environment_lib", "//test/test_common:utility_lib", + "@com_github_msgpack_cpp//:msgpack", "@envoy_api//envoy/config/accesslog/v3:pkg_cc_proto", "@envoy_api//envoy/extensions/access_loggers/fluentd/v3:pkg_cc_proto", ], diff --git a/test/extensions/access_loggers/open_telemetry/BUILD b/test/extensions/access_loggers/open_telemetry/BUILD index f569984ae4..0e7ddef73e 100644 --- a/test/extensions/access_loggers/open_telemetry/BUILD +++ b/test/extensions/access_loggers/open_telemetry/BUILD @@ -130,9 +130,6 @@ envoy_extension_cc_test( envoy_cc_benchmark_binary( name = "substitution_formatter_speed_test", srcs = ["substitution_formatter_speed_test.cc"], - external_deps = [ - "benchmark", - ], deps = [ "//source/common/formatter:formatter_extension_lib", "//source/common/http:header_map_lib", @@ -140,6 +137,7 @@ envoy_cc_benchmark_binary( "//source/extensions/access_loggers/open_telemetry:substitution_formatter_lib", "//test/common/stream_info:test_util", "//test/mocks/stream_info:stream_info_mocks", + "@com_github_google_benchmark//:benchmark", "@opentelemetry_proto//:common_cc_proto", ], ) diff --git a/test/extensions/bootstrap/wasm/BUILD b/test/extensions/bootstrap/wasm/BUILD index fd54284031..5efd44307b 100644 --- a/test/extensions/bootstrap/wasm/BUILD +++ b/test/extensions/bootstrap/wasm/BUILD @@ -97,9 +97,6 @@ envoy_extension_cc_test_binary( "//test/extensions/bootstrap/wasm/test_data:speed_cpp.wasm", ]), extension_names = ["envoy.bootstrap.wasm"], - external_deps = [ - "benchmark", - ], tags = ["skip_on_windows"], deps = [ "//source/common/event:dispatcher_lib", @@ -113,6 +110,7 @@ envoy_extension_cc_test_binary( "//test/mocks/upstream:upstream_mocks", "//test/test_common:environment_lib", "//test/test_common:simulated_time_system_lib", + "@com_github_google_benchmark//:benchmark", "@com_google_absl//absl/types:optional", ], ) diff --git a/test/extensions/clusters/eds/BUILD b/test/extensions/clusters/eds/BUILD index 09e0f59093..90d2873959 100644 --- a/test/extensions/clusters/eds/BUILD +++ b/test/extensions/clusters/eds/BUILD @@ -45,9 +45,6 @@ envoy_cc_test( envoy_cc_benchmark_binary( name = "eds_speed_test", srcs = ["eds_speed_test.cc"], - external_deps = [ - "benchmark", - ], deps = [ "//envoy/config:xds_resources_delegate_interface", "//source/common/config:protobuf_link_hacks", @@ -69,6 +66,7 @@ envoy_cc_benchmark_binary( "//test/mocks/upstream:cluster_manager_mocks", "//test/test_common:test_runtime_lib", "//test/test_common:utility_lib", + "@com_github_google_benchmark//:benchmark", "@envoy_api//envoy/config/cluster/v3:pkg_cc_proto", "@envoy_api//envoy/config/core/v3:pkg_cc_proto", "@envoy_api//envoy/config/endpoint/v3:pkg_cc_proto", diff --git a/test/extensions/common/wasm/BUILD b/test/extensions/common/wasm/BUILD index f46b84d59e..7d0cf2c213 100644 --- a/test/extensions/common/wasm/BUILD +++ b/test/extensions/common/wasm/BUILD @@ -75,9 +75,6 @@ envoy_cc_test( envoy_cc_test_binary( name = "wasm_speed_test", srcs = ["wasm_speed_test.cc"], - external_deps = [ - "benchmark", - ], tags = ["skip_on_windows"], deps = [ "//source/common/event:dispatcher_lib", @@ -86,6 +83,7 @@ envoy_cc_test_binary( "//test/mocks/server:server_mocks", "//test/mocks/upstream:upstream_mocks", "//test/test_common:environment_lib", + "@com_github_google_benchmark//:benchmark", "@com_google_absl//absl/types:optional", ], ) diff --git a/test/extensions/filters/http/compressor/BUILD b/test/extensions/filters/http/compressor/BUILD index 5853091258..001aaa5d9c 100644 --- a/test/extensions/filters/http/compressor/BUILD +++ b/test/extensions/filters/http/compressor/BUILD @@ -73,10 +73,6 @@ envoy_extension_cc_test( envoy_cc_benchmark_binary( name = "compressor_filter_speed_test", srcs = ["compressor_filter_speed_test.cc"], - external_deps = [ - "benchmark", - "googletest", - ], deps = [ "//envoy/compression/compressor:compressor_factory_interface", "//source/common/protobuf:utility_lib", @@ -91,6 +87,8 @@ envoy_cc_benchmark_binary( "//test/mocks/runtime:runtime_mocks", "//test/test_common:printers_lib", "//test/test_common:utility_lib", + "@com_github_google_benchmark//:benchmark", + "@com_google_googletest//:gtest", "@envoy_api//envoy/extensions/filters/http/compressor/v3:pkg_cc_proto", ], ) diff --git a/test/extensions/filters/http/ext_proc/BUILD b/test/extensions/filters/http/ext_proc/BUILD index 9d144ccd7c..b2dcff8c17 100644 --- a/test/extensions/filters/http/ext_proc/BUILD +++ b/test/extensions/filters/http/ext_proc/BUILD @@ -377,8 +377,6 @@ envoy_extension_cc_test_library( name = "tracer_test_filter_lib", srcs = ["tracer_test_filter.cc"], extension_names = ["envoy.filters.http.ext_proc"], - external_deps = [ - ], deps = [ ":tracer_test_filter_proto_cc_proto", "//source/common/config:utility_lib", diff --git a/test/extensions/filters/http/grpc_field_extraction/message_converter/BUILD b/test/extensions/filters/http/grpc_field_extraction/message_converter/BUILD index 67f4ecae2e..a26bf073a0 100644 --- a/test/extensions/filters/http/grpc_field_extraction/message_converter/BUILD +++ b/test/extensions/filters/http/grpc_field_extraction/message_converter/BUILD @@ -12,8 +12,6 @@ envoy_package() envoy_cc_test_library( name = "message_converter_test_lib", hdrs = ["message_converter_test_lib.h"], - external_deps = [ - ], deps = [ "//source/common/buffer:buffer_lib", "//source/common/grpc:codec_lib", diff --git a/test/extensions/filters/http/proto_message_extraction/extraction_util/BUILD b/test/extensions/filters/http/proto_message_extraction/extraction_util/BUILD index e6b9a20493..3d933ebb9d 100644 --- a/test/extensions/filters/http/proto_message_extraction/extraction_util/BUILD +++ b/test/extensions/filters/http/proto_message_extraction/extraction_util/BUILD @@ -23,7 +23,6 @@ envoy_cc_test( "@com_google_absl//absl/log:check", "@com_google_absl//absl/status:statusor", "@com_google_absl//absl/strings", - "@com_google_googletest//:gtest", "@com_google_protobuf//:protobuf", "@com_google_protoconverter//:all", "@com_google_protofieldextraction//:all_libs", diff --git a/test/extensions/filters/listener/tls_inspector/BUILD b/test/extensions/filters/listener/tls_inspector/BUILD index a843e2a574..410d6f9a58 100644 --- a/test/extensions/filters/listener/tls_inspector/BUILD +++ b/test/extensions/filters/listener/tls_inspector/BUILD @@ -58,9 +58,6 @@ envoy_extension_cc_benchmark_binary( name = "tls_inspector_benchmark", srcs = ["tls_inspector_benchmark.cc"], extension_names = ["envoy.filters.listener.tls_inspector"], - external_deps = [ - "benchmark", - ], deps = [ ":tls_utility_lib", "//source/common/http:utility_lib", @@ -71,6 +68,7 @@ envoy_extension_cc_benchmark_binary( "//test/mocks/network:network_mocks", "//test/mocks/stats:stats_mocks", "//test/test_common:threadsafe_singleton_injector_lib", + "@com_github_google_benchmark//:benchmark", ], ) diff --git a/test/extensions/filters/network/redis_proxy/BUILD b/test/extensions/filters/network/redis_proxy/BUILD index 32c3bd39ed..4b8282b6a3 100644 --- a/test/extensions/filters/network/redis_proxy/BUILD +++ b/test/extensions/filters/network/redis_proxy/BUILD @@ -136,9 +136,6 @@ envoy_extension_cc_benchmark_binary( name = "command_lookup_speed_test", srcs = ["command_lookup_speed_test.cc"], extension_names = ["envoy.filters.network.redis_proxy"], - external_deps = [ - "benchmark", - ], deps = [ ":redis_mocks", "//source/common/stats:isolated_store_lib", @@ -148,6 +145,7 @@ envoy_extension_cc_benchmark_binary( "//test/mocks/network:network_mocks", "//test/test_common:printers_lib", "//test/test_common:simulated_time_system_lib", + "@com_github_google_benchmark//:benchmark", ], ) @@ -193,9 +191,6 @@ envoy_extension_cc_benchmark_binary( name = "command_split_speed_test", srcs = ["command_split_speed_test.cc"], extension_names = ["envoy.filters.network.redis_proxy"], - external_deps = [ - "benchmark", - ], deps = [ ":redis_mocks", "//source/common/stats:isolated_store_lib", @@ -204,6 +199,7 @@ envoy_extension_cc_benchmark_binary( "//source/extensions/filters/network/redis_proxy:router_lib", "//test/test_common:printers_lib", "//test/test_common:simulated_time_system_lib", + "@com_github_google_benchmark//:benchmark", ], ) diff --git a/test/extensions/filters/udp/dns_filter/BUILD b/test/extensions/filters/udp/dns_filter/BUILD index 38b051cc6d..61b358d9b3 100644 --- a/test/extensions/filters/udp/dns_filter/BUILD +++ b/test/extensions/filters/udp/dns_filter/BUILD @@ -18,8 +18,8 @@ envoy_extension_cc_test_library( srcs = ["dns_filter_test_utils.cc"], hdrs = ["dns_filter_test_utils.h"], extension_names = ["envoy.filters.udp.dns_filter"], - external_deps = ["ares"], deps = [ + "//bazel/foreign_cc:ares", "//source/common/common:random_generator_lib", "//source/common/network:address_lib", "//source/common/network:utility_lib", diff --git a/test/extensions/load_balancing_policies/common/BUILD b/test/extensions/load_balancing_policies/common/BUILD index 48678bf4f7..2fa854c692 100644 --- a/test/extensions/load_balancing_policies/common/BUILD +++ b/test/extensions/load_balancing_policies/common/BUILD @@ -14,9 +14,6 @@ envoy_cc_test_library( name = "benchmark_base_tester_lib", srcs = ["benchmark_base_tester.cc"], hdrs = ["benchmark_base_tester.h"], - external_deps = [ - "benchmark", - ], deps = [ "//source/common/common:random_generator_lib", "//source/common/memory:stats_lib", @@ -25,6 +22,7 @@ envoy_cc_test_library( "//test/mocks/upstream:cluster_info_mocks", "//test/test_common:printers_lib", "//test/test_common:simulated_time_system_lib", + "@com_github_google_benchmark//:benchmark", "@envoy_api//envoy/config/cluster/v3:pkg_cc_proto", ], ) diff --git a/test/extensions/load_balancing_policies/subset/BUILD b/test/extensions/load_balancing_policies/subset/BUILD index 689deaaf9d..b66dab8161 100644 --- a/test/extensions/load_balancing_policies/subset/BUILD +++ b/test/extensions/load_balancing_policies/subset/BUILD @@ -81,14 +81,12 @@ envoy_extension_cc_benchmark_binary( name = "subset_benchmark", srcs = ["subset_benchmark.cc"], extension_names = ["envoy.load_balancing_policies.subset"], - external_deps = [ - "benchmark", - ], deps = [ "//source/extensions/load_balancing_policies/random:config", "//source/extensions/load_balancing_policies/subset:config", "//test/extensions/load_balancing_policies/common:benchmark_base_tester_lib", "//test/mocks/upstream:load_balancer_mocks", + "@com_github_google_benchmark//:benchmark", "@envoy_api//envoy/config/cluster/v3:pkg_cc_proto", "@envoy_api//envoy/extensions/load_balancing_policies/random/v3:pkg_cc_proto", "@envoy_api//envoy/extensions/load_balancing_policies/subset/v3:pkg_cc_proto", diff --git a/test/extensions/tracers/datadog/BUILD b/test/extensions/tracers/datadog/BUILD index 4eba5b3534..739bfd76ec 100644 --- a/test/extensions/tracers/datadog/BUILD +++ b/test/extensions/tracers/datadog/BUILD @@ -31,9 +31,6 @@ envoy_extension_cc_test( "-DDD_USE_ABSEIL_FOR_ENVOY", ], extension_names = ["envoy.tracers.datadog"], - external_deps = [ - "dd_trace_cpp", - ], # TODO(wrowe): envoy_extension_ rules don't currently exclude windows extensions tags = ["skip_on_windows"], deps = [ @@ -56,6 +53,7 @@ envoy_extension_cc_test( "//test/mocks/upstream:cluster_manager_mocks", "//test/mocks/upstream:thread_local_cluster_mocks", "//test/test_common:utility_lib", + "@com_github_datadog_dd_trace_cpp//:dd_trace_cpp", "@envoy_api//envoy/config/trace/v3:pkg_cc_proto", ], ) diff --git a/test/extensions/tracers/opentelemetry/BUILD b/test/extensions/tracers/opentelemetry/BUILD index 8aa5bb003b..ac25ecbdb9 100644 --- a/test/extensions/tracers/opentelemetry/BUILD +++ b/test/extensions/tracers/opentelemetry/BUILD @@ -22,9 +22,6 @@ envoy_extension_cc_test( "-DHAVE_ABSEIL", ], extension_names = ["envoy.tracers.opentelemetry"], - external_deps = [ - "opentelemetry_api", - ], deps = [ "//envoy/common:time_interface", "//envoy/runtime:runtime_interface", @@ -49,6 +46,7 @@ envoy_extension_cc_test( "//test/test_common:simulated_time_system_lib", "//test/test_common:utility_lib", "@com_google_absl//absl/types:optional", + "@io_opentelemetry_cpp//api", ], ) diff --git a/test/extensions/tracers/skywalking/BUILD b/test/extensions/tracers/skywalking/BUILD index 36f31a7bce..e0e017783f 100644 --- a/test/extensions/tracers/skywalking/BUILD +++ b/test/extensions/tracers/skywalking/BUILD @@ -50,14 +50,12 @@ envoy_cc_library( envoy_extension_cc_test( name = "skywalking_test_helper", extension_names = ["envoy.tracers.skywalking"], - external_deps = [ - "cpp2sky", - ], deps = [ ":skywalking_test_helper_lib", "//source/common/common:base64_lib", "//source/common/common:hex_lib", "//test/test_common:utility_lib", + "@com_github_skyapm_cpp2sky//source:cpp2sky_data_lib", ], ) diff --git a/test/extensions/transport_sockets/alts/BUILD b/test/extensions/transport_sockets/alts/BUILD index d36c654994..87a9782044 100644 --- a/test/extensions/transport_sockets/alts/BUILD +++ b/test/extensions/transport_sockets/alts/BUILD @@ -117,9 +117,7 @@ envoy_extension_cc_test( name = "tsi_socket_test", srcs = ["tsi_socket_test.cc"], extension_names = ["envoy.transport_sockets.alts"], - external_deps = [ - "grpc", - ], + external_deps = ["grpc"], deps = [ "//envoy/event:dispatcher_interface", "//envoy/network:address_interface", @@ -149,9 +147,7 @@ envoy_extension_cc_test( size = "large", srcs = envoy_select_google_grpc(["alts_integration_test.cc"]), extension_names = ["envoy.transport_sockets.alts"], - external_deps = [ - "grpc", - ], + external_deps = ["grpc"], deps = [ "//source/common/common:utility_lib", "//source/common/event:dispatcher_includes", diff --git a/test/fuzz/BUILD b/test/fuzz/BUILD index 4de7a506c7..d9dd74d003 100644 --- a/test/fuzz/BUILD +++ b/test/fuzz/BUILD @@ -59,9 +59,6 @@ envoy_cc_test_library( name = "utility_lib", srcs = ["utility.cc"], hdrs = ["utility.h"], - external_deps = [ - "quiche_http2_adapter", - ], deps = [ ":common_proto_cc_proto", "//source/common/common:empty_string", @@ -72,6 +69,7 @@ envoy_cc_test_library( "//test/mocks/ssl:ssl_mocks", "//test/mocks/upstream:upstream_mocks", "//test/test_common:utility_lib", + "@com_github_google_quiche//:http2_adapter", "@envoy_api//envoy/config/core/v3:pkg_cc_proto", ], ) diff --git a/test/server/BUILD b/test/server/BUILD index 3aea3d95c1..f984efcd48 100644 --- a/test/server/BUILD +++ b/test/server/BUILD @@ -406,15 +406,13 @@ envoy_cc_test( envoy_cc_benchmark_binary( name = "server_stats_flush_benchmark", srcs = ["server_stats_flush_benchmark_test.cc"], - external_deps = [ - "benchmark", - ], deps = [ "//envoy/stats:stats_interface", "//source/common/stats:thread_local_store_lib", "//source/server:server_lib", "//test/mocks/upstream:cluster_manager_mocks", "//test/test_common:simulated_time_system_lib", + "@com_github_google_benchmark//:benchmark", ], ) diff --git a/test/test_common/BUILD b/test/test_common/BUILD index f218ddd510..4cc616a430 100644 --- a/test/test_common/BUILD +++ b/test/test_common/BUILD @@ -17,9 +17,7 @@ envoy_cc_test_library( name = "environment_lib", srcs = ["environment.cc"], hdrs = ["environment.h"], - external_deps = [ - "bazel_runfiles", - ], + external_deps = ["bazel_runfiles"], deps = [ ":network_utility_lib", "//envoy/server:options_interface", diff --git a/test/tools/router_check/BUILD b/test/tools/router_check/BUILD index 01baa3acb9..b09a660e6d 100644 --- a/test/tools/router_check/BUILD +++ b/test/tools/router_check/BUILD @@ -36,7 +36,6 @@ envoy_cc_test_library( "router.h", ], copts = ["-DHAVE_LONG_LONG"], - external_deps = ["tclap"], deps = [ ":validation_proto_cc_proto", "//source/common/common:random_generator_lib", @@ -54,6 +53,7 @@ envoy_cc_test_library( "//test/test_common:printers_lib", "//test/test_common:test_runtime_lib", "//test/test_common:utility_lib", + "@com_github_mirror_tclap//:tclap", "@envoy_api//envoy/config/core/v3:pkg_cc_proto", "@envoy_api//envoy/config/route/v3:pkg_cc_proto", "@envoy_api//envoy/type/v3:pkg_cc_proto", diff --git a/test/tools/schema_validator/BUILD b/test/tools/schema_validator/BUILD index 4ea42313bd..ed852bdd0b 100644 --- a/test/tools/schema_validator/BUILD +++ b/test/tools/schema_validator/BUILD @@ -27,13 +27,13 @@ envoy_cc_test_library( hdrs = ["validator.h"], # TCLAP command line parser needs this to support int64_t/uint64_t in several build environments. copts = ["-DHAVE_LONG_LONG"], - external_deps = ["tclap"], deps = [ "//envoy/api:api_interface", "//source/common/protobuf:utility_lib", "//source/common/stats:isolated_store_lib", "//source/common/version:version_lib", "//test/test_common:utility_lib", + "@com_github_mirror_tclap//:tclap", "@envoy_api//envoy/config/bootstrap/v3:pkg_cc_proto", "@envoy_api//envoy/config/route/v3:pkg_cc_proto", "@envoy_api//envoy/extensions/filters/network/http_connection_manager/v3:pkg_cc_proto", diff --git a/test/tools/wee8_compile/BUILD b/test/tools/wee8_compile/BUILD index 1cad66e548..98a77602bf 100644 --- a/test/tools/wee8_compile/BUILD +++ b/test/tools/wee8_compile/BUILD @@ -23,5 +23,7 @@ envoy_cc_library( "-Wno-non-virtual-dtor", "-Wno-unused-parameter", ], - external_deps = ["wee8"], + deps = [ + "@v8//:wee8", + ], ) From 322cda13fc491aeac9852f693b15ebc204710b1b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 19 Sep 2024 10:39:22 +0100 Subject: [PATCH 19/65] build(deps): bump protobuf from 5.28.1 to 5.28.2 in /tools/base (#36207) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- tools/base/requirements.txt | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/tools/base/requirements.txt b/tools/base/requirements.txt index 7d8dd8884d..2acf5c379a 100644 --- a/tools/base/requirements.txt +++ b/tools/base/requirements.txt @@ -1056,18 +1056,18 @@ ply==3.11 \ --hash=sha256:00c7c1aaa88358b9c765b6d3000c6eec0ba42abca5351b095321aef446081da3 \ --hash=sha256:096f9b8350b65ebd2fd1346b12452efe5b9607f7482813ffca50c22722a807ce # via -r requirements.in -protobuf==5.28.1 \ - --hash=sha256:0dfd86d2b5edf03d91ec2a7c15b4e950258150f14f9af5f51c17fa224ee1931f \ - --hash=sha256:1b04bde117a10ff9d906841a89ec326686c48ececeb65690f15b8cabe7149495 \ - --hash=sha256:42597e938f83bb7f3e4b35f03aa45208d49ae8d5bcb4bc10b9fc825e0ab5e423 \ - --hash=sha256:4304e4fceb823d91699e924a1fdf95cde0e066f3b1c28edb665bda762ecde10f \ - --hash=sha256:4b4b9a0562a35773ff47a3df823177ab71a1f5eb1ff56d8f842b7432ecfd7fd2 \ - --hash=sha256:4c7f5cb38c640919791c9f74ea80c5b82314c69a8409ea36f2599617d03989af \ - --hash=sha256:51f09caab818707ab91cf09cc5c156026599cf05a4520779ccbf53c1b352fb25 \ - --hash=sha256:c529535e5c0effcf417682563719e5d8ac8d2b93de07a56108b4c2d436d7a29a \ - --hash=sha256:cabfe43044ee319ad6832b2fda332646f9ef1636b0130186a3ae0a52fc264bb4 \ - --hash=sha256:f24e5d70e6af8ee9672ff605d5503491635f63d5db2fffb6472be78ba62efd8f \ - --hash=sha256:fc063acaf7a3d9ca13146fefb5b42ac94ab943ec6e978f543cd5637da2d57957 +protobuf==5.28.2 \ + --hash=sha256:2c69461a7fcc8e24be697624c09a839976d82ae75062b11a0972e41fd2cd9132 \ + --hash=sha256:35cfcb15f213449af7ff6198d6eb5f739c37d7e4f1c09b5d0641babf2cc0c68f \ + --hash=sha256:52235802093bd8a2811abbe8bf0ab9c5f54cca0a751fdd3f6ac2a21438bffece \ + --hash=sha256:59379674ff119717404f7454647913787034f03fe7049cbef1d74a97bb4593f0 \ + --hash=sha256:5e8a95246d581eef20471b5d5ba010d55f66740942b95ba9b872d918c459452f \ + --hash=sha256:87317e9bcda04a32f2ee82089a204d3a2f0d3c8aeed16568c7daf4756e4f1fe0 \ + --hash=sha256:8ddc60bf374785fb7cb12510b267f59067fa10087325b8e1855b898a0d81d276 \ + --hash=sha256:a8b9403fc70764b08d2f593ce44f1d2920c5077bf7d311fefec999f8c40f78b7 \ + --hash=sha256:c0ea0123dac3399a2eeb1a1443d82b7afc9ff40241433296769f7da42d142ec3 \ + --hash=sha256:ca53faf29896c526863366a52a8f4d88e69cd04ec9571ed6082fa117fac3ab36 \ + --hash=sha256:eeea10f3dc0ac7e6b4933d32db20662902b4ab81bf28df12218aa389e9c2102d # via # -r requirements.in # envoy-base-utils From ec92cc38c6304d524fca818f732f3c435e7abab7 Mon Sep 17 00:00:00 2001 From: chenylh Date: Thu, 19 Sep 2024 21:16:22 +0800 Subject: [PATCH 20/65] dns: rename `Success` to `Completed` (#36143) Signed-off-by: chenyuliang5 --- envoy/network/dns.h | 6 +- .../network/connectivity_manager_test.cc | 8 +- .../logical_dns/logical_dns_cluster.cc | 2 +- .../clusters/redis/redis_cluster.cc | 4 +- .../clusters/strict_dns/strict_dns_cluster.cc | 2 +- .../dynamic_forward_proxy/dns_cache_impl.cc | 6 +- source/extensions/common/wasm/context.cc | 2 +- .../filters/udp/dns_filter/dns_filter.cc | 2 +- .../udp/dns_filter/dns_filter_resolver.cc | 4 +- .../filters/udp/dns_filter/dns_parser.h | 2 +- .../dns_resolver/apple/apple_dns_impl.cc | 2 +- .../dns_resolver/apple/apple_dns_impl.h | 2 +- .../network/dns_resolver/cares/dns_impl.cc | 4 +- .../network/dns_resolver/cares/dns_impl.h | 7 +- .../dns_resolver/getaddrinfo/getaddrinfo.cc | 4 +- .../upstream/cluster_manager_impl_test.cc | 20 +- test/common/upstream/upstream_impl_test.cc | 70 +++---- .../common/logical_host_integration_test.cc | 2 +- .../logical_dns/logical_dns_cluster_test.cc | 22 +- .../clusters/redis/redis_cluster_test.cc | 12 +- .../dns_cache_impl_test.cc | 140 ++++++------- test/extensions/common/wasm/wasm_test.cc | 8 +- .../aws_request_signing_integration_test.cc | 4 +- .../filters/udp/dns_filter/dns_filter_test.cc | 11 +- .../dns_resolver/apple/apple_dns_impl_test.cc | 192 +++++++++--------- .../dns_resolver/cares/dns_impl_test.cc | 124 +++++------ .../getaddrinfo/getaddrinfo_test.cc | 24 +-- 27 files changed, 347 insertions(+), 339 deletions(-) diff --git a/envoy/network/dns.h b/envoy/network/dns.h index 4aa5f655dd..c7847babcc 100644 --- a/envoy/network/dns.h +++ b/envoy/network/dns.h @@ -86,11 +86,11 @@ class DnsResolver { /** * Final status for a DNS resolution. - * TODO(abeyad): Rename `Success` to `Completed` or something similar. DNS resolution can return - * result statuses like NODATA and NONAME, which indicate successful completion of the query but + * DNS resolution can return result statuses like NODATA态SERVFAIL and NONAME, + * which indicate successful completion of the query but * no results, and `Completed` is a more accurate way of reflecting that. */ - enum class ResolutionStatus { Success, Failure }; + enum class ResolutionStatus { Completed, Failure }; /** * Called when a resolution attempt is complete. diff --git a/mobile/test/common/network/connectivity_manager_test.cc b/mobile/test/common/network/connectivity_manager_test.cc index 4230c3c9d4..61e36c7e83 100644 --- a/mobile/test/common/network/connectivity_manager_test.cc +++ b/mobile/test/common/network/connectivity_manager_test.cc @@ -81,15 +81,15 @@ TEST_F(ConnectivityManagerTest, WhenDrainPostDnsRefreshEnabledDrainsPostDnsRefre connectivity_manager_->onDnsResolutionComplete( "cached.example.com", std::make_shared(), - Network::DnsResolver::ResolutionStatus::Success); + Network::DnsResolver::ResolutionStatus::Completed); connectivity_manager_->onDnsResolutionComplete( "not-cached.example.com", std::make_shared(), - Network::DnsResolver::ResolutionStatus::Success); + Network::DnsResolver::ResolutionStatus::Completed); connectivity_manager_->onDnsResolutionComplete( "not-cached2.example.com", std::make_shared(), - Network::DnsResolver::ResolutionStatus::Success); + Network::DnsResolver::ResolutionStatus::Completed); } TEST_F(ConnectivityManagerTest, WhenDrainPostDnsNotEnabledDoesntDrainPostDnsRefresh) { @@ -102,7 +102,7 @@ TEST_F(ConnectivityManagerTest, WhenDrainPostDnsNotEnabledDoesntDrainPostDnsRefr EXPECT_CALL(cm_, drainConnections(_)).Times(0); connectivity_manager_->onDnsResolutionComplete( "example.com", std::make_shared(), - Network::DnsResolver::ResolutionStatus::Success); + Network::DnsResolver::ResolutionStatus::Completed); } TEST_F(ConnectivityManagerTest, diff --git a/source/extensions/clusters/logical_dns/logical_dns_cluster.cc b/source/extensions/clusters/logical_dns/logical_dns_cluster.cc index a29ac21949..ef3d443af7 100644 --- a/source/extensions/clusters/logical_dns/logical_dns_cluster.cc +++ b/source/extensions/clusters/logical_dns/logical_dns_cluster.cc @@ -107,7 +107,7 @@ void LogicalDnsCluster::startResolve() { // If the DNS resolver successfully resolved with an empty response list, the logical DNS // cluster does not update. This ensures that a potentially previously resolved address does // not stabilize back to 0 hosts. - if (status == Network::DnsResolver::ResolutionStatus::Success && !response.empty()) { + if (status == Network::DnsResolver::ResolutionStatus::Completed && !response.empty()) { info_->configUpdateStats().update_success_.inc(); const auto addrinfo = response.front().addrInfo(); // TODO(mattklein123): Move port handling into the DNS interface. diff --git a/source/extensions/clusters/redis/redis_cluster.cc b/source/extensions/clusters/redis/redis_cluster.cc index d667efea6d..ed96a0a49a 100644 --- a/source/extensions/clusters/redis/redis_cluster.cc +++ b/source/extensions/clusters/redis/redis_cluster.cc @@ -365,7 +365,7 @@ void RedisCluster::RedisDiscoverySession::resolveClusterHostnames( updateDnsStats(status, response.empty()); // If DNS resolution for a primary fails, we stop resolution for remaining, and reset // the timer. - if (status != Network::DnsResolver::ResolutionStatus::Success) { + if (status != Network::DnsResolver::ResolutionStatus::Completed) { ENVOY_LOG(error, "Unable to resolve cluster slot primary hostname {}", slot.primary_hostname_); resolve_timer_->enableTimer(parent_.cluster_refresh_rate_); @@ -419,7 +419,7 @@ void RedisCluster::RedisDiscoverySession::resolveReplicas( updateDnsStats(status, response.empty()); // If DNS resolution fails here, we move on to resolve other replicas in the list. // We log a warn message. - if (status != Network::DnsResolver::ResolutionStatus::Success) { + if (status != Network::DnsResolver::ResolutionStatus::Completed) { ENVOY_LOG(warn, "Unable to resolve cluster replica address {}", replica.first); } else { // Replica resolved diff --git a/source/extensions/clusters/strict_dns/strict_dns_cluster.cc b/source/extensions/clusters/strict_dns/strict_dns_cluster.cc index d2b1794ec5..b379ef1e89 100644 --- a/source/extensions/clusters/strict_dns/strict_dns_cluster.cc +++ b/source/extensions/clusters/strict_dns/strict_dns_cluster.cc @@ -130,7 +130,7 @@ void StrictDnsClusterImpl::ResolveTarget::startResolve() { std::chrono::milliseconds final_refresh_rate = parent_.dns_refresh_rate_ms_; - if (status == Network::DnsResolver::ResolutionStatus::Success) { + if (status == Network::DnsResolver::ResolutionStatus::Completed) { parent_.info_->configUpdateStats().update_success_.inc(); HostVector new_hosts; diff --git a/source/extensions/common/dynamic_forward_proxy/dns_cache_impl.cc b/source/extensions/common/dynamic_forward_proxy/dns_cache_impl.cc index b06e8ab4ae..d7841bad16 100644 --- a/source/extensions/common/dynamic_forward_proxy/dns_cache_impl.cc +++ b/source/extensions/common/dynamic_forward_proxy/dns_cache_impl.cc @@ -216,7 +216,7 @@ void DnsCacheImpl::startCacheLoad(const std::string& host, uint16_t default_port // If the DNS request was simply to create a host endpoint in a Dynamic Forward Proxy cluster, // fast fail the look-up as the address is not needed. if (is_proxy_lookup) { - finishResolve(host, Network::DnsResolver::ResolutionStatus::Success, "proxy_resolve", {}, {}, + finishResolve(host, Network::DnsResolver::ResolutionStatus::Completed, "proxy_resolve", {}, {}, true); } else { startResolve(host, *primary_host); @@ -503,7 +503,7 @@ void DnsCacheImpl::finishResolve(const std::string& host, runResolutionCompleteCallbacks(host, primary_host_info->host_info_, status); // Kick off the refresh timer. - if (status == Network::DnsResolver::ResolutionStatus::Success) { + if (status == Network::DnsResolver::ResolutionStatus::Completed) { primary_host_info->failure_backoff_strategy_->reset( std::chrono::duration_cast(dns_ttl).count()); primary_host_info->refresh_timer_->enableTimer(dns_ttl); @@ -682,7 +682,7 @@ void DnsCacheImpl::loadCacheEntries( key, accumulateToString(responses, [](const auto& dns_response) { return dns_response.addrInfo().address_->asString(); })); - finishResolve(key, Network::DnsResolver::ResolutionStatus::Success, "from_cache", + finishResolve(key, Network::DnsResolver::ResolutionStatus::Completed, "from_cache", std::move(responses), resolution_time); stats_.cache_load_.inc(); return KeyValueStore::Iterate::Continue; diff --git a/source/extensions/common/wasm/context.cc b/source/extensions/common/wasm/context.cc index d21983da96..8d717c38d2 100644 --- a/source/extensions/common/wasm/context.cc +++ b/source/extensions/common/wasm/context.cc @@ -202,7 +202,7 @@ void Context::onResolveDns(uint32_t token, Envoy::Network::DnsResolver::Resoluti if (wasm()->isFailed() || !wasm()->on_resolve_dns_) { return; } - if (status != Network::DnsResolver::ResolutionStatus::Success) { + if (status != Network::DnsResolver::ResolutionStatus::Completed) { buffer_.set(""); wasm()->on_resolve_dns_(this, id_, token, 0); return; diff --git a/source/extensions/filters/udp/dns_filter/dns_filter.cc b/source/extensions/filters/udp/dns_filter/dns_filter.cc index e971791fe4..d895ac8f5f 100644 --- a/source/extensions/filters/udp/dns_filter/dns_filter.cc +++ b/source/extensions/filters/udp/dns_filter/dns_filter.cc @@ -234,7 +234,7 @@ DnsFilter::DnsFilter(Network::UdpReadFilterCallbacks& callbacks, // We cannot retry the resolution if ares returns without a response. The ares context // is still dirty and will result in a segfault when it is freed during a subsequent resolve // call from here. We will retry resolutions for pending lookups only - if (context->resolution_status_ != Network::DnsResolver::ResolutionStatus::Success && + if (context->resolution_status_ != Network::DnsResolver::ResolutionStatus::Completed && !context->in_callback_ && context->retry_ > 0) { --context->retry_; ENVOY_LOG(debug, "resolving name [{}] via external resolvers [retry {}]", query->name_, diff --git a/source/extensions/filters/udp/dns_filter/dns_filter_resolver.cc b/source/extensions/filters/udp/dns_filter/dns_filter_resolver.cc index ae2a72dca5..9930ffcf45 100644 --- a/source/extensions/filters/udp/dns_filter/dns_filter_resolver.cc +++ b/source/extensions/filters/udp/dns_filter/dns_filter_resolver.cc @@ -30,7 +30,7 @@ void DnsFilterResolver::resolveExternalQuery(DnsQueryContextPtr context, // We don't support other lookups other than A and AAAA. Set success here so that we don't // retry for something that we are certain will fail. ENVOY_LOG(debug, "Unknown query type [{}] for upstream lookup", domain_query->type_); - ctx.query_context->resolution_status_ = Network::DnsResolver::ResolutionStatus::Success; + ctx.query_context->resolution_status_ = Network::DnsResolver::ResolutionStatus::Completed; ctx.resolver_status = DnsFilterResolverStatus::Complete; invokeCallback(ctx); return; @@ -87,7 +87,7 @@ void DnsFilterResolver::resolveExternalQuery(DnsQueryContextPtr context, ctx.resolver_status = DnsFilterResolverStatus::Complete; // C-ares doesn't expose the TTL in the data available here. - if (status == Network::DnsResolver::ResolutionStatus::Success) { + if (status == Network::DnsResolver::ResolutionStatus::Completed) { ctx.resolved_hosts.reserve(response.size()); for (const auto& resp : response) { const auto& addrinfo = resp.addrInfo(); diff --git a/source/extensions/filters/udp/dns_filter/dns_parser.h b/source/extensions/filters/udp/dns_filter/dns_parser.h index 3449c19d64..1b5b1a2eeb 100644 --- a/source/extensions/filters/udp/dns_filter/dns_parser.h +++ b/source/extensions/filters/udp/dns_filter/dns_parser.h @@ -200,7 +200,7 @@ class DnsQueryContext { uint64_t retry_; uint16_t id_; Network::DnsResolver::ResolutionStatus resolution_status_ = - Network::DnsResolver::ResolutionStatus::Success; + Network::DnsResolver::ResolutionStatus::Completed; DnsHeader header_; DnsHeader response_header_; DnsQueryPtrVec queries_; diff --git a/source/extensions/network/dns_resolver/apple/apple_dns_impl.cc b/source/extensions/network/dns_resolver/apple/apple_dns_impl.cc index cf2694c660..c842536933 100644 --- a/source/extensions/network/dns_resolver/apple/apple_dns_impl.cc +++ b/source/extensions/network/dns_resolver/apple/apple_dns_impl.cc @@ -72,7 +72,7 @@ AppleDnsResolverImpl::startResolution(const std::string& dns_name, ENVOY_LOG_EVENT(debug, "apple_dns_immediate_resolution", "DNS resolver resolved ({}) to ({}) without issuing call to Apple API", dns_name, address->asString()); - callback(DnsResolver::ResolutionStatus::Success, "apple_dns_success", + callback(DnsResolver::ResolutionStatus::Completed, "apple_dns_success", {DnsResponse(address, std::chrono::seconds(60))}); return {nullptr, true}; } diff --git a/source/extensions/network/dns_resolver/apple/apple_dns_impl.h b/source/extensions/network/dns_resolver/apple/apple_dns_impl.h index c89914e594..d8f01bd736 100644 --- a/source/extensions/network/dns_resolver/apple/apple_dns_impl.h +++ b/source/extensions/network/dns_resolver/apple/apple_dns_impl.h @@ -122,7 +122,7 @@ class AppleDnsResolverImpl : public DnsResolver, protected Logger::Loggablenodes != nullptr) { @@ -264,7 +264,7 @@ void DnsResolverImpl::AddrInfoPendingResolution::onAresGetAddrInfoCallback( } else if (isResponseWithNoRecords(status)) { // Treat `ARES_ENODATA` or `ARES_ENOTFOUND` here as success to populate back the // "empty records" response. - pending_response_.status_ = ResolutionStatus::Success; + pending_response_.status_ = ResolutionStatus::Completed; pending_response_.details_ = absl::StrCat("cares_norecords:", ares_strerror(status)); ASSERT(addrinfo == nullptr); } else { diff --git a/source/extensions/network/dns_resolver/cares/dns_impl.h b/source/extensions/network/dns_resolver/cares/dns_impl.h index af806315c0..a6ead67415 100644 --- a/source/extensions/network/dns_resolver/cares/dns_impl.h +++ b/source/extensions/network/dns_resolver/cares/dns_impl.h @@ -110,10 +110,9 @@ class DnsResolverImpl : public DnsResolver, protected Logger::LoggableasString(); })); - return std::make_pair(ResolutionStatus::Success, final_results); + return std::make_pair(ResolutionStatus::Completed, final_results); } // Background thread which wakes up and does resolutions. @@ -190,7 +190,7 @@ void GetAddrInfoDnsResolver::resolveThreadRoutine() { // https://github.com/envoyproxy/envoy/blob/099d85925b32ce8bf06e241ee433375a0a3d751b/source/extensions/network/dns_resolver/cares/dns_impl.h#L109-L111. ENVOY_LOG(debug, "getaddrinfo for host={} has no results rc={}", next_query->dns_name_, gai_strerror(rc.return_value_)); - response = std::make_pair(ResolutionStatus::Success, std::list()); + response = std::make_pair(ResolutionStatus::Completed, std::list()); } else { ENVOY_LOG(debug, "getaddrinfo failed for host={} with rc={} errno={}", next_query->dns_name_, gai_strerror(rc.return_value_), errorDetails(rc.errno_)); diff --git a/test/common/upstream/cluster_manager_impl_test.cc b/test/common/upstream/cluster_manager_impl_test.cc index ad2c80b5f4..8d9d2ca7b8 100644 --- a/test/common/upstream/cluster_manager_impl_test.cc +++ b/test/common/upstream/cluster_manager_impl_test.cc @@ -2824,7 +2824,7 @@ TEST_P(ClusterManagerLifecycleTest, DynamicHostRemove) { cluster_manager_->setInitializedCb([&]() -> void { initialized.ready(); }); EXPECT_CALL(initialized, ready()); - dns_callback(Network::DnsResolver::ResolutionStatus::Success, "", + dns_callback(Network::DnsResolver::ResolutionStatus::Completed, "", TestUtility::makeDnsResponse({"127.0.0.1", "127.0.0.2"})); // After we are initialized, we should immediately get called back if someone asks for an @@ -2878,7 +2878,7 @@ TEST_P(ClusterManagerLifecycleTest, DynamicHostRemove) { // Remove the first host, this should lead to the first cp being drained. dns_timer_->invokeCallback(); - dns_callback(Network::DnsResolver::ResolutionStatus::Success, "", + dns_callback(Network::DnsResolver::ResolutionStatus::Completed, "", TestUtility::makeDnsResponse({"127.0.0.2"})); cp1->idle_cb_(); cp1->idle_cb_ = nullptr; @@ -2912,7 +2912,7 @@ TEST_P(ClusterManagerLifecycleTest, DynamicHostRemove) { // Now add and remove a host that we never have a conn pool to. This should not lead to any // drain callbacks, etc. dns_timer_->invokeCallback(); - dns_callback(Network::DnsResolver::ResolutionStatus::Success, "", + dns_callback(Network::DnsResolver::ResolutionStatus::Completed, "", // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) TestUtility::makeDnsResponse({"127.0.0.2", "127.0.0.3"})); factory_.tls_.shutdownThread(); @@ -2980,7 +2980,7 @@ TEST_P(ClusterManagerLifecycleTest, DynamicHostRemoveWithTls) { cluster_manager_->setInitializedCb([&]() -> void { initialized.ready(); }); EXPECT_CALL(initialized, ready()); - dns_callback(Network::DnsResolver::ResolutionStatus::Success, "", + dns_callback(Network::DnsResolver::ResolutionStatus::Completed, "", TestUtility::makeDnsResponse({"127.0.0.1", "127.0.0.2"})); // After we are initialized, we should immediately get called back if someone asks for an @@ -3076,7 +3076,7 @@ TEST_P(ClusterManagerLifecycleTest, DynamicHostRemoveWithTls) { // Remove the first host, this should lead to the first cp being drained. dns_timer_->invokeCallback(); - dns_callback(Network::DnsResolver::ResolutionStatus::Success, "", + dns_callback(Network::DnsResolver::ResolutionStatus::Completed, "", TestUtility::makeDnsResponse({"127.0.0.2"})); cp1->idle_cb_(); cp1->idle_cb_ = nullptr; @@ -3134,7 +3134,7 @@ TEST_P(ClusterManagerLifecycleTest, DynamicHostRemoveWithTls) { // Now add and remove a host that we never have a conn pool to. This should not lead to any // drain callbacks, etc. dns_timer_->invokeCallback(); - dns_callback(Network::DnsResolver::ResolutionStatus::Success, "", + dns_callback(Network::DnsResolver::ResolutionStatus::Completed, "", // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) TestUtility::makeDnsResponse({"127.0.0.2", "127.0.0.3"})); factory_.tls_.shutdownThread(); @@ -3924,7 +3924,7 @@ TEST_P(ClusterManagerLifecycleTest, DynamicHostRemoveDefaultPriority) { EXPECT_FALSE(all_clusters.active_clusters_.at("cluster_1").get().info()->addedViaApi()); EXPECT_EQ(nullptr, cluster_manager_->getThreadLocalCluster("cluster_1")); - dns_callback(Network::DnsResolver::ResolutionStatus::Success, "", + dns_callback(Network::DnsResolver::ResolutionStatus::Completed, "", TestUtility::makeDnsResponse({"127.0.0.2"})); EXPECT_CALL(factory_, allocateConnPool_(_, _, _, _, _, _)) @@ -3957,7 +3957,7 @@ TEST_P(ClusterManagerLifecycleTest, DynamicHostRemoveDefaultPriority) { // crash. dns_timer_->invokeCallback(); // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) - dns_callback(Network::DnsResolver::ResolutionStatus::Success, "", + dns_callback(Network::DnsResolver::ResolutionStatus::Completed, "", TestUtility::makeDnsResponse({})); factory_.tls_.shutdownThread(); @@ -4018,7 +4018,7 @@ TEST_P(ClusterManagerLifecycleTest, ConnPoolDestroyWithDraining) { EXPECT_FALSE(all_clusters.active_clusters_.at("cluster_1").get().info()->addedViaApi()); EXPECT_EQ(nullptr, cluster_manager_->getThreadLocalCluster("cluster_1")); - dns_callback(Network::DnsResolver::ResolutionStatus::Success, "", + dns_callback(Network::DnsResolver::ResolutionStatus::Completed, "", TestUtility::makeDnsResponse({"127.0.0.2"})); MockConnPoolWithDestroy* mock_cp = new MockConnPoolWithDestroy(); @@ -4043,7 +4043,7 @@ TEST_P(ClusterManagerLifecycleTest, ConnPoolDestroyWithDraining) { // Remove the first host, this should lead to the cp being drained. dns_timer_->invokeCallback(); // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) - dns_callback(Network::DnsResolver::ResolutionStatus::Success, "", + dns_callback(Network::DnsResolver::ResolutionStatus::Completed, "", TestUtility::makeDnsResponse({})); // The drained callback might get called when the CP is being destroyed. diff --git a/test/common/upstream/upstream_impl_test.cc b/test/common/upstream/upstream_impl_test.cc index be63bcf58d..034c6fdefa 100644 --- a/test/common/upstream/upstream_impl_test.cc +++ b/test/common/upstream/upstream_impl_test.cc @@ -235,7 +235,7 @@ TEST_P(StrictDnsParamTest, ImmediateResolve) { EXPECT_CALL(*dns_resolver, resolve("foo.bar.com", std::get<1>(GetParam()), _)) .WillOnce(Invoke([&](const std::string&, Network::DnsLookupFamily, Network::DnsResolver::ResolveCb cb) -> Network::ActiveDnsQuery* { - cb(Network::DnsResolver::ResolutionStatus::Success, "", + cb(Network::DnsResolver::ResolutionStatus::Completed, "", TestUtility::makeDnsResponse(std::get<2>(GetParam()))); return nullptr; })); @@ -480,7 +480,7 @@ TEST_F(StrictDnsClusterImplTest, ZeroHostsHealthChecker) { EXPECT_CALL(*health_checker, addHostCheckCompleteCb(_)); EXPECT_CALL(initialized, ready()); EXPECT_CALL(*resolver.timer_, enableTimer(_, _)); - resolver.dns_callback_(Network::DnsResolver::ResolutionStatus::Success, "", {}); + resolver.dns_callback_(Network::DnsResolver::ResolutionStatus::Completed, "", {}); EXPECT_EQ(0UL, cluster->prioritySet().hostSetsPerPriority()[0]->hosts().size()); EXPECT_EQ(0UL, cluster->prioritySet().hostSetsPerPriority()[0]->healthyHosts().size()); } @@ -531,7 +531,7 @@ TEST_F(StrictDnsClusterImplTest, DontWaitForDNSOnInit) { EXPECT_CALL(*resolver.timer_, enableTimer(std::chrono::milliseconds(4000), _)); EXPECT_CALL(membership_updated, ready()); - resolver.dns_callback_(Network::DnsResolver::ResolutionStatus::Success, "", + resolver.dns_callback_(Network::DnsResolver::ResolutionStatus::Completed, "", TestUtility::makeDnsResponse({"127.0.0.2", "127.0.0.1"})); } @@ -642,7 +642,7 @@ TEST_F(StrictDnsClusterImplTest, Basic) { resolver1.expectResolve(*dns_resolver_); EXPECT_CALL(*resolver1.timer_, enableTimer(std::chrono::milliseconds(4000), _)); EXPECT_CALL(membership_updated, ready()); - resolver1.dns_callback_(Network::DnsResolver::ResolutionStatus::Success, "", + resolver1.dns_callback_(Network::DnsResolver::ResolutionStatus::Completed, "", TestUtility::makeDnsResponse({"127.0.0.1", "127.0.0.2"})); EXPECT_THAT( std::list({"127.0.0.1:11001", "127.0.0.2:11001"}), @@ -653,7 +653,7 @@ TEST_F(StrictDnsClusterImplTest, Basic) { resolver1.expectResolve(*dns_resolver_); resolver1.timer_->invokeCallback(); EXPECT_CALL(*resolver1.timer_, enableTimer(std::chrono::milliseconds(4000), _)); - resolver1.dns_callback_(Network::DnsResolver::ResolutionStatus::Success, "", + resolver1.dns_callback_(Network::DnsResolver::ResolutionStatus::Completed, "", TestUtility::makeDnsResponse({"127.0.0.2", "127.0.0.1"})); EXPECT_THAT( std::list({"127.0.0.1:11001", "127.0.0.2:11001"}), @@ -662,7 +662,7 @@ TEST_F(StrictDnsClusterImplTest, Basic) { resolver1.expectResolve(*dns_resolver_); resolver1.timer_->invokeCallback(); EXPECT_CALL(*resolver1.timer_, enableTimer(std::chrono::milliseconds(4000), _)); - resolver1.dns_callback_(Network::DnsResolver::ResolutionStatus::Success, "", + resolver1.dns_callback_(Network::DnsResolver::ResolutionStatus::Completed, "", TestUtility::makeDnsResponse({"127.0.0.2", "127.0.0.1"})); EXPECT_THAT( std::list({"127.0.0.1:11001", "127.0.0.2:11001"}), @@ -671,7 +671,7 @@ TEST_F(StrictDnsClusterImplTest, Basic) { resolver1.timer_->invokeCallback(); EXPECT_CALL(*resolver1.timer_, enableTimer(std::chrono::milliseconds(4000), _)); EXPECT_CALL(membership_updated, ready()); - resolver1.dns_callback_(Network::DnsResolver::ResolutionStatus::Success, "", + resolver1.dns_callback_(Network::DnsResolver::ResolutionStatus::Completed, "", TestUtility::makeDnsResponse({"127.0.0.3"})); EXPECT_THAT( std::list({"127.0.0.3:11001"}), @@ -680,7 +680,7 @@ TEST_F(StrictDnsClusterImplTest, Basic) { // Make sure we de-dup the same address. EXPECT_CALL(*resolver2.timer_, enableTimer(std::chrono::milliseconds(4000), _)); EXPECT_CALL(membership_updated, ready()); - resolver2.dns_callback_(Network::DnsResolver::ResolutionStatus::Success, "", + resolver2.dns_callback_(Network::DnsResolver::ResolutionStatus::Completed, "", TestUtility::makeDnsResponse({"10.0.0.1", "10.0.0.1"})); EXPECT_THAT( std::list({"127.0.0.3:11001", "10.0.0.1:11002"}), @@ -702,7 +702,7 @@ TEST_F(StrictDnsClusterImplTest, Basic) { resolver1.timer_->invokeCallback(); EXPECT_CALL(*resolver1.timer_, enableTimer(std::chrono::milliseconds(4000), _)); EXPECT_CALL(membership_updated, ready()); - resolver1.dns_callback_(Network::DnsResolver::ResolutionStatus::Success, "", + resolver1.dns_callback_(Network::DnsResolver::ResolutionStatus::Completed, "", TestUtility::makeDnsResponse({})); EXPECT_THAT( std::list({"10.0.0.1:11002"}), @@ -774,7 +774,7 @@ TEST_F(StrictDnsClusterImplTest, HostRemovalActiveHealthSkipped) { EXPECT_CALL(*health_checker, addHostCheckCompleteCb(_)); EXPECT_CALL(*resolver.timer_, enableTimer(_, _)).Times(2); - resolver.dns_callback_(Network::DnsResolver::ResolutionStatus::Success, "", + resolver.dns_callback_(Network::DnsResolver::ResolutionStatus::Completed, "", TestUtility::makeDnsResponse({"127.0.0.1", "127.0.0.2"})); // Verify that both endpoints are initially marked with FAILED_ACTIVE_HC, then @@ -792,7 +792,7 @@ TEST_F(StrictDnsClusterImplTest, HostRemovalActiveHealthSkipped) { } // Re-resolve the DNS name with only one record - resolver.dns_callback_(Network::DnsResolver::ResolutionStatus::Success, "", + resolver.dns_callback_(Network::DnsResolver::ResolutionStatus::Completed, "", TestUtility::makeDnsResponse({"127.0.0.1"})); const auto& hosts = cluster->prioritySet().hostSetsPerPriority()[0]->hosts(); @@ -835,7 +835,7 @@ TEST_F(StrictDnsClusterImplTest, HostRemovalAfterHcFail) { EXPECT_CALL(*health_checker, addHostCheckCompleteCb(_)); EXPECT_CALL(*resolver.timer_, enableTimer(_, _)).Times(2); - resolver.dns_callback_(Network::DnsResolver::ResolutionStatus::Success, "", + resolver.dns_callback_(Network::DnsResolver::ResolutionStatus::Completed, "", TestUtility::makeDnsResponse({"127.0.0.1", "127.0.0.2"})); // Verify that both endpoints are initially marked with FAILED_ACTIVE_HC, then @@ -857,7 +857,7 @@ TEST_F(StrictDnsClusterImplTest, HostRemovalAfterHcFail) { } // Re-resolve the DNS name with only one record, we should still have 2 hosts. - resolver.dns_callback_(Network::DnsResolver::ResolutionStatus::Success, "", + resolver.dns_callback_(Network::DnsResolver::ResolutionStatus::Completed, "", TestUtility::makeDnsResponse({"127.0.0.1"})); { @@ -915,7 +915,7 @@ TEST_F(StrictDnsClusterImplTest, HostUpdateWithDisabledACEndpoint) { EXPECT_CALL(*health_checker, addHostCheckCompleteCb(_)); EXPECT_CALL(*resolver.timer_, enableTimer(_, _)).Times(2); - resolver.dns_callback_(Network::DnsResolver::ResolutionStatus::Success, "", + resolver.dns_callback_(Network::DnsResolver::ResolutionStatus::Completed, "", TestUtility::makeDnsResponse({"127.0.0.1", "127.0.0.2"})); { @@ -930,7 +930,7 @@ TEST_F(StrictDnsClusterImplTest, HostUpdateWithDisabledACEndpoint) { } // Re-resolve the DNS name with only one record, we should have 1 host. - resolver.dns_callback_(Network::DnsResolver::ResolutionStatus::Success, "", + resolver.dns_callback_(Network::DnsResolver::ResolutionStatus::Completed, "", TestUtility::makeDnsResponse({"127.0.0.1"})); { @@ -1058,7 +1058,7 @@ TEST_F(StrictDnsClusterImplTest, LoadAssignmentBasic) { resolver1.expectResolve(*dns_resolver_); EXPECT_CALL(*resolver1.timer_, enableTimer(std::chrono::milliseconds(4000), _)); EXPECT_CALL(membership_updated, ready()); - resolver1.dns_callback_(Network::DnsResolver::ResolutionStatus::Success, "", + resolver1.dns_callback_(Network::DnsResolver::ResolutionStatus::Completed, "", TestUtility::makeDnsResponse({"127.0.0.1", "127.0.0.2"})); EXPECT_THAT( std::list({"127.0.0.1:11001", "127.0.0.2:11001"}), @@ -1078,7 +1078,7 @@ TEST_F(StrictDnsClusterImplTest, LoadAssignmentBasic) { resolver1.expectResolve(*dns_resolver_); resolver1.timer_->invokeCallback(); EXPECT_CALL(*resolver1.timer_, enableTimer(std::chrono::milliseconds(4000), _)); - resolver1.dns_callback_(Network::DnsResolver::ResolutionStatus::Success, "", + resolver1.dns_callback_(Network::DnsResolver::ResolutionStatus::Completed, "", TestUtility::makeDnsResponse({"127.0.0.2", "127.0.0.1"})); EXPECT_THAT( std::list({"127.0.0.1:11001", "127.0.0.2:11001"}), @@ -1092,7 +1092,7 @@ TEST_F(StrictDnsClusterImplTest, LoadAssignmentBasic) { resolver1.expectResolve(*dns_resolver_); resolver1.timer_->invokeCallback(); EXPECT_CALL(*resolver1.timer_, enableTimer(std::chrono::milliseconds(4000), _)); - resolver1.dns_callback_(Network::DnsResolver::ResolutionStatus::Success, "", + resolver1.dns_callback_(Network::DnsResolver::ResolutionStatus::Completed, "", TestUtility::makeDnsResponse({"127.0.0.2", "127.0.0.1"})); EXPECT_THAT( std::list({"127.0.0.1:11001", "127.0.0.2:11001"}), @@ -1105,7 +1105,7 @@ TEST_F(StrictDnsClusterImplTest, LoadAssignmentBasic) { EXPECT_CALL(*resolver2.timer_, enableTimer(std::chrono::milliseconds(4000), _)); EXPECT_CALL(membership_updated, ready()); - resolver2.dns_callback_(Network::DnsResolver::ResolutionStatus::Success, "", + resolver2.dns_callback_(Network::DnsResolver::ResolutionStatus::Completed, "", TestUtility::makeDnsResponse({"10.0.0.1", "10.0.0.1"})); // We received a new set of hosts for localhost2. Should rebuild the cluster-> @@ -1114,7 +1114,7 @@ TEST_F(StrictDnsClusterImplTest, LoadAssignmentBasic) { resolver1.expectResolve(*dns_resolver_); resolver1.timer_->invokeCallback(); EXPECT_CALL(*resolver1.timer_, enableTimer(std::chrono::milliseconds(4000), _)); - resolver1.dns_callback_(Network::DnsResolver::ResolutionStatus::Success, "", + resolver1.dns_callback_(Network::DnsResolver::ResolutionStatus::Completed, "", TestUtility::makeDnsResponse({"127.0.0.2", "127.0.0.1"})); // We again received the same set as before for localhost1. No rebuild this time. @@ -1123,7 +1123,7 @@ TEST_F(StrictDnsClusterImplTest, LoadAssignmentBasic) { resolver1.timer_->invokeCallback(); EXPECT_CALL(*resolver1.timer_, enableTimer(std::chrono::milliseconds(4000), _)); EXPECT_CALL(membership_updated, ready()); - resolver1.dns_callback_(Network::DnsResolver::ResolutionStatus::Success, "", + resolver1.dns_callback_(Network::DnsResolver::ResolutionStatus::Completed, "", TestUtility::makeDnsResponse({"127.0.0.3"})); EXPECT_THAT( std::list({"127.0.0.3:11001", "10.0.0.1:11002"}), @@ -1131,7 +1131,7 @@ TEST_F(StrictDnsClusterImplTest, LoadAssignmentBasic) { // Make sure we de-dup the same address. EXPECT_CALL(*resolver2.timer_, enableTimer(std::chrono::milliseconds(4000), _)); - resolver2.dns_callback_(Network::DnsResolver::ResolutionStatus::Success, "", + resolver2.dns_callback_(Network::DnsResolver::ResolutionStatus::Completed, "", TestUtility::makeDnsResponse({"10.0.0.1", "10.0.0.1"})); EXPECT_THAT( std::list({"127.0.0.3:11001", "10.0.0.1:11002"}), @@ -1146,7 +1146,7 @@ TEST_F(StrictDnsClusterImplTest, LoadAssignmentBasic) { // Make sure that we *don't* de-dup between resolve targets. EXPECT_CALL(*resolver3.timer_, enableTimer(std::chrono::milliseconds(4000), _)); EXPECT_CALL(membership_updated, ready()); - resolver3.dns_callback_(Network::DnsResolver::ResolutionStatus::Success, "", + resolver3.dns_callback_(Network::DnsResolver::ResolutionStatus::Completed, "", TestUtility::makeDnsResponse({"10.0.0.1"})); const auto hosts = cluster->prioritySet().hostSetsPerPriority()[0]->hosts(); @@ -1183,12 +1183,12 @@ TEST_F(StrictDnsClusterImplTest, LoadAssignmentBasic) { EXPECT_CALL(*resolver2.timer_, enableTimer(std::chrono::milliseconds(4000), _)); EXPECT_CALL(membership_updated, ready()); - resolver2.dns_callback_(Network::DnsResolver::ResolutionStatus::Success, "", + resolver2.dns_callback_(Network::DnsResolver::ResolutionStatus::Completed, "", TestUtility::makeDnsResponse({})); EXPECT_CALL(*resolver3.timer_, enableTimer(std::chrono::milliseconds(4000), _)); EXPECT_CALL(membership_updated, ready()); - resolver3.dns_callback_(Network::DnsResolver::ResolutionStatus::Success, "", + resolver3.dns_callback_(Network::DnsResolver::ResolutionStatus::Completed, "", TestUtility::makeDnsResponse({})); // Ensure that we called the update membership callback. @@ -1275,7 +1275,7 @@ TEST_F(StrictDnsClusterImplTest, LoadAssignmentBasicMultiplePriorities) { resolver1.expectResolve(*dns_resolver_); EXPECT_CALL(*resolver1.timer_, enableTimer(std::chrono::milliseconds(4000), _)); EXPECT_CALL(membership_updated, ready()); - resolver1.dns_callback_(Network::DnsResolver::ResolutionStatus::Success, "", + resolver1.dns_callback_(Network::DnsResolver::ResolutionStatus::Completed, "", TestUtility::makeDnsResponse({"127.0.0.1", "127.0.0.2"})); EXPECT_THAT( std::list({"127.0.0.1:11001", "127.0.0.2:11001"}), @@ -1286,7 +1286,7 @@ TEST_F(StrictDnsClusterImplTest, LoadAssignmentBasicMultiplePriorities) { resolver1.expectResolve(*dns_resolver_); resolver1.timer_->invokeCallback(); EXPECT_CALL(*resolver1.timer_, enableTimer(std::chrono::milliseconds(4000), _)); - resolver1.dns_callback_(Network::DnsResolver::ResolutionStatus::Success, "", + resolver1.dns_callback_(Network::DnsResolver::ResolutionStatus::Completed, "", TestUtility::makeDnsResponse({"127.0.0.2", "127.0.0.1"})); EXPECT_THAT( std::list({"127.0.0.1:11001", "127.0.0.2:11001"}), @@ -1295,7 +1295,7 @@ TEST_F(StrictDnsClusterImplTest, LoadAssignmentBasicMultiplePriorities) { resolver1.expectResolve(*dns_resolver_); resolver1.timer_->invokeCallback(); EXPECT_CALL(*resolver1.timer_, enableTimer(std::chrono::milliseconds(4000), _)); - resolver1.dns_callback_(Network::DnsResolver::ResolutionStatus::Success, "", + resolver1.dns_callback_(Network::DnsResolver::ResolutionStatus::Completed, "", TestUtility::makeDnsResponse({"127.0.0.2", "127.0.0.1"})); EXPECT_THAT( std::list({"127.0.0.1:11001", "127.0.0.2:11001"}), @@ -1304,7 +1304,7 @@ TEST_F(StrictDnsClusterImplTest, LoadAssignmentBasicMultiplePriorities) { resolver1.timer_->invokeCallback(); EXPECT_CALL(*resolver1.timer_, enableTimer(std::chrono::milliseconds(4000), _)); EXPECT_CALL(membership_updated, ready()); - resolver1.dns_callback_(Network::DnsResolver::ResolutionStatus::Success, "", + resolver1.dns_callback_(Network::DnsResolver::ResolutionStatus::Completed, "", TestUtility::makeDnsResponse({"127.0.0.3"})); EXPECT_THAT( std::list({"127.0.0.3:11001"}), @@ -1313,7 +1313,7 @@ TEST_F(StrictDnsClusterImplTest, LoadAssignmentBasicMultiplePriorities) { // Make sure we de-dup the same address. EXPECT_CALL(*resolver2.timer_, enableTimer(std::chrono::milliseconds(4000), _)); EXPECT_CALL(membership_updated, ready()); - resolver2.dns_callback_(Network::DnsResolver::ResolutionStatus::Success, "", + resolver2.dns_callback_(Network::DnsResolver::ResolutionStatus::Completed, "", TestUtility::makeDnsResponse({"10.0.0.1", "10.0.0.1"})); EXPECT_THAT( std::list({"127.0.0.3:11001", "10.0.0.1:11002"}), @@ -1330,7 +1330,7 @@ TEST_F(StrictDnsClusterImplTest, LoadAssignmentBasicMultiplePriorities) { EXPECT_CALL(*resolver3.timer_, enableTimer(std::chrono::milliseconds(4000), _)); EXPECT_CALL(membership_updated, ready()); - resolver3.dns_callback_(Network::DnsResolver::ResolutionStatus::Success, "", + resolver3.dns_callback_(Network::DnsResolver::ResolutionStatus::Completed, "", TestUtility::makeDnsResponse({"192.168.1.1", "192.168.1.2"})); // Make sure we have multiple priorities. @@ -1424,7 +1424,7 @@ TEST_F(StrictDnsClusterImplTest, FailureRefreshRateBackoffResetsWhenSuccessHappe // Successful call should reset the failure backoff strategy. EXPECT_CALL(*resolver.timer_, enableTimer(std::chrono::milliseconds(4000), _)); - resolver.dns_callback_(Network::DnsResolver::ResolutionStatus::Success, "", + resolver.dns_callback_(Network::DnsResolver::ResolutionStatus::Completed, "", TestUtility::makeDnsResponse({})); // Therefore, a subsequent failure should get a [0,base * 1] refresh. @@ -1475,13 +1475,13 @@ TEST_F(StrictDnsClusterImplTest, TtlAsDnsRefreshRateNoJitter) { EXPECT_CALL(membership_updated, ready()); EXPECT_CALL(*resolver.timer_, enableTimer(std::chrono::milliseconds(5000), _)); resolver.dns_callback_( - Network::DnsResolver::ResolutionStatus::Success, "", + Network::DnsResolver::ResolutionStatus::Completed, "", TestUtility::makeDnsResponse({"192.168.1.1", "192.168.1.2"}, std::chrono::seconds(5))); // If the response is successful but empty, the cluster uses the cluster configured refresh rate. EXPECT_CALL(membership_updated, ready()); EXPECT_CALL(*resolver.timer_, enableTimer(std::chrono::milliseconds(4000), _)); - resolver.dns_callback_(Network::DnsResolver::ResolutionStatus::Success, "", + resolver.dns_callback_(Network::DnsResolver::ResolutionStatus::Completed, "", TestUtility::makeDnsResponse({}, std::chrono::seconds(5))); // On failure, the cluster uses the cluster configured refresh rate. @@ -1529,7 +1529,7 @@ TEST_F(StrictDnsClusterImplTest, TtlAsDnsRefreshRateYesJitter) { enableTimer(std::chrono::milliseconds(ttl_s * 1000 + jitter_ms), _)); ON_CALL(random_, random()).WillByDefault(Return(random_return)); resolver.dns_callback_( - Network::DnsResolver::ResolutionStatus::Success, "", + Network::DnsResolver::ResolutionStatus::Completed, "", TestUtility::makeDnsResponse({"192.168.1.1", "192.168.1.2"}, std::chrono::seconds(ttl_s))); } diff --git a/test/extensions/clusters/common/logical_host_integration_test.cc b/test/extensions/clusters/common/logical_host_integration_test.cc index 8a0763814d..66beadcdd2 100644 --- a/test/extensions/clusters/common/logical_host_integration_test.cc +++ b/test/extensions/clusters/common/logical_host_integration_test.cc @@ -54,7 +54,7 @@ TEST_P(LogicalHostIntegrationTest, LogicalDNSRaceCrashTest) { Network::DnsResolver::ResolveCb dns_callback) -> Network::ActiveDnsQuery* { const uint32_t address = address_ptr->address_; // Keep changing the returned addresses to force address update. - dns_callback(Network::DnsResolver::ResolutionStatus::Success, "", + dns_callback(Network::DnsResolver::ResolutionStatus::Completed, "", TestUtility::makeDnsResponse({ // The only significant address is the first one; the other ones are // just used to populate a list whose maintenance is race-prone. diff --git a/test/extensions/clusters/logical_dns/logical_dns_cluster_test.cc b/test/extensions/clusters/logical_dns/logical_dns_cluster_test.cc index b781b28e26..8c4a1c68d4 100644 --- a/test/extensions/clusters/logical_dns/logical_dns_cluster_test.cc +++ b/test/extensions/clusters/logical_dns/logical_dns_cluster_test.cc @@ -99,7 +99,7 @@ class LogicalDnsClusterTest : public Event::TestUsingSimulatedTime, public testi EXPECT_CALL(membership_updated_, ready()); EXPECT_CALL(initialized_, ready()); EXPECT_CALL(*resolve_timer_, enableTimer(std::chrono::milliseconds(4000), _)); - dns_callback_(Network::DnsResolver::ResolutionStatus::Success, "", + dns_callback_(Network::DnsResolver::ResolutionStatus::Completed, "", TestUtility::makeDnsResponse({"127.0.0.1", "127.0.0.2"})); EXPECT_EQ(1UL, cluster_->prioritySet().hostSetsPerPriority()[0]->hosts().size()); @@ -129,7 +129,7 @@ class LogicalDnsClusterTest : public Event::TestUsingSimulatedTime, public testi // Should not cause any changes. EXPECT_CALL(*resolve_timer_, enableTimer(_, _)); - dns_callback_(Network::DnsResolver::ResolutionStatus::Success, "", + dns_callback_(Network::DnsResolver::ResolutionStatus::Completed, "", TestUtility::makeDnsResponse({"127.0.0.1", "127.0.0.2", "127.0.0.3"})); EXPECT_EQ("127.0.0.1:" + std::to_string(expected_hc_port), @@ -167,7 +167,7 @@ class LogicalDnsClusterTest : public Event::TestUsingSimulatedTime, public testi // Should cause a change. EXPECT_CALL(*resolve_timer_, enableTimer(_, _)); - dns_callback_(Network::DnsResolver::ResolutionStatus::Success, "", + dns_callback_(Network::DnsResolver::ResolutionStatus::Completed, "", TestUtility::makeDnsResponse({"127.0.0.3", "127.0.0.1", "127.0.0.2"})); EXPECT_EQ("127.0.0.3:" + std::to_string(expected_hc_port), @@ -196,10 +196,10 @@ class LogicalDnsClusterTest : public Event::TestUsingSimulatedTime, public testi .WillOnce(Return(new NiceMock())); logical_host->createConnection(server_context_.dispatcher_, nullptr, nullptr); - // Empty Success should not cause any change. + // Empty Completed should not cause any change. ON_CALL(random_, random()).WillByDefault(Return(6000)); EXPECT_CALL(*resolve_timer_, enableTimer(std::chrono::milliseconds(6000), _)); - dns_callback_(Network::DnsResolver::ResolutionStatus::Success, "", {}); + dns_callback_(Network::DnsResolver::ResolutionStatus::Completed, "", {}); EXPECT_EQ(logical_host, cluster_->prioritySet().hostSetsPerPriority()[0]->hosts()[0]); EXPECT_CALL(server_context_.dispatcher_, @@ -301,7 +301,7 @@ TEST_P(LogicalDnsParamTest, ImmediateResolve) { .WillOnce(Invoke([&](const std::string&, Network::DnsLookupFamily, Network::DnsResolver::ResolveCb cb) -> Network::ActiveDnsQuery* { EXPECT_CALL(*resolve_timer_, enableTimer(_, _)); - cb(Network::DnsResolver::ResolutionStatus::Success, "", + cb(Network::DnsResolver::ResolutionStatus::Completed, "", TestUtility::makeDnsResponse(std::get<2>(GetParam()))); return nullptr; })); @@ -350,7 +350,7 @@ TEST_F(LogicalDnsParamTest, FailureRefreshRateBackoffResetsWhenSuccessHappens) { // Successful call should reset the failure backoff strategy. EXPECT_CALL(membership_updated_, ready()); EXPECT_CALL(*resolve_timer_, enableTimer(std::chrono::milliseconds(4000), _)); - dns_callback_(Network::DnsResolver::ResolutionStatus::Success, "", + dns_callback_(Network::DnsResolver::ResolutionStatus::Completed, "", TestUtility::makeDnsResponse({"127.0.0.1", "127.0.0.2"})); EXPECT_EQ(1UL, cluster_->prioritySet().hostSetsPerPriority()[0]->hosts().size()); EXPECT_EQ(1UL, cluster_->prioritySet().hostSetsPerPriority()[0]->healthyHosts().size()); @@ -390,12 +390,12 @@ TEST_F(LogicalDnsParamTest, TtlAsDnsRefreshRate) { EXPECT_CALL(membership_updated_, ready()); EXPECT_CALL(initialized_, ready()); EXPECT_CALL(*resolve_timer_, enableTimer(std::chrono::milliseconds(5000), _)); - dns_callback_(Network::DnsResolver::ResolutionStatus::Success, "", + dns_callback_(Network::DnsResolver::ResolutionStatus::Completed, "", TestUtility::makeDnsResponse({"127.0.0.1", "127.0.0.2"}, std::chrono::seconds(5))); // If the response is successful but empty, the cluster uses the cluster configured refresh rate. EXPECT_CALL(*resolve_timer_, enableTimer(std::chrono::milliseconds(4000), _)); - dns_callback_(Network::DnsResolver::ResolutionStatus::Success, "", + dns_callback_(Network::DnsResolver::ResolutionStatus::Completed, "", TestUtility::makeDnsResponse({}, std::chrono::seconds(5))); // On failure, the cluster uses the cluster configured refresh rate. @@ -603,7 +603,7 @@ TEST_F(LogicalDnsClusterTest, DontWaitForDNSOnInit) { EXPECT_CALL(membership_updated_, ready()); EXPECT_CALL(*resolve_timer_, enableTimer(std::chrono::milliseconds(4000), _)); - dns_callback_(Network::DnsResolver::ResolutionStatus::Success, "", + dns_callback_(Network::DnsResolver::ResolutionStatus::Completed, "", TestUtility::makeDnsResponse({"127.0.0.1", "127.0.0.2"})); } @@ -643,7 +643,7 @@ TEST_F(LogicalDnsClusterTest, DNSRefreshHasJitter) { ON_CALL(random_, random()).WillByDefault(Return(random_return)); dns_callback_( - Network::DnsResolver::ResolutionStatus::Success, "", + Network::DnsResolver::ResolutionStatus::Completed, "", TestUtility::makeDnsResponse({"127.0.0.1", "127.0.0.2"}, std::chrono::seconds(3000))); } diff --git a/test/extensions/clusters/redis/redis_cluster_test.cc b/test/extensions/clusters/redis/redis_cluster_test.cc index d8236942e0..cf3e3570e3 100644 --- a/test/extensions/clusters/redis/redis_cluster_test.cc +++ b/test/extensions/clusters/redis/redis_cluster_test.cc @@ -173,7 +173,7 @@ class RedisClusterTest : public testing::Test, const std::string& expected_address, const std::list& resolved_addresses, Network::DnsResolver::ResolutionStatus status = - Network::DnsResolver::ResolutionStatus::Success) { + Network::DnsResolver::ResolutionStatus::Completed) { EXPECT_CALL(*dns_resolver_, resolve(expected_address, dns_lookup_family, _)) .WillOnce(Invoke([status, resolved_addresses]( const std::string&, Network::DnsLookupFamily, @@ -775,7 +775,7 @@ TEST_P(RedisDnsParamTest, ImmediateResolveDns) { .WillOnce(Invoke([&](const std::string&, Network::DnsLookupFamily, Network::DnsResolver::ResolveCb cb) -> Network::ActiveDnsQuery* { std::list address_pair = std::get<2>(GetParam()); - cb(Network::DnsResolver::ResolutionStatus::Success, "", + cb(Network::DnsResolver::ResolutionStatus::Completed, "", TestUtility::makeDnsResponse(address_pair)); EXPECT_CALL(*cluster_callback_, onClusterSlotUpdate(_, _)); expectClusterSlotResponse( @@ -856,9 +856,9 @@ TEST_F(RedisClusterTest, AddressAsHostnameParallelResolution) { EXPECT_CALL(*cluster_callback_, onClusterSlotUpdate(_, _)); cluster_->initialize([&]() -> void { initialized_.ready(); }); expectClusterSlotResponse(twoSlotsPrimariesHostnames("primary1.com", "primary2.com", 22120)); - primary1_resolve_cb(Network::DnsResolver::ResolutionStatus::Success, "", + primary1_resolve_cb(Network::DnsResolver::ResolutionStatus::Completed, "", TestUtility::makeDnsResponse(std::list{"127.0.1.1"})); - primary2_resolve_cb(Network::DnsResolver::ResolutionStatus::Success, "", + primary2_resolve_cb(Network::DnsResolver::ResolutionStatus::Completed, "", TestUtility::makeDnsResponse(std::list{"127.0.1.2"})); expectHealthyHosts(std::list({ "127.0.1.1:22120", @@ -1241,7 +1241,7 @@ TEST_F(RedisClusterTest, MultipleDnsDiscovery) { EXPECT_CALL(*dns_resolver_, resolve("foo.bar.com", _, _)) .WillOnce(Invoke([&](const std::string&, Network::DnsLookupFamily, Network::DnsResolver::ResolveCb cb) -> Network::ActiveDnsQuery* { - cb(Network::DnsResolver::ResolutionStatus::Success, "", + cb(Network::DnsResolver::ResolutionStatus::Completed, "", TestUtility::makeDnsResponse(std::list({"127.0.0.1", "127.0.0.2"}))); return nullptr; })); @@ -1249,7 +1249,7 @@ TEST_F(RedisClusterTest, MultipleDnsDiscovery) { EXPECT_CALL(*dns_resolver_, resolve("foo1.bar.com", _, _)) .WillOnce(Invoke([&](const std::string&, Network::DnsLookupFamily, Network::DnsResolver::ResolveCb cb) -> Network::ActiveDnsQuery* { - cb(Network::DnsResolver::ResolutionStatus::Success, "", + cb(Network::DnsResolver::ResolutionStatus::Completed, "", TestUtility::makeDnsResponse(std::list({"127.0.0.3", "127.0.0.4"}))); return nullptr; })); diff --git a/test/extensions/common/dynamic_forward_proxy/dns_cache_impl_test.cc b/test/extensions/common/dynamic_forward_proxy/dns_cache_impl_test.cc index fd3a4819cf..2cba229e1f 100644 --- a/test/extensions/common/dynamic_forward_proxy/dns_cache_impl_test.cc +++ b/test/extensions/common/dynamic_forward_proxy/dns_cache_impl_test.cc @@ -148,11 +148,11 @@ TEST_F(DnsCacheImplTest, PreresolveSuccess) { EXPECT_CALL(update_callbacks_, onDnsResolutionComplete(authority, DnsHostInfoEquals("10.0.0.1:443", "bar.baz.com", false), - Network::DnsResolver::ResolutionStatus::Success)); + Network::DnsResolver::ResolutionStatus::Completed)); initialize({{host, port}} /* preresolve_hostnames */); - resolve_cb(Network::DnsResolver::ResolutionStatus::Success, "", + resolve_cb(Network::DnsResolver::ResolutionStatus::Completed, "", TestUtility::makeDnsResponse({"10.0.0.1"})); checkStats(1 /* attempt */, 1 /* success */, 0 /* failure */, 1 /* address changed */, 1 /* added */, 0 /* removed */, 1 /* num hosts */); @@ -186,10 +186,10 @@ TEST_F(DnsCacheImplTest, DnsFirstResolveComplete) { EXPECT_CALL(update_callbacks_, onDnsResolutionComplete("bar.baz.com:443", DnsHostInfoEquals("10.0.0.1:443", "bar.baz.com", false), - Network::DnsResolver::ResolutionStatus::Success)); + Network::DnsResolver::ResolutionStatus::Completed)); initialize({{"bar.baz.com", 443}}); - resolve_cb(Network::DnsResolver::ResolutionStatus::Success, "", + resolve_cb(Network::DnsResolver::ResolutionStatus::Completed, "", TestUtility::makeDnsResponse({"10.0.0.1"})); checkStats(1 /* attempt */, 1 /* success */, 0 /* failure */, 1 /* address changed */, 1 /* added */, 0 /* removed */, 1 /* num hosts */); @@ -232,9 +232,9 @@ TEST_F(DnsCacheImplTest, ResolveSuccess) { EXPECT_CALL(update_callbacks_, onDnsResolutionComplete("foo.com:80", DnsHostInfoEquals("10.0.0.1:80", "foo.com", false), - Network::DnsResolver::ResolutionStatus::Success)); + Network::DnsResolver::ResolutionStatus::Completed)); EXPECT_CALL(*resolve_timer, enableTimer(std::chrono::milliseconds(dns_ttl_), _)); - resolve_cb(Network::DnsResolver::ResolutionStatus::Success, "", + resolve_cb(Network::DnsResolver::ResolutionStatus::Completed, "", TestUtility::makeDnsResponse({"10.0.0.1"})); checkStats(1 /* attempt */, 1 /* success */, 0 /* failure */, 1 /* address changed */, @@ -254,9 +254,9 @@ TEST_F(DnsCacheImplTest, ResolveSuccess) { EXPECT_CALL(update_callbacks_, onDnsResolutionComplete("foo.com:80", DnsHostInfoEquals("10.0.0.1:80", "foo.com", false), - Network::DnsResolver::ResolutionStatus::Success)); + Network::DnsResolver::ResolutionStatus::Completed)); EXPECT_CALL(*resolve_timer, enableTimer(std::chrono::milliseconds(dns_ttl_), _)); - resolve_cb(Network::DnsResolver::ResolutionStatus::Success, "", + resolve_cb(Network::DnsResolver::ResolutionStatus::Completed, "", TestUtility::makeDnsResponse({"10.0.0.1"})); checkStats(2 /* attempt */, 2 /* success */, 0 /* failure */, 1 /* address changed */, @@ -279,9 +279,9 @@ TEST_F(DnsCacheImplTest, ResolveSuccess) { EXPECT_CALL(update_callbacks_, onDnsResolutionComplete("foo.com:80", DnsHostInfoEquals("10.0.0.2:80", "foo.com", false), - Network::DnsResolver::ResolutionStatus::Success)); + Network::DnsResolver::ResolutionStatus::Completed)); EXPECT_CALL(*resolve_timer, enableTimer(std::chrono::milliseconds(dns_ttl_), _)); - resolve_cb(Network::DnsResolver::ResolutionStatus::Success, "", + resolve_cb(Network::DnsResolver::ResolutionStatus::Completed, "", TestUtility::makeDnsResponse({"10.0.0.2"})); checkStats(3 /* attempt */, 3 /* success */, 0 /* failure */, 2 /* address changed */, @@ -395,9 +395,9 @@ TEST_F(DnsCacheImplTest, Ipv4Address) { EXPECT_CALL(update_callbacks_, onDnsResolutionComplete("127.0.0.1:80", DnsHostInfoEquals("127.0.0.1:80", "127.0.0.1", true), - Network::DnsResolver::ResolutionStatus::Success)); + Network::DnsResolver::ResolutionStatus::Completed)); EXPECT_CALL(*resolve_timer, enableTimer(std::chrono::milliseconds(dns_ttl_), _)); - resolve_cb(Network::DnsResolver::ResolutionStatus::Success, "", + resolve_cb(Network::DnsResolver::ResolutionStatus::Completed, "", TestUtility::makeDnsResponse({"127.0.0.1"})); } @@ -429,9 +429,9 @@ TEST_F(DnsCacheImplTest, Ipv4AddressWithPort) { EXPECT_CALL(update_callbacks_, onDnsResolutionComplete("127.0.0.1:10000", DnsHostInfoEquals("127.0.0.1:10000", "127.0.0.1", true), - Network::DnsResolver::ResolutionStatus::Success)); + Network::DnsResolver::ResolutionStatus::Completed)); EXPECT_CALL(*resolve_timer, enableTimer(std::chrono::milliseconds(dns_ttl_), _)); - resolve_cb(Network::DnsResolver::ResolutionStatus::Success, "", + resolve_cb(Network::DnsResolver::ResolutionStatus::Completed, "", TestUtility::makeDnsResponse({"127.0.0.1"})); } @@ -460,9 +460,9 @@ TEST_F(DnsCacheImplTest, Ipv6Address) { EXPECT_CALL(callbacks, onLoadDnsCacheComplete(DnsHostInfoEquals("[::1]:80", "::1", true))); EXPECT_CALL(update_callbacks_, onDnsResolutionComplete("[::1]:80", DnsHostInfoEquals("[::1]:80", "::1", true), - Network::DnsResolver::ResolutionStatus::Success)); + Network::DnsResolver::ResolutionStatus::Completed)); EXPECT_CALL(*resolve_timer, enableTimer(std::chrono::milliseconds(dns_ttl_), _)); - resolve_cb(Network::DnsResolver::ResolutionStatus::Success, "", + resolve_cb(Network::DnsResolver::ResolutionStatus::Completed, "", TestUtility::makeDnsResponse({"::1"})); } @@ -491,9 +491,9 @@ TEST_F(DnsCacheImplTest, Ipv6AddressWithPort) { EXPECT_CALL(callbacks, onLoadDnsCacheComplete(DnsHostInfoEquals("[::1]:10000", "::1", true))); EXPECT_CALL(update_callbacks_, onDnsResolutionComplete("[::1]:10000", DnsHostInfoEquals("[::1]:10000", "::1", true), - Network::DnsResolver::ResolutionStatus::Success)); + Network::DnsResolver::ResolutionStatus::Completed)); EXPECT_CALL(*resolve_timer, enableTimer(std::chrono::milliseconds(dns_ttl_), _)); - resolve_cb(Network::DnsResolver::ResolutionStatus::Success, "", + resolve_cb(Network::DnsResolver::ResolutionStatus::Completed, "", TestUtility::makeDnsResponse({"::1"})); } @@ -528,9 +528,9 @@ TEST_F(DnsCacheImplTest, TTL) { EXPECT_CALL(update_callbacks_, onDnsResolutionComplete("foo.com:80", DnsHostInfoEquals("10.0.0.1:80", "foo.com", false), - Network::DnsResolver::ResolutionStatus::Success)); + Network::DnsResolver::ResolutionStatus::Completed)); EXPECT_CALL(*resolve_timer, enableTimer(std::chrono::milliseconds(6000), _)); - resolve_cb(Network::DnsResolver::ResolutionStatus::Success, "", + resolve_cb(Network::DnsResolver::ResolutionStatus::Completed, "", TestUtility::makeDnsResponse({"10.0.0.1"})); checkStats(1 /* attempt */, 1 /* success */, 0 /* failure */, 1 /* address changed */, @@ -549,9 +549,9 @@ TEST_F(DnsCacheImplTest, TTL) { EXPECT_CALL(update_callbacks_, onDnsResolutionComplete("foo.com:80", DnsHostInfoEquals("10.0.0.1:80", "foo.com", false), - Network::DnsResolver::ResolutionStatus::Success)); + Network::DnsResolver::ResolutionStatus::Completed)); EXPECT_CALL(*resolve_timer, enableTimer(std::chrono::milliseconds(6000), _)); - resolve_cb(Network::DnsResolver::ResolutionStatus::Success, "", + resolve_cb(Network::DnsResolver::ResolutionStatus::Completed, "", TestUtility::makeDnsResponse({"10.0.0.1"})); checkStats(2 /* attempt */, 2 /* success */, 0 /* failure */, 1 /* address changed */, 1 /* added */, 0 /* removed */, 1 /* num hosts */); @@ -607,9 +607,9 @@ TEST_F(DnsCacheImplTest, TTLWithMinRefreshRate) { EXPECT_CALL(update_callbacks_, onDnsResolutionComplete("foo.com:80", DnsHostInfoEquals("10.0.0.1:80", "foo.com", false), - Network::DnsResolver::ResolutionStatus::Success)); + Network::DnsResolver::ResolutionStatus::Completed)); EXPECT_CALL(*resolve_timer, enableTimer(std::chrono::milliseconds(45000), _)); - resolve_cb(Network::DnsResolver::ResolutionStatus::Success, "", + resolve_cb(Network::DnsResolver::ResolutionStatus::Completed, "", TestUtility::makeDnsResponse({"10.0.0.1"})); } @@ -644,9 +644,9 @@ TEST_F(DnsCacheImplTest, TTLWithCustomParameters) { EXPECT_CALL(update_callbacks_, onDnsResolutionComplete("foo.com:80", DnsHostInfoEquals("10.0.0.1:80", "foo.com", false), - Network::DnsResolver::ResolutionStatus::Success)); + Network::DnsResolver::ResolutionStatus::Completed)); EXPECT_CALL(*resolve_timer, enableTimer(std::chrono::milliseconds(dns_ttl_), _)); - resolve_cb(Network::DnsResolver::ResolutionStatus::Success, "", + resolve_cb(Network::DnsResolver::ResolutionStatus::Completed, "", TestUtility::makeDnsResponse({"10.0.0.1"})); // Re-resolve with ~30s passed. TTL should still be OK at 60s. @@ -659,9 +659,9 @@ TEST_F(DnsCacheImplTest, TTLWithCustomParameters) { EXPECT_CALL(update_callbacks_, onDnsResolutionComplete("foo.com:80", DnsHostInfoEquals("10.0.0.1:80", "foo.com", false), - Network::DnsResolver::ResolutionStatus::Success)); + Network::DnsResolver::ResolutionStatus::Completed)); EXPECT_CALL(*resolve_timer, enableTimer(std::chrono::milliseconds(dns_ttl_), _)); - resolve_cb(Network::DnsResolver::ResolutionStatus::Success, "", + resolve_cb(Network::DnsResolver::ResolutionStatus::Completed, "", TestUtility::makeDnsResponse({"10.0.0.1"})); // Re-resolve with ~30s passed. TTL should expire. @@ -692,7 +692,7 @@ TEST_F(DnsCacheImplTest, InlineResolve) { EXPECT_CALL(*resolver_, resolve("localhost", _, _)) .WillOnce(Invoke([](const std::string&, Network::DnsLookupFamily, Network::DnsResolver::ResolveCb callback) { - callback(Network::DnsResolver::ResolutionStatus::Success, "", + callback(Network::DnsResolver::ResolutionStatus::Completed, "", TestUtility::makeDnsResponse({"127.0.0.1"})); return nullptr; })); @@ -705,7 +705,7 @@ TEST_F(DnsCacheImplTest, InlineResolve) { EXPECT_CALL(update_callbacks_, onDnsResolutionComplete("localhost:80", DnsHostInfoEquals("127.0.0.1:80", "localhost", false), - Network::DnsResolver::ResolutionStatus::Success)); + Network::DnsResolver::ResolutionStatus::Completed)); EXPECT_CALL(*resolve_timer, enableTimer(std::chrono::milliseconds(dns_ttl_), _)); post_cb(); } @@ -880,9 +880,10 @@ TEST_F(DnsCacheImplTest, ResolveSuccessWithEmptyResult) { EXPECT_CALL(callbacks, onLoadDnsCacheComplete(DnsHostInfoAddressIsNull())); EXPECT_CALL(update_callbacks_, onDnsResolutionComplete("foo.com:80", DnsHostInfoAddressIsNull(), - Network::DnsResolver::ResolutionStatus::Success)); + Network::DnsResolver::ResolutionStatus::Completed)); EXPECT_CALL(*resolve_timer, enableTimer(std::chrono::milliseconds(configured_ttl_), _)); - resolve_cb(Network::DnsResolver::ResolutionStatus::Success, "", TestUtility::makeDnsResponse({})); + resolve_cb(Network::DnsResolver::ResolutionStatus::Completed, "", + TestUtility::makeDnsResponse({})); checkStats(1 /* attempt */, 1 /* success */, 0 /* failure */, 0 /* address changed */, 1 /* added */, 0 /* removed */, 1 /* num hosts */); @@ -926,8 +927,8 @@ TEST_F(DnsCacheImplTest, CancelResolve) { EXPECT_CALL(update_callbacks_, onDnsResolutionComplete("foo.com:80", DnsHostInfoEquals("10.0.0.1:80", "foo.com", false), - Network::DnsResolver::ResolutionStatus::Success)); - resolve_cb(Network::DnsResolver::ResolutionStatus::Success, "", + Network::DnsResolver::ResolutionStatus::Completed)); + resolve_cb(Network::DnsResolver::ResolutionStatus::Completed, "", TestUtility::makeDnsResponse({"10.0.0.1"})); } @@ -962,8 +963,8 @@ TEST_F(DnsCacheImplTest, MultipleResolveSameHost) { EXPECT_CALL(update_callbacks_, onDnsResolutionComplete("foo.com:80", DnsHostInfoEquals("10.0.0.1:80", "foo.com", false), - Network::DnsResolver::ResolutionStatus::Success)); - resolve_cb(Network::DnsResolver::ResolutionStatus::Success, "", + Network::DnsResolver::ResolutionStatus::Completed)); + resolve_cb(Network::DnsResolver::ResolutionStatus::Completed, "", TestUtility::makeDnsResponse({"10.0.0.1"})); } @@ -1000,8 +1001,8 @@ TEST_F(DnsCacheImplTest, MultipleResolveDifferentHost) { EXPECT_CALL(update_callbacks_, onDnsResolutionComplete("bar.com:443", DnsHostInfoEquals("10.0.0.1:443", "bar.com", false), - Network::DnsResolver::ResolutionStatus::Success)); - resolve_cb2(Network::DnsResolver::ResolutionStatus::Success, "", + Network::DnsResolver::ResolutionStatus::Completed)); + resolve_cb2(Network::DnsResolver::ResolutionStatus::Completed, "", TestUtility::makeDnsResponse({"10.0.0.1"})); EXPECT_CALL( @@ -1012,8 +1013,8 @@ TEST_F(DnsCacheImplTest, MultipleResolveDifferentHost) { EXPECT_CALL(update_callbacks_, onDnsResolutionComplete("foo.com:80", DnsHostInfoEquals("10.0.0.2:80", "foo.com", false), - Network::DnsResolver::ResolutionStatus::Success)); - resolve_cb1(Network::DnsResolver::ResolutionStatus::Success, "", + Network::DnsResolver::ResolutionStatus::Completed)); + resolve_cb1(Network::DnsResolver::ResolutionStatus::Completed, "", TestUtility::makeDnsResponse({"10.0.0.2"})); absl::flat_hash_map hosts; @@ -1054,8 +1055,8 @@ TEST_F(DnsCacheImplTest, CacheHit) { EXPECT_CALL(update_callbacks_, onDnsResolutionComplete("foo.com:80", DnsHostInfoEquals("10.0.0.1:80", "foo.com", false), - Network::DnsResolver::ResolutionStatus::Success)); - resolve_cb(Network::DnsResolver::ResolutionStatus::Success, "", + Network::DnsResolver::ResolutionStatus::Completed)); + resolve_cb(Network::DnsResolver::ResolutionStatus::Completed, "", TestUtility::makeDnsResponse({"10.0.0.1"})); result = dns_cache_->loadDnsCacheEntry("foo.com", 80, false, callbacks); @@ -1087,8 +1088,8 @@ TEST_F(DnsCacheImplTest, CacheHitWithDifferentDefaultPort) { EXPECT_CALL(update_callbacks_, onDnsResolutionComplete("foo.com:80", DnsHostInfoEquals("10.0.0.1:80", "foo.com", false), - Network::DnsResolver::ResolutionStatus::Success)); - resolve_cb(Network::DnsResolver::ResolutionStatus::Success, "", + Network::DnsResolver::ResolutionStatus::Completed)); + resolve_cb(Network::DnsResolver::ResolutionStatus::Completed, "", TestUtility::makeDnsResponse({"10.0.0.1"})); // Using the same DNS cache, resolve the same host but different default port 443 @@ -1136,8 +1137,9 @@ TEST_F(DnsCacheImplTest, InvalidPort) { EXPECT_CALL(callbacks, onLoadDnsCacheComplete(DnsHostInfoAddressIsNull())); EXPECT_CALL(update_callbacks_, onDnsResolutionComplete("foo.com:abc:80", DnsHostInfoAddressIsNull(), - Network::DnsResolver::ResolutionStatus::Success)); - resolve_cb(Network::DnsResolver::ResolutionStatus::Success, "", TestUtility::makeDnsResponse({})); + Network::DnsResolver::ResolutionStatus::Completed)); + resolve_cb(Network::DnsResolver::ResolutionStatus::Completed, "", + TestUtility::makeDnsResponse({})); } // Max host overflow. @@ -1275,9 +1277,9 @@ TEST_F(DnsCacheImplTest, SetIpVersionToRemoveYieldsNonEmptyResponse) { EXPECT_CALL(update_callbacks_, onDnsResolutionComplete("foo.com:80", DnsHostInfoEquals("127.0.0.2:80", "foo.com", false), - Network::DnsResolver::ResolutionStatus::Success)); + Network::DnsResolver::ResolutionStatus::Completed)); EXPECT_CALL(*resolve_timer, enableTimer(std::chrono::milliseconds(dns_ttl_), _)); - resolve_cb(Network::DnsResolver::ResolutionStatus::Success, "", + resolve_cb(Network::DnsResolver::ResolutionStatus::Completed, "", TestUtility::makeDnsResponse({"127.0.0.2", "::2"})); // Verify that only the address is now set to an IPv4. result = dns_cache_->loadDnsCacheEntry("foo.com", 80, false, callbacks); @@ -1296,10 +1298,10 @@ TEST_F(DnsCacheImplTest, SetIpVersionToRemoveYieldsNonEmptyResponse) { onDnsHostAddOrUpdate("foo.com:80", DnsHostInfoEquals("[::2]:80", "foo.com", false))); EXPECT_CALL(update_callbacks_, onDnsResolutionComplete("foo.com:80", DnsHostInfoEquals("[::2]:80", "foo.com", false), - Network::DnsResolver::ResolutionStatus::Success)); + Network::DnsResolver::ResolutionStatus::Completed)); EXPECT_CALL(*resolve_timer, enableTimer(std::chrono::milliseconds(dns_ttl_), _)); dns_cache_->forceRefreshHosts(); - resolve_cb(Network::DnsResolver::ResolutionStatus::Success, "", + resolve_cb(Network::DnsResolver::ResolutionStatus::Completed, "", TestUtility::makeDnsResponse({"127.0.0.2", "::2"})); // Verify that only the address is now set to an IPv6. result = dns_cache_->loadDnsCacheEntry("foo.com", 80, false, callbacks); @@ -1320,10 +1322,10 @@ TEST_F(DnsCacheImplTest, SetIpVersionToRemoveYieldsNonEmptyResponse) { EXPECT_CALL(update_callbacks_, onDnsResolutionComplete("foo.com:80", DnsHostInfoEquals("127.0.0.2:80", "foo.com", false), - Network::DnsResolver::ResolutionStatus::Success)); + Network::DnsResolver::ResolutionStatus::Completed)); EXPECT_CALL(*resolve_timer, enableTimer(std::chrono::milliseconds(dns_ttl_), _)); dns_cache_->forceRefreshHosts(); - resolve_cb(Network::DnsResolver::ResolutionStatus::Success, "", + resolve_cb(Network::DnsResolver::ResolutionStatus::Completed, "", TestUtility::makeDnsResponse({"127.0.0.2", "::2"})); // Verify that only the address is now set to an IPv4 (the first entry in the DNS response). result = dns_cache_->loadDnsCacheEntry("foo.com", 80, false, callbacks); @@ -1361,9 +1363,9 @@ TEST_F(DnsCacheImplTest, SetIpVersionToRemoveYieldsEmptyResponse) { EXPECT_CALL(callbacks, onLoadDnsCacheComplete(DnsHostInfoAddressIsNull())); EXPECT_CALL(update_callbacks_, onDnsResolutionComplete("foo.com:80", DnsHostInfoAddressIsNull(), - Network::DnsResolver::ResolutionStatus::Success)); + Network::DnsResolver::ResolutionStatus::Completed)); EXPECT_CALL(*resolve_timer, enableTimer(std::chrono::milliseconds(configured_ttl_), _)); - resolve_cb(Network::DnsResolver::ResolutionStatus::Success, "", + resolve_cb(Network::DnsResolver::ResolutionStatus::Completed, "", TestUtility::makeDnsResponse({"::2"})); result = dns_cache_->loadDnsCacheEntry("foo.com", 80, false, callbacks); @@ -1406,9 +1408,9 @@ TEST_F(DnsCacheImplTest, SetIpVersionToRemoveIgnoreIPv4LoopbackAddress) { EXPECT_CALL(update_callbacks_, onDnsResolutionComplete("foo.com:80", DnsHostInfoEquals("127.0.0.1:80", "foo.com", false), - Network::DnsResolver::ResolutionStatus::Success)); + Network::DnsResolver::ResolutionStatus::Completed)); EXPECT_CALL(*resolve_timer, enableTimer(std::chrono::milliseconds(dns_ttl_), _)); - resolve_cb(Network::DnsResolver::ResolutionStatus::Success, "", + resolve_cb(Network::DnsResolver::ResolutionStatus::Completed, "", TestUtility::makeDnsResponse({"127.0.0.1"})); // Verify that only the address is now set to an IPv4. result = dns_cache_->loadDnsCacheEntry("foo.com", 80, false, callbacks); @@ -1447,9 +1449,9 @@ TEST_F(DnsCacheImplTest, SetIpVersionToRemoveIgnoreIPv6LoopbackAddress) { EXPECT_CALL(callbacks, onLoadDnsCacheComplete(DnsHostInfoEquals("[::1]:80", "foo.com", false))); EXPECT_CALL(update_callbacks_, onDnsResolutionComplete("foo.com:80", DnsHostInfoEquals("[::1]:80", "foo.com", false), - Network::DnsResolver::ResolutionStatus::Success)); + Network::DnsResolver::ResolutionStatus::Completed)); EXPECT_CALL(*resolve_timer, enableTimer(std::chrono::milliseconds(dns_ttl_), _)); - resolve_cb(Network::DnsResolver::ResolutionStatus::Success, "", + resolve_cb(Network::DnsResolver::ResolutionStatus::Completed, "", TestUtility::makeDnsResponse({"::1"})); // Verify that only the address is now set to an IPv4. result = dns_cache_->loadDnsCacheEntry("foo.com", 80, false, callbacks); @@ -1472,16 +1474,16 @@ TEST_F(DnsCacheImplTest, SetIpVersionToRemoveWithDnsPreresolveHostnames) { EXPECT_CALL(update_callbacks_, onDnsResolutionComplete("foo.com:80", DnsHostInfoEquals("127.0.0.2:80", "foo.com", false), - Network::DnsResolver::ResolutionStatus::Success)) + Network::DnsResolver::ResolutionStatus::Completed)) .Times(AtLeast(1)); initialize(/* preresolve_hostnames= */ {{"foo.com", 80}}); - resolve_cb(Network::DnsResolver::ResolutionStatus::Success, "", + resolve_cb(Network::DnsResolver::ResolutionStatus::Completed, "", TestUtility::makeDnsResponse({"127.0.0.2"})); dns_cache_->setIpVersionToRemove(Network::Address::IpVersion::v4); EXPECT_ENVOY_BUG( - resolve_cb(Network::DnsResolver::ResolutionStatus::Success, "", + resolve_cb(Network::DnsResolver::ResolutionStatus::Completed, "", TestUtility::makeDnsResponse({"127.0.0.2"})), "Unable to delete IP version addresses when DNS preresolve hostnames are not empty."); @@ -1763,9 +1765,9 @@ TEST_F(DnsCacheImplTest, ResolveSuccessWithCaching) { EXPECT_CALL(update_callbacks_, onDnsResolutionComplete("foo.com:80", DnsHostInfoEquals("10.0.0.1:80", "foo.com", false), - Network::DnsResolver::ResolutionStatus::Success)); + Network::DnsResolver::ResolutionStatus::Completed)); EXPECT_CALL(*resolve_timer, enableTimer(std::chrono::milliseconds(6000), _)); - resolve_cb(Network::DnsResolver::ResolutionStatus::Success, "", + resolve_cb(Network::DnsResolver::ResolutionStatus::Completed, "", TestUtility::makeDnsResponse({"10.0.0.1"})); checkStats(1 /* attempt */, 1 /* success */, 0 /* failure */, 1 /* address changed */, @@ -1786,9 +1788,9 @@ TEST_F(DnsCacheImplTest, ResolveSuccessWithCaching) { EXPECT_CALL(update_callbacks_, onDnsResolutionComplete("foo.com:80", DnsHostInfoEquals("10.0.0.1:80", "foo.com", false), - Network::DnsResolver::ResolutionStatus::Success)); + Network::DnsResolver::ResolutionStatus::Completed)); EXPECT_CALL(*resolve_timer, enableTimer(std::chrono::milliseconds(dns_ttl_), _)); - resolve_cb(Network::DnsResolver::ResolutionStatus::Success, "", + resolve_cb(Network::DnsResolver::ResolutionStatus::Completed, "", TestUtility::makeDnsResponse({"10.0.0.1"})); checkStats(2 /* attempt */, 2 /* success */, 0 /* failure */, 1 /* address changed */, @@ -1812,9 +1814,9 @@ TEST_F(DnsCacheImplTest, ResolveSuccessWithCaching) { EXPECT_CALL(update_callbacks_, onDnsResolutionComplete("foo.com:80", DnsHostInfoEquals("10.0.0.2:80", "foo.com", false), - Network::DnsResolver::ResolutionStatus::Success)); + Network::DnsResolver::ResolutionStatus::Completed)); EXPECT_CALL(*resolve_timer, enableTimer(std::chrono::milliseconds(dns_ttl_), _)); - resolve_cb(Network::DnsResolver::ResolutionStatus::Success, "", + resolve_cb(Network::DnsResolver::ResolutionStatus::Completed, "", TestUtility::makeDnsResponse({"10.0.0.2", "10.0.0.1"})); checkStats(3 /* attempt */, 3 /* success */, 0 /* failure */, 2 /* address changed */, @@ -1834,9 +1836,9 @@ TEST_F(DnsCacheImplTest, ResolveSuccessWithCaching) { EXPECT_CALL(update_callbacks_, onDnsResolutionComplete("foo.com:80", DnsHostInfoEquals("10.0.0.2:80", "foo.com", false), - Network::DnsResolver::ResolutionStatus::Success)); + Network::DnsResolver::ResolutionStatus::Completed)); EXPECT_CALL(*resolve_timer, enableTimer(std::chrono::milliseconds(40000), _)); - resolve_cb(Network::DnsResolver::ResolutionStatus::Success, "", + resolve_cb(Network::DnsResolver::ResolutionStatus::Completed, "", TestUtility::makeDnsResponse({"10.0.0.2", "10.0.0.1"}, std::chrono::seconds(40))); } diff --git a/test/extensions/common/wasm/wasm_test.cc b/test/extensions/common/wasm/wasm_test.cc index 7544b23493..e12e68eccf 100644 --- a/test/extensions/common/wasm/wasm_test.cc +++ b/test/extensions/common/wasm/wasm_test.cc @@ -301,7 +301,7 @@ TEST_P(WasmCommonTest, Segv) { // Subsequent calls should be NOOP(s). - root_context->onResolveDns(0, Envoy::Network::DnsResolver::ResolutionStatus::Success, {}); + root_context->onResolveDns(0, Envoy::Network::DnsResolver::ResolutionStatus::Completed, {}); Envoy::Stats::MockMetricSnapshot stats_snapshot; root_context->onStatsUpdate(stats_snapshot); } @@ -1353,7 +1353,7 @@ TEST_P(WasmCommonContextTest, OnDnsResolve) { EXPECT_CALL(rootContext(), log_(spdlog::level::warn, Eq("TestRootContext::onDone 1"))); dns_callback( - Network::DnsResolver::ResolutionStatus::Success, "", + Network::DnsResolver::ResolutionStatus::Completed, "", TestUtility::makeDnsResponse({"192.168.1.101", "192.168.1.102"}, std::chrono::seconds(1001))); rootContext().onResolveDns(1 /* token */, Envoy::Network::DnsResolver::ResolutionStatus::Failure, @@ -1366,7 +1366,7 @@ TEST_P(WasmCommonContextTest, OnDnsResolve) { } // Wait till the Wasm is destroyed and then the late callback should do nothing. deferred_runner_.setFunction([dns_callback] { - dns_callback(Network::DnsResolver::ResolutionStatus::Success, "", + dns_callback(Network::DnsResolver::ResolutionStatus::Completed, "", TestUtility::makeDnsResponse({"192.168.1.101", "192.168.1.102"}, std::chrono::seconds(1001))); }); @@ -1386,7 +1386,7 @@ TEST_P(WasmCommonContextTest, EmptyContext) { setup(code, "context", "empty"); setupContext(); - root_context_->onResolveDns(0, Envoy::Network::DnsResolver::ResolutionStatus::Success, {}); + root_context_->onResolveDns(0, Envoy::Network::DnsResolver::ResolutionStatus::Completed, {}); NiceMock stats_snapshot; root_context_->onStatsUpdate(stats_snapshot); root_context_->validateConfiguration("", plugin_); diff --git a/test/extensions/filters/http/aws_request_signing/aws_request_signing_integration_test.cc b/test/extensions/filters/http/aws_request_signing/aws_request_signing_integration_test.cc index 6ddd2e81ff..ab25ca80d0 100644 --- a/test/extensions/filters/http/aws_request_signing/aws_request_signing_integration_test.cc +++ b/test/extensions/filters/http/aws_request_signing/aws_request_signing_integration_test.cc @@ -248,7 +248,7 @@ class InitializeFilterTest : public ::testing::Test, public HttpIntegrationTest EXPECT_CALL(*dns_resolver_, resolve(expected_address, _, _)) .WillRepeatedly(Invoke([&](const std::string&, Network::DnsLookupFamily, Network::DnsResolver::ResolveCb cb) -> Network::ActiveDnsQuery* { - cb(Network::DnsResolver::ResolutionStatus::Success, "", + cb(Network::DnsResolver::ResolutionStatus::Completed, "", TestUtility::makeDnsResponse({"127.0.0.1", "127.0.0.2"})); return nullptr; @@ -495,7 +495,7 @@ class CdsInteractionTest : public testing::Test, public HttpIntegrationTest { EXPECT_CALL(*dns_resolver_, resolve(expected_address, _, _)) .WillRepeatedly(Invoke([&](const std::string&, Network::DnsLookupFamily, Network::DnsResolver::ResolveCb cb) -> Network::ActiveDnsQuery* { - cb(Network::DnsResolver::ResolutionStatus::Success, "", + cb(Network::DnsResolver::ResolutionStatus::Completed, "", TestUtility::makeDnsResponse({"127.0.0.1", "127.0.0.2"})); return nullptr; diff --git a/test/extensions/filters/udp/dns_filter/dns_filter_test.cc b/test/extensions/filters/udp/dns_filter/dns_filter_test.cc index aa698ba161..985090ba7e 100644 --- a/test/extensions/filters/udp/dns_filter/dns_filter_test.cc +++ b/test/extensions/filters/udp/dns_filter/dns_filter_test.cc @@ -759,7 +759,7 @@ TEST_F(DnsFilterTest, ExternalResolutionReturnSingleAddress) { EXPECT_CALL(*timeout_timer, disableTimer()).Times(AnyNumber()); // Execute resolve callback - resolve_cb(Network::DnsResolver::ResolutionStatus::Success, "", + resolve_cb(Network::DnsResolver::ResolutionStatus::Completed, "", TestUtility::makeDnsResponse({expected_address})); // parse the result @@ -812,7 +812,7 @@ TEST_F(DnsFilterTest, ExternalResolutionIpv6SingleAddress) { EXPECT_CALL(*timeout_timer, disableTimer()); // Execute resolve callback - resolve_cb(Network::DnsResolver::ResolutionStatus::Success, "", + resolve_cb(Network::DnsResolver::ResolutionStatus::Completed, "", TestUtility::makeDnsResponse({expected_address})); // parse the result @@ -865,7 +865,7 @@ TEST_F(DnsFilterTest, ExternalResolutionReturnMultipleAddresses) { EXPECT_CALL(*timeout_timer, disableTimer()); // Execute resolve callback - resolve_cb(Network::DnsResolver::ResolutionStatus::Success, "", + resolve_cb(Network::DnsResolver::ResolutionStatus::Completed, "", TestUtility::makeDnsResponse({expected_address})); // parse the result @@ -917,7 +917,8 @@ TEST_F(DnsFilterTest, ExternalResolutionReturnNoAddresses) { EXPECT_CALL(*timeout_timer, disableTimer()); // Execute resolve callback - resolve_cb(Network::DnsResolver::ResolutionStatus::Success, "", TestUtility::makeDnsResponse({})); + resolve_cb(Network::DnsResolver::ResolutionStatus::Completed, "", + TestUtility::makeDnsResponse({})); // parse the result response_ctx_ = ResponseValidator::createResponseContext(udp_response_, counters_); @@ -1003,7 +1004,7 @@ TEST_F(DnsFilterTest, ExternalResolutionTimeout2) { // Execute resolve callback. This should harmlessly return and not alter // the response received by the client. Even though we are returning a successful // response, the client does not get an answer - resolve_cb(Network::DnsResolver::ResolutionStatus::Success, "", + resolve_cb(Network::DnsResolver::ResolutionStatus::Completed, "", TestUtility::makeDnsResponse({"130.207.244.251"})); // parse the result diff --git a/test/extensions/network/dns_resolver/apple/apple_dns_impl_test.cc b/test/extensions/network/dns_resolver/apple/apple_dns_impl_test.cc index ae263ae91f..4318229b03 100644 --- a/test/extensions/network/dns_resolver/apple/apple_dns_impl_test.cc +++ b/test/extensions/network/dns_resolver/apple/apple_dns_impl_test.cc @@ -287,35 +287,35 @@ TEST_F(AppleDnsImplTest, DestructPending) { TEST_F(AppleDnsImplTest, LocalLookup) { EXPECT_NE(nullptr, resolveWithExpectations("localhost", DnsLookupFamily::Auto, - DnsResolver::ResolutionStatus::Success, true)); + DnsResolver::ResolutionStatus::Completed, true)); dispatcher_->run(Event::Dispatcher::RunType::Block); } TEST_F(AppleDnsImplTest, DnsIpAddressVersionAuto) { EXPECT_NE(nullptr, resolveWithExpectations("google.com", DnsLookupFamily::Auto, - DnsResolver::ResolutionStatus::Success, true)); + DnsResolver::ResolutionStatus::Completed, true)); dispatcher_->run(Event::Dispatcher::RunType::Block); } TEST_F(AppleDnsImplTest, DnsIpAddressVersionV4Preferred) { EXPECT_NE(nullptr, resolveWithExpectations("google.com", DnsLookupFamily::V4Preferred, - DnsResolver::ResolutionStatus::Success, true)); + DnsResolver::ResolutionStatus::Completed, true)); dispatcher_->run(Event::Dispatcher::RunType::Block); } TEST_F(AppleDnsImplTest, DnsIpAddressVersionV4Only) { EXPECT_NE(nullptr, resolveWithExpectations("google.com", DnsLookupFamily::V4Only, - DnsResolver::ResolutionStatus::Success, true)); + DnsResolver::ResolutionStatus::Completed, true)); dispatcher_->run(Event::Dispatcher::RunType::Block); } TEST_F(AppleDnsImplTest, DnsIpAddressVersionV6Only) { EXPECT_NE(nullptr, resolveWithExpectations("google.com", DnsLookupFamily::V6Only, - DnsResolver::ResolutionStatus::Success, true)); + DnsResolver::ResolutionStatus::Completed, true)); dispatcher_->run(Event::Dispatcher::RunType::Block); EXPECT_NE(nullptr, resolveWithExpectations("google.com", DnsLookupFamily::All, - DnsResolver::ResolutionStatus::Success, true)); + DnsResolver::ResolutionStatus::Completed, true)); dispatcher_->run(Event::Dispatcher::RunType::Block); } @@ -326,114 +326,119 @@ TEST_F(AppleDnsImplTest, DnsIpAddressVersionV6Only) { TEST_F(AppleDnsImplTest, DnsIpAddressVersionAllSupportsV4Only) { EXPECT_NE(nullptr, resolveWithExpectations("ipv4.google.com", DnsLookupFamily::All, - DnsResolver::ResolutionStatus::Success, true)); + DnsResolver::ResolutionStatus::Completed, true)); dispatcher_->run(Event::Dispatcher::RunType::Block); } TEST_F(AppleDnsImplTest, DnsIpAddressVersionAllSupportsV6Only) { - auto* dns_query = resolver_->resolve("ipv6.google.com", DnsLookupFamily::All, - [=](DnsResolver::ResolutionStatus status, absl::string_view, - std::list&& results) -> void { - EXPECT_EQ(DnsResolver::ResolutionStatus::Success, status); - // On v4 only networks, there will be no results. - for (const auto& result : results) { - const auto& addrinfo = result.addrInfo(); - EXPECT_THAT(addrinfo.address_->ip()->ipv6(), NotNull()); - EXPECT_THAT(addrinfo.address_->ip()->ipv4(), IsNull()); - } - dispatcher_->exit(); - }); + auto* dns_query = + resolver_->resolve("ipv6.google.com", DnsLookupFamily::All, + [=](DnsResolver::ResolutionStatus status, absl::string_view, + std::list&& results) -> void { + EXPECT_EQ(DnsResolver::ResolutionStatus::Completed, status); + // On v4 only networks, there will be no results. + for (const auto& result : results) { + const auto& addrinfo = result.addrInfo(); + EXPECT_THAT(addrinfo.address_->ip()->ipv6(), NotNull()); + EXPECT_THAT(addrinfo.address_->ip()->ipv4(), IsNull()); + } + dispatcher_->exit(); + }); EXPECT_THAT(dns_query, NotNull()); dispatcher_->run(Event::Dispatcher::RunType::Block); } TEST_F(AppleDnsImplTest, DnsIpAddressVersionV4OnlySupportsV4Only) { EXPECT_NE(nullptr, resolveWithExpectations("ipv4.google.com", DnsLookupFamily::V4Only, - DnsResolver::ResolutionStatus::Success, true)); + DnsResolver::ResolutionStatus::Completed, true)); dispatcher_->run(Event::Dispatcher::RunType::Block); } TEST_F(AppleDnsImplTest, DnsIpAddressVersionV4OnlySupportsV6Only) { EXPECT_NE(nullptr, resolveWithExpectations("ipv6.google.com", DnsLookupFamily::V4Only, - DnsResolver::ResolutionStatus::Success, false)); + DnsResolver::ResolutionStatus::Completed, false)); dispatcher_->run(Event::Dispatcher::RunType::Block); } TEST_F(AppleDnsImplTest, DnsIpAddressVersionV6OnlySupportsV4Only) { - auto* dns_query = resolver_->resolve("ipv4.google.com", DnsLookupFamily::V6Only, - [=](DnsResolver::ResolutionStatus status, absl::string_view, - std::list&& results) -> void { - EXPECT_EQ(DnsResolver::ResolutionStatus::Success, status); - for (const auto& result : results) { - const auto& addrinfo = result.addrInfo(); - EXPECT_THAT(addrinfo.address_->ip()->ipv6(), NotNull()); - EXPECT_THAT(addrinfo.address_->ip()->ipv4(), IsNull()); - } - dispatcher_->exit(); - }); + auto* dns_query = + resolver_->resolve("ipv4.google.com", DnsLookupFamily::V6Only, + [=](DnsResolver::ResolutionStatus status, absl::string_view, + std::list&& results) -> void { + EXPECT_EQ(DnsResolver::ResolutionStatus::Completed, status); + for (const auto& result : results) { + const auto& addrinfo = result.addrInfo(); + EXPECT_THAT(addrinfo.address_->ip()->ipv6(), NotNull()); + EXPECT_THAT(addrinfo.address_->ip()->ipv4(), IsNull()); + } + dispatcher_->exit(); + }); EXPECT_THAT(dns_query, NotNull()); dispatcher_->run(Event::Dispatcher::RunType::Block); } TEST_F(AppleDnsImplTest, DnsIpAddressVersionV6OnlySupportsV6Only) { - auto* dns_query = resolver_->resolve("ipv6.google.com", DnsLookupFamily::V6Only, - [=](DnsResolver::ResolutionStatus status, absl::string_view, - std::list&& results) -> void { - EXPECT_EQ(DnsResolver::ResolutionStatus::Success, status); - EXPECT_FALSE(results.empty()); - for (const auto& result : results) { - const auto& addrinfo = result.addrInfo(); - EXPECT_THAT(addrinfo.address_->ip()->ipv6(), NotNull()); - EXPECT_THAT(addrinfo.address_->ip()->ipv4(), IsNull()); - } - dispatcher_->exit(); - }); + auto* dns_query = + resolver_->resolve("ipv6.google.com", DnsLookupFamily::V6Only, + [=](DnsResolver::ResolutionStatus status, absl::string_view, + std::list&& results) -> void { + EXPECT_EQ(DnsResolver::ResolutionStatus::Completed, status); + EXPECT_FALSE(results.empty()); + for (const auto& result : results) { + const auto& addrinfo = result.addrInfo(); + EXPECT_THAT(addrinfo.address_->ip()->ipv6(), NotNull()); + EXPECT_THAT(addrinfo.address_->ip()->ipv4(), IsNull()); + } + dispatcher_->exit(); + }); EXPECT_THAT(dns_query, NotNull()); dispatcher_->run(Event::Dispatcher::RunType::Block); } TEST_F(AppleDnsImplTest, DnsIpAddressVersionAutoSupportsV4Only) { EXPECT_NE(nullptr, resolveWithExpectations("ipv4.google.com", DnsLookupFamily::Auto, - DnsResolver::ResolutionStatus::Success, true)); + DnsResolver::ResolutionStatus::Completed, true)); dispatcher_->run(Event::Dispatcher::RunType::Block); } TEST_F(AppleDnsImplTest, DnsIpAddressVersionAutoSupportsV6Only) { - auto* dns_query = resolver_->resolve("ipv6.google.com", DnsLookupFamily::Auto, - [=](DnsResolver::ResolutionStatus status, absl::string_view, - std::list&& results) -> void { - EXPECT_EQ(DnsResolver::ResolutionStatus::Success, status); - // On v4 only networks, there will be no results. - for (const auto& result : results) { - const auto& addrinfo = result.addrInfo(); - EXPECT_THAT(addrinfo.address_->ip()->ipv6(), NotNull()); - EXPECT_THAT(addrinfo.address_->ip()->ipv4(), IsNull()); - } - dispatcher_->exit(); - }); + auto* dns_query = + resolver_->resolve("ipv6.google.com", DnsLookupFamily::Auto, + [=](DnsResolver::ResolutionStatus status, absl::string_view, + std::list&& results) -> void { + EXPECT_EQ(DnsResolver::ResolutionStatus::Completed, status); + // On v4 only networks, there will be no results. + for (const auto& result : results) { + const auto& addrinfo = result.addrInfo(); + EXPECT_THAT(addrinfo.address_->ip()->ipv6(), NotNull()); + EXPECT_THAT(addrinfo.address_->ip()->ipv4(), IsNull()); + } + dispatcher_->exit(); + }); EXPECT_THAT(dns_query, NotNull()); dispatcher_->run(Event::Dispatcher::RunType::Block); } TEST_F(AppleDnsImplTest, DnsIpAddressVersionV4PreferredSupportsV4Only) { EXPECT_NE(nullptr, resolveWithExpectations("ipv4.google.com", DnsLookupFamily::V4Preferred, - DnsResolver::ResolutionStatus::Success, true)); + DnsResolver::ResolutionStatus::Completed, true)); dispatcher_->run(Event::Dispatcher::RunType::Block); } TEST_F(AppleDnsImplTest, DnsIpAddressVersionV4PreferredSupportsV6Only) { - auto* dns_query = resolver_->resolve("ipv6.google.com", DnsLookupFamily::V4Preferred, - [=](DnsResolver::ResolutionStatus status, absl::string_view, - std::list&& results) -> void { - EXPECT_EQ(DnsResolver::ResolutionStatus::Success, status); - // On v4 only networks, there will be no results. - for (const auto& result : results) { - const auto& addrinfo = result.addrInfo(); - EXPECT_THAT(addrinfo.address_->ip()->ipv6(), NotNull()); - EXPECT_THAT(addrinfo.address_->ip()->ipv4(), IsNull()); - } - dispatcher_->exit(); - }); + auto* dns_query = + resolver_->resolve("ipv6.google.com", DnsLookupFamily::V4Preferred, + [=](DnsResolver::ResolutionStatus status, absl::string_view, + std::list&& results) -> void { + EXPECT_EQ(DnsResolver::ResolutionStatus::Completed, status); + // On v4 only networks, there will be no results. + for (const auto& result : results) { + const auto& addrinfo = result.addrInfo(); + EXPECT_THAT(addrinfo.address_->ip()->ipv6(), NotNull()); + EXPECT_THAT(addrinfo.address_->ip()->ipv4(), IsNull()); + } + dispatcher_->exit(); + }); EXPECT_THAT(dns_query, NotNull()); dispatcher_->run(Event::Dispatcher::RunType::Block); } @@ -444,43 +449,44 @@ TEST_F(AppleDnsImplTest, DnsIpAddressVersionV4PreferredSupportsV6Only) { // queries. TEST_F(AppleDnsImplTest, DoubleLookup) { EXPECT_NE(nullptr, resolveWithExpectations("google.com", DnsLookupFamily::V4Only, - DnsResolver::ResolutionStatus::Success, true)); + DnsResolver::ResolutionStatus::Completed, true)); dispatcher_->run(Event::Dispatcher::RunType::Block); EXPECT_NE(nullptr, resolveWithExpectations("google.com", DnsLookupFamily::V4Only, - DnsResolver::ResolutionStatus::Success, true)); + DnsResolver::ResolutionStatus::Completed, true)); dispatcher_->run(Event::Dispatcher::RunType::Block); } TEST_F(AppleDnsImplTest, DoubleLookupInOneLoop) { - EXPECT_NE(nullptr, resolveWithExpectations("google.com", DnsLookupFamily::V4Only, - DnsResolver::ResolutionStatus::Success, true, false)); + EXPECT_NE(nullptr, + resolveWithExpectations("google.com", DnsLookupFamily::V4Only, + DnsResolver::ResolutionStatus::Completed, true, false)); EXPECT_NE(nullptr, resolveWithExpectations("google.com", DnsLookupFamily::V4Only, - DnsResolver::ResolutionStatus::Success, true)); + DnsResolver::ResolutionStatus::Completed, true)); dispatcher_->run(Event::Dispatcher::RunType::Block); } TEST_F(AppleDnsImplTest, DnsIpAddressVersionInvalid) { // The DNS queries are successful, but return no results. EXPECT_NE(nullptr, resolveWithExpectations("invalidDnsName", DnsLookupFamily::Auto, - DnsResolver::ResolutionStatus::Success, false)); + DnsResolver::ResolutionStatus::Completed, false)); dispatcher_->run(Event::Dispatcher::RunType::Block); EXPECT_NE(nullptr, resolveWithExpectations("invalidDnsName", DnsLookupFamily::V4Preferred, - DnsResolver::ResolutionStatus::Success, false)); + DnsResolver::ResolutionStatus::Completed, false)); dispatcher_->run(Event::Dispatcher::RunType::Block); EXPECT_NE(nullptr, resolveWithExpectations("invalidDnsName", DnsLookupFamily::V4Only, - DnsResolver::ResolutionStatus::Success, false)); + DnsResolver::ResolutionStatus::Completed, false)); dispatcher_->run(Event::Dispatcher::RunType::Block); EXPECT_NE(nullptr, resolveWithExpectations("invalidDnsName", DnsLookupFamily::V6Only, - DnsResolver::ResolutionStatus::Success, false)); + DnsResolver::ResolutionStatus::Completed, false)); dispatcher_->run(Event::Dispatcher::RunType::Block); EXPECT_NE(nullptr, resolveWithExpectations("invalidDnsName", DnsLookupFamily::All, - DnsResolver::ResolutionStatus::Success, false)); + DnsResolver::ResolutionStatus::Completed, false)); dispatcher_->run(Event::Dispatcher::RunType::Block); } @@ -501,7 +507,7 @@ TEST_F(AppleDnsImplTest, Cancel) { resolveWithUnreferencedParameters("some.domain", DnsLookupFamily::Auto, false); EXPECT_NE(nullptr, resolveWithExpectations("google.com", DnsLookupFamily::Auto, - DnsResolver::ResolutionStatus::Success, true)); + DnsResolver::ResolutionStatus::Completed, true)); ASSERT_NE(nullptr, query); query->cancel(Network::ActiveDnsQuery::CancelReason::QueryAbandoned); @@ -511,7 +517,7 @@ TEST_F(AppleDnsImplTest, Cancel) { TEST_F(AppleDnsImplTest, NonExistentDomain) { EXPECT_NE(nullptr, resolveWithExpectations("some.domain", DnsLookupFamily::V6Only, - DnsResolver::ResolutionStatus::Success, false)); + DnsResolver::ResolutionStatus::Completed, false)); dispatcher_->run(Event::Dispatcher::RunType::Block); } @@ -520,7 +526,7 @@ TEST_F(AppleDnsImplTest, LocalResolution) { resolver_->resolve("0.0.0.0", DnsLookupFamily::Auto, [](DnsResolver::ResolutionStatus status, absl::string_view, std::list&& results) -> void { - EXPECT_EQ(DnsResolver::ResolutionStatus::Success, status); + EXPECT_EQ(DnsResolver::ResolutionStatus::Completed, status); EXPECT_EQ(1, results.size()); EXPECT_EQ("0.0.0.0:0", results.front().addrInfo().address_->asString()); EXPECT_EQ(std::chrono::seconds(60), results.front().addrInfo().ttl_); @@ -644,7 +650,7 @@ class AppleDnsImplFakeApiTest : public testing::Test { [&dns_callback_executed, dns_lookup_family, address_type, expected_address_size](DnsResolver::ResolutionStatus status, absl::string_view, std::list&& response) -> void { - EXPECT_EQ(DnsResolver::ResolutionStatus::Success, status); + EXPECT_EQ(DnsResolver::ResolutionStatus::Completed, status); EXPECT_EQ(expected_address_size, response.size()); if (dns_lookup_family == DnsLookupFamily::Auto) { @@ -757,7 +763,7 @@ TEST_F(AppleDnsImplFakeApiTest, ErrorInSocketAccess) { hostname, Network::DnsLookupFamily::Auto, [&dns_callback_executed](DnsResolver::ResolutionStatus status, absl::string_view, std::list&& response) -> void { - // Status is success because it isn't possible to attach a file event + // Status is Completed because it isn't possible to attach a file event // error to a specific query. EXPECT_EQ(DnsResolver::ResolutionStatus::Failure, status); EXPECT_EQ(0, response.size()); @@ -898,7 +904,7 @@ TEST_F(AppleDnsImplFakeApiTest, QuerySynchronousCompletionUnroutableFamilies) { hostname, Network::DnsLookupFamily::Auto, [&dns_callback_executed](DnsResolver::ResolutionStatus status, absl::string_view, std::list&& response) -> void { - EXPECT_EQ(DnsResolver::ResolutionStatus::Success, status); + EXPECT_EQ(DnsResolver::ResolutionStatus::Completed, status); EXPECT_EQ(1, response.size()); EXPECT_EQ("1.2.3.4:0", response.front().addrInfo().address_->asString()); EXPECT_EQ(std::chrono::seconds(30), response.front().addrInfo().ttl_); @@ -937,7 +943,7 @@ TEST_F(AppleDnsImplFakeApiTest, QuerySynchronousCompletion) { hostname, Network::DnsLookupFamily::Auto, [&dns_callback_executed](DnsResolver::ResolutionStatus status, absl::string_view, std::list&& response) -> void { - EXPECT_EQ(DnsResolver::ResolutionStatus::Success, status); + EXPECT_EQ(DnsResolver::ResolutionStatus::Completed, status); EXPECT_EQ(1, response.size()); EXPECT_EQ("1.2.3.4:0", response.front().addrInfo().address_->asString()); EXPECT_EQ(std::chrono::seconds(30), response.front().addrInfo().ttl_); @@ -993,7 +999,7 @@ TEST_F(AppleDnsImplFakeApiTest, MultipleAddresses) { hostname, Network::DnsLookupFamily::Auto, [&dns_callback_executed](DnsResolver::ResolutionStatus status, absl::string_view, std::list&& response) -> void { - EXPECT_EQ(DnsResolver::ResolutionStatus::Success, status); + EXPECT_EQ(DnsResolver::ResolutionStatus::Completed, status); EXPECT_EQ(2, response.size()); dns_callback_executed.Notify(); }); @@ -1124,7 +1130,7 @@ TEST_F(AppleDnsImplFakeApiTest, MultipleQueries) { hostname, Network::DnsLookupFamily::Auto, [&dns_callback_executed](DnsResolver::ResolutionStatus status, absl::string_view, std::list&& response) -> void { - EXPECT_EQ(DnsResolver::ResolutionStatus::Success, status); + EXPECT_EQ(DnsResolver::ResolutionStatus::Completed, status); EXPECT_EQ(1, response.size()); EXPECT_EQ("1.2.3.4:0", response.front().addrInfo().address_->asString()); EXPECT_EQ(std::chrono::seconds(30), response.front().addrInfo().ttl_); @@ -1145,7 +1151,7 @@ TEST_F(AppleDnsImplFakeApiTest, MultipleQueries) { hostname2, Network::DnsLookupFamily::V4Only, [&dns_callback_executed2](DnsResolver::ResolutionStatus status, absl::string_view, std::list&& response) -> void { - EXPECT_EQ(DnsResolver::ResolutionStatus::Success, status); + EXPECT_EQ(DnsResolver::ResolutionStatus::Completed, status); EXPECT_EQ(1, response.size()); EXPECT_EQ("5.6.7.8:0", response.front().addrInfo().address_->asString()); EXPECT_EQ(std::chrono::seconds(30), response.front().addrInfo().ttl_); @@ -1199,7 +1205,7 @@ TEST_F(AppleDnsImplFakeApiTest, MultipleQueriesOneFails) { std::list&& response) -> void { // Even though the second query will fail, this one will flush with the // state it had. - EXPECT_EQ(DnsResolver::ResolutionStatus::Success, status); + EXPECT_EQ(DnsResolver::ResolutionStatus::Completed, status); EXPECT_EQ(1, response.size()); EXPECT_EQ("1.2.3.4:0", response.front().addrInfo().address_->asString()); EXPECT_EQ(std::chrono::seconds(30), response.front().addrInfo().ttl_); @@ -1261,7 +1267,7 @@ TEST_F(AppleDnsImplFakeApiTest, ResultWithOnlyNonAdditiveReplies) { hostname, Network::DnsLookupFamily::Auto, [&dns_callback_executed](DnsResolver::ResolutionStatus status, absl::string_view, std::list&& response) -> void { - EXPECT_EQ(DnsResolver::ResolutionStatus::Success, status); + EXPECT_EQ(DnsResolver::ResolutionStatus::Completed, status); EXPECT_TRUE(response.empty()); dns_callback_executed.Notify(); }); @@ -1338,7 +1344,7 @@ TEST_F(AppleDnsImplFakeApiTest, DeallocateOnDestruction) { hostname, Network::DnsLookupFamily::Auto, [&dns_callback_executed](DnsResolver::ResolutionStatus status, absl::string_view, std::list&& response) -> void { - EXPECT_EQ(DnsResolver::ResolutionStatus::Success, status); + EXPECT_EQ(DnsResolver::ResolutionStatus::Completed, status); EXPECT_EQ(1, response.size()); dns_callback_executed.Notify(); }); diff --git a/test/extensions/network/dns_resolver/cares/dns_impl_test.cc b/test/extensions/network/dns_resolver/cares/dns_impl_test.cc index b57c5e4a80..44353d23af 100644 --- a/test/extensions/network/dns_resolver/cares/dns_impl_test.cc +++ b/test/extensions/network/dns_resolver/cares/dns_impl_test.cc @@ -841,7 +841,7 @@ class DnsImplTest : public testing::TestWithParam { return resolver_->resolve(address, lookup_family, [=, this](DnsResolver::ResolutionStatus status, absl::string_view, std::list&& results) -> void { - EXPECT_EQ(DnsResolver::ResolutionStatus::Success, status); + EXPECT_EQ(DnsResolver::ResolutionStatus::Completed, status); std::list address_as_string_list = getAddressAsStringList(results); EXPECT_EQ(0, address_as_string_list.size()); @@ -879,7 +879,7 @@ class DnsImplTest : public testing::TestWithParam { const DnsLookupFamily lookup_family, const std::list& expected_addresses, const DnsResolver::ResolutionStatus resolution_status = - DnsResolver::ResolutionStatus::Success, + DnsResolver::ResolutionStatus::Completed, const bool getifaddrs_supported = true, const bool getifaddrs_success = true) { server_->addHosts("some.good.domain", {"201.134.56.7"}, RecordType::A); @@ -1036,7 +1036,7 @@ TEST_P(DnsImplTest, LocalLookup) { if (GetParam() == Address::IpVersion::v4) { EXPECT_EQ(nullptr, resolveWithExpectations("localhost", DnsLookupFamily::V4Only, - DnsResolver::ResolutionStatus::Success, + DnsResolver::ResolutionStatus::Completed, {"127.0.0.1"}, {"::1"}, absl::nullopt)); } @@ -1045,12 +1045,12 @@ TEST_P(DnsImplTest, LocalLookup) { "Synchronous DNS IPv6 localhost resolution failed. Please verify localhost resolves to ::1 " "in /etc/hosts, since this misconfiguration is a common cause of these failures."; EXPECT_EQ(nullptr, resolveWithExpectations("localhost", DnsLookupFamily::V6Only, - DnsResolver::ResolutionStatus::Success, {"::1"}, + DnsResolver::ResolutionStatus::Completed, {"::1"}, {"127.0.0.1"}, absl::nullopt)) << error_msg; EXPECT_EQ(nullptr, resolveWithExpectations("localhost", DnsLookupFamily::Auto, - DnsResolver::ResolutionStatus::Success, {"::1"}, + DnsResolver::ResolutionStatus::Completed, {"::1"}, {"127.0.0.1"}, absl::nullopt)) << error_msg; } @@ -1059,14 +1059,14 @@ TEST_P(DnsImplTest, LocalLookup) { TEST_P(DnsImplTest, DnsIpAddressVersion) { server_->addHosts("some.good.domain", {"1.2.3.4"}, RecordType::A); EXPECT_NE(nullptr, resolveWithExpectations("some.good.domain", DnsLookupFamily::Auto, - DnsResolver::ResolutionStatus::Success, {"1.2.3.4"}, + DnsResolver::ResolutionStatus::Completed, {"1.2.3.4"}, {}, absl::nullopt)); dispatcher_->run(Event::Dispatcher::RunType::Block); checkStats(2 /*resolve_total*/, 0 /*pending_resolutions*/, 1 /*not_found*/, 0 /*get_addr_failure*/, 0 /*timeouts*/); EXPECT_NE(nullptr, resolveWithExpectations("some.good.domain", DnsLookupFamily::V4Only, - DnsResolver::ResolutionStatus::Success, {"1.2.3.4"}, + DnsResolver::ResolutionStatus::Completed, {"1.2.3.4"}, {}, absl::nullopt)); dispatcher_->run(Event::Dispatcher::RunType::Block); checkStats(3 /*resolve_total*/, 0 /*pending_resolutions*/, 1 /*not_found*/, @@ -1081,7 +1081,7 @@ TEST_P(DnsImplTest, DnsIpAddressVersion) { TEST_P(DnsImplTest, DnsIpAddressVersionV6) { server_->addHosts("some.good.domain", {"1::2"}, RecordType::AAAA); EXPECT_NE(nullptr, resolveWithExpectations("some.good.domain", DnsLookupFamily::Auto, - DnsResolver::ResolutionStatus::Success, {"1::2"}, {}, + DnsResolver::ResolutionStatus::Completed, {"1::2"}, {}, absl::nullopt)); dispatcher_->run(Event::Dispatcher::RunType::Block); checkStats(1 /*resolve_total*/, 0 /*pending_resolutions*/, 0 /*not_found*/, @@ -1093,7 +1093,7 @@ TEST_P(DnsImplTest, DnsIpAddressVersionV6) { 0 /*get_addr_failure*/, 0 /*timeouts*/); EXPECT_NE(nullptr, resolveWithExpectations("some.good.domain", DnsLookupFamily::V6Only, - DnsResolver::ResolutionStatus::Success, {"1::2"}, {}, + DnsResolver::ResolutionStatus::Completed, {"1::2"}, {}, absl::nullopt)); dispatcher_->run(Event::Dispatcher::RunType::Block); checkStats(3 /*resolve_total*/, 0 /*pending_resolutions*/, 1 /*not_found*/, @@ -1124,7 +1124,7 @@ TEST_P(DnsImplTest, DestroyChannelOnResetNetworking) { ASSERT_FALSE(peer_->isChannelDirty()); server_->addHosts("some.good.domain", {"201.134.56.7"}, RecordType::A); EXPECT_NE(nullptr, resolveWithExpectations("some.good.domain", DnsLookupFamily::Auto, - DnsResolver::ResolutionStatus::Success, + DnsResolver::ResolutionStatus::Completed, {"201.134.56.7"}, {}, absl::nullopt)); dispatcher_->run(Event::Dispatcher::RunType::Block); checkStats(2 /*resolve_total*/, 0 /*pending_resolutions*/, 1 /*not_found*/, @@ -1135,7 +1135,7 @@ TEST_P(DnsImplTest, DestroyChannelOnResetNetworking) { resetChannel(); EXPECT_NE(nullptr, resolveWithExpectations("some.good.domain", DnsLookupFamily::Auto, - DnsResolver::ResolutionStatus::Success, + DnsResolver::ResolutionStatus::Completed, {"201.134.56.7"}, {}, absl::nullopt)); dispatcher_->run(Event::Dispatcher::RunType::Block); checkStats(4 /*resolve_total*/, 0 /*pending_resolutions*/, 2 /*not_found*/, @@ -1184,7 +1184,7 @@ TEST_P(DnsImplTest, DestroyChannelOnRefused) { 1 /*get_addr_failure*/, 0 /*timeouts*/); EXPECT_NE(nullptr, resolveWithExpectations("some.good.domain", DnsLookupFamily::Auto, - DnsResolver::ResolutionStatus::Success, + DnsResolver::ResolutionStatus::Completed, {"201.134.56.7"}, {}, absl::nullopt)); dispatcher_->run(Event::Dispatcher::RunType::Block); EXPECT_FALSE(peer_->isChannelDirty()); @@ -1192,7 +1192,7 @@ TEST_P(DnsImplTest, DestroyChannelOnRefused) { 1 /*get_addr_failure*/, 0 /*timeouts*/); } -// Validate success/fail lookup behavior via TestDnsServer. This exercises the +// Validate completed/fail lookup behavior via TestDnsServer. This exercises the // network event handling in DnsResolverImpl. TEST_P(DnsImplTest, RemoteAsyncLookup) { server_->addHosts("some.good.domain", {"201.134.56.7"}, RecordType::A); @@ -1203,7 +1203,7 @@ TEST_P(DnsImplTest, RemoteAsyncLookup) { 0 /*get_addr_failure*/, 0 /*timeouts*/); EXPECT_NE(nullptr, resolveWithExpectations("some.good.domain", DnsLookupFamily::Auto, - DnsResolver::ResolutionStatus::Success, + DnsResolver::ResolutionStatus::Completed, {"201.134.56.7"}, {}, absl::nullopt)); dispatcher_->run(Event::Dispatcher::RunType::Block); checkStats(4 /*resolve_total*/, 0 /*pending_resolutions*/, 3 /*not_found*/, @@ -1216,7 +1216,7 @@ TEST_P(DnsImplTest, MultiARecordLookup) { EXPECT_NE(nullptr, resolveWithExpectations("some.good.domain", DnsLookupFamily::Auto, - DnsResolver::ResolutionStatus::Success, + DnsResolver::ResolutionStatus::Completed, {"201.134.56.7", "123.4.5.6", "6.5.4.3"}, {}, absl::nullopt)); dispatcher_->run(Event::Dispatcher::RunType::Block); checkStats(2 /*resolve_total*/, 0 /*pending_resolutions*/, 1 /*not_found*/, @@ -1230,7 +1230,7 @@ TEST_P(DnsImplTest, CNameARecordLookupV4) { server_->setCnameTtl(std::chrono::seconds(60)); EXPECT_NE(nullptr, resolveWithExpectations("root.cnam.domain", DnsLookupFamily::V4Only, - DnsResolver::ResolutionStatus::Success, + DnsResolver::ResolutionStatus::Completed, {"201.134.56.7"}, {}, std::chrono::seconds(60))); dispatcher_->run(Event::Dispatcher::RunType::Block); checkStats(1 /*resolve_total*/, 0 /*pending_resolutions*/, 0 /*not_found*/, @@ -1244,7 +1244,7 @@ TEST_P(DnsImplTest, CNameARecordLookupWithV6) { server_->setCnameTtl(std::chrono::seconds(60)); EXPECT_NE(nullptr, resolveWithExpectations("root.cnam.domain", DnsLookupFamily::Auto, - DnsResolver::ResolutionStatus::Success, + DnsResolver::ResolutionStatus::Completed, {"201.134.56.7"}, {}, std::chrono::seconds(60))); dispatcher_->run(Event::Dispatcher::RunType::Block); checkStats(2 /*resolve_total*/, 0 /*pending_resolutions*/, 1 /*not_found*/, @@ -1261,7 +1261,7 @@ TEST_P(DnsImplTest, CNameARecordLookupV4InvalidTTL) { server_->setCnameTtl(std::chrono::seconds(60)); EXPECT_NE(nullptr, resolveWithExpectations("root.cnam.domain", DnsLookupFamily::V4Only, - DnsResolver::ResolutionStatus::Success, + DnsResolver::ResolutionStatus::Completed, {"201.134.56.7"}, {}, std::chrono::seconds(0))); dispatcher_->run(Event::Dispatcher::RunType::Block); @@ -1270,7 +1270,7 @@ TEST_P(DnsImplTest, CNameARecordLookupV4InvalidTTL) { server_->setCnameTtl(std::chrono::seconds(2147483648)); EXPECT_NE(nullptr, resolveWithExpectations("root.cnam.domain", DnsLookupFamily::V4Only, - DnsResolver::ResolutionStatus::Success, + DnsResolver::ResolutionStatus::Completed, {"201.134.56.7"}, {}, std::chrono::seconds(0))); dispatcher_->run(Event::Dispatcher::RunType::Block); @@ -1280,7 +1280,7 @@ TEST_P(DnsImplTest, CNameARecordLookupV4InvalidTTL) { EXPECT_NE(nullptr, resolveWithExpectations("root.cnam.domain", DnsLookupFamily::V4Only, - DnsResolver::ResolutionStatus::Success, {"201.134.56.7"}, {}, + DnsResolver::ResolutionStatus::Completed, {"201.134.56.7"}, {}, std::chrono::seconds(2147483647))); dispatcher_->run(Event::Dispatcher::RunType::Block); checkStats(3 /*resolve_total*/, 0 /*pending_resolutions*/, 0 /*not_found*/, @@ -1293,21 +1293,21 @@ TEST_P(DnsImplTest, MultiARecordLookupWithV6) { EXPECT_NE(nullptr, resolveWithExpectations("some.good.domain", DnsLookupFamily::V4Only, - DnsResolver::ResolutionStatus::Success, + DnsResolver::ResolutionStatus::Completed, {"201.134.56.7", "123.4.5.6", "6.5.4.3"}, {}, absl::nullopt)); dispatcher_->run(Event::Dispatcher::RunType::Block); checkStats(1 /*resolve_total*/, 0 /*pending_resolutions*/, 0 /*not_found*/, 0 /*get_addr_failure*/, 0 /*timeouts*/); EXPECT_NE(nullptr, resolveWithExpectations("some.good.domain", DnsLookupFamily::Auto, - DnsResolver::ResolutionStatus::Success, + DnsResolver::ResolutionStatus::Completed, {{"1::2", "1::2:3", "1::2:3:4"}}, {}, absl::nullopt)); dispatcher_->run(Event::Dispatcher::RunType::Block); checkStats(2 /*resolve_total*/, 0 /*pending_resolutions*/, 0 /*not_found*/, 0 /*get_addr_failure*/, 0 /*timeouts*/); EXPECT_NE(nullptr, resolveWithExpectations("some.good.domain", DnsLookupFamily::V6Only, - DnsResolver::ResolutionStatus::Success, + DnsResolver::ResolutionStatus::Completed, {{"1::2", "1::2:3", "1::2:3:4"}}, {}, absl::nullopt)); dispatcher_->run(Event::Dispatcher::RunType::Block); checkStats(3 /*resolve_total*/, 0 /*pending_resolutions*/, 0 /*not_found*/, @@ -1319,8 +1319,8 @@ TEST_P(DnsImplTest, AutoOnlyV6IfBothV6andV4) { server_->addHosts("some.good.domain", {"1::2"}, RecordType::AAAA); EXPECT_NE(nullptr, resolveWithExpectations("some.good.domain", DnsLookupFamily::Auto, - DnsResolver::ResolutionStatus::Success, {{"1::2"}}, {}, - absl::nullopt)); + DnsResolver::ResolutionStatus::Completed, {{"1::2"}}, + {}, absl::nullopt)); dispatcher_->run(Event::Dispatcher::RunType::Block); checkStats(1 /*resolve_total*/, 0 /*pending_resolutions*/, 0 /*not_found*/, 0 /*get_addr_failure*/, 0 /*timeouts*/); @@ -1330,8 +1330,8 @@ TEST_P(DnsImplTest, AutoV6IfOnlyV6) { server_->addHosts("some.good.domain", {"1::2"}, RecordType::AAAA); EXPECT_NE(nullptr, resolveWithExpectations("some.good.domain", DnsLookupFamily::Auto, - DnsResolver::ResolutionStatus::Success, {{"1::2"}}, {}, - absl::nullopt)); + DnsResolver::ResolutionStatus::Completed, {{"1::2"}}, + {}, absl::nullopt)); dispatcher_->run(Event::Dispatcher::RunType::Block); checkStats(1 /*resolve_total*/, 0 /*pending_resolutions*/, 0 /*not_found*/, 0 /*get_addr_failure*/, 0 /*timeouts*/); @@ -1340,7 +1340,7 @@ TEST_P(DnsImplTest, AutoV6IfOnlyV6) { TEST_P(DnsImplTest, AutoV4IfOnlyV4) { server_->addHosts("some.good.domain", {"201.134.56.7"}, RecordType::A); EXPECT_NE(nullptr, resolveWithExpectations("some.good.domain", DnsLookupFamily::Auto, - DnsResolver::ResolutionStatus::Success, + DnsResolver::ResolutionStatus::Completed, {{"201.134.56.7"}}, {}, absl::nullopt)); dispatcher_->run(Event::Dispatcher::RunType::Block); checkStats(2 /*resolve_total*/, 0 /*pending_resolutions*/, 1 /*not_found*/, @@ -1352,7 +1352,7 @@ TEST_P(DnsImplTest, V4PreferredOnlyV4IfBothV6andV4) { server_->addHosts("some.good.domain", {"1::2"}, RecordType::AAAA); EXPECT_NE(nullptr, resolveWithExpectations("some.good.domain", DnsLookupFamily::V4Preferred, - DnsResolver::ResolutionStatus::Success, + DnsResolver::ResolutionStatus::Completed, {{"201.134.56.7"}}, {}, absl::nullopt)); dispatcher_->run(Event::Dispatcher::RunType::Block); checkStats(1 /*resolve_total*/, 0 /*pending_resolutions*/, 0 /*not_found*/, @@ -1363,8 +1363,8 @@ TEST_P(DnsImplTest, V4PreferredV6IfOnlyV6) { server_->addHosts("some.good.domain", {"1::2"}, RecordType::AAAA); EXPECT_NE(nullptr, resolveWithExpectations("some.good.domain", DnsLookupFamily::V4Preferred, - DnsResolver::ResolutionStatus::Success, {{"1::2"}}, {}, - absl::nullopt)); + DnsResolver::ResolutionStatus::Completed, {{"1::2"}}, + {}, absl::nullopt)); dispatcher_->run(Event::Dispatcher::RunType::Block); checkStats(2 /*resolve_total*/, 0 /*pending_resolutions*/, 1 /*not_found*/, 0 /*get_addr_failure*/, 0 /*timeouts*/); @@ -1373,7 +1373,7 @@ TEST_P(DnsImplTest, V4PreferredV6IfOnlyV6) { TEST_P(DnsImplTest, V4PreferredV4IfOnlyV4) { server_->addHosts("some.good.domain", {"201.134.56.7"}, RecordType::A); EXPECT_NE(nullptr, resolveWithExpectations("some.good.domain", DnsLookupFamily::V4Preferred, - DnsResolver::ResolutionStatus::Success, + DnsResolver::ResolutionStatus::Completed, {{"201.134.56.7"}}, {}, absl::nullopt)); dispatcher_->run(Event::Dispatcher::RunType::Block); checkStats(1 /*resolve_total*/, 0 /*pending_resolutions*/, 0 /*not_found*/, @@ -1385,7 +1385,7 @@ TEST_P(DnsImplTest, AllIfBothV6andV4) { server_->addHosts("some.good.domain", {"1::2"}, RecordType::AAAA); EXPECT_NE(nullptr, resolveWithExpectations("some.good.domain", DnsLookupFamily::All, - DnsResolver::ResolutionStatus::Success, + DnsResolver::ResolutionStatus::Completed, {{"201.134.56.7"}, {"1::2"}}, {}, absl::nullopt)); dispatcher_->run(Event::Dispatcher::RunType::Block); checkStats(1 /*resolve_total*/, 0 /*pending_resolutions*/, 0 /*not_found*/, @@ -1396,8 +1396,8 @@ TEST_P(DnsImplTest, AllV6IfOnlyV6) { server_->addHosts("some.good.domain", {"1::2"}, RecordType::AAAA); EXPECT_NE(nullptr, resolveWithExpectations("some.good.domain", DnsLookupFamily::All, - DnsResolver::ResolutionStatus::Success, {{"1::2"}}, {}, - absl::nullopt)); + DnsResolver::ResolutionStatus::Completed, {{"1::2"}}, + {}, absl::nullopt)); dispatcher_->run(Event::Dispatcher::RunType::Block); checkStats(1 /*resolve_total*/, 0 /*pending_resolutions*/, 0 /*not_found*/, 0 /*get_addr_failure*/, 0 /*timeouts*/); @@ -1406,7 +1406,7 @@ TEST_P(DnsImplTest, AllV6IfOnlyV6) { TEST_P(DnsImplTest, AllV4IfOnlyV4) { server_->addHosts("some.good.domain", {"201.134.56.7"}, RecordType::A); EXPECT_NE(nullptr, resolveWithExpectations("some.good.domain", DnsLookupFamily::All, - DnsResolver::ResolutionStatus::Success, + DnsResolver::ResolutionStatus::Completed, {{"201.134.56.7"}}, {}, absl::nullopt)); dispatcher_->run(Event::Dispatcher::RunType::Block); checkStats(1 /*resolve_total*/, 0 /*pending_resolutions*/, 0 /*not_found*/, @@ -1421,7 +1421,7 @@ TEST_P(DnsImplTest, Cancel) { resolveWithUnreferencedParameters("some.domain", DnsLookupFamily::Auto, false); EXPECT_NE(nullptr, resolveWithExpectations("some.good.domain", DnsLookupFamily::Auto, - DnsResolver::ResolutionStatus::Success, + DnsResolver::ResolutionStatus::Completed, {"201.134.56.7"}, {}, absl::nullopt)); ASSERT_NE(nullptr, query); @@ -1442,7 +1442,7 @@ TEST_P(DnsImplTest, RecordTtlLookup) { uint64_t resolve_total = 0; if (GetParam() == Address::IpVersion::v4) { EXPECT_EQ(nullptr, resolveWithExpectations("localhost", DnsLookupFamily::V4Only, - DnsResolver::ResolutionStatus::Success, + DnsResolver::ResolutionStatus::Completed, {"127.0.0.1"}, {}, std::chrono::seconds(0))); dispatcher_->run(Event::Dispatcher::RunType::Block); checkStats(1 /*resolve_total*/, 0 /*pending_resolutions*/, 0 /*not_found*/, @@ -1452,16 +1452,16 @@ TEST_P(DnsImplTest, RecordTtlLookup) { if (GetParam() == Address::IpVersion::v6) { EXPECT_EQ(nullptr, resolveWithExpectations("localhost", DnsLookupFamily::V6Only, - DnsResolver::ResolutionStatus::Success, {"::1"}, {}, - std::chrono::seconds(0))); + DnsResolver::ResolutionStatus::Completed, {"::1"}, + {}, std::chrono::seconds(0))); dispatcher_->run(Event::Dispatcher::RunType::Block); checkStats(resolve_total + 1 /*resolve_total*/, 0 /*pending_resolutions*/, 0 /*not_found*/, 0 /*get_addr_failure*/, 0 /*timeouts*/); resolve_total++; EXPECT_EQ(nullptr, resolveWithExpectations("localhost", DnsLookupFamily::Auto, - DnsResolver::ResolutionStatus::Success, {"::1"}, {}, - std::chrono::seconds(0))); + DnsResolver::ResolutionStatus::Completed, {"::1"}, + {}, std::chrono::seconds(0))); dispatcher_->run(Event::Dispatcher::RunType::Block); checkStats(resolve_total + 1 /*resolve_total*/, 0 /*pending_resolutions*/, 0 /*not_found*/, 0 /*get_addr_failure*/, 0 /*timeouts*/); @@ -1474,7 +1474,7 @@ TEST_P(DnsImplTest, RecordTtlLookup) { EXPECT_NE(nullptr, resolveWithExpectations("some.good.domain", DnsLookupFamily::V4Only, - DnsResolver::ResolutionStatus::Success, + DnsResolver::ResolutionStatus::Completed, {"201.134.56.7", "123.4.5.6", "6.5.4.3"}, {"1::2", "1::2:3", "1::2:3:4"}, std::chrono::seconds(300))); dispatcher_->run(Event::Dispatcher::RunType::Block); @@ -1484,7 +1484,7 @@ TEST_P(DnsImplTest, RecordTtlLookup) { EXPECT_NE(nullptr, resolveWithExpectations( "some.good.domain", DnsLookupFamily::Auto, - DnsResolver::ResolutionStatus::Success, {"1::2", "1::2:3", "1::2:3:4"}, + DnsResolver::ResolutionStatus::Completed, {"1::2", "1::2:3", "1::2:3:4"}, {"201.134.56.7", "123.4.5.6", "6.5.4.3"}, std::chrono::seconds(300))); dispatcher_->run(Event::Dispatcher::RunType::Block); checkStats(resolve_total + 1 /*resolve_total*/, 0 /*pending_resolutions*/, 0 /*not_found*/, @@ -1493,7 +1493,7 @@ TEST_P(DnsImplTest, RecordTtlLookup) { EXPECT_NE(nullptr, resolveWithExpectations( "some.good.domain", DnsLookupFamily::V6Only, - DnsResolver::ResolutionStatus::Success, {"1::2", "1::2:3", "1::2:3:4"}, + DnsResolver::ResolutionStatus::Completed, {"1::2", "1::2:3", "1::2:3:4"}, {"201.134.56.7", "123.4.5.6", "6.5.4.3"}, std::chrono::seconds(300))); dispatcher_->run(Event::Dispatcher::RunType::Block); checkStats(resolve_total + 1 /*resolve_total*/, 0 /*pending_resolutions*/, 0 /*not_found*/, @@ -1538,7 +1538,7 @@ TEST_P(DnsImplTest, PendingTimerEnable) { TEST_P(DnsImplTest, PendingResolutions) { server_->addHosts("some.good.domain", {"201.134.56.7"}, RecordType::A); EXPECT_NE(nullptr, resolveWithExpectations("some.good.domain", DnsLookupFamily::V4Only, - DnsResolver::ResolutionStatus::Success, + DnsResolver::ResolutionStatus::Completed, {{"201.134.56.7"}}, {}, absl::nullopt)); checkStats(0 /*resolve_total*/, 1 /*pending_resolutions*/, 0 /*not_found*/, @@ -1579,7 +1579,7 @@ TEST_P(DnsImplTest, WithNoRecord) { TEST_P(DnsImplTest, WithARecord) { server_->addHosts("some.good.domain", {"201.134.56.7"}, RecordType::A); EXPECT_NE(nullptr, resolveWithExpectations("some.good.domain", DnsLookupFamily::V4Only, - DnsResolver::ResolutionStatus::Success, + DnsResolver::ResolutionStatus::Completed, {"201.134.56.7"}, {}, absl::nullopt)); dispatcher_->run(Event::Dispatcher::RunType::Block); checkStats(1 /*resolve_total*/, 0 /*pending_resolutions*/, 0 /*not_found*/, @@ -1591,21 +1591,21 @@ TEST_P(DnsImplTest, WithARecord) { 0 /*get_addr_failure*/, 0 /*timeouts*/); EXPECT_NE(nullptr, resolveWithExpectations("some.good.domain", DnsLookupFamily::Auto, - DnsResolver::ResolutionStatus::Success, + DnsResolver::ResolutionStatus::Completed, {"201.134.56.7"}, {}, absl::nullopt)); dispatcher_->run(Event::Dispatcher::RunType::Block); checkStats(4 /*resolve_total*/, 0 /*pending_resolutions*/, 2 /*not_found*/, 0 /*get_addr_failure*/, 0 /*timeouts*/); EXPECT_NE(nullptr, resolveWithExpectations("some.good.domain", DnsLookupFamily::V4Preferred, - DnsResolver::ResolutionStatus::Success, + DnsResolver::ResolutionStatus::Completed, {"201.134.56.7"}, {}, absl::nullopt)); dispatcher_->run(Event::Dispatcher::RunType::Block); checkStats(5 /*resolve_total*/, 0 /*pending_resolutions*/, 2 /*not_found*/, 0 /*get_addr_failure*/, 0 /*timeouts*/); EXPECT_NE(nullptr, resolveWithExpectations("some.good.domain", DnsLookupFamily::All, - DnsResolver::ResolutionStatus::Success, + DnsResolver::ResolutionStatus::Completed, {"201.134.56.7"}, {}, absl::nullopt)); dispatcher_->run(Event::Dispatcher::RunType::Block); checkStats(6 /*resolve_total*/, 0 /*pending_resolutions*/, 2 /*not_found*/, @@ -1620,28 +1620,28 @@ TEST_P(DnsImplTest, WithAAAARecord) { 0 /*get_addr_failure*/, 0 /*timeouts*/); EXPECT_NE(nullptr, resolveWithExpectations("some.good.domain", DnsLookupFamily::V6Only, - DnsResolver::ResolutionStatus::Success, {"1::2"}, {}, + DnsResolver::ResolutionStatus::Completed, {"1::2"}, {}, absl::nullopt)); dispatcher_->run(Event::Dispatcher::RunType::Block); checkStats(2 /*resolve_total*/, 0 /*pending_resolutions*/, 1 /*not_found*/, 0 /*get_addr_failure*/, 0 /*timeouts*/); EXPECT_NE(nullptr, resolveWithExpectations("some.good.domain", DnsLookupFamily::Auto, - DnsResolver::ResolutionStatus::Success, {"1::2"}, {}, + DnsResolver::ResolutionStatus::Completed, {"1::2"}, {}, absl::nullopt)); dispatcher_->run(Event::Dispatcher::RunType::Block); checkStats(3 /*resolve_total*/, 0 /*pending_resolutions*/, 1 /*not_found*/, 0 /*get_addr_failure*/, 0 /*timeouts*/); EXPECT_NE(nullptr, resolveWithExpectations("some.good.domain", DnsLookupFamily::V4Preferred, - DnsResolver::ResolutionStatus::Success, {"1::2"}, {}, + DnsResolver::ResolutionStatus::Completed, {"1::2"}, {}, absl::nullopt)); dispatcher_->run(Event::Dispatcher::RunType::Block); checkStats(5 /*resolve_total*/, 0 /*pending_resolutions*/, 2 /*not_found*/, 0 /*get_addr_failure*/, 0 /*timeouts*/); EXPECT_NE(nullptr, resolveWithExpectations("some.good.domain", DnsLookupFamily::All, - DnsResolver::ResolutionStatus::Success, {"1::2"}, {}, + DnsResolver::ResolutionStatus::Completed, {"1::2"}, {}, absl::nullopt)); dispatcher_->run(Event::Dispatcher::RunType::Block); checkStats(6 /*resolve_total*/, 0 /*pending_resolutions*/, 2 /*not_found*/, @@ -1652,35 +1652,35 @@ TEST_P(DnsImplTest, WithBothAAndAAAARecord) { server_->addHosts("some.good.domain", {"201.134.56.7"}, RecordType::A); server_->addHosts("some.good.domain", {"1::2"}, RecordType::AAAA); EXPECT_NE(nullptr, resolveWithExpectations("some.good.domain", DnsLookupFamily::V4Only, - DnsResolver::ResolutionStatus::Success, + DnsResolver::ResolutionStatus::Completed, {"201.134.56.7"}, {}, absl::nullopt)); dispatcher_->run(Event::Dispatcher::RunType::Block); checkStats(1 /*resolve_total*/, 0 /*pending_resolutions*/, 0 /*not_found*/, 0 /*get_addr_failure*/, 0 /*timeouts*/); EXPECT_NE(nullptr, resolveWithExpectations("some.good.domain", DnsLookupFamily::V6Only, - DnsResolver::ResolutionStatus::Success, {"1::2"}, {}, + DnsResolver::ResolutionStatus::Completed, {"1::2"}, {}, absl::nullopt)); dispatcher_->run(Event::Dispatcher::RunType::Block); checkStats(2 /*resolve_total*/, 0 /*pending_resolutions*/, 0 /*not_found*/, 0 /*get_addr_failure*/, 0 /*timeouts*/); EXPECT_NE(nullptr, resolveWithExpectations("some.good.domain", DnsLookupFamily::Auto, - DnsResolver::ResolutionStatus::Success, {"1::2"}, {}, + DnsResolver::ResolutionStatus::Completed, {"1::2"}, {}, absl::nullopt)); dispatcher_->run(Event::Dispatcher::RunType::Block); checkStats(3 /*resolve_total*/, 0 /*pending_resolutions*/, 0 /*not_found*/, 0 /*get_addr_failure*/, 0 /*timeouts*/); EXPECT_NE(nullptr, resolveWithExpectations("some.good.domain", DnsLookupFamily::V4Preferred, - DnsResolver::ResolutionStatus::Success, + DnsResolver::ResolutionStatus::Completed, {"201.134.56.7"}, {}, absl::nullopt)); dispatcher_->run(Event::Dispatcher::RunType::Block); checkStats(4 /*resolve_total*/, 0 /*pending_resolutions*/, 0 /*not_found*/, 0 /*get_addr_failure*/, 0 /*timeouts*/); EXPECT_NE(nullptr, resolveWithExpectations("some.good.domain", DnsLookupFamily::All, - DnsResolver::ResolutionStatus::Success, + DnsResolver::ResolutionStatus::Completed, {"201.134.56.7", "1::2"}, {}, absl::nullopt)); dispatcher_->run(Event::Dispatcher::RunType::Block); checkStats(5 /*resolve_total*/, 0 /*pending_resolutions*/, 0 /*not_found*/, @@ -1872,14 +1872,14 @@ TEST_P(DnsImplFilterUnroutableFamiliesTest, FilterAllV6) { TEST_P(DnsImplFilterUnroutableFamiliesTest, DontFilterIfGetifaddrsIsNotSupported) { testFilterAddresses({}, DnsLookupFamily::All, {"201.134.56.7", "1::2"}, - DnsResolver::ResolutionStatus::Success, false /* getifaddrs_supported */); + DnsResolver::ResolutionStatus::Completed, false /* getifaddrs_supported */); checkStats(1 /*resolve_total*/, 0 /*pending_resolutions*/, 0 /*not_found*/, 0 /*get_addr_failure*/, 0 /*timeouts*/); } TEST_P(DnsImplFilterUnroutableFamiliesTest, DontFilterIfThereIsAGetifaddrsFailure) { testFilterAddresses({}, DnsLookupFamily::All, {"201.134.56.7", "1::2"}, - DnsResolver::ResolutionStatus::Success, true /* getifaddrs_supported */, + DnsResolver::ResolutionStatus::Completed, true /* getifaddrs_supported */, false /* getifaddrs_success */); checkStats(1 /*resolve_total*/, 0 /*pending_resolutions*/, 0 /*not_found*/, 0 /*get_addr_failure*/, 0 /*timeouts*/); @@ -2099,7 +2099,7 @@ TEST_P(DnsImplCustomResolverTest, CustomResolverValidAfterChannelDestruction) { // server's address was passed as a custom resolver on construction, the new channel should still // point to the test dns server, and the query should succeed. EXPECT_NE(nullptr, resolveWithExpectations("some.good.domain", DnsLookupFamily::Auto, - DnsResolver::ResolutionStatus::Success, + DnsResolver::ResolutionStatus::Completed, {"201.134.56.7"}, {}, absl::nullopt)); dispatcher_->run(Event::Dispatcher::RunType::Block); EXPECT_FALSE(peer_->isChannelDirty()); diff --git a/test/extensions/network/dns_resolver/getaddrinfo/getaddrinfo_test.cc b/test/extensions/network/dns_resolver/getaddrinfo/getaddrinfo_test.cc index 932fc270bd..b2a830cd21 100644 --- a/test/extensions/network/dns_resolver/getaddrinfo/getaddrinfo_test.cc +++ b/test/extensions/network/dns_resolver/getaddrinfo/getaddrinfo_test.cc @@ -93,7 +93,7 @@ class GetAddrInfoDnsImplTest : public testing::Test { std::list&& response) { // Since we use AF_UNSPEC, depending on the CI environment we might get either 1 or 2 // addresses. - EXPECT_EQ(status, DnsResolver::ResolutionStatus::Success); + EXPECT_EQ(status, DnsResolver::ResolutionStatus::Completed); EXPECT_TRUE(response.size() == 1 || response.size() == 2); EXPECT_TRUE("127.0.0.1:0" == response.front().addrInfo().address_->asString() || "[::1]:0" == response.front().addrInfo().address_->asString()); @@ -166,7 +166,7 @@ TEST_F(GetAddrInfoDnsImplTest, NoData) { resolver_->resolve("localhost", DnsLookupFamily::All, [this](DnsResolver::ResolutionStatus status, absl::string_view, std::list&& response) { - EXPECT_EQ(status, DnsResolver::ResolutionStatus::Success); + EXPECT_EQ(status, DnsResolver::ResolutionStatus::Completed); EXPECT_TRUE(response.empty()); dispatcher_->exit(); @@ -183,7 +183,7 @@ TEST_F(GetAddrInfoDnsImplTest, NoName) { resolver_->resolve("localhost", DnsLookupFamily::All, [this](DnsResolver::ResolutionStatus status, absl::string_view, std::list&& response) { - EXPECT_EQ(status, DnsResolver::ResolutionStatus::Success); + EXPECT_EQ(status, DnsResolver::ResolutionStatus::Completed); EXPECT_TRUE(response.empty()); dispatcher_->exit(); @@ -203,7 +203,7 @@ TEST_F(GetAddrInfoDnsImplTest, TryAgainIndefinitelyAndSuccess) { resolver_->resolve("localhost", DnsLookupFamily::All, [this](DnsResolver::ResolutionStatus status, absl::string_view, std::list&& response) { - EXPECT_EQ(status, DnsResolver::ResolutionStatus::Success); + EXPECT_EQ(status, DnsResolver::ResolutionStatus::Completed); EXPECT_TRUE(response.empty()); dispatcher_->exit(); @@ -247,7 +247,7 @@ TEST_F(GetAddrInfoDnsImplTest, TryAgainWithNumRetriesAndSuccess) { resolver_->resolve("localhost", DnsLookupFamily::All, [this](DnsResolver::ResolutionStatus status, absl::string_view, std::list&& response) { - EXPECT_EQ(status, DnsResolver::ResolutionStatus::Success); + EXPECT_EQ(status, DnsResolver::ResolutionStatus::Completed); EXPECT_TRUE(response.empty()); dispatcher_->exit(); @@ -293,7 +293,7 @@ TEST_F(GetAddrInfoDnsImplTest, All) { "localhost", DnsLookupFamily::All, [this](DnsResolver::ResolutionStatus status, absl::string_view, std::list&& response) { - EXPECT_EQ(status, DnsResolver::ResolutionStatus::Success); + EXPECT_EQ(status, DnsResolver::ResolutionStatus::Completed); EXPECT_EQ(2, response.size()); EXPECT_EQ("[[::1]:0, 127.0.0.1:0]", accumulateToString(response, [](const auto& dns_response) { @@ -317,7 +317,7 @@ TEST_F(GetAddrInfoDnsImplTest, V4Only) { "localhost", DnsLookupFamily::V4Only, [this](DnsResolver::ResolutionStatus status, absl::string_view, std::list&& response) { - EXPECT_EQ(status, DnsResolver::ResolutionStatus::Success); + EXPECT_EQ(status, DnsResolver::ResolutionStatus::Completed); EXPECT_EQ(1, response.size()); EXPECT_EQ("[127.0.0.1:0]", accumulateToString(response, [](const auto& dns_response) { @@ -341,7 +341,7 @@ TEST_F(GetAddrInfoDnsImplTest, V6Only) { "localhost", DnsLookupFamily::V6Only, [this](DnsResolver::ResolutionStatus status, absl::string_view, std::list&& response) { - EXPECT_EQ(status, DnsResolver::ResolutionStatus::Success); + EXPECT_EQ(status, DnsResolver::ResolutionStatus::Completed); EXPECT_EQ(1, response.size()); EXPECT_EQ("[[::1]:0]", accumulateToString(response, [](const auto& dns_response) { @@ -365,7 +365,7 @@ TEST_F(GetAddrInfoDnsImplTest, V4Preferred) { "localhost", DnsLookupFamily::V4Preferred, [this](DnsResolver::ResolutionStatus status, absl::string_view, std::list&& response) { - EXPECT_EQ(status, DnsResolver::ResolutionStatus::Success); + EXPECT_EQ(status, DnsResolver::ResolutionStatus::Completed); EXPECT_EQ(1, response.size()); EXPECT_EQ("[127.0.0.1:0]", accumulateToString(response, [](const auto& dns_response) { @@ -389,7 +389,7 @@ TEST_F(GetAddrInfoDnsImplTest, V4PreferredNoV4) { "localhost", DnsLookupFamily::V4Preferred, [this](DnsResolver::ResolutionStatus status, absl::string_view, std::list&& response) { - EXPECT_EQ(status, DnsResolver::ResolutionStatus::Success); + EXPECT_EQ(status, DnsResolver::ResolutionStatus::Completed); EXPECT_EQ(1, response.size()); EXPECT_EQ("[[::1]:0]", accumulateToString(response, [](const auto& dns_response) { @@ -413,7 +413,7 @@ TEST_F(GetAddrInfoDnsImplTest, Auto) { "localhost", DnsLookupFamily::Auto, [this](DnsResolver::ResolutionStatus status, absl::string_view, std::list&& response) { - EXPECT_EQ(status, DnsResolver::ResolutionStatus::Success); + EXPECT_EQ(status, DnsResolver::ResolutionStatus::Completed); EXPECT_EQ(1, response.size()); EXPECT_EQ("[[::1]:0]", accumulateToString(response, [](const auto& dns_response) { @@ -437,7 +437,7 @@ TEST_F(GetAddrInfoDnsImplTest, AutoNoV6) { "localhost", DnsLookupFamily::Auto, [this](DnsResolver::ResolutionStatus status, absl::string_view, std::list&& response) { - EXPECT_EQ(status, DnsResolver::ResolutionStatus::Success); + EXPECT_EQ(status, DnsResolver::ResolutionStatus::Completed); EXPECT_EQ(1, response.size()); EXPECT_EQ("[127.0.0.1:0]", accumulateToString(response, [](const auto& dns_response) { From bf6012177c4b54d31f40f8edeaed72957c8dfd33 Mon Sep 17 00:00:00 2001 From: Raven Black Date: Thu, 19 Sep 2024 10:39:52 -0400 Subject: [PATCH 21/65] MockDispatcher to not accidentally run on other threads (#36134) Commit Message: MockDispatcher to not accidentally run on other threads Additional Description: Several issues have been found recently where the MockDispatcher's default behavior of just running the callback immediately causes tests to pass, but asan/tsan/release tests fail, because it ends up running the callback on a different thread, exactly the opposite of almost the whole point of posting things on a dispatcher which is to put them on a specific thread. This change makes MockDispatcher insist on being on whichever thread created the dispatcher, most likely the main thread in tests. This is still not great because the behavior of running the callback immediately is still quite different from the behavior of a dispatcher in production, e.g. ``` auto x = std::make_shared(0); this_thread_dispatcher.post([x]() { *x += 5; }); *x += 1; std::cerr << *x << std::endl; ``` would always output 6 with a default MockDispatcher, and would always output 1 with a production dispatcher, but at least cases like that can be debugged linearly and will be the same in all test environments, versus the running on a different (and incorrect) thread problem is very difficult to debug and sometimes only shows up (and sometimes flakily) in the harder to run test contexts. (But still pretty bad in that test coverage would say a thing works, then in production it could do a different thing than it did in tests.) Since it's a mock the behavior can also be manually overridden to be the old way. Arguably it should have just always required explicit manual interception because it's supposed to be a mock not a fake. Risk Level: Should be safe since it's test-only. Testing: This is test-only. Docs Changes: n/a Release Notes: n/a Platform Specific Features: n/a --------- Signed-off-by: Raven Black --- test/common/thread_local/thread_local_impl_test.cc | 4 +++- .../common/redis/cluster_refresh_manager_test.cc | 14 +++++++++++--- test/mocks/event/mocks.cc | 13 +++++++++++-- 3 files changed, 25 insertions(+), 6 deletions(-) diff --git a/test/common/thread_local/thread_local_impl_test.cc b/test/common/thread_local/thread_local_impl_test.cc index 4ae9409fa4..fe95397605 100644 --- a/test/common/thread_local/thread_local_impl_test.cc +++ b/test/common/thread_local/thread_local_impl_test.cc @@ -378,7 +378,9 @@ TEST(ThreadLocalInstanceImplDispatcherTest, DestroySlotOnWorker) { EXPECT_CALL(main_dispatcher, isThreadSafe()).WillOnce(Return(false)); // Destroy the slot on worker thread and expect the post() of main dispatcher to be called. - EXPECT_CALL(main_dispatcher, post(_)); + // Override the behavior to do nothing, because the default mock behavior asserts that the + // callback must run on the same thread as the dispatcher. + EXPECT_CALL(main_dispatcher, post(_)).WillOnce([]() {}); slot.reset(); diff --git a/test/extensions/common/redis/cluster_refresh_manager_test.cc b/test/extensions/common/redis/cluster_refresh_manager_test.cc index e54c77037d..f834d6fc4a 100644 --- a/test/extensions/common/redis/cluster_refresh_manager_test.cc +++ b/test/extensions/common/redis/cluster_refresh_manager_test.cc @@ -25,11 +25,11 @@ namespace Common { namespace Redis { // TODO: rewrite the tests to fix the flaky test -class ClusterRefreshManagerTest : public testing::Test { +class ClusterRefreshManagerTest : public testing::Test, public Event::TestUsingSimulatedTime { public: ClusterRefreshManagerTest() : cluster_name_("fake_cluster"), refresh_manager_(std::make_shared( - dispatcher_, cm_, time_system_)) { + *dispatcher_, cm_, time_system_)) { time_system_.setMonotonicTime(std::chrono::seconds(1)); cluster_maps_.active_clusters_.emplace("fake_cluster", mock_cluster_); ON_CALL(cm_, clusters()).WillByDefault(Return(cluster_maps_)); @@ -100,7 +100,8 @@ class ClusterRefreshManagerTest : public testing::Test { } const std::string cluster_name_; - NiceMock dispatcher_; + Api::ApiPtr api_ = Api::createApiForTest(); + Event::DispatcherPtr dispatcher_ = api_->allocateDispatcher("test_thread"); NiceMock cm_; Upstream::ClusterManager::ClusterInfoMaps cluster_maps_; Upstream::MockClusterMockPrioritySet mock_cluster_; @@ -142,6 +143,7 @@ TEST_F(ClusterRefreshManagerTest, Basic) { advanceTime(MonotonicTime(std::chrono::seconds(3)), 2); thread_1->join(); thread_2->join(); + dispatcher_->run(Event::Dispatcher::RunType::Block); EXPECT_GE(callback_count_, 2); EXPECT_EQ(cluster_info->redirects_count_, 0); @@ -187,6 +189,7 @@ TEST_F(ClusterRefreshManagerTest, BasicFailureEvents) { thread_1->join(); thread_2->join(); + dispatcher_->run(Event::Dispatcher::RunType::Block); EXPECT_GE(callback_count_, 2); EXPECT_EQ(cluster_info->failures_count_, 0); EXPECT_EQ(cluster_info->last_callback_time_ms_.load(), 3000); @@ -197,6 +200,7 @@ TEST_F(ClusterRefreshManagerTest, BasicFailureEvents) { callback_count_ = 0; advanceTime(MonotonicTime(std::chrono::seconds(5))); + dispatcher_->run(Event::Dispatcher::RunType::Block); EXPECT_FALSE(refresh_manager_->onFailure("unregistered_cluster_name")); EXPECT_EQ(callback_count_, 0); @@ -231,6 +235,7 @@ TEST_F(ClusterRefreshManagerTest, BasicDegradedEvents) { thread_1->join(); thread_2->join(); + dispatcher_->run(Event::Dispatcher::RunType::Block); EXPECT_GE(callback_count_, 2); EXPECT_EQ(cluster_info->host_degraded_count_, 0); EXPECT_EQ(cluster_info->last_callback_time_ms_.load(), 3000); @@ -241,6 +246,7 @@ TEST_F(ClusterRefreshManagerTest, BasicDegradedEvents) { callback_count_ = 0; advanceTime(MonotonicTime(std::chrono::seconds(5))); + dispatcher_->run(Event::Dispatcher::RunType::Block); EXPECT_FALSE(refresh_manager_->onHostDegraded("unregistered_cluster_name")); EXPECT_EQ(callback_count_, 0); @@ -290,6 +296,7 @@ TEST_F(ClusterRefreshManagerTest, HighVolume) { thread_1->join(); thread_2->join(); + dispatcher_->run(Event::Dispatcher::RunType::Block); EXPECT_EQ(callback_count_, thread1_callback_count + thread2_callback_count); EXPECT_EQ(callback_count_, 30); } @@ -305,6 +312,7 @@ TEST_F(ClusterRefreshManagerTest, FeatureDisabled) { EXPECT_FALSE(refresh_manager_->onFailure(cluster_name_)); EXPECT_FALSE(refresh_manager_->onHostDegraded(cluster_name_)); + dispatcher_->run(Event::Dispatcher::RunType::Block); EXPECT_GE(callback_count_, 0); EXPECT_EQ(cluster_info->redirects_count_, 0); EXPECT_EQ(cluster_info->failures_count_, 0); diff --git a/test/mocks/event/mocks.cc b/test/mocks/event/mocks.cc index e6a0b436f6..5a557332e3 100644 --- a/test/mocks/event/mocks.cc +++ b/test/mocks/event/mocks.cc @@ -20,6 +20,8 @@ MockDispatcher::MockDispatcher() : MockDispatcher("test_thread") {} MockDispatcher::MockDispatcher(const std::string& name) : name_(name) { time_system_ = std::make_unique(); + auto thread_factory = &Api::createApiForTest()->threadFactory(); + Envoy::Thread::ThreadId thread_id = thread_factory->currentThreadId(); ON_CALL(*this, initializeStats(_, _)).WillByDefault(Return()); ON_CALL(*this, clearDeferredDeleteList()).WillByDefault(Invoke([this]() -> void { to_delete_.clear(); @@ -28,14 +30,21 @@ MockDispatcher::MockDispatcher(const std::string& name) : name_(name) { ON_CALL(*this, createScaledTimer_(_, _)).WillByDefault(ReturnNew>()); ON_CALL(*this, createScaledTypedTimer_(_, _)) .WillByDefault(ReturnNew>()); - ON_CALL(*this, post(_)).WillByDefault(Invoke([](PostCb cb) -> void { cb(); })); + ON_CALL(*this, post(_)).WillByDefault([thread_factory, thread_id](PostCb cb) -> void { + ASSERT(thread_factory->currentThreadId() == thread_id, + "MockDispatcher tried to execute a callback on a different thread - a test with threads " + "should probably use a dispatcher from Api::createApiForTest() instead."); + cb(); + }); ON_CALL(buffer_factory_, createBuffer_(_, _, _)) .WillByDefault(Invoke([](std::function below_low, std::function above_high, std::function above_overflow) -> Buffer::Instance* { return new Buffer::WatermarkBuffer(below_low, above_high, above_overflow); })); - ON_CALL(*this, isThreadSafe()).WillByDefault(Return(true)); + ON_CALL(*this, isThreadSafe()).WillByDefault([thread_factory, thread_id]() { + return thread_factory->currentThreadId() == thread_id; + }); } MockDispatcher::~MockDispatcher() = default; From 4cbb5806a37e3ed5ea126faaa09d3636fdffc64d Mon Sep 17 00:00:00 2001 From: botengyao Date: Thu, 19 Sep 2024 10:44:16 -0400 Subject: [PATCH 22/65] sec-release: update the Q3 actual security release date (#35909) Signed-off-by: Boteng Yao --- RELEASES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RELEASES.md b/RELEASES.md index 258aa17c14..1435704556 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -138,6 +138,6 @@ Security releases are published on a 3-monthly cycle, around the mid point betwe | Quarter | Expected | Actual | Difference | |:-------:|:----------:|:----------:|:----------:| | 2024 Q2 | 2024/06/04 | 2024/06/04 | 0 days | -| 2024 Q3 | 2024/09/03 | +| 2024 Q3 | 2024/09/03 | 2024/09/19 | 16 days | NOTE: Zero-day vulnerabilities, and upstream vulnerabilities disclosed to us under embargo, may necessitate an emergency release with little or no warning. From f3ff3306f53fc0ebb6314ffad947896b56b23d29 Mon Sep 17 00:00:00 2001 From: Chao-Han Tsai Date: Thu, 19 Sep 2024 10:03:32 -0700 Subject: [PATCH 23/65] basic_auth: support authorization header override (#36046) Commit Message: basic_auth: support authorization header override Additional Description: provide a way to do basic authorization on headers other than `:Authorization`. Say we are doing two level of basic authorization. One at the proxy level with header name `Proxy-Authorization` and the other one at the application level with header name `Authorization`. Risk Level: low Testing: unit test Docs Changes: changelog Release Notes: Platform Specific Features: [Optional Runtime guard:] [Optional Fixes #Issue] [Optional Fixes commit #PR or SHA] [Optional Deprecated:] [Optional [API Considerations](https://github.com/envoyproxy/envoy/blob/main/api/review_checklist.md):] --------- Signed-off-by: Networking team Co-authored-by: Networking team --- .../http/basic_auth/v3/basic_auth.proto | 6 +++++ changelogs/current.yaml | 5 +++++ .../http/basic_auth/basic_auth_filter.cc | 11 +++++++++- .../http/basic_auth/basic_auth_filter.h | 5 ++++- .../filters/http/basic_auth/config.cc | 3 ++- .../filters/http/basic_auth/filter_test.cc | 22 ++++++++++++++++++- 6 files changed, 48 insertions(+), 4 deletions(-) diff --git a/api/envoy/extensions/filters/http/basic_auth/v3/basic_auth.proto b/api/envoy/extensions/filters/http/basic_auth/v3/basic_auth.proto index 995d2c3bca..af3c442c03 100644 --- a/api/envoy/extensions/filters/http/basic_auth/v3/basic_auth.proto +++ b/api/envoy/extensions/filters/http/basic_auth/v3/basic_auth.proto @@ -41,6 +41,12 @@ message BasicAuth { // If it is not specified, the username will not be forwarded. string forward_username_header = 2 [(validate.rules).string = {well_known_regex: HTTP_HEADER_NAME strict: false}]; + + // This field specifies the request header to load the basic credential from. + // + // If it is not specified, the filter loads the credential from the "Authorization" header. + string authentication_header = 3 + [(validate.rules).string = {well_known_regex: HTTP_HEADER_NAME strict: false}]; } // Extra settings that may be added to per-route configuration for diff --git a/changelogs/current.yaml b/changelogs/current.yaml index bfc2be2fc5..e17a1dd935 100644 --- a/changelogs/current.yaml +++ b/changelogs/current.yaml @@ -353,5 +353,10 @@ new_features: change: | Added two new methods ``oidsPeerCertificate()`` and ``oidsLocalCertificate()`` to SSL connection object API :ref:`SSL connection info object `. +- area: basic_auth + change: | + Added support to provide an override + :ref:`authentication_header ` + to load Basic Auth credential. deprecated: diff --git a/source/extensions/filters/http/basic_auth/basic_auth_filter.cc b/source/extensions/filters/http/basic_auth/basic_auth_filter.cc index fdb3465064..df7929f42b 100644 --- a/source/extensions/filters/http/basic_auth/basic_auth_filter.cc +++ b/source/extensions/filters/http/basic_auth/basic_auth_filter.cc @@ -2,6 +2,8 @@ #include +#include "envoy/http/header_map.h" + #include "source/common/common/base64.h" #include "source/common/http/header_utility.h" #include "source/common/http/headers.h" @@ -29,8 +31,10 @@ std::string computeSHA1(absl::string_view password) { } // namespace FilterConfig::FilterConfig(UserMap&& users, const std::string& forward_username_header, + const std::string& authentication_header, const std::string& stats_prefix, Stats::Scope& scope) : users_(std::move(users)), forward_username_header_(forward_username_header), + authentication_header_(Http::LowerCaseString(authentication_header)), stats_(generateStats(stats_prefix + "basic_auth.", scope)) {} BasicAuthFilter::BasicAuthFilter(FilterConfigConstSharedPtr config) : config_(std::move(config)) {} @@ -43,7 +47,12 @@ Http::FilterHeadersStatus BasicAuthFilter::decodeHeaders(Http::RequestHeaderMap& users = &route_specific_settings->users(); } - auto auth_header = headers.get(Http::CustomHeaders::get().Authorization); + Http::HeaderMap::GetResult auth_header; + if (!config_->authenticationHeader().get().empty()) { + auth_header = headers.get(config_->authenticationHeader()); + } else { + auth_header = headers.get(Http::CustomHeaders::get().Authorization); + } if (auth_header.empty()) { return onDenied("User authentication failed. Missing username and password.", diff --git a/source/extensions/filters/http/basic_auth/basic_auth_filter.h b/source/extensions/filters/http/basic_auth/basic_auth_filter.h index 4d1c9a8621..d257450416 100644 --- a/source/extensions/filters/http/basic_auth/basic_auth_filter.h +++ b/source/extensions/filters/http/basic_auth/basic_auth_filter.h @@ -45,10 +45,12 @@ using UserMap = absl::flat_hash_map; class FilterConfig { public: FilterConfig(UserMap&& users, const std::string& forward_username_header, - const std::string& stats_prefix, Stats::Scope& scope); + const std::string& authentication_header, const std::string& stats_prefix, + Stats::Scope& scope); const BasicAuthStats& stats() const { return stats_; } const std::string& forwardUsernameHeader() const { return forward_username_header_; } const UserMap& users() const { return users_; } + const Http::LowerCaseString& authenticationHeader() const { return authentication_header_; } private: static BasicAuthStats generateStats(const std::string& prefix, Stats::Scope& scope) { @@ -57,6 +59,7 @@ class FilterConfig { const UserMap users_; const std::string forward_username_header_; + const Http::LowerCaseString authentication_header_; BasicAuthStats stats_; }; using FilterConfigConstSharedPtr = std::shared_ptr; diff --git a/source/extensions/filters/http/basic_auth/config.cc b/source/extensions/filters/http/basic_auth/config.cc index 20e66b767a..828899b71c 100644 --- a/source/extensions/filters/http/basic_auth/config.cc +++ b/source/extensions/filters/http/basic_auth/config.cc @@ -68,7 +68,8 @@ Http::FilterFactoryCb BasicAuthFilterFactory::createFilterFactoryFromProtoTyped( Config::DataSource::read(proto_config.users(), false, context.serverFactoryContext().api()), std::string)); FilterConfigConstSharedPtr config = std::make_unique( - std::move(users), proto_config.forward_username_header(), stats_prefix, context.scope()); + std::move(users), proto_config.forward_username_header(), + proto_config.authentication_header(), stats_prefix, context.scope()); return [config](Http::FilterChainFactoryCallbacks& callbacks) -> void { callbacks.addStreamDecoderFilter(std::make_shared(config)); }; diff --git a/test/extensions/filters/http/basic_auth/filter_test.cc b/test/extensions/filters/http/basic_auth/filter_test.cc index 87296f0eef..aeeb1a9909 100644 --- a/test/extensions/filters/http/basic_auth/filter_test.cc +++ b/test/extensions/filters/http/basic_auth/filter_test.cc @@ -18,7 +18,7 @@ class FilterTest : public testing::Test { UserMap users; users.insert({"user1", {"user1", "tESsBmE/yNY3lb6a0L6vVQEZNqw="}}); // user1:test1 users.insert({"user2", {"user2", "EJ9LPFDXsN9ynSmbxvjp75Bmlx8="}}); // user2:test2 - config_ = std::make_unique(std::move(users), "x-username", "stats", + config_ = std::make_unique(std::move(users), "x-username", "", "stats", *stats_.rootScope()); filter_ = std::make_shared(config_); filter_->setDecoderFilterCallbacks(decoder_filter_callbacks_); @@ -272,6 +272,26 @@ TEST_F(FilterTest, BasicAuthPerRouteEnabled) { filter_->decodeHeaders(invalid_credentials, true)); } +TEST_F(FilterTest, OverrideAuthorizationHeaderProvided) { + UserMap users; + users.insert({"user1", {"user1", "tESsBmE/yNY3lb6a0L6vVQEZNqw="}}); // user1:test1 + + FilterConfigConstSharedPtr config = std::make_unique( + std::move(users), "x-username", "x-authorization-override", "stats", *stats_.rootScope()); + std::shared_ptr filter = std::make_shared(config); + filter->setDecoderFilterCallbacks(decoder_filter_callbacks_); + + Http::TestRequestHeaderMapImpl request_headers_user1{ + {"x-authorization-override", "Basic dXNlcjE6dGVzdDE="}}; + request_headers_user1.setScheme("http"); + request_headers_user1.setHost("host"); + request_headers_user1.setPath("/"); + + EXPECT_EQ(Http::FilterHeadersStatus::Continue, + filter->decodeHeaders(request_headers_user1, true)); + EXPECT_EQ("user1", request_headers_user1.get_("x-username")); +} + } // namespace BasicAuth } // namespace HttpFilters } // namespace Extensions From 5550967f21ffc621609a573a085ffb97311332b7 Mon Sep 17 00:00:00 2001 From: Kuat Yessenov Date: Tue, 9 Jul 2024 18:37:25 +0000 Subject: [PATCH 24/65] jwt: fix clear route cache with remote JWKs Change-Id: If54c7143ecb1bf936e88fbb3371d9c47f6d8f671 Signed-off-by: Kuat Yessenov Signed-off-by: Ryan Northey --- changelogs/current.yaml | 5 ++ .../filters/http/jwt_authn/authenticator.cc | 10 ++-- .../http/jwt_authn/filter_integration_test.cc | 51 +++++++++++++++++-- 3 files changed, 56 insertions(+), 10 deletions(-) diff --git a/changelogs/current.yaml b/changelogs/current.yaml index e17a1dd935..3f59975758 100644 --- a/changelogs/current.yaml +++ b/changelogs/current.yaml @@ -143,6 +143,11 @@ bug_fixes: Fixed an inconsistency in how boolean values are loaded in RTDS, where they were previously converted to "1"/"0" instead of "true"/"false". The correct string representation ("true"/"false") will now be used. This change can be reverted by setting the runtime guard ``envoy.reloadable_features.boolean_to_string_fix`` to false. +- area: jwt + change: | + Fixed a bug where using ``clear_route_cache`` with remote JWKs works + incorrectly and may cause a crash when the modified request does not match + any route. removed_config_or_runtime: # *Normally occurs at the end of the* :ref:`deprecation period ` diff --git a/source/extensions/filters/http/jwt_authn/authenticator.cc b/source/extensions/filters/http/jwt_authn/authenticator.cc index 62e175651c..cecbc2c0b0 100644 --- a/source/extensions/filters/http/jwt_authn/authenticator.cc +++ b/source/extensions/filters/http/jwt_authn/authenticator.cc @@ -480,6 +480,11 @@ void AuthenticatorImpl::doneWithStatus(const Status& status) { // Unless allowing failed or missing, all tokens must be verified successfully. if ((Status::Ok != status && !is_allow_failed_ && !is_allow_missing_) || tokens_.empty()) { tokens_.clear(); + if (clear_route_cache_ && clear_route_cb_) { + clear_route_cb_(); + } + clear_route_cb_ = nullptr; + if (is_allow_failed_) { callback_(Status::Ok); } else if (is_allow_missing_ && status == Status::JwtMissed) { @@ -489,11 +494,6 @@ void AuthenticatorImpl::doneWithStatus(const Status& status) { } callback_ = nullptr; - if (clear_route_cache_ && clear_route_cb_) { - clear_route_cb_(); - } - clear_route_cb_ = nullptr; - return; } diff --git a/test/extensions/filters/http/jwt_authn/filter_integration_test.cc b/test/extensions/filters/http/jwt_authn/filter_integration_test.cc index 94f2dff75b..1203f4c008 100644 --- a/test/extensions/filters/http/jwt_authn/filter_integration_test.cc +++ b/test/extensions/filters/http/jwt_authn/filter_integration_test.cc @@ -20,7 +20,7 @@ namespace JwtAuthn { namespace { std::string getAuthFilterConfig(const std::string& config_str, bool use_local_jwks, - bool strip_failure_response) { + bool strip_failure_response, bool clear_route_cache = false) { JwtAuthentication proto_config; TestUtility::loadFromYaml(config_str, proto_config); proto_config.set_strip_failure_response(strip_failure_response); @@ -32,6 +32,11 @@ std::string getAuthFilterConfig(const std::string& config_str, bool use_local_jw local_jwks->set_inline_string(PublicKey); } + if (clear_route_cache) { + auto& provider0 = (*proto_config.mutable_providers())[std::string(ProviderName)]; + provider0.set_clear_route_cache(true); + } + HttpFilter filter; filter.set_name("envoy.filters.http.jwt_authn"); filter.mutable_typed_config()->PackFrom(proto_config); @@ -57,8 +62,10 @@ std::string getAsyncFetchFilterConfig(const std::string& config_str, bool fast_l return MessageUtil::getJsonStringFromMessageOrError(filter); } -std::string getFilterConfig(bool use_local_jwks, bool strip_failure_response) { - return getAuthFilterConfig(ExampleConfig, use_local_jwks, strip_failure_response); +std::string getFilterConfig(bool use_local_jwks, bool strip_failure_response, + bool clear_route_cache = false) { + return getAuthFilterConfig(ExampleConfig, use_local_jwks, strip_failure_response, + clear_route_cache); } class LocalJwksIntegrationTest : public HttpProtocolIntegrationTest {}; @@ -378,8 +385,8 @@ class RemoteJwksIntegrationTest : public HttpProtocolIntegrationTest { addFakeUpstream(GetParam().upstream_protocol); } - void initializeFilter(bool add_cluster) { - config_helper_.prependFilter(getFilterConfig(false, false)); + void initializeFilter(bool add_cluster, bool clear_route_cache = false) { + config_helper_.prependFilter(getFilterConfig(false, false, clear_route_cache)); if (add_cluster) { config_helper_.addConfigModifier([](envoy::config::bootstrap::v3::Bootstrap& bootstrap) { @@ -390,6 +397,17 @@ class RemoteJwksIntegrationTest : public HttpProtocolIntegrationTest { } else { config_helper_.skipPortUsageValidation(); } + if (clear_route_cache) { + config_helper_.addConfigModifier( + [](envoy::extensions::filters::network::http_connection_manager::v3:: + HttpConnectionManager& hcm) { + auto* virtual_host = hcm.mutable_route_config()->mutable_virtual_hosts(0); + auto* route = virtual_host->mutable_routes(0); + auto* header = route->mutable_match()->add_headers(); + header->set_name("x-jwt-claim-sub"); + header->mutable_string_match()->set_exact("test"); + }); + } initialize(); } @@ -481,6 +499,29 @@ TEST_P(RemoteJwksIntegrationTest, WithGoodToken) { cleanup(); } +TEST_P(RemoteJwksIntegrationTest, WithGoodTokenClearRouteCache) { + initializeFilter(/*add_cluster=*/true, true); + + codec_client_ = makeHttpConnection(lookupPort("http")); + + auto response = codec_client_->makeHeaderOnlyRequest(Http::TestRequestHeaderMapImpl{ + {":method", "GET"}, + {":path", "/"}, + {":scheme", "http"}, + {":authority", "host"}, + {"x-jwt-claim-sub", "test"}, + {"Authorization", "Bearer " + std::string(GoodToken)}, + }); + + waitForJwksResponse("200", PublicKey); + + ASSERT_TRUE(response->waitForEndStream()); + ASSERT_TRUE(response->complete()); + EXPECT_EQ("404", response->headers().getStatusValue()); + + cleanup(); +} + // With remote Jwks, this test verifies a request is rejected even with a good Jwt token // when the remote jwks server replied with 500. TEST_P(RemoteJwksIntegrationTest, FetchFailedJwks) { From 0ee424bb06bbeb97549788946f392f9110ac1e33 Mon Sep 17 00:00:00 2001 From: Alyssa Wilk Date: Thu, 8 Aug 2024 20:00:11 +0000 Subject: [PATCH 25/65] internal_address_config: change the default to be more secure for service mesh environments Signed-off-by: Alyssa Wilk Signed-off-by: Boteng Yao Signed-off-by: Ryan Northey --- .../v3/http_connection_manager.proto | 28 +++++++++++++ changelogs/current.yaml | 8 ++++ source/common/http/conn_manager_config.h | 4 ++ source/common/runtime/runtime_features.cc | 2 + .../network/http_connection_manager/config.cc | 4 ++ .../http_connection_manager/config_test.cc | 41 +++++++++++++++++++ test/integration/http_integration.cc | 15 +++++++ test/mocks/http/mocks.h | 9 +++- 8 files changed, 110 insertions(+), 1 deletion(-) diff --git a/api/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.proto b/api/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.proto index 712512ddb0..4cbbbc20d3 100644 --- a/api/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.proto +++ b/api/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.proto @@ -684,6 +684,34 @@ message HttpConnectionManager { // purposes. If unspecified, only RFC1918 IP addresses will be considered internal. // See the documentation for :ref:`config_http_conn_man_headers_x-envoy-internal` for more // information about internal/external addresses. + // + // .. warning:: + // In the next release, no IP addresses will be considered trusted. If you have tooling such as probes + // on your private network which need to be treated as trusted (e.g. changing arbitrary x-envoy headers) + // you will have to manually include those addresses or CIDR ranges like: + // + // .. validated-code-block:: yaml + // :type-name: envoy.extensions.filters.network.http_connection_manager.v3.InternalAddressConfig + // + // cidr_ranges: + // address_prefix: 10.0.0.0 + // prefix_len: 8 + // cidr_ranges: + // address_prefix: 192.168.0.0 + // prefix_len: 16 + // cidr_ranges: + // address_prefix: 172.16.0.0 + // prefix_len: 12 + // cidr_ranges: + // address_prefix: 127.0.0.1 + // prefix_len: 32 + // cidr_ranges: + // address_prefix: fd00:: + // prefix_len: 8 + // cidr_ranges: + // address_prefix: ::1 + // prefix_len: 128 + // InternalAddressConfig internal_address_config = 25; // If set, Envoy will not append the remote address to the diff --git a/changelogs/current.yaml b/changelogs/current.yaml index 3f59975758..6d520b8b17 100644 --- a/changelogs/current.yaml +++ b/changelogs/current.yaml @@ -39,6 +39,14 @@ behavior_changes: change: | Added new tag extraction so that scoped rds stats have their :ref:'scope_route_config_name ' and stat prefix extracted. +- area: http + change: | + The default configuration of Envoy will continue to trust internal addresses while in the future it will not trust them by default. + If you have tooling such as probes on your private network which need to be treated as trusted (e.g. changing arbitrary ``x-envoy`` + headers) please explictily include those addresses or CIDR ranges into :ref:`internal_address_config + ` + See the config examples from the above ``internal_address_config`` link. This default no trust internal address can be turned on by + setting runtime guard ``envoy.reloadable_features.explicit_internal_address_config`` to ``true``. minor_behavior_changes: # *Changes that may cause incompatibilities for some users, but should not for most* diff --git a/source/common/http/conn_manager_config.h b/source/common/http/conn_manager_config.h index 7a2b300b83..629eee958d 100644 --- a/source/common/http/conn_manager_config.h +++ b/source/common/http/conn_manager_config.h @@ -191,6 +191,10 @@ class InternalAddressConfig { class DefaultInternalAddressConfig : public Http::InternalAddressConfig { public: bool isInternalAddress(const Network::Address::Instance& address) const override { + if (Runtime::runtimeFeatureEnabled( + "envoy.reloadable_features.explicit_internal_address_config")) { + return false; + } return Network::Utility::isInternalAddress(address); } }; diff --git a/source/common/runtime/runtime_features.cc b/source/common/runtime/runtime_features.cc index ac6d760161..0464f76248 100644 --- a/source/common/runtime/runtime_features.cc +++ b/source/common/runtime/runtime_features.cc @@ -152,6 +152,8 @@ FALSE_RUNTIME_GUARD(envoy_restart_features_xds_failover_support); FALSE_RUNTIME_GUARD(envoy_reloadable_features_dns_cache_set_ip_version_to_remove); // TODO(alyssawilk): evaluate and make this a config knob or remove. FALSE_RUNTIME_GUARD(envoy_reloadable_features_reset_brokenness_on_nework_change); +// TODO(botengyao): this will be default true in the next release after this warning release. +FALSE_RUNTIME_GUARD(envoy_reloadable_features_explicit_internal_address_config); // A flag to set the maximum TLS version for google_grpc client to TLS1.2, when needed for // compliance restrictions. diff --git a/source/extensions/filters/network/http_connection_manager/config.cc b/source/extensions/filters/network/http_connection_manager/config.cc index a8a036a70a..563ece44c9 100644 --- a/source/extensions/filters/network/http_connection_manager/config.cc +++ b/source/extensions/filters/network/http_connection_manager/config.cc @@ -77,6 +77,10 @@ std::unique_ptr createInternalAddressConfig( return std::make_unique(config.internal_address_config(), creation_status); } + ENVOY_LOG_ONCE_MISC(warn, + "internal_address_config is not configured. The existing default behaviour " + "will trust RFC1918 IP addresses, but this will be changed in next release. " + "Please explictily config internal address config as the migration step."); return std::make_unique(); } diff --git a/test/extensions/filters/network/http_connection_manager/config_test.cc b/test/extensions/filters/network/http_connection_manager/config_test.cc index 23964105ce..5f39f9935a 100644 --- a/test/extensions/filters/network/http_connection_manager/config_test.cc +++ b/test/extensions/filters/network/http_connection_manager/config_test.cc @@ -708,6 +708,47 @@ TEST_F(HttpConnectionManagerConfigTest, UnixSocketInternalAddress) { EXPECT_FALSE(config.internalAddressConfig().isInternalAddress(externalIpAddress)); } +TEST_F(HttpConnectionManagerConfigTest, FutureDefaultInternalAddress) { + TestScopedRuntime scoped_runtime; + scoped_runtime.mergeValues( + {{"envoy.reloadable_features.explicit_internal_address_config", "true"}}); + const std::string yaml_string = R"EOF( + stat_prefix: ingress_http + route_config: + name: local_route + http_filters: + - name: envoy.filters.http.router + )EOF"; + + HttpConnectionManagerConfig config(parseHttpConnectionManagerFromYaml(yaml_string), context_, + date_provider_, route_config_provider_manager_, + &scoped_routes_config_provider_manager_, tracer_manager_, + filter_config_provider_manager_, creation_status_); + ASSERT_TRUE(creation_status_.ok()); + // Envoy no longer considers RFC1918 IP addresses to be internal if runtime guard is enabled. + Network::Address::Ipv4Instance default_ip_address{"10.48.179.130", 0, nullptr}; + EXPECT_FALSE(config.internalAddressConfig().isInternalAddress(default_ip_address)); +} + +TEST_F(HttpConnectionManagerConfigTest, DefaultInternalAddress) { + const std::string yaml_string = R"EOF( + stat_prefix: ingress_http + route_config: + name: local_route + http_filters: + - name: envoy.filters.http.router + )EOF"; + + HttpConnectionManagerConfig config(parseHttpConnectionManagerFromYaml(yaml_string), context_, + date_provider_, route_config_provider_manager_, + &scoped_routes_config_provider_manager_, tracer_manager_, + filter_config_provider_manager_, creation_status_); + ASSERT_TRUE(creation_status_.ok()); + // Previously, Envoy considered RFC1918 IP addresses to be internal, by default. + Network::Address::Ipv4Instance default_ip_address{"10.48.179.130", 0, nullptr}; + EXPECT_TRUE(config.internalAddressConfig().isInternalAddress(default_ip_address)); +} + TEST_F(HttpConnectionManagerConfigTest, CidrRangeBasedInternalAddress) { const std::string yaml_string = R"EOF( stat_prefix: ingress_http diff --git a/test/integration/http_integration.cc b/test/integration/http_integration.cc index 47738157c3..d8bc506c18 100644 --- a/test/integration/http_integration.cc +++ b/test/integration/http_integration.cc @@ -341,6 +341,21 @@ HttpIntegrationTest::HttpIntegrationTest(Http::CodecType downstream_protocol, // Allow extension lookup by name in the integration tests. config_helper_.addRuntimeOverride("envoy.reloadable_features.no_extension_lookup_by_name", "false"); + + config_helper_.addConfigModifier( + [](envoy::extensions::filters::network::http_connection_manager::v3::HttpConnectionManager& + hcm) { + auto* range = hcm.mutable_internal_address_config()->add_cidr_ranges(); + // Set loopback to be trusted so tests can set x-envoy headers. + range->set_address_prefix("127.0.0.1"); + range->mutable_prefix_len()->set_value(32); + // Legacy tests also set XFF: 10.0.0.1 + range->set_address_prefix("10.0.0.0"); + range->mutable_prefix_len()->set_value(8); + range = hcm.mutable_internal_address_config()->add_cidr_ranges(); + range->set_address_prefix("::1"); + range->mutable_prefix_len()->set_value(128); + }); } void HttpIntegrationTest::useAccessLog( diff --git a/test/mocks/http/mocks.h b/test/mocks/http/mocks.h index 7dcf37ca99..db48b01f42 100644 --- a/test/mocks/http/mocks.h +++ b/test/mocks/http/mocks.h @@ -695,8 +695,15 @@ class MockConnectionManagerConfig : public ConnectionManagerConfig { MOCK_METHOD(bool, appendXForwardedPort, (), (const)); MOCK_METHOD(bool, addProxyProtocolConnectionState, (), (const)); + class AllowInternalAddressConfig : public Http::InternalAddressConfig { + public: + bool isInternalAddress(const Network::Address::Instance& address) const override { + return Network::Utility::isInternalAddress(address); + } + }; + std::unique_ptr internal_address_config_ = - std::make_unique(); + std::make_unique(); std::vector early_header_mutation_extensions_; absl::optional scheme_; bool scheme_match_upstream_; From 34d8d36b60b9efe7cc907c3468636f46602e556c Mon Sep 17 00:00:00 2001 From: Boteng Yao Date: Wed, 24 Jul 2024 21:48:19 +0000 Subject: [PATCH 26/65] fix local reply in async client and destroy order Signed-off-by: Boteng Yao Signed-off-by: Ryan Northey --- changelogs/current.yaml | 3 + source/common/http/async_client_impl.cc | 45 +++++++++- source/common/http/async_client_impl.h | 28 ++---- .../ext_authz/ext_authz_integration_test.cc | 86 +++++++++++++++++++ 4 files changed, 138 insertions(+), 24 deletions(-) diff --git a/changelogs/current.yaml b/changelogs/current.yaml index 6d520b8b17..7f151c9113 100644 --- a/changelogs/current.yaml +++ b/changelogs/current.yaml @@ -156,6 +156,9 @@ bug_fixes: Fixed a bug where using ``clear_route_cache`` with remote JWKs works incorrectly and may cause a crash when the modified request does not match any route. +- area: http_async_client + change: | + Fixed the local reply and destroy order crashes when using the http async client for websocket handshake. removed_config_or_runtime: # *Normally occurs at the end of the* :ref:`deprecation period ` diff --git a/source/common/http/async_client_impl.cc b/source/common/http/async_client_impl.cc index a3b968c747..8fe0f75161 100644 --- a/source/common/http/async_client_impl.cc +++ b/source/common/http/async_client_impl.cc @@ -9,6 +9,7 @@ #include "source/common/grpc/common.h" #include "source/common/http/null_route_impl.h" #include "source/common/http/utility.h" +#include "source/common/local_reply/local_reply.h" #include "source/common/protobuf/message_validator_impl.h" #include "source/common/stream_info/filter_state_impl.h" #include "source/common/tracing/http_tracer_impl.h" @@ -32,7 +33,8 @@ AsyncClientImpl::AsyncClientImpl(Upstream::ClusterInfoConstSharedPtr cluster, factory_context.api().randomGenerator(), std::move(shadow_writer), true, false, false, false, false, false, Protobuf::RepeatedPtrField{}, dispatcher.timeSource(), http_context, router_context)), - dispatcher_(dispatcher), runtime_(factory_context.runtime()) {} + dispatcher_(dispatcher), runtime_(factory_context.runtime()), + local_reply_(LocalReply::Factory::createDefault()) {} AsyncClientImpl::~AsyncClientImpl() { while (!active_streams_.empty()) { @@ -120,7 +122,7 @@ AsyncStreamImpl::AsyncStreamImpl(AsyncClientImpl& parent, AsyncClient::StreamCal ? options.filter_state : std::make_shared( StreamInfo::FilterState::LifeSpan::FilterChain)), - tracing_config_(Tracing::EgressConfig::get()), + tracing_config_(Tracing::EgressConfig::get()), local_reply_(*parent.local_reply_), retry_policy_(createRetryPolicy(parent, options, parent_.factory_context_, creation_status)), route_(std::make_shared( parent_.cluster_->name(), @@ -145,6 +147,35 @@ AsyncStreamImpl::AsyncStreamImpl(AsyncClientImpl& parent, AsyncClient::StreamCal // TODO(mattklein123): Correctly set protocol in stream info when we support access logging. } +void AsyncStreamImpl::sendLocalReply(Code code, absl::string_view body, + std::function modify_headers, + const absl::optional grpc_status, + absl::string_view details) { + if (encoded_response_headers_) { + resetStream(); + return; + } + Utility::sendLocalReply( + remote_closed_, + Utility::EncodeFunctions{ + [modify_headers](ResponseHeaderMap& headers) -> void { + if (modify_headers != nullptr) { + modify_headers(headers); + } + }, + [this](ResponseHeaderMap& response_headers, Code& code, std::string& body, + absl::string_view& content_type) -> void { + local_reply_.rewrite(request_headers_, response_headers, stream_info_, code, body, + content_type); + }, + [this, &details](ResponseHeaderMapPtr&& headers, bool end_stream) -> void { + encodeHeaders(std::move(headers), end_stream, details); + }, + [this](Buffer::Instance& data, bool end_stream) -> void { + encodeData(data, end_stream); + }}, + Utility::LocalReplyData{is_grpc_request_, code, body, grpc_status, is_head_request_}); +} void AsyncStreamImpl::encodeHeaders(ResponseHeaderMapPtr&& headers, bool end_stream, absl::string_view) { ENVOY_LOG(debug, "async http request response headers (end_stream={}):\n{}", end_stream, @@ -288,16 +319,24 @@ void AsyncStreamImpl::closeRemote(bool end_stream) { } void AsyncStreamImpl::reset() { - router_.onDestroy(); + routerDestroy(); resetStream(); } +void AsyncStreamImpl::routerDestroy() { + if (!router_destroyed_) { + router_destroyed_ = true; + router_.onDestroy(); + } +} + void AsyncStreamImpl::cleanup() { ASSERT(dispatcher().isThreadSafe()); local_closed_ = remote_closed_ = true; // This will destroy us, but only do so if we are actually in a list. This does not happen in // the immediate failure case. if (inserted()) { + routerDestroy(); dispatcher().deferredDelete(removeFromList(parent_.active_streams_)); } } diff --git a/source/common/http/async_client_impl.h b/source/common/http/async_client_impl.h index e0dc6562b3..2805cb6aeb 100644 --- a/source/common/http/async_client_impl.h +++ b/source/common/http/async_client_impl.h @@ -38,6 +38,7 @@ #include "source/common/common/linked_object.h" #include "source/common/http/message_impl.h" #include "source/common/http/null_route_impl.h" +#include "source/common/local_reply/local_reply.h" #include "source/common/router/config_impl.h" #include "source/common/router/router.h" #include "source/common/stream_info/stream_info_impl.h" @@ -84,6 +85,7 @@ class AsyncClientImpl final : public AsyncClient { Event::Dispatcher& dispatcher_; std::list> active_streams_; Runtime::Loader& runtime_; + const LocalReply::LocalReplyPtr local_reply_; friend class AsyncStreamImpl; friend class AsyncRequestSharedImpl; @@ -109,7 +111,7 @@ class AsyncStreamImpl : public virtual AsyncClient::Stream, } ~AsyncStreamImpl() override { - router_.onDestroy(); + routerDestroy(); // UpstreamRequest::cleanUp() is guaranteed to reset the high watermark calls. ENVOY_BUG(high_watermark_calls_ == 0, "Excess high watermark calls after async stream ended."); if (destructor_callback_.has_value()) { @@ -171,6 +173,7 @@ class AsyncStreamImpl : public virtual AsyncClient::Stream, void cleanup(); void closeRemote(bool end_stream); bool complete() { return local_closed_ && remote_closed_; } + void routerDestroy(); // Http::StreamDecoderFilterCallbacks OptRef connection() override { return {}; } @@ -201,26 +204,7 @@ class AsyncStreamImpl : public virtual AsyncClient::Stream, void sendLocalReply(Code code, absl::string_view body, std::function modify_headers, const absl::optional grpc_status, - absl::string_view details) override { - if (encoded_response_headers_) { - resetStream(); - return; - } - Utility::sendLocalReply( - remote_closed_, - Utility::EncodeFunctions{nullptr, nullptr, - [this, modify_headers, &details](ResponseHeaderMapPtr&& headers, - bool end_stream) -> void { - if (modify_headers != nullptr) { - modify_headers(*headers); - } - encodeHeaders(std::move(headers), end_stream, details); - }, - [this](Buffer::Instance& data, bool end_stream) -> void { - encodeData(data, end_stream); - }}, - Utility::LocalReplyData{is_grpc_request_, code, body, grpc_status, is_head_request_}); - } + absl::string_view details) override; // The async client won't pause if sending 1xx headers so simply swallow any. void encode1xxHeaders(ResponseHeaderMapPtr&&) override {} void encodeHeaders(ResponseHeaderMapPtr&& headers, bool end_stream, @@ -290,6 +274,7 @@ class AsyncStreamImpl : public virtual AsyncClient::Stream, StreamInfo::StreamInfoImpl stream_info_; Tracing::NullSpan active_span_; const Tracing::Config& tracing_config_; + const LocalReply::LocalReply& local_reply_; const std::unique_ptr retry_policy_; std::shared_ptr route_; uint32_t high_watermark_calls_{}; @@ -305,6 +290,7 @@ class AsyncStreamImpl : public virtual AsyncClient::Stream, bool is_head_request_{false}; bool send_xff_{true}; bool send_internal_{true}; + bool router_destroyed_{false}; friend class AsyncClientImpl; friend class AsyncClientImplUnitTest; diff --git a/test/extensions/filters/http/ext_authz/ext_authz_integration_test.cc b/test/extensions/filters/http/ext_authz/ext_authz_integration_test.cc index 0586b80e7a..2cc89af51b 100644 --- a/test/extensions/filters/http/ext_authz/ext_authz_integration_test.cc +++ b/test/extensions/filters/http/ext_authz/ext_authz_integration_test.cc @@ -1619,6 +1619,92 @@ TEST_P(ExtAuthzLocalReplyIntegrationTest, DeniedHeaderTest) { cleanup(); } +// This will trigger the http async client sendLocalReply since the websocket upgrade failed. +// Verify that there is no response code duplication and crash in the async stream destructor. +TEST_P(ExtAuthzLocalReplyIntegrationTest, AsyncClientSendLocalReply) { + config_helper_.addConfigModifier([this](envoy::config::bootstrap::v3::Bootstrap& bootstrap) { + auto* ext_authz_cluster = bootstrap.mutable_static_resources()->add_clusters(); + ext_authz_cluster->MergeFrom(bootstrap.static_resources().clusters()[0]); + ext_authz_cluster->set_name("ext_authz"); + + envoy::extensions::filters::http::ext_authz::v3::ExtAuthz proto_config; + // Explicitly allow upgrade and connection header. + const std::string ext_authz_config = R"EOF( + http_service: + server_uri: + uri: "ext_authz:9000" + cluster: "ext_authz" + timeout: 300s + allowed_headers: + patterns: + - exact: upgrade + - exact: connection + )EOF"; + TestUtility::loadFromYaml(ext_authz_config, proto_config); + + envoy::config::listener::v3::Filter ext_authz_filter; + ext_authz_filter.set_name("envoy.filters.http.ext_authz"); + ext_authz_filter.mutable_typed_config()->PackFrom(proto_config); + config_helper_.prependFilter(MessageUtil::getJsonStringFromMessageOrError(ext_authz_filter)); + }); + + config_helper_.addConfigModifier( + [](envoy::extensions::filters::network::http_connection_manager::v3::HttpConnectionManager& + hcm) { hcm.add_upgrade_configs()->set_upgrade_type("websocket"); }); + + const std::string local_reply_yaml = R"EOF( +body_format: + json_format: + code: "%RESPONSE_CODE%" + message: "%LOCAL_REPLY_BODY%" + )EOF"; + envoy::extensions::filters::network::http_connection_manager::v3::LocalReplyConfig + local_reply_config; + TestUtility::loadFromYaml(local_reply_yaml, local_reply_config); + config_helper_.setLocalReply(local_reply_config); + + HttpIntegrationTest::initialize(); + + auto conn = makeClientConnection(lookupPort("http")); + codec_client_ = makeHttpConnection(std::move(conn)); + auto response = codec_client_->makeHeaderOnlyRequest( + Http::TestRequestHeaderMapImpl{{":method", "GET"}, + {":path", "/"}, + {":scheme", "http"}, + {":authority", "host"}, + {"upgrade", "websocket"}, + {"connection", "Upgrade"}}); + + AssertionResult result = + fake_upstreams_.back()->waitForHttpConnection(*dispatcher_, fake_ext_authz_connection_); + RELEASE_ASSERT(result, result.message()); + FakeStreamPtr ext_authz_request; + result = fake_ext_authz_connection_->waitForNewStream(*dispatcher_, ext_authz_request); + RELEASE_ASSERT(result, result.message()); + + // This will fail the websocket upgrade. + Http::TestResponseHeaderMapImpl ext_authz_response_headers{ + {":status", "401"}, + {"content-type", "fake-type"}, + }; + ext_authz_request->encodeHeaders(ext_authz_response_headers, true); + + ASSERT_TRUE(response->waitForEndStream()); + EXPECT_TRUE(response->complete()); + + EXPECT_EQ("401", response->headers().Status()->value().getStringView()); + EXPECT_EQ("application/json", response->headers().ContentType()->value().getStringView()); + EXPECT_EQ("26", response->headers().ContentLength()->value().getStringView()); + + const std::string expected_body = R"({ + "code": 401, + "message": "" +})"; + EXPECT_TRUE(TestUtility::jsonStringEqual(response->body(), expected_body)); + + cleanup(); +} + TEST_P(ExtAuthzGrpcIntegrationTest, GoogleAsyncClientCreation) { initializeConfig(); setDownstreamProtocol(Http::CodecType::HTTP2); From 285a4084236bc6112079bfc1e23ee8186db9a545 Mon Sep 17 00:00:00 2001 From: Boteng Yao Date: Mon, 19 Aug 2024 18:27:48 +0000 Subject: [PATCH 27/65] flip oghttp flag Signed-off-by: Boteng Yao Signed-off-by: Ryan Northey --- changelogs/current.yaml | 4 ++++ source/common/runtime/runtime_features.cc | 3 ++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/changelogs/current.yaml b/changelogs/current.yaml index 7f151c9113..1b7708944c 100644 --- a/changelogs/current.yaml +++ b/changelogs/current.yaml @@ -94,6 +94,10 @@ minor_behavior_changes: change: | Enhanced listener filter chain execution to include the case that listener filter has maxReadBytes() of 0, but may return StopIteration in onAccept to wait for asynchronous callback. +- area: http2 + change: | + Changes the default value of ``envoy.reloadable_features.http2_use_oghttp2`` to ``false``. This changes the codec used for HTTP/2 + requests and responses to address to address stability concerns. This behavior can be reverted by setting the feature to ``true``. bug_fixes: # *Changes expected to improve the state of the world and are unlikely to have negative effects* diff --git a/source/common/runtime/runtime_features.cc b/source/common/runtime/runtime_features.cc index 0464f76248..28517bea8e 100644 --- a/source/common/runtime/runtime_features.cc +++ b/source/common/runtime/runtime_features.cc @@ -56,7 +56,6 @@ RUNTIME_GUARD(envoy_reloadable_features_http1_balsa_disallow_lone_cr_in_chunk_ex RUNTIME_GUARD(envoy_reloadable_features_http1_use_balsa_parser); RUNTIME_GUARD(envoy_reloadable_features_http2_discard_host_header); // Ignore the automated "remove this flag" issue: we should keep this for 1 year. -RUNTIME_GUARD(envoy_reloadable_features_http2_use_oghttp2); RUNTIME_GUARD(envoy_reloadable_features_http2_use_visitor_for_data); RUNTIME_GUARD(envoy_reloadable_features_http3_happy_eyeballs); RUNTIME_GUARD(envoy_reloadable_features_http3_remove_empty_trailers); @@ -123,6 +122,8 @@ FALSE_RUNTIME_GUARD(envoy_reloadable_features_test_feature_false); FALSE_RUNTIME_GUARD(envoy_reloadable_features_streaming_shadow); // TODO(adisuissa) reset to true to enable unified mux by default FALSE_RUNTIME_GUARD(envoy_reloadable_features_unified_mux); +// TODO(birenroy) flip after the security issue is addressed. +FALSE_RUNTIME_GUARD(envoy_reloadable_features_http2_use_oghttp2); // Used to track if runtime is initialized. FALSE_RUNTIME_GUARD(envoy_reloadable_features_runtime_initialized); // TODO(mattklein123): Flip this to true and/or remove completely once verified by Envoy Mobile. From 30c7d6cda5d4afafeeecb0ccb85b91c7c86b010c Mon Sep 17 00:00:00 2001 From: tyxia Date: Mon, 19 Aug 2024 00:52:55 +0000 Subject: [PATCH 28/65] escape invalid host name Signed-off-by: tyxia Signed-off-by: Boteng Yao Signed-off-by: Ryan Northey --- changelogs/current.yaml | 4 ++ source/common/common/utility.cc | 17 ++++++ source/common/common/utility.h | 9 +++ .../common/formatter/stream_info_formatter.cc | 10 ++- source/common/runtime/runtime_features.cc | 1 + .../formatter/substitution_formatter_test.cc | 61 +++++++++++++++++-- 6 files changed, 94 insertions(+), 8 deletions(-) diff --git a/changelogs/current.yaml b/changelogs/current.yaml index 1b7708944c..5fd9945a3a 100644 --- a/changelogs/current.yaml +++ b/changelogs/current.yaml @@ -98,6 +98,10 @@ minor_behavior_changes: change: | Changes the default value of ``envoy.reloadable_features.http2_use_oghttp2`` to ``false``. This changes the codec used for HTTP/2 requests and responses to address to address stability concerns. This behavior can be reverted by setting the feature to ``true``. +- area: access_log + change: | + Sanitize SNI for potential log injection. The invalid character will be replaced by ``_`` with an ``invalid:`` marker. If runtime + flag ``envoy.reloadable_features.sanitize_sni_in_access_log`` is set to ``false``, the sanitize behavior is disabled. bug_fixes: # *Changes expected to improve the state of the world and are unlikely to have negative effects* diff --git a/source/common/common/utility.cc b/source/common/common/utility.cc index 91dcd9d0f2..ab79b2cf56 100644 --- a/source/common/common/utility.cc +++ b/source/common/common/utility.cc @@ -586,6 +586,23 @@ void StringUtil::escapeToOstream(std::ostream& os, absl::string_view view) { } } +std::string StringUtil::sanitizeInvalidHostname(const absl::string_view source) { + std::string ret_str = std::string(source); + bool sanitized = false; + for (size_t i = 0; i < ret_str.size(); ++i) { + if (absl::ascii_isalnum(ret_str[i]) || ret_str[i] == '.' || ret_str[i] == '-') { + continue; + } + sanitized = true; + ret_str[i] = '_'; + } + + if (sanitized) { + ret_str = absl::StrCat("invalid:", ret_str); + } + return ret_str; +} + const std::string& getDefaultDateFormat(bool local_time) { if (local_time) { CONSTRUCT_ON_FIRST_USE(std::string, "%Y-%m-%dT%H:%M:%E3S%z"); diff --git a/source/common/common/utility.h b/source/common/common/utility.h index 47d1082da1..06a404fbd6 100644 --- a/source/common/common/utility.h +++ b/source/common/common/utility.h @@ -490,6 +490,15 @@ class StringUtil { */ static void escapeToOstream(std::ostream& os, absl::string_view view); + /** + * Sanitize host name strings for logging purposes. Replace invalid hostname characters (anything + * that's not alphanumeric, hyphen, or period) with underscore. The sanitized string is not a + * valid host name. + * @param source supplies the string to sanitize. + * @return sanitized string. + */ + static std::string sanitizeInvalidHostname(const absl::string_view source); + /** * Provide a default value for a string if empty. * @param s string. diff --git a/source/common/formatter/stream_info_formatter.cc b/source/common/formatter/stream_info_formatter.cc index 50681ffcda..c7f532db00 100644 --- a/source/common/formatter/stream_info_formatter.cc +++ b/source/common/formatter/stream_info_formatter.cc @@ -1353,8 +1353,14 @@ const StreamInfoFormatterProviderLookupTable& getKnownStreamInfoFormatterProvide [](const StreamInfo::StreamInfo& stream_info) { absl::optional result; if (!stream_info.downstreamAddressProvider().requestedServerName().empty()) { - result = std::string( - stream_info.downstreamAddressProvider().requestedServerName()); + if (Runtime::runtimeFeatureEnabled( + "envoy.reloadable_features.sanitize_sni_in_access_log")) { + result = StringUtil::sanitizeInvalidHostname( + stream_info.downstreamAddressProvider().requestedServerName()); + } else { + result = std::string( + stream_info.downstreamAddressProvider().requestedServerName()); + } } return result; }); diff --git a/source/common/runtime/runtime_features.cc b/source/common/runtime/runtime_features.cc index 28517bea8e..650205fcc8 100644 --- a/source/common/runtime/runtime_features.cc +++ b/source/common/runtime/runtime_features.cc @@ -86,6 +86,7 @@ RUNTIME_GUARD(envoy_reloadable_features_quic_upstream_socket_use_address_cache_f RUNTIME_GUARD(envoy_reloadable_features_reject_invalid_yaml); RUNTIME_GUARD(envoy_reloadable_features_report_stream_reset_error_code); RUNTIME_GUARD(envoy_reloadable_features_sanitize_http2_headers_without_nghttp2); +RUNTIME_GUARD(envoy_reloadable_features_sanitize_sni_in_access_log); RUNTIME_GUARD(envoy_reloadable_features_sanitize_te); RUNTIME_GUARD(envoy_reloadable_features_send_local_reply_when_no_buffer_and_upstream_request); RUNTIME_GUARD(envoy_reloadable_features_skip_dns_lookup_for_proxied_requests); diff --git a/test/common/formatter/substitution_formatter_test.cc b/test/common/formatter/substitution_formatter_test.cc index a87f2f447e..d7e1697ef5 100644 --- a/test/common/formatter/substitution_formatter_test.cc +++ b/test/common/formatter/substitution_formatter_test.cc @@ -973,20 +973,69 @@ TEST(SubstitutionFormatterTest, streamInfoFormatter) { { StreamInfoFormatter upstream_format("REQUESTED_SERVER_NAME"); - std::string requested_server_name = "stub_server"; + std::string requested_server_name; stream_info.downstream_connection_info_provider_->setRequestedServerName(requested_server_name); - EXPECT_EQ("stub_server", upstream_format.formatWithContext({}, stream_info)); + EXPECT_EQ(absl::nullopt, upstream_format.formatWithContext({}, stream_info)); EXPECT_THAT(upstream_format.formatValueWithContext({}, stream_info), - ProtoEq(ValueUtil::stringValue("stub_server"))); + ProtoEq(ValueUtil::nullValue())); } { StreamInfoFormatter upstream_format("REQUESTED_SERVER_NAME"); - std::string requested_server_name; + std::string requested_server_name = "stub-server"; stream_info.downstream_connection_info_provider_->setRequestedServerName(requested_server_name); - EXPECT_EQ(absl::nullopt, upstream_format.formatWithContext({}, stream_info)); + EXPECT_EQ("stub-server", upstream_format.formatWithContext({}, stream_info)); EXPECT_THAT(upstream_format.formatValueWithContext({}, stream_info), - ProtoEq(ValueUtil::nullValue())); + ProtoEq(ValueUtil::stringValue("stub-server"))); + } + + { + StreamInfoFormatter upstream_format("REQUESTED_SERVER_NAME"); + std::string requested_server_name = "stub_server\n"; + stream_info.downstream_connection_info_provider_->setRequestedServerName(requested_server_name); + EXPECT_EQ("invalid:stub_server_", upstream_format.formatWithContext({}, stream_info)); + EXPECT_THAT(upstream_format.formatValueWithContext({}, stream_info), + ProtoEq(ValueUtil::stringValue("invalid:stub_server_"))); + } + + { + StreamInfoFormatter upstream_format("REQUESTED_SERVER_NAME"); + std::string requested_server_name = "\e[0;34m\n$(echo -e $blue)end"; + stream_info.downstream_connection_info_provider_->setRequestedServerName(requested_server_name); + EXPECT_EQ("invalid:__0_34m___echo_-e__blue_end_script_alert____script_", + upstream_format.formatWithContext({}, stream_info)); + EXPECT_THAT(upstream_format.formatValueWithContext({}, stream_info), + ProtoEq(ValueUtil::stringValue( + "invalid:__0_34m___echo_-e__blue_end_script_alert____script_"))); + } + + { + StreamInfoFormatter upstream_format("REQUESTED_SERVER_NAME"); + std::string invalid_utf8_string("prefix"); + invalid_utf8_string.append(1, char(0xc3)); + invalid_utf8_string.append(1, char(0xc7)); + invalid_utf8_string.append("valid_middle"); + invalid_utf8_string.append(1, char(0xc4)); + invalid_utf8_string.append("valid_suffix"); + stream_info.downstream_connection_info_provider_->setRequestedServerName(invalid_utf8_string); + EXPECT_EQ("invalid:prefix__valid_middle_valid_suffix", + upstream_format.formatWithContext({}, stream_info)); + EXPECT_THAT(upstream_format.formatValueWithContext({}, stream_info), + ProtoEq(ValueUtil::stringValue("invalid:prefix__valid_middle_valid_suffix"))); + } + + { + TestScopedRuntime scoped_runtime; + scoped_runtime.mergeValues({ + {"envoy.reloadable_features.sanitize_sni_in_access_log", "false"}, + }); + + StreamInfoFormatter upstream_format("REQUESTED_SERVER_NAME"); + std::string requested_server_name = "stub_server\n"; + stream_info.downstream_connection_info_provider_->setRequestedServerName(requested_server_name); + EXPECT_EQ("stub_server\n", upstream_format.formatWithContext({}, stream_info)); + EXPECT_THAT(upstream_format.formatValueWithContext({}, stream_info), + ProtoEq(ValueUtil::stringValue("stub_server\n"))); } { From 52d8f340a7da76b647f4802328bfc848a4aece2f Mon Sep 17 00:00:00 2001 From: Rickyp Date: Thu, 19 Sep 2024 14:07:59 -0400 Subject: [PATCH 29/65] Update QUICHE from 9808dac40 to 42b2e66c7 (#36208) https://github.com/google/quiche/compare/9808dac40..42b2e66c7 Risk Level: Low Testing: Existing tests pass Docs Changes: N/A Release Notes: N/A Platform Specific Features: N/A --------- Signed-off-by: Ricardo Perez --- bazel/external/quiche.BUILD | 21 +++++++++++++++++++ bazel/repository_locations.bzl | 6 +++--- .../integration/quic_http_integration_test.cc | 2 +- 3 files changed, 25 insertions(+), 4 deletions(-) diff --git a/bazel/external/quiche.BUILD b/bazel/external/quiche.BUILD index 3923966229..ccd6261ad6 100644 --- a/bazel/external/quiche.BUILD +++ b/bazel/external/quiche.BUILD @@ -2113,6 +2113,26 @@ envoy_quic_cc_library( ], ) +envoy_quic_cc_library( + name = "quic_core_congestion_control_prague_sender_lib", + srcs = [ + "quiche/quic/core/congestion_control/prague_sender.cc", + ], + hdrs = [ + "quiche/quic/core/congestion_control/prague_sender.h", + ], + deps = [ + ":quic_core_clock_lib", + ":quic_core_congestion_control_congestion_control_interface_lib", + ":quic_core_congestion_control_rtt_stats_lib", + ":quic_core_congestion_control_tcp_cubic_bytes_lib", + ":quic_core_connection_stats_lib", + ":quic_core_time_lib", + ":quic_core_types_lib", + ":quiche_common_platform_export", + ], +) + envoy_quic_cc_library( name = "quic_core_congestion_control_bbr2_lib", srcs = [ @@ -2194,6 +2214,7 @@ envoy_quic_cc_library( ":quic_core_config_lib", ":quic_core_congestion_control_bbr2_lib", ":quic_core_congestion_control_bbr_lib", + ":quic_core_congestion_control_prague_sender_lib", ":quic_core_congestion_control_tcp_cubic_bytes_lib", ":quic_core_connection_stats_lib", ":quic_core_crypto_random_lib", diff --git a/bazel/repository_locations.bzl b/bazel/repository_locations.bzl index 6752ec066c..8fee557bbb 100644 --- a/bazel/repository_locations.bzl +++ b/bazel/repository_locations.bzl @@ -1208,12 +1208,12 @@ REPOSITORY_LOCATIONS_SPEC = dict( project_name = "QUICHE", project_desc = "QUICHE (QUIC, HTTP/2, Etc) is Googleā€˜s implementation of QUIC and related protocols", project_url = "https://github.com/google/quiche", - version = "9808dac40e034f09d7af53d3d79589a02e39c211", - sha256 = "b59e6e5b9b249a8d0cb521851d54a09ac74d2beb01a233498a006f75c86c9b76", + version = "42b2e66c721f442bb439b40a1e037897360cf1b2", + sha256 = "f72f78d7fa57154ad302d559fee6b72e0695d51391684891ec991b2b5d90491f", urls = ["https://github.com/google/quiche/archive/{version}.tar.gz"], strip_prefix = "quiche-{version}", use_category = ["controlplane", "dataplane_core"], - release_date = "2024-09-10", + release_date = "2024-09-17", cpe = "N/A", license = "BSD-3-Clause", license_url = "https://github.com/google/quiche/blob/{version}/LICENSE", diff --git a/test/integration/quic_http_integration_test.cc b/test/integration/quic_http_integration_test.cc index 65251998c9..efc3e6b922 100644 --- a/test/integration/quic_http_integration_test.cc +++ b/test/integration/quic_http_integration_test.cc @@ -1085,7 +1085,7 @@ TEST_P(QuicHttpIntegrationTest, CertVerificationFailure) { EXPECT_FALSE(codec_client_->connected()); std::string failure_reason = "QUIC_TLS_CERTIFICATE_UNKNOWN with details: TLS handshake failure " "(ENCRYPTION_HANDSHAKE) 46: " - "certificate unknown"; + "certificate unknown. SSLErrorStack:"; EXPECT_EQ(failure_reason, codec_client_->connection()->transportFailureReason()); } From d6120f3c769e70c988ddcc5c7e9cbc2737b5f63c Mon Sep 17 00:00:00 2001 From: Akshay Gupta Date: Thu, 19 Sep 2024 13:09:57 -0700 Subject: [PATCH 30/65] docs: fix install commands for linux distribution (#36226) Signed-off-by: Akshay Gupta Signed-off-by: Akshay Gupta --- docs/root/start/install.rst | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/docs/root/start/install.rst b/docs/root/start/install.rst index 88a621a86f..8ce96acad9 100644 --- a/docs/root/start/install.rst +++ b/docs/root/start/install.rst @@ -19,32 +19,32 @@ Install Envoy on Debian-based Linux .. code-tab:: console Debian bookworm - $ wget https://apt.envoyproxy.io/signing.key | sudo gpg --dearmor -o /etc/apt/keyrings/envoy-keyring.gpg - $ echo "deb[signed-by=/etc/apt/keyrings/envoy-keyring.gpg] https://apt.envoyproxy.io bookworm main" | sudo tee /etc/apt/sources.list.d/envoy.list + $ wget -O- https://apt.envoyproxy.io/signing.key | sudo gpg --dearmor -o /etc/apt/keyrings/envoy-keyring.gpg + $ echo "deb [signed-by=/etc/apt/keyrings/envoy-keyring.gpg] https://apt.envoyproxy.io bookworm main" | sudo tee /etc/apt/sources.list.d/envoy.list $ sudo apt-get update $ sudo apt-get install envoy $ envoy --version .. code-tab:: console Debian bullseye - $ wget https://apt.envoyproxy.io/signing.key | sudo gpg --dearmor -o /etc/apt/keyrings/envoy-keyring.gpg - $ echo "deb[signed-by=/etc/apt/keyrings/envoy-keyring.gpg] https://apt.envoyproxy.io bullseye main" | sudo tee /etc/apt/sources.list.d/envoy.list + $ wget -O- https://apt.envoyproxy.io/signing.key | sudo gpg --dearmor -o /etc/apt/keyrings/envoy-keyring.gpg + $ echo "deb [signed-by=/etc/apt/keyrings/envoy-keyring.gpg] https://apt.envoyproxy.io bullseye main" | sudo tee /etc/apt/sources.list.d/envoy.list $ sudo apt-get update $ sudo apt-get install envoy $ envoy --version .. code-tab:: console Ubuntu focal - $ wget https://apt.envoyproxy.io/signing.key | sudo gpg --dearmor -o /etc/apt/keyrings/envoy-keyring.gpg - $ echo "deb[signed-by=/etc/apt/keyrings/envoy-keyring.gpg] https://apt.envoyproxy.io focal main" | sudo tee /etc/apt/sources.list.d/envoy.list + $ wget -O- https://apt.envoyproxy.io/signing.key | sudo gpg --dearmor -o /etc/apt/keyrings/envoy-keyring.gpg + $ echo "deb [signed-by=/etc/apt/keyrings/envoy-keyring.gpg] https://apt.envoyproxy.io focal main" | sudo tee /etc/apt/sources.list.d/envoy.list $ sudo apt-get update $ sudo apt-get install envoy $ envoy --version .. code-tab:: console Ubuntu jammy - $ wget https://apt.envoyproxy.io/signing.key | sudo gpg --dearmor -o /etc/apt/keyrings/envoy-keyring.gpg - $ echo "deb[signed-by=/etc/apt/keyrings/envoy-keyring.gpg] https://apt.envoyproxy.io jammy main" | sudo tee /etc/apt/sources.list.d/envoy.list + $ wget -O- https://apt.envoyproxy.io/signing.key | sudo gpg --dearmor -o /etc/apt/keyrings/envoy-keyring.gpg + $ echo "deb [signed-by=/etc/apt/keyrings/envoy-keyring.gpg] https://apt.envoyproxy.io jammy main" | sudo tee /etc/apt/sources.list.d/envoy.list $ sudo apt-get update $ sudo apt-get install envoy $ envoy --version From bb2dfc91ebd5912a7569a92d8a85a3707474c5f0 Mon Sep 17 00:00:00 2001 From: phlax Date: Fri, 20 Sep 2024 10:04:20 +0100 Subject: [PATCH 31/65] release/ci: Fix code scanning pin alerts (#36219) Signed-off-by: Ryan Northey --- ci/Dockerfile-envoy | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/ci/Dockerfile-envoy b/ci/Dockerfile-envoy index 134511d212..e2a8738d2e 100644 --- a/ci/Dockerfile-envoy +++ b/ci/Dockerfile-envoy @@ -1,5 +1,6 @@ ARG BUILD_OS=ubuntu -ARG BUILD_TAG=22.04@sha256:adbb90115a21969d2fe6fa7f9af4253e16d45f8d4c1e930182610c4731962658 +ARG BUILD_TAG=22.04 +ARG BUILD_SHA=adbb90115a21969d2fe6fa7f9af4253e16d45f8d4c1e930182610c4731962658 ARG ENVOY_VRP_BASE_IMAGE=envoy-base @@ -13,7 +14,7 @@ ADD "${TARGETPLATFORM}/release.tar.zst" /usr/local/bin/ # STAGE: envoy-base -FROM ${BUILD_OS}:${BUILD_TAG} AS envoy-base +FROM ${BUILD_OS}:${BUILD_TAG}@sha256:${BUILD_SHA} AS envoy-base ENV DEBIAN_FRONTEND=noninteractive EXPOSE 10000 CMD ["envoy", "-c", "/etc/envoy/envoy.yaml"] From d22681349325b0022a70085dc224a24fb1553272 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 20 Sep 2024 11:10:22 +0100 Subject: [PATCH 32/65] build(deps): bump github/codeql-action from 3.26.7 to 3.26.8 (#36244) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/codeql-daily.yml | 4 ++-- .github/workflows/codeql-push.yml | 4 ++-- .github/workflows/scorecard.yml | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/codeql-daily.yml b/.github/workflows/codeql-daily.yml index f29c5f85c5..d8640ef866 100644 --- a/.github/workflows/codeql-daily.yml +++ b/.github/workflows/codeql-daily.yml @@ -34,7 +34,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@8214744c546c1e5c8f03dde8fab3a7353211988d # codeql-bundle-v3.26.7 + uses: github/codeql-action/init@294a9d92911152fe08befb9ec03e240add280cb3 # codeql-bundle-v3.26.8 # Override language selection by uncommenting this and choosing your languages with: languages: cpp @@ -73,4 +73,4 @@ jobs: git clean -xdf - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@8214744c546c1e5c8f03dde8fab3a7353211988d # codeql-bundle-v3.26.7 + uses: github/codeql-action/analyze@294a9d92911152fe08befb9ec03e240add280cb3 # codeql-bundle-v3.26.8 diff --git a/.github/workflows/codeql-push.yml b/.github/workflows/codeql-push.yml index 791937329d..9fd8db2781 100644 --- a/.github/workflows/codeql-push.yml +++ b/.github/workflows/codeql-push.yml @@ -65,7 +65,7 @@ jobs: - name: Initialize CodeQL if: ${{ env.BUILD_TARGETS != '' }} - uses: github/codeql-action/init@8214744c546c1e5c8f03dde8fab3a7353211988d # codeql-bundle-v3.26.7 + uses: github/codeql-action/init@294a9d92911152fe08befb9ec03e240add280cb3 # codeql-bundle-v3.26.8 with: languages: cpp @@ -108,4 +108,4 @@ jobs: - name: Perform CodeQL Analysis if: ${{ env.BUILD_TARGETS != '' }} - uses: github/codeql-action/analyze@8214744c546c1e5c8f03dde8fab3a7353211988d # codeql-bundle-v3.26.7 + uses: github/codeql-action/analyze@294a9d92911152fe08befb9ec03e240add280cb3 # codeql-bundle-v3.26.8 diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index 3a03313309..9c574f263d 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -40,6 +40,6 @@ jobs: retention-days: 5 - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@8214744c546c1e5c8f03dde8fab3a7353211988d # v3.26.7 + uses: github/codeql-action/upload-sarif@294a9d92911152fe08befb9ec03e240add280cb3 # v3.26.8 with: sarif_file: results.sarif From 4779e4ab8c959d9799c59fab1ec7d48f538dcb10 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 20 Sep 2024 10:10:33 +0000 Subject: [PATCH 33/65] build(deps): bump clang-tidy from 14.0.6 to 19.1.0 in /tools/base (#36243) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- tools/base/requirements.in | 2 +- tools/base/requirements.txt | 19 ++++++++++--------- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/tools/base/requirements.in b/tools/base/requirements.in index 0cd07a89d4..a252ecfd2c 100644 --- a/tools/base/requirements.in +++ b/tools/base/requirements.in @@ -7,7 +7,7 @@ aiohttp>=3.8.1 aioquic>=0.9.21 cffi>=1.15.0 clang-format==14.0.6 -clang-tidy==14.0.6 +clang-tidy==19.1.0 colorama coloredlogs cryptography>=43.0.1 diff --git a/tools/base/requirements.txt b/tools/base/requirements.txt index 2acf5c379a..2fa912886b 100644 --- a/tools/base/requirements.txt +++ b/tools/base/requirements.txt @@ -433,15 +433,16 @@ clang-format==14.0.6 \ --hash=sha256:d7c1c5e404c58e55f0170f01b3c5611dce6c119e62b5d1020347e0ad97d5a047 \ --hash=sha256:dbfd60528eb3bb7d7cfe8576faa70845fbf93601f815ef75163d36606e87f388 # via -r requirements.in -clang-tidy==14.0.6 \ - --hash=sha256:02bce40a56cc344e20d2f63bef6b85acf9837954559e0091804d6e748dfc0359 \ - --hash=sha256:173a757415108095b541eb9a2d0c222d41f5624e7bb5b98772476957228ce2c7 \ - --hash=sha256:4635f6553f9e3eb7a81fec29d15e4e70b49c1780f31a17550c11007fc9bba4b3 \ - --hash=sha256:5b56edb6b7215eb79fede7ab8a4f9b94454bdfe1091d026acc1afdc7696abb68 \ - --hash=sha256:7f75eb4839dc996dea494a07814b3a70200be75bc7d9acb54d3d5916f24bcd8d \ - --hash=sha256:c9ffcb91f17ee920fdd7a83f30484f3cb4c183f7b490d092373e4a6f2c82729d \ - --hash=sha256:d595b8e9a155d63b6b9dec0afa62725590626c9f0e945c3d9e448a28e0082b39 \ - --hash=sha256:fef62fb706adccef94128761ca0796973a196e2d60fb938a312cfa2bc59730bd +clang-tidy==19.1.0 \ + --hash=sha256:082f520652a5268c4c97d94c1ff04686e31c9a76c29077beead491f6c345ab94 \ + --hash=sha256:27104b3f7a6841d45ece284ba27f93ac7c982a5bf38a30fc6f280c4f0cd2fcfb \ + --hash=sha256:61c81df8fbb032888d26ea7145b0a33d0b8539c1923f80084724bc6ee71f6220 \ + --hash=sha256:6ae7e3fb47b0969a9ed3197f029165366ee4818437b5ce675426789279b35595 \ + --hash=sha256:79050ed7771520cf9825786f5207dc55ba7b281fff96aca037c0962b104de6ba \ + --hash=sha256:8441c66560a25e37bb57e3b8d63ac4067f9b6f92c4887f2952d26ed9e49143a0 \ + --hash=sha256:be843086d18f7c794fe43d9f3378c0c556fd09151a2375ed1943ff703c144970 \ + --hash=sha256:c7403c57db174bc17f94fec651a4c6c0bb050da74dc12e542be44edea8a77546 \ + --hash=sha256:ee2fe7afb34529dd6be9b8f367eaa864814c47e91479d34e3caedd56df80549b # via -r requirements.in colorama==0.4.6 \ --hash=sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44 \ From 5b320f5ec8774814c15d4ab3a1d05355c9a1930c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 20 Sep 2024 11:10:48 +0100 Subject: [PATCH 34/65] build(deps): bump slack-sdk from 3.33.0 to 3.33.1 in /tools/base (#36242) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- tools/base/requirements.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/base/requirements.txt b/tools/base/requirements.txt index 2fa912886b..f2b74091a5 100644 --- a/tools/base/requirements.txt +++ b/tools/base/requirements.txt @@ -1278,9 +1278,9 @@ six==1.16.0 \ # pyu2f # sphinxcontrib-httpdomain # thrift -slack-sdk==3.33.0 \ - --hash=sha256:070eb1fb355c149a5f80fa0be6eeb5f5588e4ddff4dd76acf060454435cb037e \ - --hash=sha256:853bb55154115d080cae342c4099f2ccb559a78ae8d0f5109b49842401a920fa +slack-sdk==3.33.1 \ + --hash=sha256:e328bb661d95db5f66b993b1d64288ac7c72201a745b4c7cf8848dafb7b74e40 \ + --hash=sha256:ef93beec3ce9c8f64da02fd487598a05ec4bc9c92ceed58f122dbe632691cbe2 # via -r requirements.in smmap==5.0.1 \ --hash=sha256:dceeb6c0028fdb6734471eb07c0cd2aae706ccaecab45965ee83f11c8d3b1f62 \ From 7a831dd4cfb68aa556a51f3409ea830ae17711a3 Mon Sep 17 00:00:00 2001 From: "publish-envoy[bot]" <140627008+publish-envoy[bot]@users.noreply.github.com> Date: Fri, 20 Sep 2024 10:21:02 +0000 Subject: [PATCH 35/65] repo: Sync version histories (#36255) Signed-off-by: publish-envoy[bot] Co-authored-by: publish-envoy[bot] <140627008+publish-envoy[bot]@users.noreply.github.com> --- changelogs/1.28.7.yaml | 22 ++++++++++++++++++++ changelogs/1.29.9.yaml | 27 +++++++++++++++++++++++++ changelogs/1.30.6.yaml | 27 +++++++++++++++++++++++++ changelogs/1.31.2.yaml | 31 +++++++++++++++++++++++++++++ docs/inventories/v1.28/objects.inv | Bin 164530 -> 164553 bytes docs/inventories/v1.29/objects.inv | Bin 168384 -> 168427 bytes docs/inventories/v1.30/objects.inv | Bin 172115 -> 172187 bytes docs/inventories/v1.31/objects.inv | Bin 175670 -> 175768 bytes docs/versions.yaml | 8 ++++---- 9 files changed, 111 insertions(+), 4 deletions(-) create mode 100644 changelogs/1.28.7.yaml create mode 100644 changelogs/1.29.9.yaml create mode 100644 changelogs/1.30.6.yaml create mode 100644 changelogs/1.31.2.yaml diff --git a/changelogs/1.28.7.yaml b/changelogs/1.28.7.yaml new file mode 100644 index 0000000000..da5d914b7b --- /dev/null +++ b/changelogs/1.28.7.yaml @@ -0,0 +1,22 @@ +date: September 19, 2024 + +behavior_changes: +- area: http + change: | + The default configuration of Envoy will continue to trust internal addresses while in the future it will not trust them by default. + If you have tooling such as probes on your private network which need to be treated as trusted (e.g. changing arbitrary ``x-envoy`` + headers) please explictily include those addresses or CIDR ranges into :ref:`internal_address_config + ` + See the config examples from the above ``internal_address_config`` link. This default no trust internal address can be turned on by + setting runtime guard ``envoy.reloadable_features.explicit_internal_address_config`` to ``true``. + +minor_behavior_changes: +- area: access_log + change: | + Sanitize SNI for potential log injection. The invalid character will be replaced by ``_`` with an ``invalid:`` marker. If runtime + flag ``envoy.reloadable_features.sanitize_sni_in_access_log`` is set to ``false``, the sanitize behavior is disabled. + +bug_fixes: +- area: http_async_client + change: | + Fixed the local reply and destroy order crashes when using the http async client for websocket handshake. diff --git a/changelogs/1.29.9.yaml b/changelogs/1.29.9.yaml new file mode 100644 index 0000000000..dbd5efcf23 --- /dev/null +++ b/changelogs/1.29.9.yaml @@ -0,0 +1,27 @@ +date: September 19, 2024 + +behavior_changes: +- area: http + change: | + The default configuration of Envoy will continue to trust internal addresses while in the future it will not trust them by default. + If you have tooling such as probes on your private network which need to be treated as trusted (e.g. changing arbitrary ``x-envoy`` + headers) please explictily include those addresses or CIDR ranges into :ref:`internal_address_config + ` + See the config examples from the above ``internal_address_config`` link. This default no trust internal address can be turned on by + setting runtime guard ``envoy.reloadable_features.explicit_internal_address_config`` to ``true``. + +minor_behavior_changes: +- area: access_log + change: | + Sanitize SNI for potential log injection. The invalid character will be replaced by ``_`` with an ``invalid:`` marker. If runtime + flag ``envoy.reloadable_features.sanitize_sni_in_access_log`` is set to ``false``, the sanitize behavior is disabled. + +bug_fixes: +- area: jwt + change: | + Fixed a bug where using ``clear_route_cache`` with remote JWKs works + incorrectly and may cause a crash when the modified request does not match + any route. +- area: http_async_client + change: | + Fixed the local reply and destroy order crashes when using the http async client for websocket handshake. diff --git a/changelogs/1.30.6.yaml b/changelogs/1.30.6.yaml new file mode 100644 index 0000000000..dbd5efcf23 --- /dev/null +++ b/changelogs/1.30.6.yaml @@ -0,0 +1,27 @@ +date: September 19, 2024 + +behavior_changes: +- area: http + change: | + The default configuration of Envoy will continue to trust internal addresses while in the future it will not trust them by default. + If you have tooling such as probes on your private network which need to be treated as trusted (e.g. changing arbitrary ``x-envoy`` + headers) please explictily include those addresses or CIDR ranges into :ref:`internal_address_config + ` + See the config examples from the above ``internal_address_config`` link. This default no trust internal address can be turned on by + setting runtime guard ``envoy.reloadable_features.explicit_internal_address_config`` to ``true``. + +minor_behavior_changes: +- area: access_log + change: | + Sanitize SNI for potential log injection. The invalid character will be replaced by ``_`` with an ``invalid:`` marker. If runtime + flag ``envoy.reloadable_features.sanitize_sni_in_access_log`` is set to ``false``, the sanitize behavior is disabled. + +bug_fixes: +- area: jwt + change: | + Fixed a bug where using ``clear_route_cache`` with remote JWKs works + incorrectly and may cause a crash when the modified request does not match + any route. +- area: http_async_client + change: | + Fixed the local reply and destroy order crashes when using the http async client for websocket handshake. diff --git a/changelogs/1.31.2.yaml b/changelogs/1.31.2.yaml new file mode 100644 index 0000000000..b188a39d5c --- /dev/null +++ b/changelogs/1.31.2.yaml @@ -0,0 +1,31 @@ +date: September 19, 2024 + +behavior_changes: +- area: http + change: | + The default configuration of Envoy will continue to trust internal addresses while in the future it will not trust them by default. + If you have tooling such as probes on your private network which need to be treated as trusted (e.g. changing arbitrary + ``x-envoy`` headers) please explictily include those addresses or CIDR ranges into :ref:`internal_address_config + ` + See the config examples from the above ``internal_address_config`` link. This default no trust internal address can be turned on by + setting runtime guard ``envoy.reloadable_features.explicit_internal_address_config`` to ``true``. +- area: http2 + change: | + Changes the default value of ``envoy.reloadable_features.http2_use_oghttp2`` to ``false``. This changes the codec used for HTTP/2 + requests and responses to address to address stability concerns. This behavior can be reverted by setting the feature to ``true``. + +minor_behavior_changes: +- area: access_log + change: | + Sanitize SNI for potential log injection. The invalid character will be replaced by ``_`` with an ``invalid:`` marker. If runtime + flag ``envoy.reloadable_features.sanitize_sni_in_access_log`` is set to ``false``, the sanitize behavior is disabled. + +bug_fixes: +- area: jwt + change: | + Fixed a bug where using ``clear_route_cache`` with remote JWKs works + incorrectly and may cause a crash when the modified request does not match + any route. +- area: http_async_client + change: | + Fixed the local reply and destroy order crashes when using the http async client for websocket handshake. diff --git a/docs/inventories/v1.28/objects.inv b/docs/inventories/v1.28/objects.inv index 2fd3b18a0dfb5fb63023254ac00f0bf35858cd22..fd7a066d88dd6aeab16fb0fb0fd9667936f22510 100644 GIT binary patch delta 3782 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 delta 23137 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 diff --git a/docs/inventories/v1.30/objects.inv b/docs/inventories/v1.30/objects.inv index 2a52602afc3ace69ca086872714271a5af76ddc2..f961430394b95159aa9662dbe818688c0d4bb607 100644 GIT binary patch delta 20446 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 diff --git a/docs/inventories/v1.31/objects.inv b/docs/inventories/v1.31/objects.inv index 144ce7dbd8121b04b1a45e66e65858850736ab3d..8bd3786841cb44937eb0d734f954bd9f8e7adebe 100644 GIT binary patch delta 4394 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 JD_7Zu{||AtJdFSV delta 4295 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 Date: Fri, 20 Sep 2024 12:58:21 +0100 Subject: [PATCH 36/65] deps: Bump `rules_rust` -> 0.51.0 (#36260) Fix #36253 Signed-off-by: dependency-envoy[bot] <148525496+dependency-envoy[bot]@users.noreply.github.com> Signed-off-by: dependency-envoy[bot] <148525496+dependency-envoy[bot]@users.noreply.github.com> Co-authored-by: dependency-envoy[bot] <148525496+dependency-envoy[bot]@users.noreply.github.com> --- bazel/repository_locations.bzl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/bazel/repository_locations.bzl b/bazel/repository_locations.bzl index 8fee557bbb..f04b5b6886 100644 --- a/bazel/repository_locations.bzl +++ b/bazel/repository_locations.bzl @@ -1452,9 +1452,9 @@ REPOSITORY_LOCATIONS_SPEC = dict( project_name = "Bazel rust rules", project_desc = "Bazel rust rules (used by Wasm)", project_url = "https://github.com/bazelbuild/rules_rust", - version = "0.50.1", + version = "0.51.0", strip_prefix = "rules_rust-{version}", - sha256 = "ddfc0210b19498086d09c458672ef2a6fb7790103dbb1b2da73c54677c330ed1", + sha256 = "44ffa703f95fe693c15fefb58432ad009379848d24012338a3c2eb9951b371e7", urls = ["https://github.com/bazelbuild/rules_rust/archive/{version}.tar.gz"], use_category = [ "controlplane", @@ -1463,7 +1463,7 @@ REPOSITORY_LOCATIONS_SPEC = dict( ], implied_untracked_deps = ["rules_cc"], extensions = ["envoy.wasm.runtime.wasmtime"], - release_date = "2024-09-11", + release_date = "2024-09-19", cpe = "N/A", license = "Apache-2.0", license_url = "https://github.com/bazelbuild/rules_rust/blob/{version}/LICENSE.txt", From ab0d4e7051f7158abc1ea85ec558d4d48598900a Mon Sep 17 00:00:00 2001 From: "dependency-envoy[bot]" <148525496+dependency-envoy[bot]@users.noreply.github.com> Date: Fri, 20 Sep 2024 11:58:30 +0000 Subject: [PATCH 37/65] deps/api: Bump `dev_cel` -> 0.16.2 (#36259) Fix #36251 Signed-off-by: dependency-envoy[bot] <148525496+dependency-envoy[bot]@users.noreply.github.com> Signed-off-by: dependency-envoy[bot] <148525496+dependency-envoy[bot]@users.noreply.github.com> Co-authored-by: dependency-envoy[bot] <148525496+dependency-envoy[bot]@users.noreply.github.com> --- api/bazel/repository_locations.bzl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/api/bazel/repository_locations.bzl b/api/bazel/repository_locations.bzl index dc3c4389c3..6bad5a5db5 100644 --- a/api/bazel/repository_locations.bzl +++ b/api/bazel/repository_locations.bzl @@ -169,11 +169,11 @@ REPOSITORY_LOCATIONS_SPEC = dict( project_desc = "Common Expression Language -- specification and binary representation", project_url = "https://github.com/google/cel-spec", strip_prefix = "cel-spec-{version}", - sha256 = "24fd9b5aa218044f2923b8bcfccbf996eb024f05d1acbe1b27aca554f2720ac6", - version = "0.16.1", + sha256 = "ad735dcea00992c36c7e94a56bceebedad475a01ee63b49c6796c1fcb7b6a41c", + version = "0.16.2", urls = ["https://github.com/google/cel-spec/archive/v{version}.tar.gz"], use_category = ["api"], - release_date = "2024-08-28", + release_date = "2024-09-18", ), envoy_toolshed = dict( project_name = "envoy_toolshed", From 490149464dabb50255aa99d4c9aedb464a73ce72 Mon Sep 17 00:00:00 2001 From: "dependency-envoy[bot]" <148525496+dependency-envoy[bot]@users.noreply.github.com> Date: Fri, 20 Sep 2024 11:58:35 +0000 Subject: [PATCH 38/65] deps/api: Bump `com_github_bufbuild_buf` -> 1.42.0 (#36258) Fix #36249 Signed-off-by: dependency-envoy[bot] <148525496+dependency-envoy[bot]@users.noreply.github.com> Signed-off-by: dependency-envoy[bot] <148525496+dependency-envoy[bot]@users.noreply.github.com> Co-authored-by: dependency-envoy[bot] <148525496+dependency-envoy[bot]@users.noreply.github.com> --- api/bazel/repository_locations.bzl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/api/bazel/repository_locations.bzl b/api/bazel/repository_locations.bzl index 6bad5a5db5..a7738a68bc 100644 --- a/api/bazel/repository_locations.bzl +++ b/api/bazel/repository_locations.bzl @@ -144,11 +144,11 @@ REPOSITORY_LOCATIONS_SPEC = dict( project_name = "buf", project_desc = "A new way of working with Protocol Buffers.", # Used for breaking change detection in API protobufs project_url = "https://buf.build", - version = "1.41.0", - sha256 = "47952564762b3f7e248fb70cba1956e68db80242fac3e825ba21eb2632074c93", + version = "1.42.0", + sha256 = "412c8bdc2a4361f796df59735eb8b8f1cb85f7bfa91f443e471bf0b090d7c6c2", strip_prefix = "buf", urls = ["https://github.com/bufbuild/buf/releases/download/v{version}/buf-Linux-x86_64.tar.gz"], - release_date = "2024-09-11", + release_date = "2024-09-18", use_category = ["api"], license = "Apache-2.0", license_url = "https://github.com/bufbuild/buf/blob/v{version}/LICENSE", From 061d60f69b0269478cee9c0b5ab6c2ca0c740fce Mon Sep 17 00:00:00 2001 From: "dependency-envoy[bot]" <148525496+dependency-envoy[bot]@users.noreply.github.com> Date: Fri, 20 Sep 2024 11:58:44 +0000 Subject: [PATCH 39/65] deps: Bump `aspect_bazel_lib` -> 2.9.0 (#36256) Fix #36247 Signed-off-by: dependency-envoy[bot] <148525496+dependency-envoy[bot]@users.noreply.github.com> Signed-off-by: Ryan Northey Co-authored-by: dependency-envoy[bot] <148525496+dependency-envoy[bot]@users.noreply.github.com> --- bazel/repository_locations.bzl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/bazel/repository_locations.bzl b/bazel/repository_locations.bzl index f04b5b6886..d8f816fb5f 100644 --- a/bazel/repository_locations.bzl +++ b/bazel/repository_locations.bzl @@ -167,12 +167,12 @@ REPOSITORY_LOCATIONS_SPEC = dict( project_name = "Aspect Bazel helpers", project_desc = "Base Starlark libraries and basic Bazel rules which are useful for constructing rulesets and BUILD files", project_url = "https://github.com/aspect-build/bazel-lib", - version = "2.8.1", - sha256 = "d96f4dc5c129a033e6851a03b04219513bd32aed66f13f93d87879e3cb0349db", + version = "2.9.0", + sha256 = "04299d5460ef8ed92f1251d468a3c1ce746f9f3003047c728383c42048950cb5", strip_prefix = "bazel-lib-{version}", urls = ["https://github.com/aspect-build/bazel-lib/archive/v{version}.tar.gz"], use_category = ["build"], - release_date = "2024-08-19", + release_date = "2024-09-19", cpe = "N/A", license = "Apache-2.0", license_url = "https://github.com/aspect-build/bazel-lib/blob/v{version}/LICENSE", From cdd9bfcc86bbba816bafdcc10d89fc0a33cb1565 Mon Sep 17 00:00:00 2001 From: "dependency-envoy[bot]" <148525496+dependency-envoy[bot]@users.noreply.github.com> Date: Fri, 20 Sep 2024 11:58:52 +0000 Subject: [PATCH 40/65] deps: Bump `build_bazel_rules_apple` -> 3.9.0 (#36257) Fix #36248 Signed-off-by: dependency-envoy[bot] <148525496+dependency-envoy[bot]@users.noreply.github.com> Signed-off-by: dependency-envoy[bot] <148525496+dependency-envoy[bot]@users.noreply.github.com> Co-authored-by: dependency-envoy[bot] <148525496+dependency-envoy[bot]@users.noreply.github.com> --- bazel/repository_locations.bzl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/bazel/repository_locations.bzl b/bazel/repository_locations.bzl index d8f816fb5f..2405fb248b 100644 --- a/bazel/repository_locations.bzl +++ b/bazel/repository_locations.bzl @@ -73,10 +73,10 @@ REPOSITORY_LOCATIONS_SPEC = dict( project_name = "Apple Rules for Bazel", project_desc = "Bazel rules for Apple platforms", project_url = "https://github.com/bazelbuild/rules_apple", - version = "3.8.0", - sha256 = "62847b3f444ce514ae386704a119ad7b29fa6dfb65a38bff4ae239f2389a0429", + version = "3.9.0", + sha256 = "f8fa96115c33e128cb72e9b7118a5f9294731a7dda8e36d04ddb582671f48dc1", urls = ["https://github.com/bazelbuild/rules_apple/releases/download/{version}/rules_apple.{version}.tar.gz"], - release_date = "2024-08-12", + release_date = "2024-09-18", use_category = ["build"], license = "Apache-2.0", license_url = "https://github.com/bazelbuild/rules_apple/blob/{version}/LICENSE", From 0c1b103ed3d28894e0883980bb1bd40b920f750e Mon Sep 17 00:00:00 2001 From: "Adi (Suissa) Peleg" Date: Fri, 20 Sep 2024 08:20:06 -0400 Subject: [PATCH 41/65] grpc-xDS: reserve vector size (#36230) Signed-off-by: Adi Suissa-Peleg --- source/extensions/config_subscription/grpc/watch_map.cc | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/source/extensions/config_subscription/grpc/watch_map.cc b/source/extensions/config_subscription/grpc/watch_map.cc index 5b40d625fa..815bcca485 100644 --- a/source/extensions/config_subscription/grpc/watch_map.cc +++ b/source/extensions/config_subscription/grpc/watch_map.cc @@ -206,6 +206,7 @@ void WatchMap::onConfigUpdate(const Protobuf::RepeatedPtrField } std::vector decoded_resources; + decoded_resources.reserve(resources.size()); for (const auto& r : resources) { decoded_resources.emplace_back( DecodedResourceImpl::fromResource((*watches_.begin())->resource_decoder_, r, version_info)); @@ -227,6 +228,10 @@ void WatchMap::onConfigUpdate( // into the individual onConfigUpdate()s. std::vector decoded_resources; absl::flat_hash_map> per_watch_added; + // If the server behaves according to the protocol, it will only send the + // resources the watch map is interested in. Reserve the correct amount of + // space for the vector for the good case. + decoded_resources.reserve(added_resources.size()); for (const auto& r : added_resources) { const absl::flat_hash_set& interested_in_r = watchesInterestedIn(r.name()); // If there are no watches, then we don't need to decode. If there are watches, they should all From 6da051b1f229235ef5956df18c2894198ce3a807 Mon Sep 17 00:00:00 2001 From: Huabing Zhao Date: Fri, 20 Sep 2024 20:46:14 +0800 Subject: [PATCH 42/65] chore: fix the incorrect `scope` claim name in the API doc (#36241) Signed-off-by: Huabing Zhao --- api/envoy/extensions/filters/http/jwt_authn/v3/config.proto | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/api/envoy/extensions/filters/http/jwt_authn/v3/config.proto b/api/envoy/extensions/filters/http/jwt_authn/v3/config.proto index 85f96eeef8..99212f3edf 100644 --- a/api/envoy/extensions/filters/http/jwt_authn/v3/config.proto +++ b/api/envoy/extensions/filters/http/jwt_authn/v3/config.proto @@ -63,9 +63,9 @@ message JwtProvider { message NormalizePayload { // Each claim in this list will be interpreted as a space-delimited string // and converted to a list of strings based on the delimited values. - // Example: a token with a claim ``scopes: "email profile"`` is translated - // to dynamic metadata ``scopes: ["email", "profile"]`` if this field is - // set value ``["scopes"]``. This special handling of ``scopes`` is + // Example: a token with a claim ``scope: "email profile"`` is translated + // to dynamic metadata ``scope: ["email", "profile"]`` if this field is + // set value ``["scope"]``. This special handling of ``scope`` is // recommended by `RFC8693 // `_. repeated string space_delimited_claims = 1; From d7394605f0f530349c1c9fca6c6b7b975d8a7cf0 Mon Sep 17 00:00:00 2001 From: phlax Date: Fri, 20 Sep 2024 18:48:19 +0100 Subject: [PATCH 43/65] bazel/repo: Add release hash to blow project data cache (#36262) Signed-off-by: Ryan Northey --- bazel/BUILD | 1 + bazel/generate_release_hash.sh | 17 +++++++++++++++++ bazel/repo.bzl | 28 ++++++++++++++++++++++++++++ 3 files changed, 46 insertions(+) create mode 100755 bazel/generate_release_hash.sh diff --git a/bazel/BUILD b/bazel/BUILD index 896cc84586..adb3fe7905 100644 --- a/bazel/BUILD +++ b/bazel/BUILD @@ -14,6 +14,7 @@ envoy_package() exports_files([ "gen_sh_test_runner.sh", + "generate_release_hash.sh", "sh_test_wrapper.sh", "test_for_benchmark_wrapper.sh", "repository_locations.bzl", diff --git a/bazel/generate_release_hash.sh b/bazel/generate_release_hash.sh new file mode 100755 index 0000000000..d866c26a00 --- /dev/null +++ b/bazel/generate_release_hash.sh @@ -0,0 +1,17 @@ +#!/usr/bin/env bash + +set -e -o pipefail + +ENVOY_SRCDIR="${1}" + +if [[ ! -e "$ENVOY_SRCDIR" ]]; then + echo "Unable to find Envoy src dir: ${ENVOY_SRCDIR}" >&2 + exit 1 +fi + +git -C "$ENVOY_SRCDIR" fetch --tags + +git -C "$ENVOY_SRCDIR" tag --list 'v[0-9]*.[0-9]*.[0-9]*' \ + | grep -E '^v[0-9]+\.[0-9]+\.[0-9]+$' \ + | sort -u \ + | sha256sum diff --git a/bazel/repo.bzl b/bazel/repo.bzl index a2d909b3f9..a4e421cf11 100644 --- a/bazel/repo.bzl +++ b/bazel/repo.bzl @@ -66,6 +66,33 @@ envoy_entry_point( init_data = [":__init__.py"], ) +sh_binary( + name = "generate_release_hash", + srcs = ["generate_release_hash.sh"], + visibility = ["//visibility:public"], +) + +# This sets a default hash based on currently visible tagged versions. +# Its very questionably hermetic, making assumptions about git, the repo remotes and so on. +# The general idea here is to make this cache blow any time there are release changes. +# You can use the above sh_binary to generate a custom/correct hash to override below. +genrule( + name = "default_release_hash", + outs = ["default_release_hash.txt"], + cmd = """ + $(location @envoy//bazel:generate_release_hash.sh) %s > $@ + """ % PATH, + stamp = True, + tags = ["no-remote-exec"], + tools = ["@envoy//bazel:generate_release_hash.sh"], +) + +label_flag( + name = "release-hash", + build_setting_default = ":default_release_hash", + visibility = ["//visibility:public"], +) + genrule( name = "project", outs = ["project.json"], @@ -74,6 +101,7 @@ genrule( """, tools = [ ":get_project_json", + ":release-hash", "@envoy//:VERSION.txt", "@envoy//changelogs", ], From a93ea37c132465703460667a8061b7903fa41775 Mon Sep 17 00:00:00 2001 From: Greg Greenway Date: Fri, 20 Sep 2024 11:01:40 -0700 Subject: [PATCH 44/65] Fix typo in test name (#36196) Risk Level: low Testing: n/a Docs Changes: n/a Release Notes: n/a Signed-off-by: Greg Greenway --- test/integration/health_check_integration_test.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/integration/health_check_integration_test.cc b/test/integration/health_check_integration_test.cc index 2ca266e826..628829fcdf 100644 --- a/test/integration/health_check_integration_test.cc +++ b/test/integration/health_check_integration_test.cc @@ -496,7 +496,7 @@ TEST_P(HttpHealthCheckIntegrationTest, SingleEndpointGoAway) { // followup health check would happen. Using real time solves this because then // the ordering of advancing the time system and enabling the health check timer // is inconsequential. -TEST_P(RealTimeHttpHealthCheckIntegrationTest, SingleEndpointGoAwayErroSingleEndpointGoAwayErrorr) { +TEST_P(RealTimeHttpHealthCheckIntegrationTest, SingleEndpointGoAwayError) { initialize(); // GOAWAY doesn't exist in HTTP1. From 31cef1fc15bddfee08c895421aa5be130840f3dd Mon Sep 17 00:00:00 2001 From: phlax Date: Fri, 20 Sep 2024 19:02:45 +0100 Subject: [PATCH 45/65] release/ci: Remove windows Docker setup (#36220) Signed-off-by: Ryan Northey --- ci/Dockerfile-envoy-windows | 22 ------ ci/docker_ci.sh | 106 ++++++++------------------ ci/test/docker/windows/dev/main | 9 --- ci/test/docker/windows/dev/other | 2 - ci/test/docker/windows/dev/release | 2 - ci/test/docker/windows/dev/tag | 2 - ci/test/docker/windows/nondev/main | 9 --- ci/test/docker/windows/nondev/other | 2 - ci/test/docker/windows/nondev/release | 9 --- ci/test/docker/windows/nondev/tag | 2 - ci/test_docker_ci.sh | 10 +-- docs/conf.py | 12 +-- 12 files changed, 34 insertions(+), 153 deletions(-) delete mode 100644 ci/Dockerfile-envoy-windows delete mode 100644 ci/test/docker/windows/dev/main delete mode 100644 ci/test/docker/windows/dev/other delete mode 100644 ci/test/docker/windows/dev/release delete mode 100644 ci/test/docker/windows/dev/tag delete mode 100644 ci/test/docker/windows/nondev/main delete mode 100644 ci/test/docker/windows/nondev/other delete mode 100644 ci/test/docker/windows/nondev/release delete mode 100644 ci/test/docker/windows/nondev/tag diff --git a/ci/Dockerfile-envoy-windows b/ci/Dockerfile-envoy-windows deleted file mode 100644 index 4ed5816642..0000000000 --- a/ci/Dockerfile-envoy-windows +++ /dev/null @@ -1,22 +0,0 @@ -ARG BUILD_OS=mcr.microsoft.com/windows/servercore -ARG BUILD_TAG=ltsc2019@sha256:56c5fe9f320b41a873f73ce5d019a9650dce2e10cb27b234d425418bef9310dd - -FROM $BUILD_OS:$BUILD_TAG - -USER ContainerAdministrator -RUN net accounts /MaxPWAge:unlimited -RUN net user /add "EnvoyUser" /expires:never -RUN net localgroup "Network Configuration Operators" "EnvoyUser" /add - -RUN mkdir "C:\\Program\ Files\\envoy" -RUN setx /M path "%path%;c:\Program Files\envoy" -ADD ["windows/amd64/envoy.exe", "C:/Program Files/envoy/"] - -RUN mkdir "C:\\ProgramData\\envoy" -ADD ["configs/envoyproxy_io_proxy.yaml", "C:/ProgramData/envoy/envoy.yaml"] - -EXPOSE 10000 - -COPY ci/docker-entrypoint.bat C:/ -ENTRYPOINT ["C:/docker-entrypoint.bat"] -CMD ["envoy.exe", "-c", "C:\\ProgramData\\envoy\\envoy.yaml"] diff --git a/ci/docker_ci.sh b/ci/docker_ci.sh index 1917459d4d..12a14833e7 100755 --- a/ci/docker_ci.sh +++ b/ci/docker_ci.sh @@ -25,18 +25,8 @@ DOCKER_BUILD_TIMEOUT="${DOCKER_BUILD_TIMEOUT:-500}" DOCKER_PLATFORM="${DOCKER_PLATFORM:-linux/arm64,linux/amd64}" -function is_windows() { - [[ -n "$DOCKER_FAKE_WIN" ]] || [[ "$(uname -s)" == *NT* ]] -} - if [[ -n "$DOCKER_CI_DRYRUN" ]]; then CI_SHA1="${CI_SHA1:-MOCKSHA}" - - if is_windows; then - WINDOWS_IMAGE_BASE="${WINDOWS_IMAGE_BASE:-mcr.microsoft.com/windows/fakecore}" - WINDOWS_IMAGE_TAG="${WINDOWS_IMAGE_TAG:-ltsc1992}" - WINDOWS_BUILD_TYPE="${WINDOWS_BUILD_TYPE:-legacy}" - fi fi MAIN_BRANCH="refs/heads/main" @@ -101,18 +91,12 @@ config_env() { docker buildx create --use --name multi-builder --platform "${DOCKER_PLATFORM}" } -if is_windows; then - BUILD_TYPES=("-${WINDOWS_BUILD_TYPE}") - # BuildKit is not available for Windows images, use standard build command - BUILD_COMMAND=("build") -else - # "-google-vrp" must come afer "" to ensure we rebuild the local base image dependency. - BUILD_TYPES=("" "-debug" "-contrib" "-contrib-debug" "-distroless" "-google-vrp" "-tools") +# "-google-vrp" must come afer "" to ensure we rebuild the local base image dependency. +BUILD_TYPES=("" "-debug" "-contrib" "-contrib-debug" "-distroless" "-google-vrp" "-tools") - # Configure docker-buildx tools - BUILD_COMMAND=("buildx" "build") - config_env -fi +# Configure docker-buildx tools +BUILD_COMMAND=("buildx" "build") +config_env old_image_tag_name () { # envoyproxy/envoy-dev:latest @@ -150,9 +134,7 @@ new_image_tag_name () { build_platforms() { local build_type=$1 - if is_windows; then - echo -n "windows/amd64" - elif [[ "${build_type}" == *-google-vrp ]]; then + if [[ "${build_type}" == *-google-vrp ]]; then echo -n "linux/amd64" else echo -n "$DOCKER_PLATFORM" @@ -162,13 +144,9 @@ build_platforms() { build_args() { local build_type=$1 target - if is_windows; then - printf ' -f ci/Dockerfile-envoy-windows --build-arg BUILD_OS=%s --build-arg BUILD_TAG=%s' "${WINDOWS_IMAGE_BASE}" "${WINDOWS_IMAGE_TAG}" - else - target="${build_type/-debug/}" - target="${target/-contrib/}" - printf ' -f ci/Dockerfile-envoy --target %s' "envoy${target}" - fi + target="${build_type/-debug/}" + target="${target/-contrib/}" + printf ' -f ci/Dockerfile-envoy --target %s' "envoy${target}" if [[ "${build_type}" == *-contrib* ]]; then printf ' --build-arg ENVOY_BINARY=envoy-contrib' @@ -180,10 +158,6 @@ build_args() { } use_builder() { - # BuildKit is not available for Windows images, skip this - if is_windows; then - return - fi echo ">> BUILDX: use multi-builder" echo "> docker buildx use multi-builder" @@ -207,27 +181,25 @@ build_and_maybe_push_image () { build_tag="$(old_image_tag_name "${image_type}")" docker_image_tarball="${ENVOY_DOCKER_IMAGE_DIRECTORY}/envoy${image_type}.tar" - if ! is_windows; then - # `--sbom` and `--provenance` args added for skopeo 1.5.0 compat, - # can probably be removed for later versions. - args+=( - "--sbom=false" - "--provenance=false") - if [[ -n "$LOAD_IMAGES" ]]; then - action="BUILD+LOAD" - args+=("--load") - elif [[ "${image_type}" =~ debug ]]; then - # For linux if its the debug image then push immediately for release branches, - # otherwise just test the build - if [[ -n "$PUSH_IMAGES_TO_REGISTRY" ]]; then - action="BUILD+PUSH" - args+=("--push") - fi - else - # For linux non-debug builds, save it first in the tarball, we will push it - # with skopeo from there if needed. - args+=("-o" "type=oci,dest=${docker_image_tarball}") + # `--sbom` and `--provenance` args added for skopeo 1.5.0 compat, + # can probably be removed for later versions. + args+=( + "--sbom=false" + "--provenance=false") + if [[ -n "$LOAD_IMAGES" ]]; then + action="BUILD+LOAD" + args+=("--load") + elif [[ "${image_type}" =~ debug ]]; then + # For linux if its the debug image then push immediately for release branches, + # otherwise just test the build + if [[ -n "$PUSH_IMAGES_TO_REGISTRY" ]]; then + action="BUILD+PUSH" + args+=("--push") fi + else + # For linux non-debug builds, save it first in the tarball, we will push it + # with skopeo from there if needed. + args+=("-o" "type=oci,dest=${docker_image_tarball}") fi docker_build_args=( @@ -256,13 +228,7 @@ build_and_maybe_push_image () { return fi - if is_windows; then - echo ">> PUSH: ${build_tag}" - echo "> docker push ${build_tag}" - if [[ -z "$DOCKER_CI_DRYRUN" ]]; then - docker push "$build_tag" - fi - elif ! [[ "${image_type}" =~ debug ]]; then + if ! [[ "${image_type}" =~ debug ]]; then push_image_from_tarball "$build_tag" "$docker_image_tarball" fi } @@ -276,18 +242,6 @@ tag_image () { echo ">> TAG: ${build_tag} -> ${tag}" - if is_windows; then - # we cant use buildx to tag remote images on windows - echo "> docker tag ${build_tag} ${tag}" - echo ">> PUSH: ${tag}" - echo "> docker push ${tag}" - if [[ -z "$DOCKER_CI_DRYRUN" ]]; then - docker tag "$build_tag" "$tag" - docker push "$tag" - fi - return - fi - docker_tag_args=( buildx imagetools create "${DOCKER_REGISTRY}/${build_tag}" @@ -341,7 +295,7 @@ tag_variants () { build_tag="$(old_image_tag_name "${image_type}")" new_image_name="$(new_image_tag_name "${image_type}")" - if ! is_windows && [[ "$build_tag" != "$new_image_name" ]]; then + if [[ "$build_tag" != "$new_image_name" ]]; then tag_image "${build_tag}" "${new_image_name}" fi @@ -359,7 +313,7 @@ tag_variants () { tag_name="$(old_image_tag_name "${image_type}" "${variant_type}")" new_tag_name="$(new_image_tag_name "${image_type}" "${variant_type}")" tag_image "${build_tag}" "${tag_name}" - if ! is_windows && ! [[ "$tag_name" == "$new_tag_name" ]]; then + if [[ "$tag_name" != "$new_tag_name" ]]; then tag_image "${build_tag}" "${new_tag_name}" fi fi diff --git a/ci/test/docker/windows/dev/main b/ci/test/docker/windows/dev/main deleted file mode 100644 index 2e5fc316f8..0000000000 --- a/ci/test/docker/windows/dev/main +++ /dev/null @@ -1,9 +0,0 @@ ->> LOGIN ->> BUILD: mocktest/repo-legacy-dev:MOCKSHA -> docker build --platform windows/amd64 -f ci/Dockerfile-envoy-windows --build-arg BUILD_OS=mcr.microsoft.com/windows/fakecore --build-arg BUILD_TAG=ltsc1992 -t mocktest/repo-legacy-dev:MOCKSHA . ->> PUSH: mocktest/repo-legacy-dev:MOCKSHA -> docker push mocktest/repo-legacy-dev:MOCKSHA ->> TAG: mocktest/repo-legacy-dev:MOCKSHA -> mocktest/repo-legacy-dev:latest -> docker tag mocktest/repo-legacy-dev:MOCKSHA mocktest/repo-legacy-dev:latest ->> PUSH: mocktest/repo-legacy-dev:latest -> docker push mocktest/repo-legacy-dev:latest diff --git a/ci/test/docker/windows/dev/other b/ci/test/docker/windows/dev/other deleted file mode 100644 index 01c4ab93e2..0000000000 --- a/ci/test/docker/windows/dev/other +++ /dev/null @@ -1,2 +0,0 @@ ->> BUILD: mocktest/repo-legacy-dev:MOCKSHA -> docker build --platform windows/amd64 -f ci/Dockerfile-envoy-windows --build-arg BUILD_OS=mcr.microsoft.com/windows/fakecore --build-arg BUILD_TAG=ltsc1992 -t mocktest/repo-legacy-dev:MOCKSHA . diff --git a/ci/test/docker/windows/dev/release b/ci/test/docker/windows/dev/release deleted file mode 100644 index 01c4ab93e2..0000000000 --- a/ci/test/docker/windows/dev/release +++ /dev/null @@ -1,2 +0,0 @@ ->> BUILD: mocktest/repo-legacy-dev:MOCKSHA -> docker build --platform windows/amd64 -f ci/Dockerfile-envoy-windows --build-arg BUILD_OS=mcr.microsoft.com/windows/fakecore --build-arg BUILD_TAG=ltsc1992 -t mocktest/repo-legacy-dev:MOCKSHA . diff --git a/ci/test/docker/windows/dev/tag b/ci/test/docker/windows/dev/tag deleted file mode 100644 index 01c4ab93e2..0000000000 --- a/ci/test/docker/windows/dev/tag +++ /dev/null @@ -1,2 +0,0 @@ ->> BUILD: mocktest/repo-legacy-dev:MOCKSHA -> docker build --platform windows/amd64 -f ci/Dockerfile-envoy-windows --build-arg BUILD_OS=mcr.microsoft.com/windows/fakecore --build-arg BUILD_TAG=ltsc1992 -t mocktest/repo-legacy-dev:MOCKSHA . diff --git a/ci/test/docker/windows/nondev/main b/ci/test/docker/windows/nondev/main deleted file mode 100644 index 089ccd84cf..0000000000 --- a/ci/test/docker/windows/nondev/main +++ /dev/null @@ -1,9 +0,0 @@ ->> LOGIN ->> BUILD: mocktest/repo-legacy:v1.73.0 -> docker build --platform windows/amd64 -f ci/Dockerfile-envoy-windows --build-arg BUILD_OS=mcr.microsoft.com/windows/fakecore --build-arg BUILD_TAG=ltsc1992 -t mocktest/repo-legacy:v1.73.0 . ->> PUSH: mocktest/repo-legacy:v1.73.0 -> docker push mocktest/repo-legacy:v1.73.0 ->> TAG: mocktest/repo-legacy:v1.73.0 -> mocktest/repo-legacy:v1.73-latest -> docker tag mocktest/repo-legacy:v1.73.0 mocktest/repo-legacy:v1.73-latest ->> PUSH: mocktest/repo-legacy:v1.73-latest -> docker push mocktest/repo-legacy:v1.73-latest diff --git a/ci/test/docker/windows/nondev/other b/ci/test/docker/windows/nondev/other deleted file mode 100644 index 051304c7c8..0000000000 --- a/ci/test/docker/windows/nondev/other +++ /dev/null @@ -1,2 +0,0 @@ ->> BUILD: mocktest/repo-legacy:v1.73.3 -> docker build --platform windows/amd64 -f ci/Dockerfile-envoy-windows --build-arg BUILD_OS=mcr.microsoft.com/windows/fakecore --build-arg BUILD_TAG=ltsc1992 -t mocktest/repo-legacy:v1.73.3 . diff --git a/ci/test/docker/windows/nondev/release b/ci/test/docker/windows/nondev/release deleted file mode 100644 index f9619d883b..0000000000 --- a/ci/test/docker/windows/nondev/release +++ /dev/null @@ -1,9 +0,0 @@ ->> LOGIN ->> BUILD: mocktest/repo-legacy:v1.73.3 -> docker build --platform windows/amd64 -f ci/Dockerfile-envoy-windows --build-arg BUILD_OS=mcr.microsoft.com/windows/fakecore --build-arg BUILD_TAG=ltsc1992 -t mocktest/repo-legacy:v1.73.3 . ->> PUSH: mocktest/repo-legacy:v1.73.3 -> docker push mocktest/repo-legacy:v1.73.3 ->> TAG: mocktest/repo-legacy:v1.73.3 -> mocktest/repo-legacy:v1.73-latest -> docker tag mocktest/repo-legacy:v1.73.3 mocktest/repo-legacy:v1.73-latest ->> PUSH: mocktest/repo-legacy:v1.73-latest -> docker push mocktest/repo-legacy:v1.73-latest diff --git a/ci/test/docker/windows/nondev/tag b/ci/test/docker/windows/nondev/tag deleted file mode 100644 index 051304c7c8..0000000000 --- a/ci/test/docker/windows/nondev/tag +++ /dev/null @@ -1,2 +0,0 @@ ->> BUILD: mocktest/repo-legacy:v1.73.3 -> docker build --platform windows/amd64 -f ci/Dockerfile-envoy-windows --build-arg BUILD_OS=mcr.microsoft.com/windows/fakecore --build-arg BUILD_TAG=ltsc1992 -t mocktest/repo-legacy:v1.73.3 . diff --git a/ci/test_docker_ci.sh b/ci/test_docker_ci.sh index f29964f353..cb33828714 100755 --- a/ci/test_docker_ci.sh +++ b/ci/test_docker_ci.sh @@ -20,7 +20,7 @@ TAG_BRANCH="refs/tags/vXXX" MAIN_BRANCH="refs/heads/main" OTHER_BRANCH="refs/heads/something/else" -PLATFORMS=(linux windows) +PLATFORMS=(linux) TEST_TYPES=(dev nondev) BRANCH_TYPES=(tag release main other) @@ -62,19 +62,15 @@ _test () { export ENVOY_DOCKER_IMAGE_DIRECTORY=/non/existent/test/path export DOCKER_IMAGE_PREFIX=mocktest/repo - if [[ "$platform" == "windows" ]]; then - export DOCKER_FAKE_WIN=1 - fi - if [[ "$DOCKER_CI_TEST_COMMIT" ]]; then echo "COMMIT(${name}): > ${testdata}" - echo " DOCKER_FAKE_WIN=${DOCKER_FAKE_WIN} ENVOY_VERSION=${version} ENVOY_DOCKER_IMAGE_DIRECTORY=/non/existent/test/path CI_BRANCH=${branch} DOCKER_CI_DRYRUN=1 ./ci/docker_ci.sh | grep -E \"^>\"" + echo " ENVOY_VERSION=${version} ENVOY_DOCKER_IMAGE_DIRECTORY=/non/existent/test/path CI_BRANCH=${branch} DOCKER_CI_DRYRUN=1 ./ci/docker_ci.sh | grep -E \"^>\"" ./ci/docker_ci.sh | grep -E "^>" > "$testdata" return fi echo "TEST(${name}): <> ${testdata}" - echo " DOCKER_FAKE_WIN=${DOCKER_FAKE_WIN} ENVOY_VERSION=${version} ENVOY_DOCKER_IMAGE_DIRECTORY=/non/existent/test/path CI_BRANCH=${branch} DOCKER_CI_DRYRUN=1 ./ci/docker_ci.sh | grep -E \"^>\"" + echo " ENVOY_VERSION=${version} ENVOY_DOCKER_IMAGE_DIRECTORY=/non/existent/test/path CI_BRANCH=${branch} DOCKER_CI_DRYRUN=1 ./ci/docker_ci.sh | grep -E \"^>\"" generated="$(mktemp)" ./ci/docker_ci.sh | grep -E "^>" > "$generated" diff --git a/docs/conf.py b/docs/conf.py index 45b46b6ee6..40099cb9d6 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -68,16 +68,8 @@ def dockerhub_envoy_role( if part.startswith("envoy"): part = part[len("envoy"):] - # windows images - if part == "windows-dev": - title = f"envoyproxy/envoy-{part}" - full_url = f"https://hub.docker.com/r/envoyproxy/envoy-{part}/tags?name=latest" - elif part == "windows": - title = f"envoyproxy/envoy-{part}:{_config('docker_image_tag_name')}" - full_url = f"https://hub.docker.com/r/envoyproxy/envoy-{part}/tags?name={_config('docker_image_tag_name')}" - # envoy-build-ubuntu images - elif part.startswith("build"): + if part.startswith("build"): parts = part.split("-") if len(parts) > 2: title = f"envoyproxy/envoy-build-ubuntu:{''.join(parts[2:])}-" @@ -177,12 +169,10 @@ def _config(key): if 'pre-release' in release_level: substitutions = [ ('|envoy_docker_image|', 'envoy:dev-{}'.format(blob_sha)), - ('|envoy_windows_docker_image|', 'envoy-windows-dev:{}'.format(blob_sha)), ('|envoy_distroless_docker_image|', 'envoy:distroless-dev-{}'.format(blob_sha)) ] else: substitutions = [('|envoy_docker_image|', 'envoy:{}'.format(blob_sha)), - ('|envoy_windows_docker_image|', 'envoy-windows:{}'.format(blob_sha)), ('|envoy_distroless_docker_image|', 'envoy:distroless-{}'.format(blob_sha))] # Add any paths that contain templates here, relative to this directory. From 135a6a29c16eacf46fdc8f1a87b4864e3c403eb6 Mon Sep 17 00:00:00 2001 From: Misha Efimov Date: Fri, 20 Sep 2024 14:05:56 -0400 Subject: [PATCH 46/65] Add `metric_names_for_computing_utilization` field to `ClientSideWeightedRoundRobin` LB Policy proto. (#36201) This is a minor change to unblock config plane work while #35905 is going through review. See #35905 for initial LB policy implementation. Docs Changes: n/a Release Notes: n/a Platform Specific Features: n/a Part of #34777 Signed-off-by: Misha Efimov --- .../v3/client_side_weighted_round_robin.proto | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/api/envoy/extensions/load_balancing_policies/client_side_weighted_round_robin/v3/client_side_weighted_round_robin.proto b/api/envoy/extensions/load_balancing_policies/client_side_weighted_round_robin/v3/client_side_weighted_round_robin.proto index c70360a094..7ad46a56de 100644 --- a/api/envoy/extensions/load_balancing_policies/client_side_weighted_round_robin/v3/client_side_weighted_round_robin.proto +++ b/api/envoy/extensions/load_balancing_policies/client_side_weighted_round_robin/v3/client_side_weighted_round_robin.proto @@ -30,11 +30,12 @@ option (udpa.annotations.file_status).package_version_status = ACTIVE; // regardless of result. Only failed queries count toward eps. A config // parameter error_utilization_penalty controls the penalty to adjust endpoint // weights using eps and qps. The weight of a given endpoint is computed as: -// qps / (utilization + eps/qps * error_utilization_penalty) +// ``qps / (utilization + eps/qps * error_utilization_penalty)``. // -// See the :ref:`load balancing architecture overview` for more information. +// See the :ref:`load balancing architecture +// overview` for more information. // -// [#next-free-field: 7] +// [#next-free-field: 8] message ClientSideWeightedRoundRobin { // Whether to enable out-of-band utilization reporting collection from // the endpoints. By default, per-request utilization reporting is used. @@ -68,4 +69,10 @@ message ClientSideWeightedRoundRobin { // calculated as eps/qps. Configuration is rejected if this value is negative. // Default is 1.0. google.protobuf.FloatValue error_utilization_penalty = 6 [(validate.rules).float = {gte: 0.0}]; + + // By default, endpoint weight is computed based on the :ref:`application_utilization ` field reported by the endpoint. + // If that field is not set, then utilization will instead be computed by taking the max of the values of the metrics specified here. + // For map fields in the ORCA proto, the string will be of the form ``.``. For example, the string ``named_metrics.foo`` will mean to look for the key ``foo`` in the ORCA :ref:`named_metrics ` field. + // If none of the specified metrics are present in the load report, then :ref:`cpu_utilization ` is used instead. + repeated string metric_names_for_computing_utilization = 7; } From cfb1b7e793a4a7f6c5e2dcf49027b980c05a3b0b Mon Sep 17 00:00:00 2001 From: danzh Date: Fri, 20 Sep 2024 14:10:18 -0400 Subject: [PATCH 47/65] quic: fix connection close error when blocked socket gets unblocked (#36238) Today the connection will be closed with QUIC_INTERNAL_ERROR because of https://github.com/google/quiche/blob/4249f8025caed1e3d71d04d9cadf42251acb7cac/quiche/quic/core/quic_connection.cc#L2703 if the socket becomes write blocked and then unblocked. This change fixes it by calling OnBlockedWriterCanWrite()(https://github.com/google/quiche/blob/4249f8025caed1e3d71d04d9cadf42251acb7cac/quiche/quic/core/quic_connection.cc#L2692) instead which set the writer to be unblocked before OnCanWrite(). Risk Level: low, fix existing issue Testing: added unit tests Docs Changes: N/A Release Notes: N/A Platform Specific Features: N/A Signed-off-by: Dan Zhang --- .../quic/envoy_quic_client_connection.cc | 15 +++--- .../quic/envoy_quic_client_connection.h | 2 + test/common/quic/BUILD | 1 + .../quic/envoy_quic_client_session_test.cc | 46 +++++++++++++++++++ 4 files changed, 57 insertions(+), 7 deletions(-) diff --git a/source/common/quic/envoy_quic_client_connection.cc b/source/common/quic/envoy_quic_client_connection.cc index d332108545..a2b817dadd 100644 --- a/source/common/quic/envoy_quic_client_connection.cc +++ b/source/common/quic/envoy_quic_client_connection.cc @@ -242,7 +242,7 @@ void EnvoyQuicClientConnection::onFileEvent(uint32_t events, ASSERT(events & (Event::FileReadyType::Read | Event::FileReadyType::Write)); if (events & Event::FileReadyType::Write) { - OnCanWrite(); + OnBlockedWriterCanWrite(); } bool is_probing_socket = @@ -261,14 +261,15 @@ void EnvoyQuicClientConnection::onFileEvent(uint32_t events, connection_socket.ioHandle(), *connection_socket.connectionInfoProvider().localAddress(), *this, dispatcher_.timeSource(), prefer_gro_, !disallow_mmsg_, packets_dropped_); if (err == nullptr) { - // In the case where the path validation fails, the probing socket will be closed and its IO - // events are no longer interesting. - if (!is_probing_socket || HasPendingPathValidation() || - connectionSocket().get() == &connection_socket) { + // If this READ event is on the probing socket and any packet read failed the path validation + // (i.e. via STATELESS_RESET), the probing socket should have been closed and the default + // socket remained unchanged. In this case any remaining unread packets are no longer + // interesting. Only re-register READ event to continue reading the remaining packets in the + // next loop if this is not the case. + if (!(is_probing_socket && !HasPendingPathValidation() && + connectionSocket().get() != &connection_socket)) { connection_socket.ioHandle().activateFileEvents(Event::FileReadyType::Read); - return; } - } else if (err->getErrorCode() != Api::IoError::IoErrorCode::Again) { ENVOY_CONN_LOG(error, "recvmsg result {}: {}", *this, static_cast(err->getErrorCode()), err->getErrorDetails()); diff --git a/source/common/quic/envoy_quic_client_connection.h b/source/common/quic/envoy_quic_client_connection.h index 197f12ebf7..d673033ed9 100644 --- a/source/common/quic/envoy_quic_client_connection.h +++ b/source/common/quic/envoy_quic_client_connection.h @@ -121,6 +121,8 @@ class EnvoyQuicClientConnection : public quic::QuicConnection, probeAndMigrateToServerPreferredAddress(const quic::QuicSocketAddress& server_preferred_address); private: + friend class EnvoyQuicClientConnectionPeer; + // Receives notifications from the Quiche layer on path validation results. class EnvoyPathValidationResultDelegate : public quic::QuicPathValidator::ResultDelegate { public: diff --git a/test/common/quic/BUILD b/test/common/quic/BUILD index 71fa7de681..0a4e8ad774 100644 --- a/test/common/quic/BUILD +++ b/test/common/quic/BUILD @@ -200,6 +200,7 @@ envoy_cc_test( "//source/common/quic:envoy_quic_client_session_lib", "//source/common/quic:envoy_quic_connection_helper_lib", "//source/extensions/quic/crypto_stream:envoy_quic_crypto_client_stream_lib", + "//test/mocks/api:api_mocks", "//test/mocks/http:http_mocks", "//test/mocks/http:stream_decoder_mock", "//test/mocks/network:network_mocks", diff --git a/test/common/quic/envoy_quic_client_session_test.cc b/test/common/quic/envoy_quic_client_session_test.cc index 592b7782dd..d757f03a0b 100644 --- a/test/common/quic/envoy_quic_client_session_test.cc +++ b/test/common/quic/envoy_quic_client_session_test.cc @@ -2,6 +2,7 @@ #include "source/common/api/os_sys_calls_impl.h" #include "source/common/network/transport_socket_options_impl.h" +#include "source/common/network/udp_packet_writer_handler_impl.h" #include "source/common/quic/client_codec_impl.h" #include "source/common/quic/envoy_quic_alarm_factory.h" #include "source/common/quic/envoy_quic_client_connection.h" @@ -11,6 +12,7 @@ #include "source/extensions/quic/crypto_stream/envoy_quic_crypto_client_stream.h" #include "test/common/quic/test_utils.h" +#include "test/mocks/api/mocks.h" #include "test/mocks/event/mocks.h" #include "test/mocks/http/mocks.h" #include "test/mocks/http/stream_decoder.h" @@ -37,6 +39,14 @@ using testing::Return; namespace Envoy { namespace Quic { +class EnvoyQuicClientConnectionPeer { +public: + static void onFileEvent(EnvoyQuicClientConnection& connection, uint32_t events, + Network::ConnectionSocket& connection_socket) { + connection.onFileEvent(events, connection_socket); + } +}; + class TestEnvoyQuicClientConnection : public EnvoyQuicClientConnection { public: TestEnvoyQuicClientConnection(const quic::QuicConnectionId& server_connection_id, @@ -636,6 +646,42 @@ TEST_P(EnvoyQuicClientSessionTest, UseSocketAddressCache) { EXPECT_EQ(last_peer_address.get(), quic_connection_->getLastPeerAddress().get()); } +TEST_P(EnvoyQuicClientSessionTest, WriteBlockedAndUnblock) { + Api::MockOsSysCalls os_sys_calls; + TestThreadsafeSingletonInjector singleton_injector{&os_sys_calls}; + + // Switch to a real writer, and synthesize a write block on it. + quic_connection_->SetQuicPacketWriter( + new EnvoyQuicPacketWriter(std::make_unique( + quic_connection_->connectionSocket()->ioHandle())), + true); + if (quic_connection_->connectionSocket()->ioHandle().wasConnected()) { + EXPECT_CALL(os_sys_calls, send(_, _, _, _)) + .Times(2) + .WillOnce(Return(Api::SysCallSizeResult{-1, SOCKET_ERROR_AGAIN})); + } else { + EXPECT_CALL(os_sys_calls, sendmsg(_, _, _)) + .Times(2) + .WillOnce(Return(Api::SysCallSizeResult{-1, SOCKET_ERROR_AGAIN})); + } + // OnCanWrite() would close the connection if the underlying writer is not unblocked. + EXPECT_CALL(*quic_connection_, SendConnectionClosePacket(quic::QUIC_INTERNAL_ERROR, _, _)) + .Times(0); + Http::MockResponseDecoder response_decoder; + Http::MockStreamCallbacks stream_callbacks; + EnvoyQuicClientStream& stream = sendGetRequest(response_decoder, stream_callbacks); + EXPECT_TRUE(quic_connection_->writer()->IsWriteBlocked()); + + // Synthesize a WRITE event. + EnvoyQuicClientConnectionPeer::onFileEvent(*quic_connection_, Event::FileReadyType::Write, + *quic_connection_->connectionSocket()); + EXPECT_FALSE(quic_connection_->writer()->IsWriteBlocked()); + EXPECT_CALL(stream_callbacks, + onResetStream(Http::StreamResetReason::LocalReset, "QUIC_STREAM_REQUEST_REJECTED")); + EXPECT_CALL(*quic_connection_, SendControlFrame(_)); + stream.resetStream(Http::StreamResetReason::LocalReset); +} + class MockOsSysCallsImpl : public Api::OsSysCallsImpl { public: MOCK_METHOD(Api::SysCallSizeResult, recvmsg, (os_fd_t socket, msghdr* msg, int flags), From a65a5b673e6ac0ef12a3d8c5c2cdd2be4295927b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20R=2E=20Sede=C3=B1o?= Date: Fri, 20 Sep 2024 15:56:06 -0400 Subject: [PATCH 48/65] Updates to mobile/third_party/rbe_configs/cc/ (#36269) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This updates files containing paths to older versions of the docker container being used in CI. This matters when clang modules are being used and some dependency (looking at absl) turns on layering checks. Not updating these files prevents abseil from including many standard headers. These files should be regenerated whenever our base docker container or toolchain is updated. These files were regenerated following the instructions in https://github.com/bazelbuild/bazel-toolchains Specifically: ``` $ ./rbe_configs_gen \ --bazel_version="6.5.0" \ --toolchain_container="docker.io/envoyproxy/envoy-build-ubuntu:f94a38f62220a2b017878b790b6ea98a0f6c5f9c" \ --exec_os="linux" \ --target_os="linux" \ --output_src_root="/path/to/envoy-mobile" \ --output_config_path="third_party/rbe_configs" \ --cpp_env_json=clang.json \ --generate_java_configs=False $ cat clang.json {"CC": "/opt/llvm/bin/clang", "CXX": "/opt/llvm/bin/clang++"} ``` Other files were also regenerated, but this commit only contains changes to files with paths. Risk Level: low Testing: CI, since this specifically affects the CI. Signed-off-by: Alejandro R SedeƱo --- mobile/third_party/rbe_configs/cc/BUILD | 7 +- .../cc/builtin_include_directory_paths | 7 +- .../rbe_configs/cc/module.modulemap | 3722 +++++++++-------- 3 files changed, 1909 insertions(+), 1827 deletions(-) diff --git a/mobile/third_party/rbe_configs/cc/BUILD b/mobile/third_party/rbe_configs/cc/BUILD index ef5c08e321..9c50a3630c 100644 --- a/mobile/third_party/rbe_configs/cc/BUILD +++ b/mobile/third_party/rbe_configs/cc/BUILD @@ -84,9 +84,10 @@ cc_toolchain_config( "/usr/include/x86_64-linux-gnu", "/usr/include", "/opt/llvm/lib/clang/14.0.0/share", - "/usr/include/c++/9", - "/usr/include/x86_64-linux-gnu/c++/9", - "/usr/include/c++/9/backward", + "/usr/include/c++/11", + "/usr/include/x86_64-linux-gnu/c++/11", + "/usr/include/c++/11/backward", + "/opt/llvm/include/x86_64-unknown-linux-gnu/c++/v1", "/opt/llvm/include/c++/v1"], tool_paths = {"ar": "/usr/bin/ar", "ld": "/usr/bin/ld", diff --git a/mobile/third_party/rbe_configs/cc/builtin_include_directory_paths b/mobile/third_party/rbe_configs/cc/builtin_include_directory_paths index cb7a9aa164..4b05ac9206 100644 --- a/mobile/third_party/rbe_configs/cc/builtin_include_directory_paths +++ b/mobile/third_party/rbe_configs/cc/builtin_include_directory_paths @@ -9,7 +9,8 @@ declared action inputs or the action commandline changes. /usr/include/x86_64-linux-gnu /usr/include /opt/llvm/lib/clang/14.0.0/share -/usr/include/c++/9 -/usr/include/x86_64-linux-gnu/c++/9 -/usr/include/c++/9/backward +/usr/include/c++/11 +/usr/include/x86_64-linux-gnu/c++/11 +/usr/include/c++/11/backward +/opt/llvm/include/x86_64-unknown-linux-gnu/c++/v1 /opt/llvm/include/c++/v1 diff --git a/mobile/third_party/rbe_configs/cc/module.modulemap b/mobile/third_party/rbe_configs/cc/module.modulemap index b6f69ccde7..a19420cd33 100644 --- a/mobile/third_party/rbe_configs/cc/module.modulemap +++ b/mobile/third_party/rbe_configs/cc/module.modulemap @@ -205,7 +205,6 @@ module "crosstool" [system] { textual header "/usr/include/x86_64-linux-gnu/asm/fcntl.h" textual header "/usr/include/x86_64-linux-gnu/asm/hw_breakpoint.h" textual header "/usr/include/x86_64-linux-gnu/asm/hwcap2.h" - textual header "/usr/include/x86_64-linux-gnu/asm/hyperv.h" textual header "/usr/include/x86_64-linux-gnu/asm/ioctl.h" textual header "/usr/include/x86_64-linux-gnu/asm/ioctls.h" textual header "/usr/include/x86_64-linux-gnu/asm/ipcbuf.h" @@ -256,20 +255,24 @@ module "crosstool" [system] { textual header "/usr/include/x86_64-linux-gnu/asm/vmx.h" textual header "/usr/include/x86_64-linux-gnu/asm/vsyscall.h" textual header "/usr/include/x86_64-linux-gnu/bits/a.out.h" + textual header "/usr/include/x86_64-linux-gnu/bits/argp-ldbl.h" textual header "/usr/include/x86_64-linux-gnu/bits/auxv.h" - textual header "/usr/include/x86_64-linux-gnu/bits/byteswap-16.h" textual header "/usr/include/x86_64-linux-gnu/bits/byteswap.h" textual header "/usr/include/x86_64-linux-gnu/bits/cmathcalls.h" textual header "/usr/include/x86_64-linux-gnu/bits/confname.h" textual header "/usr/include/x86_64-linux-gnu/bits/cpu-set.h" + textual header "/usr/include/x86_64-linux-gnu/bits/dirent_ext.h" textual header "/usr/include/x86_64-linux-gnu/bits/dirent.h" textual header "/usr/include/x86_64-linux-gnu/bits/dlfcn.h" textual header "/usr/include/x86_64-linux-gnu/bits/elfclass.h" textual header "/usr/include/x86_64-linux-gnu/bits/endian.h" + textual header "/usr/include/x86_64-linux-gnu/bits/endianness.h" textual header "/usr/include/x86_64-linux-gnu/bits/environments.h" textual header "/usr/include/x86_64-linux-gnu/bits/epoll.h" + textual header "/usr/include/x86_64-linux-gnu/bits/err-ldbl.h" textual header "/usr/include/x86_64-linux-gnu/bits/errno.h" textual header "/usr/include/x86_64-linux-gnu/bits/error.h" + textual header "/usr/include/x86_64-linux-gnu/bits/error-ldbl.h" textual header "/usr/include/x86_64-linux-gnu/bits/eventfd.h" textual header "/usr/include/x86_64-linux-gnu/bits/fcntl2.h" textual header "/usr/include/x86_64-linux-gnu/bits/fcntl.h" @@ -281,22 +284,21 @@ module "crosstool" [system] { textual header "/usr/include/x86_64-linux-gnu/bits/flt-eval-method.h" textual header "/usr/include/x86_64-linux-gnu/bits/fp-fast.h" textual header "/usr/include/x86_64-linux-gnu/bits/fp-logb.h" - textual header "/usr/include/x86_64-linux-gnu/bits/_G_config.h" textual header "/usr/include/x86_64-linux-gnu/bits/getopt_core.h" textual header "/usr/include/x86_64-linux-gnu/bits/getopt_ext.h" textual header "/usr/include/x86_64-linux-gnu/bits/getopt_posix.h" textual header "/usr/include/x86_64-linux-gnu/bits/hwcap.h" + textual header "/usr/include/x86_64-linux-gnu/bits/indirect-return.h" textual header "/usr/include/x86_64-linux-gnu/bits/in.h" textual header "/usr/include/x86_64-linux-gnu/bits/initspin.h" textual header "/usr/include/x86_64-linux-gnu/bits/inotify.h" textual header "/usr/include/x86_64-linux-gnu/bits/ioctls.h" textual header "/usr/include/x86_64-linux-gnu/bits/ioctl-types.h" textual header "/usr/include/x86_64-linux-gnu/bits/ipc.h" + textual header "/usr/include/x86_64-linux-gnu/bits/ipc-perm.h" textual header "/usr/include/x86_64-linux-gnu/bits/ipctypes.h" textual header "/usr/include/x86_64-linux-gnu/bits/iscanonical.h" textual header "/usr/include/x86_64-linux-gnu/bits/libc-header-start.h" - textual header "/usr/include/x86_64-linux-gnu/bits/libio.h" - textual header "/usr/include/x86_64-linux-gnu/bits/libio-ldbl.h" textual header "/usr/include/x86_64-linux-gnu/bits/libm-simd-decl-stubs.h" textual header "/usr/include/x86_64-linux-gnu/bits/link.h" textual header "/usr/include/x86_64-linux-gnu/bits/locale.h" @@ -304,17 +306,19 @@ module "crosstool" [system] { textual header "/usr/include/x86_64-linux-gnu/bits/long-double.h" textual header "/usr/include/x86_64-linux-gnu/bits/mathcalls.h" textual header "/usr/include/x86_64-linux-gnu/bits/mathcalls-helper-functions.h" + textual header "/usr/include/x86_64-linux-gnu/bits/mathcalls-narrow.h" textual header "/usr/include/x86_64-linux-gnu/bits/mathdef.h" - textual header "/usr/include/x86_64-linux-gnu/bits/math-finite.h" textual header "/usr/include/x86_64-linux-gnu/bits/mathinline.h" textual header "/usr/include/x86_64-linux-gnu/bits/math-vector.h" textual header "/usr/include/x86_64-linux-gnu/bits/mman.h" textual header "/usr/include/x86_64-linux-gnu/bits/mman-linux.h" + textual header "/usr/include/x86_64-linux-gnu/bits/mman-map-flags-generic.h" textual header "/usr/include/x86_64-linux-gnu/bits/mman-shared.h" textual header "/usr/include/x86_64-linux-gnu/bits/monetary-ldbl.h" textual header "/usr/include/x86_64-linux-gnu/bits/mqueue2.h" textual header "/usr/include/x86_64-linux-gnu/bits/mqueue.h" textual header "/usr/include/x86_64-linux-gnu/bits/msq.h" + textual header "/usr/include/x86_64-linux-gnu/bits/msq-pad.h" textual header "/usr/include/x86_64-linux-gnu/bits/netdb.h" textual header "/usr/include/x86_64-linux-gnu/bits/param.h" textual header "/usr/include/x86_64-linux-gnu/bits/poll2.h" @@ -323,6 +327,10 @@ module "crosstool" [system] { textual header "/usr/include/x86_64-linux-gnu/bits/posix2_lim.h" textual header "/usr/include/x86_64-linux-gnu/bits/posix_opt.h" textual header "/usr/include/x86_64-linux-gnu/bits/printf-ldbl.h" + textual header "/usr/include/x86_64-linux-gnu/bits/procfs-extra.h" + textual header "/usr/include/x86_64-linux-gnu/bits/procfs.h" + textual header "/usr/include/x86_64-linux-gnu/bits/procfs-id.h" + textual header "/usr/include/x86_64-linux-gnu/bits/procfs-prregset.h" textual header "/usr/include/x86_64-linux-gnu/bits/pthreadtypes-arch.h" textual header "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" textual header "/usr/include/x86_64-linux-gnu/bits/ptrace-shared.h" @@ -332,15 +340,19 @@ module "crosstool" [system] { textual header "/usr/include/x86_64-linux-gnu/bits/select.h" textual header "/usr/include/x86_64-linux-gnu/bits/semaphore.h" textual header "/usr/include/x86_64-linux-gnu/bits/sem.h" + textual header "/usr/include/x86_64-linux-gnu/bits/sem-pad.h" textual header "/usr/include/x86_64-linux-gnu/bits/setjmp2.h" textual header "/usr/include/x86_64-linux-gnu/bits/setjmp.h" textual header "/usr/include/x86_64-linux-gnu/bits/shm.h" + textual header "/usr/include/x86_64-linux-gnu/bits/shmlba.h" + textual header "/usr/include/x86_64-linux-gnu/bits/shm-pad.h" textual header "/usr/include/x86_64-linux-gnu/bits/sigaction.h" textual header "/usr/include/x86_64-linux-gnu/bits/sigcontext.h" textual header "/usr/include/x86_64-linux-gnu/bits/sigevent-consts.h" textual header "/usr/include/x86_64-linux-gnu/bits/siginfo-arch.h" textual header "/usr/include/x86_64-linux-gnu/bits/siginfo-consts-arch.h" textual header "/usr/include/x86_64-linux-gnu/bits/siginfo-consts.h" + textual header "/usr/include/x86_64-linux-gnu/bits/signal_ext.h" textual header "/usr/include/x86_64-linux-gnu/bits/signalfd.h" textual header "/usr/include/x86_64-linux-gnu/bits/signum-generic.h" textual header "/usr/include/x86_64-linux-gnu/bits/signum.h" @@ -348,6 +360,7 @@ module "crosstool" [system] { textual header "/usr/include/x86_64-linux-gnu/bits/sigthread.h" textual header "/usr/include/x86_64-linux-gnu/bits/sockaddr.h" textual header "/usr/include/x86_64-linux-gnu/bits/socket2.h" + textual header "/usr/include/x86_64-linux-gnu/bits/socket-constants.h" textual header "/usr/include/x86_64-linux-gnu/bits/socket.h" textual header "/usr/include/x86_64-linux-gnu/bits/socket_type.h" textual header "/usr/include/x86_64-linux-gnu/bits/ss_flags.h" @@ -355,6 +368,8 @@ module "crosstool" [system] { textual header "/usr/include/x86_64-linux-gnu/bits/statfs.h" textual header "/usr/include/x86_64-linux-gnu/bits/stat.h" textual header "/usr/include/x86_64-linux-gnu/bits/statvfs.h" + textual header "/usr/include/x86_64-linux-gnu/bits/statx-generic.h" + textual header "/usr/include/x86_64-linux-gnu/bits/statx.h" textual header "/usr/include/x86_64-linux-gnu/bits/stdint-intn.h" textual header "/usr/include/x86_64-linux-gnu/bits/stdint-uintn.h" textual header "/usr/include/x86_64-linux-gnu/bits/stdio2.h" @@ -367,7 +382,8 @@ module "crosstool" [system] { textual header "/usr/include/x86_64-linux-gnu/bits/stdlib-ldbl.h" textual header "/usr/include/x86_64-linux-gnu/bits/string_fortified.h" textual header "/usr/include/x86_64-linux-gnu/bits/strings_fortified.h" - textual header "/usr/include/x86_64-linux-gnu/bits/stropts.h" + textual header "/usr/include/x86_64-linux-gnu/bits/struct_mutex.h" + textual header "/usr/include/x86_64-linux-gnu/bits/struct_rwlock.h" textual header "/usr/include/x86_64-linux-gnu/bits/syscall.h" textual header "/usr/include/x86_64-linux-gnu/bits/sysctl.h" textual header "/usr/include/x86_64-linux-gnu/bits/sys_errlist.h" @@ -375,15 +391,30 @@ module "crosstool" [system] { textual header "/usr/include/x86_64-linux-gnu/bits/syslog-ldbl.h" textual header "/usr/include/x86_64-linux-gnu/bits/syslog-path.h" textual header "/usr/include/x86_64-linux-gnu/bits/sysmacros.h" + textual header "/usr/include/x86_64-linux-gnu/bits/termios-baud.h" + textual header "/usr/include/x86_64-linux-gnu/bits/termios-c_cc.h" + textual header "/usr/include/x86_64-linux-gnu/bits/termios-c_cflag.h" + textual header "/usr/include/x86_64-linux-gnu/bits/termios-c_iflag.h" + textual header "/usr/include/x86_64-linux-gnu/bits/termios-c_lflag.h" + textual header "/usr/include/x86_64-linux-gnu/bits/termios-c_oflag.h" textual header "/usr/include/x86_64-linux-gnu/bits/termios.h" + textual header "/usr/include/x86_64-linux-gnu/bits/termios-misc.h" + textual header "/usr/include/x86_64-linux-gnu/bits/termios-struct.h" + textual header "/usr/include/x86_64-linux-gnu/bits/termios-tcflow.h" textual header "/usr/include/x86_64-linux-gnu/bits/thread-shared-types.h" + textual header "/usr/include/x86_64-linux-gnu/bits/time64.h" textual header "/usr/include/x86_64-linux-gnu/bits/time.h" textual header "/usr/include/x86_64-linux-gnu/bits/timerfd.h" + textual header "/usr/include/x86_64-linux-gnu/bits/timesize.h" textual header "/usr/include/x86_64-linux-gnu/bits/timex.h" textual header "/usr/include/x86_64-linux-gnu/bits/types/clockid_t.h" textual header "/usr/include/x86_64-linux-gnu/bits/types/clock_t.h" + textual header "/usr/include/x86_64-linux-gnu/bits/types/cookie_io_functions_t.h" + textual header "/usr/include/x86_64-linux-gnu/bits/types/error_t.h" textual header "/usr/include/x86_64-linux-gnu/bits/types/__FILE.h" textual header "/usr/include/x86_64-linux-gnu/bits/types/FILE.h" + textual header "/usr/include/x86_64-linux-gnu/bits/types/__fpos64_t.h" + textual header "/usr/include/x86_64-linux-gnu/bits/types/__fpos_t.h" textual header "/usr/include/x86_64-linux-gnu/bits/types.h" textual header "/usr/include/x86_64-linux-gnu/bits/typesizes.h" textual header "/usr/include/x86_64-linux-gnu/bits/types/__locale_t.h" @@ -399,11 +430,15 @@ module "crosstool" [system] { textual header "/usr/include/x86_64-linux-gnu/bits/types/__sigval_t.h" textual header "/usr/include/x86_64-linux-gnu/bits/types/sigval_t.h" textual header "/usr/include/x86_64-linux-gnu/bits/types/stack_t.h" + textual header "/usr/include/x86_64-linux-gnu/bits/types/struct_FILE.h" textual header "/usr/include/x86_64-linux-gnu/bits/types/struct_iovec.h" textual header "/usr/include/x86_64-linux-gnu/bits/types/struct_itimerspec.h" textual header "/usr/include/x86_64-linux-gnu/bits/types/struct_osockaddr.h" textual header "/usr/include/x86_64-linux-gnu/bits/types/struct_rusage.h" + textual header "/usr/include/x86_64-linux-gnu/bits/types/struct_sched_param.h" textual header "/usr/include/x86_64-linux-gnu/bits/types/struct_sigstack.h" + textual header "/usr/include/x86_64-linux-gnu/bits/types/struct_statx.h" + textual header "/usr/include/x86_64-linux-gnu/bits/types/struct_statx_timestamp.h" textual header "/usr/include/x86_64-linux-gnu/bits/types/struct_timespec.h" textual header "/usr/include/x86_64-linux-gnu/bits/types/struct_timeval.h" textual header "/usr/include/x86_64-linux-gnu/bits/types/struct_tm.h" @@ -413,8 +448,8 @@ module "crosstool" [system] { textual header "/usr/include/x86_64-linux-gnu/bits/uintn-identity.h" textual header "/usr/include/x86_64-linux-gnu/bits/uio-ext.h" textual header "/usr/include/x86_64-linux-gnu/bits/uio_lim.h" + textual header "/usr/include/x86_64-linux-gnu/bits/unistd_ext.h" textual header "/usr/include/x86_64-linux-gnu/bits/unistd.h" - textual header "/usr/include/x86_64-linux-gnu/bits/ustat.h" textual header "/usr/include/x86_64-linux-gnu/bits/utmp.h" textual header "/usr/include/x86_64-linux-gnu/bits/utmpx.h" textual header "/usr/include/x86_64-linux-gnu/bits/utsname.h" @@ -426,31 +461,29 @@ module "crosstool" [system] { textual header "/usr/include/x86_64-linux-gnu/bits/wctype-wchar.h" textual header "/usr/include/x86_64-linux-gnu/bits/wordsize.h" textual header "/usr/include/x86_64-linux-gnu/bits/xopen_lim.h" - textual header "/usr/include/x86_64-linux-gnu/bits/xtitypes.h" - textual header "/usr/include/x86_64-linux-gnu/c++/9/bits/atomic_word.h" - textual header "/usr/include/x86_64-linux-gnu/c++/9/bits/basic_file.h" - textual header "/usr/include/x86_64-linux-gnu/c++/9/bits/c++allocator.h" - textual header "/usr/include/x86_64-linux-gnu/c++/9/bits/c++config.h" - textual header "/usr/include/x86_64-linux-gnu/c++/9/bits/c++io.h" - textual header "/usr/include/x86_64-linux-gnu/c++/9/bits/c++locale.h" - textual header "/usr/include/x86_64-linux-gnu/c++/9/bits/cpu_defines.h" - textual header "/usr/include/x86_64-linux-gnu/c++/9/bits/ctype_base.h" - textual header "/usr/include/x86_64-linux-gnu/c++/9/bits/ctype_inline.h" - textual header "/usr/include/x86_64-linux-gnu/c++/9/bits/cxxabi_tweaks.h" - textual header "/usr/include/x86_64-linux-gnu/c++/9/bits/error_constants.h" - textual header "/usr/include/x86_64-linux-gnu/c++/9/bits/extc++.h" - textual header "/usr/include/x86_64-linux-gnu/c++/9/bits/gthr-default.h" - textual header "/usr/include/x86_64-linux-gnu/c++/9/bits/gthr.h" - textual header "/usr/include/x86_64-linux-gnu/c++/9/bits/gthr-posix.h" - textual header "/usr/include/x86_64-linux-gnu/c++/9/bits/gthr-single.h" - textual header "/usr/include/x86_64-linux-gnu/c++/9/bits/messages_members.h" - textual header "/usr/include/x86_64-linux-gnu/c++/9/bits/opt_random.h" - textual header "/usr/include/x86_64-linux-gnu/c++/9/bits/os_defines.h" - textual header "/usr/include/x86_64-linux-gnu/c++/9/bits/stdc++.h" - textual header "/usr/include/x86_64-linux-gnu/c++/9/bits/stdtr1c++.h" - textual header "/usr/include/x86_64-linux-gnu/c++/9/bits/time_members.h" - textual header "/usr/include/x86_64-linux-gnu/c++/9/ext/opt_random.h" - textual header "/usr/include/x86_64-linux-gnu/expat_config.h" + textual header "/usr/include/x86_64-linux-gnu/c++/11/bits/atomic_word.h" + textual header "/usr/include/x86_64-linux-gnu/c++/11/bits/basic_file.h" + textual header "/usr/include/x86_64-linux-gnu/c++/11/bits/c++allocator.h" + textual header "/usr/include/x86_64-linux-gnu/c++/11/bits/c++config.h" + textual header "/usr/include/x86_64-linux-gnu/c++/11/bits/c++io.h" + textual header "/usr/include/x86_64-linux-gnu/c++/11/bits/c++locale.h" + textual header "/usr/include/x86_64-linux-gnu/c++/11/bits/cpu_defines.h" + textual header "/usr/include/x86_64-linux-gnu/c++/11/bits/ctype_base.h" + textual header "/usr/include/x86_64-linux-gnu/c++/11/bits/ctype_inline.h" + textual header "/usr/include/x86_64-linux-gnu/c++/11/bits/cxxabi_tweaks.h" + textual header "/usr/include/x86_64-linux-gnu/c++/11/bits/error_constants.h" + textual header "/usr/include/x86_64-linux-gnu/c++/11/bits/extc++.h" + textual header "/usr/include/x86_64-linux-gnu/c++/11/bits/gthr-default.h" + textual header "/usr/include/x86_64-linux-gnu/c++/11/bits/gthr.h" + textual header "/usr/include/x86_64-linux-gnu/c++/11/bits/gthr-posix.h" + textual header "/usr/include/x86_64-linux-gnu/c++/11/bits/gthr-single.h" + textual header "/usr/include/x86_64-linux-gnu/c++/11/bits/messages_members.h" + textual header "/usr/include/x86_64-linux-gnu/c++/11/bits/opt_random.h" + textual header "/usr/include/x86_64-linux-gnu/c++/11/bits/os_defines.h" + textual header "/usr/include/x86_64-linux-gnu/c++/11/bits/stdc++.h" + textual header "/usr/include/x86_64-linux-gnu/c++/11/bits/stdtr1c++.h" + textual header "/usr/include/x86_64-linux-gnu/c++/11/bits/time_members.h" + textual header "/usr/include/x86_64-linux-gnu/c++/11/ext/opt_random.h" textual header "/usr/include/x86_64-linux-gnu/ffi.h" textual header "/usr/include/x86_64-linux-gnu/ffitarget.h" textual header "/usr/include/x86_64-linux-gnu/fpu_control.h" @@ -460,7 +493,7 @@ module "crosstool" [system] { textual header "/usr/include/x86_64-linux-gnu/gnu/stubs-64.h" textual header "/usr/include/x86_64-linux-gnu/gnu/stubs.h" textual header "/usr/include/x86_64-linux-gnu/ieee754.h" - textual header "/usr/include/x86_64-linux-gnu/python3.10/pyconfig.h" + textual header "/usr/include/x86_64-linux-gnu/openssl/opensslconf.h" textual header "/usr/include/x86_64-linux-gnu/sys/acct.h" textual header "/usr/include/x86_64-linux-gnu/sys/auxv.h" textual header "/usr/include/x86_64-linux-gnu/sys/bitypes.h" @@ -515,7 +548,6 @@ module "crosstool" [system] { textual header "/usr/include/x86_64-linux-gnu/sys/statfs.h" textual header "/usr/include/x86_64-linux-gnu/sys/stat.h" textual header "/usr/include/x86_64-linux-gnu/sys/statvfs.h" - textual header "/usr/include/x86_64-linux-gnu/sys/stropts.h" textual header "/usr/include/x86_64-linux-gnu/sys/swap.h" textual header "/usr/include/x86_64-linux-gnu/sys/syscall.h" textual header "/usr/include/x86_64-linux-gnu/sys/sysctl.h" @@ -536,7 +568,6 @@ module "crosstool" [system] { textual header "/usr/include/x86_64-linux-gnu/sys/un.h" textual header "/usr/include/x86_64-linux-gnu/sys/unistd.h" textual header "/usr/include/x86_64-linux-gnu/sys/user.h" - textual header "/usr/include/x86_64-linux-gnu/sys/ustat.h" textual header "/usr/include/x86_64-linux-gnu/sys/utsname.h" textual header "/usr/include/x86_64-linux-gnu/sys/vfs.h" textual header "/usr/include/x86_64-linux-gnu/sys/vlimit.h" @@ -580,7 +611,6 @@ module "crosstool" [system] { textual header "/usr/include/asm-generic/sembuf.h" textual header "/usr/include/asm-generic/setup.h" textual header "/usr/include/asm-generic/shmbuf.h" - textual header "/usr/include/asm-generic/shmparam.h" textual header "/usr/include/asm-generic/siginfo.h" textual header "/usr/include/asm-generic/signal-defs.h" textual header "/usr/include/asm-generic/signal.h" @@ -596,770 +626,779 @@ module "crosstool" [system] { textual header "/usr/include/asm-generic/unistd.h" textual header "/usr/include/assert.h" textual header "/usr/include/byteswap.h" - textual header "/usr/include/c++/9/algorithm" - textual header "/usr/include/c++/9/any" - textual header "/usr/include/c++/9/array" - textual header "/usr/include/c++/9/atomic" - textual header "/usr/include/c++/9/backward/auto_ptr.h" - textual header "/usr/include/c++/9/backward/backward_warning.h" - textual header "/usr/include/c++/9/backward/binders.h" - textual header "/usr/include/c++/9/backward/hash_fun.h" - textual header "/usr/include/c++/9/backward/hash_map" - textual header "/usr/include/c++/9/backward/hash_set" - textual header "/usr/include/c++/9/backward/hashtable.h" - textual header "/usr/include/c++/9/backward/strstream" - textual header "/usr/include/c++/9/bit" - textual header "/usr/include/c++/9/bits/algorithmfwd.h" - textual header "/usr/include/c++/9/bits/allocated_ptr.h" - textual header "/usr/include/c++/9/bits/allocator.h" - textual header "/usr/include/c++/9/bits/alloc_traits.h" - textual header "/usr/include/c++/9/bits/atomic_base.h" - textual header "/usr/include/c++/9/bits/atomic_futex.h" - textual header "/usr/include/c++/9/bits/atomic_lockfree_defines.h" - textual header "/usr/include/c++/9/bits/basic_ios.h" - textual header "/usr/include/c++/9/bits/basic_ios.tcc" - textual header "/usr/include/c++/9/bits/basic_string.h" - textual header "/usr/include/c++/9/bits/basic_string.tcc" - textual header "/usr/include/c++/9/bits/boost_concept_check.h" - textual header "/usr/include/c++/9/bits/c++0x_warning.h" - textual header "/usr/include/c++/9/bits/char_traits.h" - textual header "/usr/include/c++/9/bits/codecvt.h" - textual header "/usr/include/c++/9/bits/concept_check.h" - textual header "/usr/include/c++/9/bits/cpp_type_traits.h" - textual header "/usr/include/c++/9/bits/cxxabi_forced.h" - textual header "/usr/include/c++/9/bits/cxxabi_init_exception.h" - textual header "/usr/include/c++/9/bits/deque.tcc" - textual header "/usr/include/c++/9/bits/enable_special_members.h" - textual header "/usr/include/c++/9/bits/erase_if.h" - textual header "/usr/include/c++/9/bitset" - textual header "/usr/include/c++/9/bits/exception_defines.h" - textual header "/usr/include/c++/9/bits/exception.h" - textual header "/usr/include/c++/9/bits/exception_ptr.h" - textual header "/usr/include/c++/9/bits/forward_list.h" - textual header "/usr/include/c++/9/bits/forward_list.tcc" - textual header "/usr/include/c++/9/bits/fs_dir.h" - textual header "/usr/include/c++/9/bits/fs_fwd.h" - textual header "/usr/include/c++/9/bits/fs_ops.h" - textual header "/usr/include/c++/9/bits/fs_path.h" - textual header "/usr/include/c++/9/bits/fstream.tcc" - textual header "/usr/include/c++/9/bits/functexcept.h" - textual header "/usr/include/c++/9/bits/functional_hash.h" - textual header "/usr/include/c++/9/bits/gslice_array.h" - textual header "/usr/include/c++/9/bits/gslice.h" - textual header "/usr/include/c++/9/bits/hash_bytes.h" - textual header "/usr/include/c++/9/bits/hashtable.h" - textual header "/usr/include/c++/9/bits/hashtable_policy.h" - textual header "/usr/include/c++/9/bits/indirect_array.h" - textual header "/usr/include/c++/9/bits/invoke.h" - textual header "/usr/include/c++/9/bits/ios_base.h" - textual header "/usr/include/c++/9/bits/istream.tcc" - textual header "/usr/include/c++/9/bits/list.tcc" - textual header "/usr/include/c++/9/bits/locale_classes.h" - textual header "/usr/include/c++/9/bits/locale_classes.tcc" - textual header "/usr/include/c++/9/bits/locale_conv.h" - textual header "/usr/include/c++/9/bits/locale_facets.h" - textual header "/usr/include/c++/9/bits/locale_facets_nonio.h" - textual header "/usr/include/c++/9/bits/locale_facets_nonio.tcc" - textual header "/usr/include/c++/9/bits/locale_facets.tcc" - textual header "/usr/include/c++/9/bits/localefwd.h" - textual header "/usr/include/c++/9/bits/mask_array.h" - textual header "/usr/include/c++/9/bits/memoryfwd.h" - textual header "/usr/include/c++/9/bits/move.h" - textual header "/usr/include/c++/9/bits/nested_exception.h" - textual header "/usr/include/c++/9/bits/node_handle.h" - textual header "/usr/include/c++/9/bits/ostream_insert.h" - textual header "/usr/include/c++/9/bits/ostream.tcc" - textual header "/usr/include/c++/9/bits/parse_numbers.h" - textual header "/usr/include/c++/9/bits/postypes.h" - textual header "/usr/include/c++/9/bits/predefined_ops.h" - textual header "/usr/include/c++/9/bits/ptr_traits.h" - textual header "/usr/include/c++/9/bits/quoted_string.h" - textual header "/usr/include/c++/9/bits/random.h" - textual header "/usr/include/c++/9/bits/random.tcc" - textual header "/usr/include/c++/9/bits/range_access.h" - textual header "/usr/include/c++/9/bits/refwrap.h" - textual header "/usr/include/c++/9/bits/regex_automaton.h" - textual header "/usr/include/c++/9/bits/regex_automaton.tcc" - textual header "/usr/include/c++/9/bits/regex_compiler.h" - textual header "/usr/include/c++/9/bits/regex_compiler.tcc" - textual header "/usr/include/c++/9/bits/regex_constants.h" - textual header "/usr/include/c++/9/bits/regex_error.h" - textual header "/usr/include/c++/9/bits/regex_executor.h" - textual header "/usr/include/c++/9/bits/regex_executor.tcc" - textual header "/usr/include/c++/9/bits/regex.h" - textual header "/usr/include/c++/9/bits/regex_scanner.h" - textual header "/usr/include/c++/9/bits/regex_scanner.tcc" - textual header "/usr/include/c++/9/bits/regex.tcc" - textual header "/usr/include/c++/9/bits/shared_ptr_atomic.h" - textual header "/usr/include/c++/9/bits/shared_ptr_base.h" - textual header "/usr/include/c++/9/bits/shared_ptr.h" - textual header "/usr/include/c++/9/bits/slice_array.h" - textual header "/usr/include/c++/9/bits/specfun.h" - textual header "/usr/include/c++/9/bits/sstream.tcc" - textual header "/usr/include/c++/9/bits/std_abs.h" - textual header "/usr/include/c++/9/bits/std_function.h" - textual header "/usr/include/c++/9/bits/std_mutex.h" - textual header "/usr/include/c++/9/bits/stl_algobase.h" - textual header "/usr/include/c++/9/bits/stl_algo.h" - textual header "/usr/include/c++/9/bits/stl_bvector.h" - textual header "/usr/include/c++/9/bits/stl_construct.h" - textual header "/usr/include/c++/9/bits/stl_deque.h" - textual header "/usr/include/c++/9/bits/stl_function.h" - textual header "/usr/include/c++/9/bits/stl_heap.h" - textual header "/usr/include/c++/9/bits/stl_iterator_base_funcs.h" - textual header "/usr/include/c++/9/bits/stl_iterator_base_types.h" - textual header "/usr/include/c++/9/bits/stl_iterator.h" - textual header "/usr/include/c++/9/bits/stl_list.h" - textual header "/usr/include/c++/9/bits/stl_map.h" - textual header "/usr/include/c++/9/bits/stl_multimap.h" - textual header "/usr/include/c++/9/bits/stl_multiset.h" - textual header "/usr/include/c++/9/bits/stl_numeric.h" - textual header "/usr/include/c++/9/bits/stl_pair.h" - textual header "/usr/include/c++/9/bits/stl_queue.h" - textual header "/usr/include/c++/9/bits/stl_raw_storage_iter.h" - textual header "/usr/include/c++/9/bits/stl_relops.h" - textual header "/usr/include/c++/9/bits/stl_set.h" - textual header "/usr/include/c++/9/bits/stl_stack.h" - textual header "/usr/include/c++/9/bits/stl_tempbuf.h" - textual header "/usr/include/c++/9/bits/stl_tree.h" - textual header "/usr/include/c++/9/bits/stl_uninitialized.h" - textual header "/usr/include/c++/9/bits/stl_vector.h" - textual header "/usr/include/c++/9/bits/streambuf_iterator.h" - textual header "/usr/include/c++/9/bits/streambuf.tcc" - textual header "/usr/include/c++/9/bits/stream_iterator.h" - textual header "/usr/include/c++/9/bits/stringfwd.h" - textual header "/usr/include/c++/9/bits/string_view.tcc" - textual header "/usr/include/c++/9/bits/uniform_int_dist.h" - textual header "/usr/include/c++/9/bits/unique_lock.h" - textual header "/usr/include/c++/9/bits/unique_ptr.h" - textual header "/usr/include/c++/9/bits/unordered_map.h" - textual header "/usr/include/c++/9/bits/unordered_set.h" - textual header "/usr/include/c++/9/bits/uses_allocator.h" - textual header "/usr/include/c++/9/bits/valarray_after.h" - textual header "/usr/include/c++/9/bits/valarray_array.h" - textual header "/usr/include/c++/9/bits/valarray_array.tcc" - textual header "/usr/include/c++/9/bits/valarray_before.h" - textual header "/usr/include/c++/9/bits/vector.tcc" - textual header "/usr/include/c++/9/cassert" - textual header "/usr/include/c++/9/ccomplex" - textual header "/usr/include/c++/9/cctype" - textual header "/usr/include/c++/9/cerrno" - textual header "/usr/include/c++/9/cfenv" - textual header "/usr/include/c++/9/cfloat" - textual header "/usr/include/c++/9/charconv" - textual header "/usr/include/c++/9/chrono" - textual header "/usr/include/c++/9/cinttypes" - textual header "/usr/include/c++/9/ciso646" - textual header "/usr/include/c++/9/climits" - textual header "/usr/include/c++/9/clocale" - textual header "/usr/include/c++/9/cmath" - textual header "/usr/include/c++/9/codecvt" - textual header "/usr/include/c++/9/complex" - textual header "/usr/include/c++/9/complex.h" - textual header "/usr/include/c++/9/condition_variable" - textual header "/usr/include/c++/9/csetjmp" - textual header "/usr/include/c++/9/csignal" - textual header "/usr/include/c++/9/cstdalign" - textual header "/usr/include/c++/9/cstdarg" - textual header "/usr/include/c++/9/cstdbool" - textual header "/usr/include/c++/9/cstddef" - textual header "/usr/include/c++/9/cstdint" - textual header "/usr/include/c++/9/cstdio" - textual header "/usr/include/c++/9/cstdlib" - textual header "/usr/include/c++/9/cstring" - textual header "/usr/include/c++/9/ctgmath" - textual header "/usr/include/c++/9/ctime" - textual header "/usr/include/c++/9/cuchar" - textual header "/usr/include/c++/9/cwchar" - textual header "/usr/include/c++/9/cwctype" - textual header "/usr/include/c++/9/cxxabi.h" - textual header "/usr/include/c++/9/debug/array" - textual header "/usr/include/c++/9/debug/assertions.h" - textual header "/usr/include/c++/9/debug/bitset" - textual header "/usr/include/c++/9/debug/debug.h" - textual header "/usr/include/c++/9/debug/deque" - textual header "/usr/include/c++/9/debug/formatter.h" - textual header "/usr/include/c++/9/debug/forward_list" - textual header "/usr/include/c++/9/debug/functions.h" - textual header "/usr/include/c++/9/debug/helper_functions.h" - textual header "/usr/include/c++/9/debug/list" - textual header "/usr/include/c++/9/debug/macros.h" - textual header "/usr/include/c++/9/debug/map" - textual header "/usr/include/c++/9/debug/map.h" - textual header "/usr/include/c++/9/debug/multimap.h" - textual header "/usr/include/c++/9/debug/multiset.h" - textual header "/usr/include/c++/9/debug/safe_base.h" - textual header "/usr/include/c++/9/debug/safe_container.h" - textual header "/usr/include/c++/9/debug/safe_iterator.h" - textual header "/usr/include/c++/9/debug/safe_iterator.tcc" - textual header "/usr/include/c++/9/debug/safe_local_iterator.h" - textual header "/usr/include/c++/9/debug/safe_local_iterator.tcc" - textual header "/usr/include/c++/9/debug/safe_sequence.h" - textual header "/usr/include/c++/9/debug/safe_sequence.tcc" - textual header "/usr/include/c++/9/debug/safe_unordered_base.h" - textual header "/usr/include/c++/9/debug/safe_unordered_container.h" - textual header "/usr/include/c++/9/debug/safe_unordered_container.tcc" - textual header "/usr/include/c++/9/debug/set" - textual header "/usr/include/c++/9/debug/set.h" - textual header "/usr/include/c++/9/debug/stl_iterator.h" - textual header "/usr/include/c++/9/debug/string" - textual header "/usr/include/c++/9/debug/unordered_map" - textual header "/usr/include/c++/9/debug/unordered_set" - textual header "/usr/include/c++/9/debug/vector" - textual header "/usr/include/c++/9/decimal/decimal" - textual header "/usr/include/c++/9/decimal/decimal.h" - textual header "/usr/include/c++/9/deque" - textual header "/usr/include/c++/9/exception" - textual header "/usr/include/c++/9/execution" - textual header "/usr/include/c++/9/experimental/algorithm" - textual header "/usr/include/c++/9/experimental/any" - textual header "/usr/include/c++/9/experimental/array" - textual header "/usr/include/c++/9/experimental/bits/fs_dir.h" - textual header "/usr/include/c++/9/experimental/bits/fs_fwd.h" - textual header "/usr/include/c++/9/experimental/bits/fs_ops.h" - textual header "/usr/include/c++/9/experimental/bits/fs_path.h" - textual header "/usr/include/c++/9/experimental/bits/lfts_config.h" - textual header "/usr/include/c++/9/experimental/bits/net.h" - textual header "/usr/include/c++/9/experimental/bits/shared_ptr.h" - textual header "/usr/include/c++/9/experimental/bits/string_view.tcc" - textual header "/usr/include/c++/9/experimental/buffer" - textual header "/usr/include/c++/9/experimental/chrono" - textual header "/usr/include/c++/9/experimental/deque" - textual header "/usr/include/c++/9/experimental/executor" - textual header "/usr/include/c++/9/experimental/filesystem" - textual header "/usr/include/c++/9/experimental/forward_list" - textual header "/usr/include/c++/9/experimental/functional" - textual header "/usr/include/c++/9/experimental/internet" - textual header "/usr/include/c++/9/experimental/io_context" - textual header "/usr/include/c++/9/experimental/iterator" - textual header "/usr/include/c++/9/experimental/list" - textual header "/usr/include/c++/9/experimental/map" - textual header "/usr/include/c++/9/experimental/memory" - textual header "/usr/include/c++/9/experimental/memory_resource" - textual header "/usr/include/c++/9/experimental/net" - textual header "/usr/include/c++/9/experimental/netfwd" - textual header "/usr/include/c++/9/experimental/numeric" - textual header "/usr/include/c++/9/experimental/optional" - textual header "/usr/include/c++/9/experimental/propagate_const" - textual header "/usr/include/c++/9/experimental/random" - textual header "/usr/include/c++/9/experimental/ratio" - textual header "/usr/include/c++/9/experimental/regex" - textual header "/usr/include/c++/9/experimental/set" - textual header "/usr/include/c++/9/experimental/socket" - textual header "/usr/include/c++/9/experimental/source_location" - textual header "/usr/include/c++/9/experimental/string" - textual header "/usr/include/c++/9/experimental/string_view" - textual header "/usr/include/c++/9/experimental/system_error" - textual header "/usr/include/c++/9/experimental/timer" - textual header "/usr/include/c++/9/experimental/tuple" - textual header "/usr/include/c++/9/experimental/type_traits" - textual header "/usr/include/c++/9/experimental/unordered_map" - textual header "/usr/include/c++/9/experimental/unordered_set" - textual header "/usr/include/c++/9/experimental/utility" - textual header "/usr/include/c++/9/experimental/vector" - textual header "/usr/include/c++/9/ext/algorithm" - textual header "/usr/include/c++/9/ext/aligned_buffer.h" - textual header "/usr/include/c++/9/ext/alloc_traits.h" - textual header "/usr/include/c++/9/ext/array_allocator.h" - textual header "/usr/include/c++/9/ext/atomicity.h" - textual header "/usr/include/c++/9/ext/bitmap_allocator.h" - textual header "/usr/include/c++/9/ext/cast.h" - textual header "/usr/include/c++/9/ext/cmath" - textual header "/usr/include/c++/9/ext/codecvt_specializations.h" - textual header "/usr/include/c++/9/ext/concurrence.h" - textual header "/usr/include/c++/9/ext/debug_allocator.h" - textual header "/usr/include/c++/9/ext/enc_filebuf.h" - textual header "/usr/include/c++/9/ext/extptr_allocator.h" - textual header "/usr/include/c++/9/ext/functional" - textual header "/usr/include/c++/9/ext/hash_map" - textual header "/usr/include/c++/9/ext/hash_set" - textual header "/usr/include/c++/9/ext/iterator" - textual header "/usr/include/c++/9/ext/malloc_allocator.h" - textual header "/usr/include/c++/9/ext/memory" - textual header "/usr/include/c++/9/ext/mt_allocator.h" - textual header "/usr/include/c++/9/ext/new_allocator.h" - textual header "/usr/include/c++/9/ext/numeric" - textual header "/usr/include/c++/9/ext/numeric_traits.h" - textual header "/usr/include/c++/9/ext/pb_ds/assoc_container.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/binary_heap_/binary_heap_.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/binary_heap_/const_iterator.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/binary_heap_/constructors_destructor_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/binary_heap_/debug_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/binary_heap_/entry_cmp.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/binary_heap_/entry_pred.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/binary_heap_/erase_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/binary_heap_/find_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/binary_heap_/info_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/binary_heap_/insert_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/binary_heap_/iterators_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/binary_heap_/point_const_iterator.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/binary_heap_/policy_access_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/binary_heap_/resize_policy.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/binary_heap_/split_join_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/binary_heap_/trace_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/binomial_heap_base_/binomial_heap_base_.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/binomial_heap_base_/constructors_destructor_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/binomial_heap_base_/debug_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/binomial_heap_base_/erase_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/binomial_heap_base_/find_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/binomial_heap_base_/insert_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/binomial_heap_base_/split_join_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/binomial_heap_/binomial_heap_.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/binomial_heap_/constructors_destructor_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/binomial_heap_/debug_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/bin_search_tree_/bin_search_tree_.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/bin_search_tree_/constructors_destructor_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/bin_search_tree_/debug_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/bin_search_tree_/erase_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/bin_search_tree_/find_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/bin_search_tree_/info_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/bin_search_tree_/insert_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/bin_search_tree_/iterators_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/bin_search_tree_/node_iterators.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/bin_search_tree_/point_iterators.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/bin_search_tree_/policy_access_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/bin_search_tree_/r_erase_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/bin_search_tree_/rotate_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/bin_search_tree_/split_join_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/bin_search_tree_/traits.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/branch_policy/branch_policy.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/branch_policy/null_node_metadata.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/branch_policy/traits.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/cc_hash_table_map_/cc_ht_map_.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/cc_hash_table_map_/cmp_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/cc_hash_table_map_/cond_key_dtor_entry_dealtor.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/cc_hash_table_map_/constructor_destructor_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/cc_hash_table_map_/constructor_destructor_no_store_hash_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/cc_hash_table_map_/constructor_destructor_store_hash_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/cc_hash_table_map_/debug_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/cc_hash_table_map_/debug_no_store_hash_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/cc_hash_table_map_/debug_store_hash_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/cc_hash_table_map_/entry_list_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/cc_hash_table_map_/erase_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/cc_hash_table_map_/erase_no_store_hash_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/cc_hash_table_map_/erase_store_hash_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/cc_hash_table_map_/find_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/cc_hash_table_map_/find_store_hash_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/cc_hash_table_map_/info_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/cc_hash_table_map_/insert_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/cc_hash_table_map_/insert_no_store_hash_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/cc_hash_table_map_/insert_store_hash_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/cc_hash_table_map_/iterators_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/cc_hash_table_map_/policy_access_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/cc_hash_table_map_/resize_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/cc_hash_table_map_/resize_no_store_hash_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/cc_hash_table_map_/resize_store_hash_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/cc_hash_table_map_/size_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/cc_hash_table_map_/trace_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/cond_dealtor.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/container_base_dispatch.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/debug_map_base.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/eq_fn/eq_by_less.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/eq_fn/hash_eq_fn.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/gp_hash_table_map_/constructor_destructor_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/gp_hash_table_map_/constructor_destructor_no_store_hash_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/gp_hash_table_map_/constructor_destructor_store_hash_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/gp_hash_table_map_/debug_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/gp_hash_table_map_/debug_no_store_hash_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/gp_hash_table_map_/debug_store_hash_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/gp_hash_table_map_/erase_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/gp_hash_table_map_/erase_no_store_hash_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/gp_hash_table_map_/erase_store_hash_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/gp_hash_table_map_/find_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/gp_hash_table_map_/find_no_store_hash_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/gp_hash_table_map_/find_store_hash_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/gp_hash_table_map_/gp_ht_map_.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/gp_hash_table_map_/info_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/gp_hash_table_map_/insert_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/gp_hash_table_map_/insert_no_store_hash_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/gp_hash_table_map_/insert_store_hash_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/gp_hash_table_map_/iterator_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/gp_hash_table_map_/policy_access_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/gp_hash_table_map_/resize_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/gp_hash_table_map_/resize_no_store_hash_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/gp_hash_table_map_/resize_store_hash_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/gp_hash_table_map_/trace_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/hash_fn/direct_mask_range_hashing_imp.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/hash_fn/direct_mod_range_hashing_imp.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/hash_fn/linear_probe_fn_imp.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/hash_fn/mask_based_range_hashing.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/hash_fn/mod_based_range_hashing.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/hash_fn/probe_fn_base.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/hash_fn/quadratic_probe_fn_imp.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/hash_fn/ranged_hash_fn.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/hash_fn/ranged_probe_fn.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/hash_fn/sample_probe_fn.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/hash_fn/sample_ranged_hash_fn.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/hash_fn/sample_ranged_probe_fn.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/hash_fn/sample_range_hashing.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/left_child_next_sibling_heap_/const_iterator.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/left_child_next_sibling_heap_/constructors_destructor_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/left_child_next_sibling_heap_/debug_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/left_child_next_sibling_heap_/erase_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/left_child_next_sibling_heap_/info_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/left_child_next_sibling_heap_/insert_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/left_child_next_sibling_heap_/iterators_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/left_child_next_sibling_heap_/left_child_next_sibling_heap_.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/left_child_next_sibling_heap_/node.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/left_child_next_sibling_heap_/point_const_iterator.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/left_child_next_sibling_heap_/policy_access_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/left_child_next_sibling_heap_/trace_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/list_update_map_/constructor_destructor_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/list_update_map_/debug_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/list_update_map_/entry_metadata_base.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/list_update_map_/erase_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/list_update_map_/find_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/list_update_map_/info_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/list_update_map_/insert_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/list_update_map_/iterators_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/list_update_map_/lu_map_.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/list_update_map_/trace_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/list_update_policy/lu_counter_metadata.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/list_update_policy/sample_update_policy.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/ov_tree_map_/constructors_destructor_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/ov_tree_map_/debug_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/ov_tree_map_/erase_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/ov_tree_map_/info_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/ov_tree_map_/insert_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/ov_tree_map_/iterators_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/ov_tree_map_/node_iterators.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/ov_tree_map_/ov_tree_map_.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/ov_tree_map_/policy_access_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/ov_tree_map_/split_join_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/ov_tree_map_/traits.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/pairing_heap_/constructors_destructor_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/pairing_heap_/debug_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/pairing_heap_/erase_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/pairing_heap_/find_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/pairing_heap_/insert_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/pairing_heap_/pairing_heap_.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/pairing_heap_/split_join_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/pat_trie_/constructors_destructor_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/pat_trie_/debug_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/pat_trie_/erase_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/pat_trie_/find_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/pat_trie_/info_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/pat_trie_/insert_join_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/pat_trie_/iterators_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/pat_trie_/pat_trie_base.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/pat_trie_/pat_trie_.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/pat_trie_/policy_access_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/pat_trie_/r_erase_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/pat_trie_/rotate_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/pat_trie_/split_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/pat_trie_/synth_access_traits.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/pat_trie_/trace_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/pat_trie_/traits.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/pat_trie_/update_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/priority_queue_base_dispatch.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/rb_tree_map_/constructors_destructor_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/rb_tree_map_/debug_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/rb_tree_map_/erase_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/rb_tree_map_/find_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/rb_tree_map_/info_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/rb_tree_map_/insert_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/rb_tree_map_/node.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/rb_tree_map_/rb_tree_.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/rb_tree_map_/split_join_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/rb_tree_map_/traits.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/rc_binomial_heap_/constructors_destructor_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/rc_binomial_heap_/debug_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/rc_binomial_heap_/erase_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/rc_binomial_heap_/insert_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/rc_binomial_heap_/rc_binomial_heap_.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/rc_binomial_heap_/rc.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/rc_binomial_heap_/split_join_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/rc_binomial_heap_/trace_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/resize_policy/cc_hash_max_collision_check_resize_trigger_imp.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/resize_policy/hash_exponential_size_policy_imp.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/resize_policy/hash_load_check_resize_trigger_imp.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/resize_policy/hash_load_check_resize_trigger_size_base.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/resize_policy/hash_prime_size_policy_imp.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/resize_policy/hash_standard_resize_policy_imp.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/resize_policy/sample_resize_policy.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/resize_policy/sample_resize_trigger.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/resize_policy/sample_size_policy.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/splay_tree_/constructors_destructor_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/splay_tree_/debug_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/splay_tree_/erase_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/splay_tree_/find_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/splay_tree_/info_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/splay_tree_/insert_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/splay_tree_/node.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/splay_tree_/splay_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/splay_tree_/splay_tree_.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/splay_tree_/split_join_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/splay_tree_/traits.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/standard_policies.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/thin_heap_/constructors_destructor_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/thin_heap_/debug_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/thin_heap_/erase_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/thin_heap_/find_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/thin_heap_/insert_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/thin_heap_/split_join_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/thin_heap_/thin_heap_.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/thin_heap_/trace_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/tree_policy/node_metadata_selector.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/tree_policy/order_statistics_imp.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/tree_policy/sample_tree_node_update.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/tree_trace_base.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/trie_policy/node_metadata_selector.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/trie_policy/order_statistics_imp.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/trie_policy/prefix_search_node_update_imp.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/trie_policy/sample_trie_access_traits.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/trie_policy/sample_trie_node_update.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/trie_policy/trie_policy_base.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/trie_policy/trie_string_access_traits_imp.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/types_traits.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/type_utils.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/unordered_iterator/const_iterator.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/unordered_iterator/iterator.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/unordered_iterator/point_const_iterator.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/unordered_iterator/point_iterator.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/exception.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/hash_policy.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/list_update_policy.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/priority_queue.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/tag_and_trait.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/tree_policy.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/trie_policy.hpp" - textual header "/usr/include/c++/9/ext/pod_char_traits.h" - textual header "/usr/include/c++/9/ext/pointer.h" - textual header "/usr/include/c++/9/ext/pool_allocator.h" - textual header "/usr/include/c++/9/ext/random" - textual header "/usr/include/c++/9/ext/random.tcc" - textual header "/usr/include/c++/9/ext/rb_tree" - textual header "/usr/include/c++/9/ext/rc_string_base.h" - textual header "/usr/include/c++/9/ext/rope" - textual header "/usr/include/c++/9/ext/ropeimpl.h" - textual header "/usr/include/c++/9/ext/slist" - textual header "/usr/include/c++/9/ext/sso_string_base.h" - textual header "/usr/include/c++/9/ext/stdio_filebuf.h" - textual header "/usr/include/c++/9/ext/stdio_sync_filebuf.h" - textual header "/usr/include/c++/9/ext/string_conversions.h" - textual header "/usr/include/c++/9/ext/throw_allocator.h" - textual header "/usr/include/c++/9/ext/typelist.h" - textual header "/usr/include/c++/9/ext/type_traits.h" - textual header "/usr/include/c++/9/ext/vstring_fwd.h" - textual header "/usr/include/c++/9/ext/vstring.h" - textual header "/usr/include/c++/9/ext/vstring.tcc" - textual header "/usr/include/c++/9/ext/vstring_util.h" - textual header "/usr/include/c++/9/fenv.h" - textual header "/usr/include/c++/9/filesystem" - textual header "/usr/include/c++/9/forward_list" - textual header "/usr/include/c++/9/fstream" - textual header "/usr/include/c++/9/functional" - textual header "/usr/include/c++/9/future" - textual header "/usr/include/c++/9/initializer_list" - textual header "/usr/include/c++/9/iomanip" - textual header "/usr/include/c++/9/ios" - textual header "/usr/include/c++/9/iosfwd" - textual header "/usr/include/c++/9/iostream" - textual header "/usr/include/c++/9/istream" - textual header "/usr/include/c++/9/iterator" - textual header "/usr/include/c++/9/limits" - textual header "/usr/include/c++/9/list" - textual header "/usr/include/c++/9/locale" - textual header "/usr/include/c++/9/map" - textual header "/usr/include/c++/9/math.h" - textual header "/usr/include/c++/9/memory" - textual header "/usr/include/c++/9/memory_resource" - textual header "/usr/include/c++/9/mutex" - textual header "/usr/include/c++/9/new" - textual header "/usr/include/c++/9/numeric" - textual header "/usr/include/c++/9/optional" - textual header "/usr/include/c++/9/ostream" - textual header "/usr/include/c++/9/parallel/algobase.h" - textual header "/usr/include/c++/9/parallel/algo.h" - textual header "/usr/include/c++/9/parallel/algorithm" - textual header "/usr/include/c++/9/parallel/algorithmfwd.h" - textual header "/usr/include/c++/9/parallel/balanced_quicksort.h" - textual header "/usr/include/c++/9/parallel/base.h" - textual header "/usr/include/c++/9/parallel/basic_iterator.h" - textual header "/usr/include/c++/9/parallel/checkers.h" - textual header "/usr/include/c++/9/parallel/compatibility.h" - textual header "/usr/include/c++/9/parallel/compiletime_settings.h" - textual header "/usr/include/c++/9/parallel/equally_split.h" - textual header "/usr/include/c++/9/parallel/features.h" - textual header "/usr/include/c++/9/parallel/find.h" - textual header "/usr/include/c++/9/parallel/find_selectors.h" - textual header "/usr/include/c++/9/parallel/for_each.h" - textual header "/usr/include/c++/9/parallel/for_each_selectors.h" - textual header "/usr/include/c++/9/parallel/iterator.h" - textual header "/usr/include/c++/9/parallel/list_partition.h" - textual header "/usr/include/c++/9/parallel/losertree.h" - textual header "/usr/include/c++/9/parallel/merge.h" - textual header "/usr/include/c++/9/parallel/multiseq_selection.h" - textual header "/usr/include/c++/9/parallel/multiway_merge.h" - textual header "/usr/include/c++/9/parallel/multiway_mergesort.h" - textual header "/usr/include/c++/9/parallel/numeric" - textual header "/usr/include/c++/9/parallel/numericfwd.h" - textual header "/usr/include/c++/9/parallel/omp_loop.h" - textual header "/usr/include/c++/9/parallel/omp_loop_static.h" - textual header "/usr/include/c++/9/parallel/parallel.h" - textual header "/usr/include/c++/9/parallel/par_loop.h" - textual header "/usr/include/c++/9/parallel/partial_sum.h" - textual header "/usr/include/c++/9/parallel/partition.h" - textual header "/usr/include/c++/9/parallel/queue.h" - textual header "/usr/include/c++/9/parallel/quicksort.h" - textual header "/usr/include/c++/9/parallel/random_number.h" - textual header "/usr/include/c++/9/parallel/random_shuffle.h" - textual header "/usr/include/c++/9/parallel/search.h" - textual header "/usr/include/c++/9/parallel/set_operations.h" - textual header "/usr/include/c++/9/parallel/settings.h" - textual header "/usr/include/c++/9/parallel/sort.h" - textual header "/usr/include/c++/9/parallel/tags.h" - textual header "/usr/include/c++/9/parallel/types.h" - textual header "/usr/include/c++/9/parallel/unique_copy.h" - textual header "/usr/include/c++/9/parallel/workstealing.h" - textual header "/usr/include/c++/9/profile/array" - textual header "/usr/include/c++/9/profile/base.h" - textual header "/usr/include/c++/9/profile/bitset" - textual header "/usr/include/c++/9/profile/deque" - textual header "/usr/include/c++/9/profile/forward_list" - textual header "/usr/include/c++/9/profile/impl/profiler_algos.h" - textual header "/usr/include/c++/9/profile/impl/profiler_container_size.h" - textual header "/usr/include/c++/9/profile/impl/profiler.h" - textual header "/usr/include/c++/9/profile/impl/profiler_hash_func.h" - textual header "/usr/include/c++/9/profile/impl/profiler_hashtable_size.h" - textual header "/usr/include/c++/9/profile/impl/profiler_list_to_slist.h" - textual header "/usr/include/c++/9/profile/impl/profiler_list_to_vector.h" - textual header "/usr/include/c++/9/profile/impl/profiler_map_to_unordered_map.h" - textual header "/usr/include/c++/9/profile/impl/profiler_node.h" - textual header "/usr/include/c++/9/profile/impl/profiler_state.h" - textual header "/usr/include/c++/9/profile/impl/profiler_trace.h" - textual header "/usr/include/c++/9/profile/impl/profiler_vector_size.h" - textual header "/usr/include/c++/9/profile/impl/profiler_vector_to_list.h" - textual header "/usr/include/c++/9/profile/iterator_tracker.h" - textual header "/usr/include/c++/9/profile/list" - textual header "/usr/include/c++/9/profile/map" - textual header "/usr/include/c++/9/profile/map.h" - textual header "/usr/include/c++/9/profile/multimap.h" - textual header "/usr/include/c++/9/profile/multiset.h" - textual header "/usr/include/c++/9/profile/ordered_base.h" - textual header "/usr/include/c++/9/profile/set" - textual header "/usr/include/c++/9/profile/set.h" - textual header "/usr/include/c++/9/profile/unordered_base.h" - textual header "/usr/include/c++/9/profile/unordered_map" - textual header "/usr/include/c++/9/profile/unordered_set" - textual header "/usr/include/c++/9/profile/vector" - textual header "/usr/include/c++/9/pstl/algorithm_fwd.h" - textual header "/usr/include/c++/9/pstl/algorithm_impl.h" - textual header "/usr/include/c++/9/pstl/execution_defs.h" - textual header "/usr/include/c++/9/pstl/execution_impl.h" - textual header "/usr/include/c++/9/pstl/glue_algorithm_defs.h" - textual header "/usr/include/c++/9/pstl/glue_algorithm_impl.h" - textual header "/usr/include/c++/9/pstl/glue_execution_defs.h" - textual header "/usr/include/c++/9/pstl/glue_memory_defs.h" - textual header "/usr/include/c++/9/pstl/glue_memory_impl.h" - textual header "/usr/include/c++/9/pstl/glue_numeric_defs.h" - textual header "/usr/include/c++/9/pstl/glue_numeric_impl.h" - textual header "/usr/include/c++/9/pstl/memory_impl.h" - textual header "/usr/include/c++/9/pstl/numeric_fwd.h" - textual header "/usr/include/c++/9/pstl/numeric_impl.h" - textual header "/usr/include/c++/9/pstl/parallel_backend.h" - textual header "/usr/include/c++/9/pstl/parallel_backend_tbb.h" - textual header "/usr/include/c++/9/pstl/parallel_backend_utils.h" - textual header "/usr/include/c++/9/pstl/parallel_impl.h" - textual header "/usr/include/c++/9/pstl/pstl_config.h" - textual header "/usr/include/c++/9/pstl/unseq_backend_simd.h" - textual header "/usr/include/c++/9/pstl/utils.h" - textual header "/usr/include/c++/9/queue" - textual header "/usr/include/c++/9/random" - textual header "/usr/include/c++/9/ratio" - textual header "/usr/include/c++/9/regex" - textual header "/usr/include/c++/9/scoped_allocator" - textual header "/usr/include/c++/9/set" - textual header "/usr/include/c++/9/shared_mutex" - textual header "/usr/include/c++/9/sstream" - textual header "/usr/include/c++/9/stack" - textual header "/usr/include/c++/9/stdexcept" - textual header "/usr/include/c++/9/stdlib.h" - textual header "/usr/include/c++/9/streambuf" - textual header "/usr/include/c++/9/string" - textual header "/usr/include/c++/9/string_view" - textual header "/usr/include/c++/9/system_error" - textual header "/usr/include/c++/9/tgmath.h" - textual header "/usr/include/c++/9/thread" - textual header "/usr/include/c++/9/tr1/array" - textual header "/usr/include/c++/9/tr1/bessel_function.tcc" - textual header "/usr/include/c++/9/tr1/beta_function.tcc" - textual header "/usr/include/c++/9/tr1/ccomplex" - textual header "/usr/include/c++/9/tr1/cctype" - textual header "/usr/include/c++/9/tr1/cfenv" - textual header "/usr/include/c++/9/tr1/cfloat" - textual header "/usr/include/c++/9/tr1/cinttypes" - textual header "/usr/include/c++/9/tr1/climits" - textual header "/usr/include/c++/9/tr1/cmath" - textual header "/usr/include/c++/9/tr1/complex" - textual header "/usr/include/c++/9/tr1/complex.h" - textual header "/usr/include/c++/9/tr1/cstdarg" - textual header "/usr/include/c++/9/tr1/cstdbool" - textual header "/usr/include/c++/9/tr1/cstdint" - textual header "/usr/include/c++/9/tr1/cstdio" - textual header "/usr/include/c++/9/tr1/cstdlib" - textual header "/usr/include/c++/9/tr1/ctgmath" - textual header "/usr/include/c++/9/tr1/ctime" - textual header "/usr/include/c++/9/tr1/ctype.h" - textual header "/usr/include/c++/9/tr1/cwchar" - textual header "/usr/include/c++/9/tr1/cwctype" - textual header "/usr/include/c++/9/tr1/ell_integral.tcc" - textual header "/usr/include/c++/9/tr1/exp_integral.tcc" - textual header "/usr/include/c++/9/tr1/fenv.h" - textual header "/usr/include/c++/9/tr1/float.h" - textual header "/usr/include/c++/9/tr1/functional" - textual header "/usr/include/c++/9/tr1/functional_hash.h" - textual header "/usr/include/c++/9/tr1/gamma.tcc" - textual header "/usr/include/c++/9/tr1/hashtable.h" - textual header "/usr/include/c++/9/tr1/hashtable_policy.h" - textual header "/usr/include/c++/9/tr1/hypergeometric.tcc" - textual header "/usr/include/c++/9/tr1/inttypes.h" - textual header "/usr/include/c++/9/tr1/legendre_function.tcc" - textual header "/usr/include/c++/9/tr1/limits.h" - textual header "/usr/include/c++/9/tr1/math.h" - textual header "/usr/include/c++/9/tr1/memory" - textual header "/usr/include/c++/9/tr1/modified_bessel_func.tcc" - textual header "/usr/include/c++/9/tr1/poly_hermite.tcc" - textual header "/usr/include/c++/9/tr1/poly_laguerre.tcc" - textual header "/usr/include/c++/9/tr1/random" - textual header "/usr/include/c++/9/tr1/random.h" - textual header "/usr/include/c++/9/tr1/random.tcc" - textual header "/usr/include/c++/9/tr1/regex" - textual header "/usr/include/c++/9/tr1/riemann_zeta.tcc" - textual header "/usr/include/c++/9/tr1/shared_ptr.h" - textual header "/usr/include/c++/9/tr1/special_function_util.h" - textual header "/usr/include/c++/9/tr1/stdarg.h" - textual header "/usr/include/c++/9/tr1/stdbool.h" - textual header "/usr/include/c++/9/tr1/stdint.h" - textual header "/usr/include/c++/9/tr1/stdio.h" - textual header "/usr/include/c++/9/tr1/stdlib.h" - textual header "/usr/include/c++/9/tr1/tgmath.h" - textual header "/usr/include/c++/9/tr1/tuple" - textual header "/usr/include/c++/9/tr1/type_traits" - textual header "/usr/include/c++/9/tr1/unordered_map" - textual header "/usr/include/c++/9/tr1/unordered_map.h" - textual header "/usr/include/c++/9/tr1/unordered_set" - textual header "/usr/include/c++/9/tr1/unordered_set.h" - textual header "/usr/include/c++/9/tr1/utility" - textual header "/usr/include/c++/9/tr1/wchar.h" - textual header "/usr/include/c++/9/tr1/wctype.h" - textual header "/usr/include/c++/9/tr2/bool_set" - textual header "/usr/include/c++/9/tr2/bool_set.tcc" - textual header "/usr/include/c++/9/tr2/dynamic_bitset" - textual header "/usr/include/c++/9/tr2/dynamic_bitset.tcc" - textual header "/usr/include/c++/9/tr2/ratio" - textual header "/usr/include/c++/9/tr2/type_traits" - textual header "/usr/include/c++/9/tuple" - textual header "/usr/include/c++/9/typeindex" - textual header "/usr/include/c++/9/typeinfo" - textual header "/usr/include/c++/9/type_traits" - textual header "/usr/include/c++/9/unordered_map" - textual header "/usr/include/c++/9/unordered_set" - textual header "/usr/include/c++/9/utility" - textual header "/usr/include/c++/9/valarray" - textual header "/usr/include/c++/9/variant" - textual header "/usr/include/c++/9/vector" - textual header "/usr/include/c++/9/version" + textual header "/usr/include/c++/11/algorithm" + textual header "/usr/include/c++/11/any" + textual header "/usr/include/c++/11/array" + textual header "/usr/include/c++/11/atomic" + textual header "/usr/include/c++/11/backward/auto_ptr.h" + textual header "/usr/include/c++/11/backward/backward_warning.h" + textual header "/usr/include/c++/11/backward/binders.h" + textual header "/usr/include/c++/11/backward/hash_fun.h" + textual header "/usr/include/c++/11/backward/hash_map" + textual header "/usr/include/c++/11/backward/hash_set" + textual header "/usr/include/c++/11/backward/hashtable.h" + textual header "/usr/include/c++/11/backward/strstream" + textual header "/usr/include/c++/11/barrier" + textual header "/usr/include/c++/11/bit" + textual header "/usr/include/c++/11/bits/algorithmfwd.h" + textual header "/usr/include/c++/11/bits/align.h" + textual header "/usr/include/c++/11/bits/allocated_ptr.h" + textual header "/usr/include/c++/11/bits/allocator.h" + textual header "/usr/include/c++/11/bits/alloc_traits.h" + textual header "/usr/include/c++/11/bits/atomic_base.h" + textual header "/usr/include/c++/11/bits/atomic_futex.h" + textual header "/usr/include/c++/11/bits/atomic_lockfree_defines.h" + textual header "/usr/include/c++/11/bits/atomic_timed_wait.h" + textual header "/usr/include/c++/11/bits/atomic_wait.h" + textual header "/usr/include/c++/11/bits/basic_ios.h" + textual header "/usr/include/c++/11/bits/basic_ios.tcc" + textual header "/usr/include/c++/11/bits/basic_string.h" + textual header "/usr/include/c++/11/bits/basic_string.tcc" + textual header "/usr/include/c++/11/bits/boost_concept_check.h" + textual header "/usr/include/c++/11/bits/c++0x_warning.h" + textual header "/usr/include/c++/11/bits/charconv.h" + textual header "/usr/include/c++/11/bits/char_traits.h" + textual header "/usr/include/c++/11/bits/codecvt.h" + textual header "/usr/include/c++/11/bits/concept_check.h" + textual header "/usr/include/c++/11/bits/cpp_type_traits.h" + textual header "/usr/include/c++/11/bits/cxxabi_forced.h" + textual header "/usr/include/c++/11/bits/cxxabi_init_exception.h" + textual header "/usr/include/c++/11/bits/deque.tcc" + textual header "/usr/include/c++/11/bits/enable_special_members.h" + textual header "/usr/include/c++/11/bits/erase_if.h" + textual header "/usr/include/c++/11/bitset" + textual header "/usr/include/c++/11/bits/exception_defines.h" + textual header "/usr/include/c++/11/bits/exception.h" + textual header "/usr/include/c++/11/bits/exception_ptr.h" + textual header "/usr/include/c++/11/bits/forward_list.h" + textual header "/usr/include/c++/11/bits/forward_list.tcc" + textual header "/usr/include/c++/11/bits/fs_dir.h" + textual header "/usr/include/c++/11/bits/fs_fwd.h" + textual header "/usr/include/c++/11/bits/fs_ops.h" + textual header "/usr/include/c++/11/bits/fs_path.h" + textual header "/usr/include/c++/11/bits/fstream.tcc" + textual header "/usr/include/c++/11/bits/functexcept.h" + textual header "/usr/include/c++/11/bits/functional_hash.h" + textual header "/usr/include/c++/11/bits/gslice_array.h" + textual header "/usr/include/c++/11/bits/gslice.h" + textual header "/usr/include/c++/11/bits/hash_bytes.h" + textual header "/usr/include/c++/11/bits/hashtable.h" + textual header "/usr/include/c++/11/bits/hashtable_policy.h" + textual header "/usr/include/c++/11/bits/indirect_array.h" + textual header "/usr/include/c++/11/bits/invoke.h" + textual header "/usr/include/c++/11/bits/ios_base.h" + textual header "/usr/include/c++/11/bits/istream.tcc" + textual header "/usr/include/c++/11/bits/iterator_concepts.h" + textual header "/usr/include/c++/11/bits/list.tcc" + textual header "/usr/include/c++/11/bits/locale_classes.h" + textual header "/usr/include/c++/11/bits/locale_classes.tcc" + textual header "/usr/include/c++/11/bits/locale_conv.h" + textual header "/usr/include/c++/11/bits/locale_facets.h" + textual header "/usr/include/c++/11/bits/locale_facets_nonio.h" + textual header "/usr/include/c++/11/bits/locale_facets_nonio.tcc" + textual header "/usr/include/c++/11/bits/locale_facets.tcc" + textual header "/usr/include/c++/11/bits/localefwd.h" + textual header "/usr/include/c++/11/bits/mask_array.h" + textual header "/usr/include/c++/11/bits/max_size_type.h" + textual header "/usr/include/c++/11/bits/memoryfwd.h" + textual header "/usr/include/c++/11/bits/move.h" + textual header "/usr/include/c++/11/bits/nested_exception.h" + textual header "/usr/include/c++/11/bits/node_handle.h" + textual header "/usr/include/c++/11/bits/ostream_insert.h" + textual header "/usr/include/c++/11/bits/ostream.tcc" + textual header "/usr/include/c++/11/bits/parse_numbers.h" + textual header "/usr/include/c++/11/bits/postypes.h" + textual header "/usr/include/c++/11/bits/predefined_ops.h" + textual header "/usr/include/c++/11/bits/ptr_traits.h" + textual header "/usr/include/c++/11/bits/quoted_string.h" + textual header "/usr/include/c++/11/bits/random.h" + textual header "/usr/include/c++/11/bits/random.tcc" + textual header "/usr/include/c++/11/bits/range_access.h" + textual header "/usr/include/c++/11/bits/ranges_algobase.h" + textual header "/usr/include/c++/11/bits/ranges_algo.h" + textual header "/usr/include/c++/11/bits/ranges_base.h" + textual header "/usr/include/c++/11/bits/ranges_cmp.h" + textual header "/usr/include/c++/11/bits/ranges_uninitialized.h" + textual header "/usr/include/c++/11/bits/ranges_util.h" + textual header "/usr/include/c++/11/bits/refwrap.h" + textual header "/usr/include/c++/11/bits/regex_automaton.h" + textual header "/usr/include/c++/11/bits/regex_automaton.tcc" + textual header "/usr/include/c++/11/bits/regex_compiler.h" + textual header "/usr/include/c++/11/bits/regex_compiler.tcc" + textual header "/usr/include/c++/11/bits/regex_constants.h" + textual header "/usr/include/c++/11/bits/regex_error.h" + textual header "/usr/include/c++/11/bits/regex_executor.h" + textual header "/usr/include/c++/11/bits/regex_executor.tcc" + textual header "/usr/include/c++/11/bits/regex.h" + textual header "/usr/include/c++/11/bits/regex_scanner.h" + textual header "/usr/include/c++/11/bits/regex_scanner.tcc" + textual header "/usr/include/c++/11/bits/regex.tcc" + textual header "/usr/include/c++/11/bits/semaphore_base.h" + textual header "/usr/include/c++/11/bits/shared_ptr_atomic.h" + textual header "/usr/include/c++/11/bits/shared_ptr_base.h" + textual header "/usr/include/c++/11/bits/shared_ptr.h" + textual header "/usr/include/c++/11/bits/slice_array.h" + textual header "/usr/include/c++/11/bits/specfun.h" + textual header "/usr/include/c++/11/bits/sstream.tcc" + textual header "/usr/include/c++/11/bits/std_abs.h" + textual header "/usr/include/c++/11/bits/std_function.h" + textual header "/usr/include/c++/11/bits/std_mutex.h" + textual header "/usr/include/c++/11/bits/std_thread.h" + textual header "/usr/include/c++/11/bits/stl_algobase.h" + textual header "/usr/include/c++/11/bits/stl_algo.h" + textual header "/usr/include/c++/11/bits/stl_bvector.h" + textual header "/usr/include/c++/11/bits/stl_construct.h" + textual header "/usr/include/c++/11/bits/stl_deque.h" + textual header "/usr/include/c++/11/bits/stl_function.h" + textual header "/usr/include/c++/11/bits/stl_heap.h" + textual header "/usr/include/c++/11/bits/stl_iterator_base_funcs.h" + textual header "/usr/include/c++/11/bits/stl_iterator_base_types.h" + textual header "/usr/include/c++/11/bits/stl_iterator.h" + textual header "/usr/include/c++/11/bits/stl_list.h" + textual header "/usr/include/c++/11/bits/stl_map.h" + textual header "/usr/include/c++/11/bits/stl_multimap.h" + textual header "/usr/include/c++/11/bits/stl_multiset.h" + textual header "/usr/include/c++/11/bits/stl_numeric.h" + textual header "/usr/include/c++/11/bits/stl_pair.h" + textual header "/usr/include/c++/11/bits/stl_queue.h" + textual header "/usr/include/c++/11/bits/stl_raw_storage_iter.h" + textual header "/usr/include/c++/11/bits/stl_relops.h" + textual header "/usr/include/c++/11/bits/stl_set.h" + textual header "/usr/include/c++/11/bits/stl_stack.h" + textual header "/usr/include/c++/11/bits/stl_tempbuf.h" + textual header "/usr/include/c++/11/bits/stl_tree.h" + textual header "/usr/include/c++/11/bits/stl_uninitialized.h" + textual header "/usr/include/c++/11/bits/stl_vector.h" + textual header "/usr/include/c++/11/bits/streambuf_iterator.h" + textual header "/usr/include/c++/11/bits/streambuf.tcc" + textual header "/usr/include/c++/11/bits/stream_iterator.h" + textual header "/usr/include/c++/11/bits/stringfwd.h" + textual header "/usr/include/c++/11/bits/string_view.tcc" + textual header "/usr/include/c++/11/bits/this_thread_sleep.h" + textual header "/usr/include/c++/11/bits/uniform_int_dist.h" + textual header "/usr/include/c++/11/bits/unique_lock.h" + textual header "/usr/include/c++/11/bits/unique_ptr.h" + textual header "/usr/include/c++/11/bits/unordered_map.h" + textual header "/usr/include/c++/11/bits/unordered_set.h" + textual header "/usr/include/c++/11/bits/uses_allocator_args.h" + textual header "/usr/include/c++/11/bits/uses_allocator.h" + textual header "/usr/include/c++/11/bits/valarray_after.h" + textual header "/usr/include/c++/11/bits/valarray_array.h" + textual header "/usr/include/c++/11/bits/valarray_array.tcc" + textual header "/usr/include/c++/11/bits/valarray_before.h" + textual header "/usr/include/c++/11/bits/vector.tcc" + textual header "/usr/include/c++/11/cassert" + textual header "/usr/include/c++/11/ccomplex" + textual header "/usr/include/c++/11/cctype" + textual header "/usr/include/c++/11/cerrno" + textual header "/usr/include/c++/11/cfenv" + textual header "/usr/include/c++/11/cfloat" + textual header "/usr/include/c++/11/charconv" + textual header "/usr/include/c++/11/chrono" + textual header "/usr/include/c++/11/cinttypes" + textual header "/usr/include/c++/11/ciso646" + textual header "/usr/include/c++/11/climits" + textual header "/usr/include/c++/11/clocale" + textual header "/usr/include/c++/11/cmath" + textual header "/usr/include/c++/11/codecvt" + textual header "/usr/include/c++/11/compare" + textual header "/usr/include/c++/11/complex" + textual header "/usr/include/c++/11/complex.h" + textual header "/usr/include/c++/11/concepts" + textual header "/usr/include/c++/11/condition_variable" + textual header "/usr/include/c++/11/coroutine" + textual header "/usr/include/c++/11/csetjmp" + textual header "/usr/include/c++/11/csignal" + textual header "/usr/include/c++/11/cstdalign" + textual header "/usr/include/c++/11/cstdarg" + textual header "/usr/include/c++/11/cstdbool" + textual header "/usr/include/c++/11/cstddef" + textual header "/usr/include/c++/11/cstdint" + textual header "/usr/include/c++/11/cstdio" + textual header "/usr/include/c++/11/cstdlib" + textual header "/usr/include/c++/11/cstring" + textual header "/usr/include/c++/11/ctgmath" + textual header "/usr/include/c++/11/ctime" + textual header "/usr/include/c++/11/cuchar" + textual header "/usr/include/c++/11/cwchar" + textual header "/usr/include/c++/11/cwctype" + textual header "/usr/include/c++/11/cxxabi.h" + textual header "/usr/include/c++/11/debug/assertions.h" + textual header "/usr/include/c++/11/debug/bitset" + textual header "/usr/include/c++/11/debug/debug.h" + textual header "/usr/include/c++/11/debug/deque" + textual header "/usr/include/c++/11/debug/formatter.h" + textual header "/usr/include/c++/11/debug/forward_list" + textual header "/usr/include/c++/11/debug/functions.h" + textual header "/usr/include/c++/11/debug/helper_functions.h" + textual header "/usr/include/c++/11/debug/list" + textual header "/usr/include/c++/11/debug/macros.h" + textual header "/usr/include/c++/11/debug/map" + textual header "/usr/include/c++/11/debug/map.h" + textual header "/usr/include/c++/11/debug/multimap.h" + textual header "/usr/include/c++/11/debug/multiset.h" + textual header "/usr/include/c++/11/debug/safe_base.h" + textual header "/usr/include/c++/11/debug/safe_container.h" + textual header "/usr/include/c++/11/debug/safe_iterator.h" + textual header "/usr/include/c++/11/debug/safe_iterator.tcc" + textual header "/usr/include/c++/11/debug/safe_local_iterator.h" + textual header "/usr/include/c++/11/debug/safe_local_iterator.tcc" + textual header "/usr/include/c++/11/debug/safe_sequence.h" + textual header "/usr/include/c++/11/debug/safe_sequence.tcc" + textual header "/usr/include/c++/11/debug/safe_unordered_base.h" + textual header "/usr/include/c++/11/debug/safe_unordered_container.h" + textual header "/usr/include/c++/11/debug/safe_unordered_container.tcc" + textual header "/usr/include/c++/11/debug/set" + textual header "/usr/include/c++/11/debug/set.h" + textual header "/usr/include/c++/11/debug/stl_iterator.h" + textual header "/usr/include/c++/11/debug/string" + textual header "/usr/include/c++/11/debug/unordered_map" + textual header "/usr/include/c++/11/debug/unordered_set" + textual header "/usr/include/c++/11/debug/vector" + textual header "/usr/include/c++/11/decimal/decimal" + textual header "/usr/include/c++/11/decimal/decimal.h" + textual header "/usr/include/c++/11/deque" + textual header "/usr/include/c++/11/exception" + textual header "/usr/include/c++/11/execution" + textual header "/usr/include/c++/11/experimental/algorithm" + textual header "/usr/include/c++/11/experimental/any" + textual header "/usr/include/c++/11/experimental/array" + textual header "/usr/include/c++/11/experimental/bits/fs_dir.h" + textual header "/usr/include/c++/11/experimental/bits/fs_fwd.h" + textual header "/usr/include/c++/11/experimental/bits/fs_ops.h" + textual header "/usr/include/c++/11/experimental/bits/fs_path.h" + textual header "/usr/include/c++/11/experimental/bits/lfts_config.h" + textual header "/usr/include/c++/11/experimental/bits/net.h" + textual header "/usr/include/c++/11/experimental/bits/numeric_traits.h" + textual header "/usr/include/c++/11/experimental/bits/shared_ptr.h" + textual header "/usr/include/c++/11/experimental/bits/simd_builtin.h" + textual header "/usr/include/c++/11/experimental/bits/simd_converter.h" + textual header "/usr/include/c++/11/experimental/bits/simd_detail.h" + textual header "/usr/include/c++/11/experimental/bits/simd_fixed_size.h" + textual header "/usr/include/c++/11/experimental/bits/simd.h" + textual header "/usr/include/c++/11/experimental/bits/simd_math.h" + textual header "/usr/include/c++/11/experimental/bits/simd_neon.h" + textual header "/usr/include/c++/11/experimental/bits/simd_ppc.h" + textual header "/usr/include/c++/11/experimental/bits/simd_scalar.h" + textual header "/usr/include/c++/11/experimental/bits/simd_x86_conversions.h" + textual header "/usr/include/c++/11/experimental/bits/simd_x86.h" + textual header "/usr/include/c++/11/experimental/bits/string_view.tcc" + textual header "/usr/include/c++/11/experimental/buffer" + textual header "/usr/include/c++/11/experimental/chrono" + textual header "/usr/include/c++/11/experimental/deque" + textual header "/usr/include/c++/11/experimental/executor" + textual header "/usr/include/c++/11/experimental/filesystem" + textual header "/usr/include/c++/11/experimental/forward_list" + textual header "/usr/include/c++/11/experimental/functional" + textual header "/usr/include/c++/11/experimental/internet" + textual header "/usr/include/c++/11/experimental/io_context" + textual header "/usr/include/c++/11/experimental/iterator" + textual header "/usr/include/c++/11/experimental/list" + textual header "/usr/include/c++/11/experimental/map" + textual header "/usr/include/c++/11/experimental/memory" + textual header "/usr/include/c++/11/experimental/memory_resource" + textual header "/usr/include/c++/11/experimental/net" + textual header "/usr/include/c++/11/experimental/netfwd" + textual header "/usr/include/c++/11/experimental/numeric" + textual header "/usr/include/c++/11/experimental/optional" + textual header "/usr/include/c++/11/experimental/propagate_const" + textual header "/usr/include/c++/11/experimental/random" + textual header "/usr/include/c++/11/experimental/ratio" + textual header "/usr/include/c++/11/experimental/regex" + textual header "/usr/include/c++/11/experimental/set" + textual header "/usr/include/c++/11/experimental/simd" + textual header "/usr/include/c++/11/experimental/socket" + textual header "/usr/include/c++/11/experimental/source_location" + textual header "/usr/include/c++/11/experimental/string" + textual header "/usr/include/c++/11/experimental/string_view" + textual header "/usr/include/c++/11/experimental/system_error" + textual header "/usr/include/c++/11/experimental/timer" + textual header "/usr/include/c++/11/experimental/tuple" + textual header "/usr/include/c++/11/experimental/type_traits" + textual header "/usr/include/c++/11/experimental/unordered_map" + textual header "/usr/include/c++/11/experimental/unordered_set" + textual header "/usr/include/c++/11/experimental/utility" + textual header "/usr/include/c++/11/experimental/vector" + textual header "/usr/include/c++/11/ext/algorithm" + textual header "/usr/include/c++/11/ext/aligned_buffer.h" + textual header "/usr/include/c++/11/ext/alloc_traits.h" + textual header "/usr/include/c++/11/ext/atomicity.h" + textual header "/usr/include/c++/11/ext/bitmap_allocator.h" + textual header "/usr/include/c++/11/ext/cast.h" + textual header "/usr/include/c++/11/ext/cmath" + textual header "/usr/include/c++/11/ext/codecvt_specializations.h" + textual header "/usr/include/c++/11/ext/concurrence.h" + textual header "/usr/include/c++/11/ext/debug_allocator.h" + textual header "/usr/include/c++/11/ext/enc_filebuf.h" + textual header "/usr/include/c++/11/ext/extptr_allocator.h" + textual header "/usr/include/c++/11/ext/functional" + textual header "/usr/include/c++/11/ext/hash_map" + textual header "/usr/include/c++/11/ext/hash_set" + textual header "/usr/include/c++/11/ext/iterator" + textual header "/usr/include/c++/11/ext/malloc_allocator.h" + textual header "/usr/include/c++/11/ext/memory" + textual header "/usr/include/c++/11/ext/mt_allocator.h" + textual header "/usr/include/c++/11/ext/new_allocator.h" + textual header "/usr/include/c++/11/ext/numeric" + textual header "/usr/include/c++/11/ext/numeric_traits.h" + textual header "/usr/include/c++/11/ext/pb_ds/assoc_container.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/binary_heap_/binary_heap_.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/binary_heap_/const_iterator.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/binary_heap_/constructors_destructor_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/binary_heap_/debug_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/binary_heap_/entry_cmp.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/binary_heap_/entry_pred.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/binary_heap_/erase_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/binary_heap_/find_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/binary_heap_/info_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/binary_heap_/insert_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/binary_heap_/iterators_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/binary_heap_/point_const_iterator.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/binary_heap_/policy_access_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/binary_heap_/resize_policy.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/binary_heap_/split_join_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/binary_heap_/trace_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/binomial_heap_base_/binomial_heap_base_.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/binomial_heap_base_/constructors_destructor_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/binomial_heap_base_/debug_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/binomial_heap_base_/erase_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/binomial_heap_base_/find_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/binomial_heap_base_/insert_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/binomial_heap_base_/split_join_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/binomial_heap_/binomial_heap_.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/binomial_heap_/constructors_destructor_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/binomial_heap_/debug_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/bin_search_tree_/bin_search_tree_.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/bin_search_tree_/constructors_destructor_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/bin_search_tree_/debug_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/bin_search_tree_/erase_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/bin_search_tree_/find_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/bin_search_tree_/info_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/bin_search_tree_/insert_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/bin_search_tree_/iterators_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/bin_search_tree_/node_iterators.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/bin_search_tree_/point_iterators.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/bin_search_tree_/policy_access_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/bin_search_tree_/r_erase_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/bin_search_tree_/rotate_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/bin_search_tree_/split_join_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/bin_search_tree_/traits.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/branch_policy/branch_policy.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/branch_policy/null_node_metadata.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/branch_policy/traits.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/cc_hash_table_map_/cc_ht_map_.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/cc_hash_table_map_/cmp_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/cc_hash_table_map_/cond_key_dtor_entry_dealtor.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/cc_hash_table_map_/constructor_destructor_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/cc_hash_table_map_/constructor_destructor_no_store_hash_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/cc_hash_table_map_/constructor_destructor_store_hash_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/cc_hash_table_map_/debug_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/cc_hash_table_map_/debug_no_store_hash_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/cc_hash_table_map_/debug_store_hash_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/cc_hash_table_map_/entry_list_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/cc_hash_table_map_/erase_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/cc_hash_table_map_/erase_no_store_hash_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/cc_hash_table_map_/erase_store_hash_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/cc_hash_table_map_/find_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/cc_hash_table_map_/find_store_hash_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/cc_hash_table_map_/info_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/cc_hash_table_map_/insert_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/cc_hash_table_map_/insert_no_store_hash_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/cc_hash_table_map_/insert_store_hash_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/cc_hash_table_map_/iterators_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/cc_hash_table_map_/policy_access_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/cc_hash_table_map_/resize_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/cc_hash_table_map_/resize_no_store_hash_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/cc_hash_table_map_/resize_store_hash_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/cc_hash_table_map_/size_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/cc_hash_table_map_/trace_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/cond_dealtor.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/container_base_dispatch.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/debug_map_base.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/eq_fn/eq_by_less.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/eq_fn/hash_eq_fn.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/gp_hash_table_map_/constructor_destructor_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/gp_hash_table_map_/constructor_destructor_no_store_hash_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/gp_hash_table_map_/constructor_destructor_store_hash_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/gp_hash_table_map_/debug_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/gp_hash_table_map_/debug_no_store_hash_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/gp_hash_table_map_/debug_store_hash_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/gp_hash_table_map_/erase_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/gp_hash_table_map_/erase_no_store_hash_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/gp_hash_table_map_/erase_store_hash_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/gp_hash_table_map_/find_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/gp_hash_table_map_/find_no_store_hash_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/gp_hash_table_map_/find_store_hash_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/gp_hash_table_map_/gp_ht_map_.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/gp_hash_table_map_/info_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/gp_hash_table_map_/insert_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/gp_hash_table_map_/insert_no_store_hash_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/gp_hash_table_map_/insert_store_hash_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/gp_hash_table_map_/iterator_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/gp_hash_table_map_/policy_access_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/gp_hash_table_map_/resize_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/gp_hash_table_map_/resize_no_store_hash_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/gp_hash_table_map_/resize_store_hash_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/gp_hash_table_map_/trace_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/hash_fn/direct_mask_range_hashing_imp.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/hash_fn/direct_mod_range_hashing_imp.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/hash_fn/linear_probe_fn_imp.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/hash_fn/mask_based_range_hashing.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/hash_fn/mod_based_range_hashing.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/hash_fn/probe_fn_base.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/hash_fn/quadratic_probe_fn_imp.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/hash_fn/ranged_hash_fn.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/hash_fn/ranged_probe_fn.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/hash_fn/sample_probe_fn.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/hash_fn/sample_ranged_hash_fn.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/hash_fn/sample_ranged_probe_fn.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/hash_fn/sample_range_hashing.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/left_child_next_sibling_heap_/const_iterator.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/left_child_next_sibling_heap_/constructors_destructor_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/left_child_next_sibling_heap_/debug_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/left_child_next_sibling_heap_/erase_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/left_child_next_sibling_heap_/info_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/left_child_next_sibling_heap_/insert_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/left_child_next_sibling_heap_/iterators_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/left_child_next_sibling_heap_/left_child_next_sibling_heap_.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/left_child_next_sibling_heap_/node.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/left_child_next_sibling_heap_/point_const_iterator.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/left_child_next_sibling_heap_/policy_access_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/left_child_next_sibling_heap_/trace_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/list_update_map_/constructor_destructor_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/list_update_map_/debug_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/list_update_map_/entry_metadata_base.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/list_update_map_/erase_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/list_update_map_/find_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/list_update_map_/info_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/list_update_map_/insert_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/list_update_map_/iterators_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/list_update_map_/lu_map_.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/list_update_map_/trace_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/list_update_policy/lu_counter_metadata.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/list_update_policy/sample_update_policy.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/ov_tree_map_/constructors_destructor_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/ov_tree_map_/debug_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/ov_tree_map_/erase_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/ov_tree_map_/info_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/ov_tree_map_/insert_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/ov_tree_map_/iterators_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/ov_tree_map_/node_iterators.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/ov_tree_map_/ov_tree_map_.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/ov_tree_map_/policy_access_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/ov_tree_map_/split_join_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/ov_tree_map_/traits.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/pairing_heap_/constructors_destructor_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/pairing_heap_/debug_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/pairing_heap_/erase_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/pairing_heap_/find_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/pairing_heap_/insert_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/pairing_heap_/pairing_heap_.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/pairing_heap_/split_join_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/pat_trie_/constructors_destructor_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/pat_trie_/debug_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/pat_trie_/erase_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/pat_trie_/find_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/pat_trie_/info_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/pat_trie_/insert_join_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/pat_trie_/iterators_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/pat_trie_/pat_trie_base.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/pat_trie_/pat_trie_.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/pat_trie_/policy_access_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/pat_trie_/r_erase_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/pat_trie_/rotate_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/pat_trie_/split_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/pat_trie_/synth_access_traits.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/pat_trie_/trace_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/pat_trie_/traits.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/pat_trie_/update_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/priority_queue_base_dispatch.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/rb_tree_map_/constructors_destructor_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/rb_tree_map_/debug_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/rb_tree_map_/erase_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/rb_tree_map_/find_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/rb_tree_map_/info_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/rb_tree_map_/insert_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/rb_tree_map_/node.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/rb_tree_map_/rb_tree_.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/rb_tree_map_/split_join_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/rb_tree_map_/traits.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/rc_binomial_heap_/constructors_destructor_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/rc_binomial_heap_/debug_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/rc_binomial_heap_/erase_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/rc_binomial_heap_/insert_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/rc_binomial_heap_/rc_binomial_heap_.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/rc_binomial_heap_/rc.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/rc_binomial_heap_/split_join_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/rc_binomial_heap_/trace_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/resize_policy/cc_hash_max_collision_check_resize_trigger_imp.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/resize_policy/hash_exponential_size_policy_imp.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/resize_policy/hash_load_check_resize_trigger_imp.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/resize_policy/hash_load_check_resize_trigger_size_base.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/resize_policy/hash_prime_size_policy_imp.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/resize_policy/hash_standard_resize_policy_imp.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/resize_policy/sample_resize_policy.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/resize_policy/sample_resize_trigger.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/resize_policy/sample_size_policy.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/splay_tree_/constructors_destructor_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/splay_tree_/debug_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/splay_tree_/erase_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/splay_tree_/find_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/splay_tree_/info_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/splay_tree_/insert_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/splay_tree_/node.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/splay_tree_/splay_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/splay_tree_/splay_tree_.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/splay_tree_/split_join_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/splay_tree_/traits.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/standard_policies.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/thin_heap_/constructors_destructor_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/thin_heap_/debug_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/thin_heap_/erase_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/thin_heap_/find_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/thin_heap_/insert_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/thin_heap_/split_join_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/thin_heap_/thin_heap_.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/thin_heap_/trace_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/tree_policy/node_metadata_selector.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/tree_policy/order_statistics_imp.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/tree_policy/sample_tree_node_update.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/tree_trace_base.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/trie_policy/node_metadata_selector.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/trie_policy/order_statistics_imp.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/trie_policy/prefix_search_node_update_imp.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/trie_policy/sample_trie_access_traits.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/trie_policy/sample_trie_node_update.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/trie_policy/trie_policy_base.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/trie_policy/trie_string_access_traits_imp.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/types_traits.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/type_utils.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/unordered_iterator/const_iterator.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/unordered_iterator/iterator.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/unordered_iterator/point_const_iterator.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/unordered_iterator/point_iterator.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/exception.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/hash_policy.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/list_update_policy.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/priority_queue.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/tag_and_trait.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/tree_policy.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/trie_policy.hpp" + textual header "/usr/include/c++/11/ext/pod_char_traits.h" + textual header "/usr/include/c++/11/ext/pointer.h" + textual header "/usr/include/c++/11/ext/pool_allocator.h" + textual header "/usr/include/c++/11/ext/random" + textual header "/usr/include/c++/11/ext/random.tcc" + textual header "/usr/include/c++/11/ext/rb_tree" + textual header "/usr/include/c++/11/ext/rc_string_base.h" + textual header "/usr/include/c++/11/ext/rope" + textual header "/usr/include/c++/11/ext/ropeimpl.h" + textual header "/usr/include/c++/11/ext/slist" + textual header "/usr/include/c++/11/ext/sso_string_base.h" + textual header "/usr/include/c++/11/ext/stdio_filebuf.h" + textual header "/usr/include/c++/11/ext/stdio_sync_filebuf.h" + textual header "/usr/include/c++/11/ext/string_conversions.h" + textual header "/usr/include/c++/11/ext/throw_allocator.h" + textual header "/usr/include/c++/11/ext/typelist.h" + textual header "/usr/include/c++/11/ext/type_traits.h" + textual header "/usr/include/c++/11/ext/vstring_fwd.h" + textual header "/usr/include/c++/11/ext/vstring.h" + textual header "/usr/include/c++/11/ext/vstring.tcc" + textual header "/usr/include/c++/11/ext/vstring_util.h" + textual header "/usr/include/c++/11/fenv.h" + textual header "/usr/include/c++/11/filesystem" + textual header "/usr/include/c++/11/forward_list" + textual header "/usr/include/c++/11/fstream" + textual header "/usr/include/c++/11/functional" + textual header "/usr/include/c++/11/future" + textual header "/usr/include/c++/11/initializer_list" + textual header "/usr/include/c++/11/iomanip" + textual header "/usr/include/c++/11/ios" + textual header "/usr/include/c++/11/iosfwd" + textual header "/usr/include/c++/11/iostream" + textual header "/usr/include/c++/11/istream" + textual header "/usr/include/c++/11/iterator" + textual header "/usr/include/c++/11/latch" + textual header "/usr/include/c++/11/limits" + textual header "/usr/include/c++/11/list" + textual header "/usr/include/c++/11/locale" + textual header "/usr/include/c++/11/map" + textual header "/usr/include/c++/11/math.h" + textual header "/usr/include/c++/11/memory" + textual header "/usr/include/c++/11/memory_resource" + textual header "/usr/include/c++/11/mutex" + textual header "/usr/include/c++/11/new" + textual header "/usr/include/c++/11/numbers" + textual header "/usr/include/c++/11/numeric" + textual header "/usr/include/c++/11/optional" + textual header "/usr/include/c++/11/ostream" + textual header "/usr/include/c++/11/parallel/algobase.h" + textual header "/usr/include/c++/11/parallel/algo.h" + textual header "/usr/include/c++/11/parallel/algorithm" + textual header "/usr/include/c++/11/parallel/algorithmfwd.h" + textual header "/usr/include/c++/11/parallel/balanced_quicksort.h" + textual header "/usr/include/c++/11/parallel/base.h" + textual header "/usr/include/c++/11/parallel/basic_iterator.h" + textual header "/usr/include/c++/11/parallel/checkers.h" + textual header "/usr/include/c++/11/parallel/compatibility.h" + textual header "/usr/include/c++/11/parallel/compiletime_settings.h" + textual header "/usr/include/c++/11/parallel/equally_split.h" + textual header "/usr/include/c++/11/parallel/features.h" + textual header "/usr/include/c++/11/parallel/find.h" + textual header "/usr/include/c++/11/parallel/find_selectors.h" + textual header "/usr/include/c++/11/parallel/for_each.h" + textual header "/usr/include/c++/11/parallel/for_each_selectors.h" + textual header "/usr/include/c++/11/parallel/iterator.h" + textual header "/usr/include/c++/11/parallel/list_partition.h" + textual header "/usr/include/c++/11/parallel/losertree.h" + textual header "/usr/include/c++/11/parallel/merge.h" + textual header "/usr/include/c++/11/parallel/multiseq_selection.h" + textual header "/usr/include/c++/11/parallel/multiway_merge.h" + textual header "/usr/include/c++/11/parallel/multiway_mergesort.h" + textual header "/usr/include/c++/11/parallel/numeric" + textual header "/usr/include/c++/11/parallel/numericfwd.h" + textual header "/usr/include/c++/11/parallel/omp_loop.h" + textual header "/usr/include/c++/11/parallel/omp_loop_static.h" + textual header "/usr/include/c++/11/parallel/parallel.h" + textual header "/usr/include/c++/11/parallel/par_loop.h" + textual header "/usr/include/c++/11/parallel/partial_sum.h" + textual header "/usr/include/c++/11/parallel/partition.h" + textual header "/usr/include/c++/11/parallel/queue.h" + textual header "/usr/include/c++/11/parallel/quicksort.h" + textual header "/usr/include/c++/11/parallel/random_number.h" + textual header "/usr/include/c++/11/parallel/random_shuffle.h" + textual header "/usr/include/c++/11/parallel/search.h" + textual header "/usr/include/c++/11/parallel/set_operations.h" + textual header "/usr/include/c++/11/parallel/settings.h" + textual header "/usr/include/c++/11/parallel/sort.h" + textual header "/usr/include/c++/11/parallel/tags.h" + textual header "/usr/include/c++/11/parallel/types.h" + textual header "/usr/include/c++/11/parallel/unique_copy.h" + textual header "/usr/include/c++/11/parallel/workstealing.h" + textual header "/usr/include/c++/11/pstl/algorithm_fwd.h" + textual header "/usr/include/c++/11/pstl/algorithm_impl.h" + textual header "/usr/include/c++/11/pstl/execution_defs.h" + textual header "/usr/include/c++/11/pstl/execution_impl.h" + textual header "/usr/include/c++/11/pstl/glue_algorithm_defs.h" + textual header "/usr/include/c++/11/pstl/glue_algorithm_impl.h" + textual header "/usr/include/c++/11/pstl/glue_execution_defs.h" + textual header "/usr/include/c++/11/pstl/glue_memory_defs.h" + textual header "/usr/include/c++/11/pstl/glue_memory_impl.h" + textual header "/usr/include/c++/11/pstl/glue_numeric_defs.h" + textual header "/usr/include/c++/11/pstl/glue_numeric_impl.h" + textual header "/usr/include/c++/11/pstl/memory_impl.h" + textual header "/usr/include/c++/11/pstl/numeric_fwd.h" + textual header "/usr/include/c++/11/pstl/numeric_impl.h" + textual header "/usr/include/c++/11/pstl/parallel_backend.h" + textual header "/usr/include/c++/11/pstl/parallel_backend_serial.h" + textual header "/usr/include/c++/11/pstl/parallel_backend_tbb.h" + textual header "/usr/include/c++/11/pstl/parallel_backend_utils.h" + textual header "/usr/include/c++/11/pstl/parallel_impl.h" + textual header "/usr/include/c++/11/pstl/pstl_config.h" + textual header "/usr/include/c++/11/pstl/unseq_backend_simd.h" + textual header "/usr/include/c++/11/pstl/utils.h" + textual header "/usr/include/c++/11/queue" + textual header "/usr/include/c++/11/random" + textual header "/usr/include/c++/11/ranges" + textual header "/usr/include/c++/11/ratio" + textual header "/usr/include/c++/11/regex" + textual header "/usr/include/c++/11/scoped_allocator" + textual header "/usr/include/c++/11/semaphore" + textual header "/usr/include/c++/11/set" + textual header "/usr/include/c++/11/shared_mutex" + textual header "/usr/include/c++/11/source_location" + textual header "/usr/include/c++/11/span" + textual header "/usr/include/c++/11/sstream" + textual header "/usr/include/c++/11/stack" + textual header "/usr/include/c++/11/stdexcept" + textual header "/usr/include/c++/11/stdlib.h" + textual header "/usr/include/c++/11/stop_token" + textual header "/usr/include/c++/11/streambuf" + textual header "/usr/include/c++/11/string" + textual header "/usr/include/c++/11/string_view" + textual header "/usr/include/c++/11/syncstream" + textual header "/usr/include/c++/11/system_error" + textual header "/usr/include/c++/11/tgmath.h" + textual header "/usr/include/c++/11/thread" + textual header "/usr/include/c++/11/tr1/array" + textual header "/usr/include/c++/11/tr1/bessel_function.tcc" + textual header "/usr/include/c++/11/tr1/beta_function.tcc" + textual header "/usr/include/c++/11/tr1/ccomplex" + textual header "/usr/include/c++/11/tr1/cctype" + textual header "/usr/include/c++/11/tr1/cfenv" + textual header "/usr/include/c++/11/tr1/cfloat" + textual header "/usr/include/c++/11/tr1/cinttypes" + textual header "/usr/include/c++/11/tr1/climits" + textual header "/usr/include/c++/11/tr1/cmath" + textual header "/usr/include/c++/11/tr1/complex" + textual header "/usr/include/c++/11/tr1/complex.h" + textual header "/usr/include/c++/11/tr1/cstdarg" + textual header "/usr/include/c++/11/tr1/cstdbool" + textual header "/usr/include/c++/11/tr1/cstdint" + textual header "/usr/include/c++/11/tr1/cstdio" + textual header "/usr/include/c++/11/tr1/cstdlib" + textual header "/usr/include/c++/11/tr1/ctgmath" + textual header "/usr/include/c++/11/tr1/ctime" + textual header "/usr/include/c++/11/tr1/ctype.h" + textual header "/usr/include/c++/11/tr1/cwchar" + textual header "/usr/include/c++/11/tr1/cwctype" + textual header "/usr/include/c++/11/tr1/ell_integral.tcc" + textual header "/usr/include/c++/11/tr1/exp_integral.tcc" + textual header "/usr/include/c++/11/tr1/fenv.h" + textual header "/usr/include/c++/11/tr1/float.h" + textual header "/usr/include/c++/11/tr1/functional" + textual header "/usr/include/c++/11/tr1/functional_hash.h" + textual header "/usr/include/c++/11/tr1/gamma.tcc" + textual header "/usr/include/c++/11/tr1/hashtable.h" + textual header "/usr/include/c++/11/tr1/hashtable_policy.h" + textual header "/usr/include/c++/11/tr1/hypergeometric.tcc" + textual header "/usr/include/c++/11/tr1/inttypes.h" + textual header "/usr/include/c++/11/tr1/legendre_function.tcc" + textual header "/usr/include/c++/11/tr1/limits.h" + textual header "/usr/include/c++/11/tr1/math.h" + textual header "/usr/include/c++/11/tr1/memory" + textual header "/usr/include/c++/11/tr1/modified_bessel_func.tcc" + textual header "/usr/include/c++/11/tr1/poly_hermite.tcc" + textual header "/usr/include/c++/11/tr1/poly_laguerre.tcc" + textual header "/usr/include/c++/11/tr1/random" + textual header "/usr/include/c++/11/tr1/random.h" + textual header "/usr/include/c++/11/tr1/random.tcc" + textual header "/usr/include/c++/11/tr1/regex" + textual header "/usr/include/c++/11/tr1/riemann_zeta.tcc" + textual header "/usr/include/c++/11/tr1/shared_ptr.h" + textual header "/usr/include/c++/11/tr1/special_function_util.h" + textual header "/usr/include/c++/11/tr1/stdarg.h" + textual header "/usr/include/c++/11/tr1/stdbool.h" + textual header "/usr/include/c++/11/tr1/stdint.h" + textual header "/usr/include/c++/11/tr1/stdio.h" + textual header "/usr/include/c++/11/tr1/stdlib.h" + textual header "/usr/include/c++/11/tr1/tgmath.h" + textual header "/usr/include/c++/11/tr1/tuple" + textual header "/usr/include/c++/11/tr1/type_traits" + textual header "/usr/include/c++/11/tr1/unordered_map" + textual header "/usr/include/c++/11/tr1/unordered_map.h" + textual header "/usr/include/c++/11/tr1/unordered_set" + textual header "/usr/include/c++/11/tr1/unordered_set.h" + textual header "/usr/include/c++/11/tr1/utility" + textual header "/usr/include/c++/11/tr1/wchar.h" + textual header "/usr/include/c++/11/tr1/wctype.h" + textual header "/usr/include/c++/11/tr2/bool_set" + textual header "/usr/include/c++/11/tr2/bool_set.tcc" + textual header "/usr/include/c++/11/tr2/dynamic_bitset" + textual header "/usr/include/c++/11/tr2/dynamic_bitset.tcc" + textual header "/usr/include/c++/11/tr2/ratio" + textual header "/usr/include/c++/11/tr2/type_traits" + textual header "/usr/include/c++/11/tuple" + textual header "/usr/include/c++/11/typeindex" + textual header "/usr/include/c++/11/typeinfo" + textual header "/usr/include/c++/11/type_traits" + textual header "/usr/include/c++/11/unordered_map" + textual header "/usr/include/c++/11/unordered_set" + textual header "/usr/include/c++/11/utility" + textual header "/usr/include/c++/11/valarray" + textual header "/usr/include/c++/11/variant" + textual header "/usr/include/c++/11/vector" + textual header "/usr/include/c++/11/version" textual header "/usr/include/complex.h" textual header "/usr/include/cpio.h" textual header "/usr/include/crypt.h" @@ -1383,16 +1422,19 @@ module "crosstool" [system] { textual header "/usr/include/drm/exynos_drm.h" textual header "/usr/include/drm/i810_drm.h" textual header "/usr/include/drm/i915_drm.h" + textual header "/usr/include/drm/lima_drm.h" textual header "/usr/include/drm/mga_drm.h" textual header "/usr/include/drm/msm_drm.h" textual header "/usr/include/drm/nouveau_drm.h" textual header "/usr/include/drm/omap_drm.h" + textual header "/usr/include/drm/panfrost_drm.h" textual header "/usr/include/drm/qxl_drm.h" textual header "/usr/include/drm/r128_drm.h" textual header "/usr/include/drm/radeon_drm.h" textual header "/usr/include/drm/savage_drm.h" textual header "/usr/include/drm/sis_drm.h" textual header "/usr/include/drm/tegra_drm.h" + textual header "/usr/include/drm/v3d_drm.h" textual header "/usr/include/drm/vc4_drm.h" textual header "/usr/include/drm/vgem_drm.h" textual header "/usr/include/drm/via_drm.h" @@ -1407,18 +1449,17 @@ module "crosstool" [system] { textual header "/usr/include/eti.h" textual header "/usr/include/etip.h" textual header "/usr/include/execinfo.h" - textual header "/usr/include/expat_external.h" - textual header "/usr/include/expat.h" textual header "/usr/include/fcntl.h" textual header "/usr/include/features.h" textual header "/usr/include/fenv.h" + textual header "/usr/include/finclude/math-vector-fortran.h" textual header "/usr/include/fmtmsg.h" textual header "/usr/include/fnmatch.h" textual header "/usr/include/form.h" textual header "/usr/include/fstab.h" textual header "/usr/include/fts.h" textual header "/usr/include/ftw.h" - textual header "/usr/include/_G_config.h" + textual header "/usr/include/gawkapi.h" textual header "/usr/include/gconv.h" textual header "/usr/include/gdb/jit-reader.h" textual header "/usr/include/getopt.h" @@ -1430,11 +1471,11 @@ module "crosstool" [system] { textual header "/usr/include/iconv.h" textual header "/usr/include/ifaddrs.h" textual header "/usr/include/inttypes.h" + textual header "/usr/include/iproute2/bpf_elf.h" textual header "/usr/include/langinfo.h" textual header "/usr/include/lastlog.h" textual header "/usr/include/libgen.h" textual header "/usr/include/libintl.h" - textual header "/usr/include/libio.h" textual header "/usr/include/limits.h" textual header "/usr/include/link.h" textual header "/usr/include/linux/acct.h" @@ -1444,12 +1485,14 @@ module "crosstool" [system] { textual header "/usr/include/linux/agpgart.h" textual header "/usr/include/linux/aio_abi.h" textual header "/usr/include/linux/am437x-vpfe.h" + textual header "/usr/include/linux/android/binderfs.h" textual header "/usr/include/linux/android/binder.h" textual header "/usr/include/linux/a.out.h" textual header "/usr/include/linux/apm_bios.h" textual header "/usr/include/linux/arcfb.h" textual header "/usr/include/linux/arm_sdei.h" textual header "/usr/include/linux/aspeed-lpc-ctrl.h" + textual header "/usr/include/linux/aspeed-p2a-ctrl.h" textual header "/usr/include/linux/atalk.h" textual header "/usr/include/linux/atmapi.h" textual header "/usr/include/linux/atmarp.h" @@ -1477,6 +1520,7 @@ module "crosstool" [system] { textual header "/usr/include/linux/auxvec.h" textual header "/usr/include/linux/ax25.h" textual header "/usr/include/linux/b1lli.h" + textual header "/usr/include/linux/batadv_packet.h" textual header "/usr/include/linux/batman_adv.h" textual header "/usr/include/linux/baycom.h" textual header "/usr/include/linux/bcache.h" @@ -1488,10 +1532,12 @@ module "crosstool" [system] { textual header "/usr/include/linux/blkzoned.h" textual header "/usr/include/linux/bpf_common.h" textual header "/usr/include/linux/bpf.h" + textual header "/usr/include/linux/bpfilter.h" textual header "/usr/include/linux/bpf_perf_event.h" textual header "/usr/include/linux/bpqether.h" textual header "/usr/include/linux/bsg.h" textual header "/usr/include/linux/bt-bmc.h" + textual header "/usr/include/linux/btf.h" textual header "/usr/include/linux/btrfs.h" textual header "/usr/include/linux/btrfs_tree.h" textual header "/usr/include/linux/byteorder/big_endian.h" @@ -1502,6 +1548,7 @@ module "crosstool" [system] { textual header "/usr/include/linux/can/error.h" textual header "/usr/include/linux/can/gw.h" textual header "/usr/include/linux/can.h" + textual header "/usr/include/linux/can/j1939.h" textual header "/usr/include/linux/can/netlink.h" textual header "/usr/include/linux/can/raw.h" textual header "/usr/include/linux/can/vxcan.h" @@ -1518,7 +1565,6 @@ module "crosstool" [system] { textual header "/usr/include/linux/cm4000_cs.h" textual header "/usr/include/linux/cn_proc.h" textual header "/usr/include/linux/coda.h" - textual header "/usr/include/linux/coda_psdev.h" textual header "/usr/include/linux/coff.h" textual header "/usr/include/linux/connector.h" textual header "/usr/include/linux/const.h" @@ -1539,7 +1585,7 @@ module "crosstool" [system] { textual header "/usr/include/linux/dma-buf.h" textual header "/usr/include/linux/dm-ioctl.h" textual header "/usr/include/linux/dm-log-userspace.h" - textual header "/usr/include/linux/dn.h" + textual header "/usr/include/linux/dns_resolver.h" textual header "/usr/include/linux/dqblk_xfs.h" textual header "/usr/include/linux/dvb/audio.h" textual header "/usr/include/linux/dvb/ca.h" @@ -1557,6 +1603,7 @@ module "crosstool" [system] { textual header "/usr/include/linux/elf.h" textual header "/usr/include/linux/errno.h" textual header "/usr/include/linux/errqueue.h" + textual header "/usr/include/linux/erspan.h" textual header "/usr/include/linux/ethtool.h" textual header "/usr/include/linux/eventpoll.h" textual header "/usr/include/linux/fadvise.h" @@ -1571,11 +1618,14 @@ module "crosstool" [system] { textual header "/usr/include/linux/filter.h" textual header "/usr/include/linux/firewire-cdev.h" textual header "/usr/include/linux/firewire-constants.h" - textual header "/usr/include/linux/flat.h" textual header "/usr/include/linux/fou.h" + textual header "/usr/include/linux/fpga-dfl.h" + textual header "/usr/include/linux/fscrypt.h" textual header "/usr/include/linux/fs.h" + textual header "/usr/include/linux/fsi.h" textual header "/usr/include/linux/fsl_hypervisor.h" textual header "/usr/include/linux/fsmap.h" + textual header "/usr/include/linux/fsverity.h" textual header "/usr/include/linux/fuse.h" textual header "/usr/include/linux/futex.h" textual header "/usr/include/linux/gameport.h" @@ -1640,6 +1690,7 @@ module "crosstool" [system] { textual header "/usr/include/linux/if_tunnel.h" textual header "/usr/include/linux/if_vlan.h" textual header "/usr/include/linux/if_x25.h" + textual header "/usr/include/linux/if_xdp.h" textual header "/usr/include/linux/igmp.h" textual header "/usr/include/linux/iio/events.h" textual header "/usr/include/linux/iio/types.h" @@ -1652,9 +1703,12 @@ module "crosstool" [system] { textual header "/usr/include/linux/input.h" textual header "/usr/include/linux/in_route.h" textual header "/usr/include/linux/ioctl.h" + textual header "/usr/include/linux/iommu.h" + textual header "/usr/include/linux/io_uring.h" textual header "/usr/include/linux/ip6_tunnel.h" textual header "/usr/include/linux/ipc.h" textual header "/usr/include/linux/ip.h" + textual header "/usr/include/linux/ipmi_bmc.h" textual header "/usr/include/linux/ipmi.h" textual header "/usr/include/linux/ipmi_msgdefs.h" textual header "/usr/include/linux/ipsec.h" @@ -1662,17 +1716,12 @@ module "crosstool" [system] { textual header "/usr/include/linux/ipv6_route.h" textual header "/usr/include/linux/ip_vs.h" textual header "/usr/include/linux/ipx.h" - textual header "/usr/include/linux/irda.h" textual header "/usr/include/linux/irqnr.h" textual header "/usr/include/linux/isdn/capicmd.h" - textual header "/usr/include/linux/isdn_divertif.h" - textual header "/usr/include/linux/isdn.h" - textual header "/usr/include/linux/isdnif.h" - textual header "/usr/include/linux/isdn_ppp.h" textual header "/usr/include/linux/iso_fs.h" + textual header "/usr/include/linux/isst_if.h" textual header "/usr/include/linux/ivtvfb.h" textual header "/usr/include/linux/ivtv.h" - textual header "/usr/include/linux/ixjuser.h" textual header "/usr/include/linux/jffs2.h" textual header "/usr/include/linux/joystick.h" textual header "/usr/include/linux/kcm.h" @@ -1719,6 +1768,7 @@ module "crosstool" [system] { textual header "/usr/include/linux/mmc/ioctl.h" textual header "/usr/include/linux/mmtimer.h" textual header "/usr/include/linux/module.h" + textual header "/usr/include/linux/mount.h" textual header "/usr/include/linux/mpls.h" textual header "/usr/include/linux/mpls_iptunnel.h" textual header "/usr/include/linux/mqueue.h" @@ -1729,10 +1779,6 @@ module "crosstool" [system] { textual header "/usr/include/linux/mtio.h" textual header "/usr/include/linux/nbd.h" textual header "/usr/include/linux/nbd-netlink.h" - textual header "/usr/include/linux/ncp_fs.h" - textual header "/usr/include/linux/ncp.h" - textual header "/usr/include/linux/ncp_mount.h" - textual header "/usr/include/linux/ncp_no.h" textual header "/usr/include/linux/ncsi.h" textual header "/usr/include/linux/ndctl.h" textual header "/usr/include/linux/neighbour.h" @@ -1760,7 +1806,6 @@ module "crosstool" [system] { textual header "/usr/include/linux/netfilter_bridge/ebt_stp.h" textual header "/usr/include/linux/netfilter_bridge/ebt_vlan.h" textual header "/usr/include/linux/netfilter_bridge.h" - textual header "/usr/include/linux/netfilter_decnet.h" textual header "/usr/include/linux/netfilter.h" textual header "/usr/include/linux/netfilter/ipset/ip_set_bitmap.h" textual header "/usr/include/linux/netfilter/ipset/ip_set.h" @@ -1789,6 +1834,7 @@ module "crosstool" [system] { textual header "/usr/include/linux/netfilter_ipv6/ip6t_opts.h" textual header "/usr/include/linux/netfilter_ipv6/ip6t_REJECT.h" textual header "/usr/include/linux/netfilter_ipv6/ip6t_rt.h" + textual header "/usr/include/linux/netfilter_ipv6/ip6t_srh.h" textual header "/usr/include/linux/netfilter/nf_conntrack_common.h" textual header "/usr/include/linux/netfilter/nf_conntrack_ftp.h" textual header "/usr/include/linux/netfilter/nf_conntrack_sctp.h" @@ -1803,7 +1849,9 @@ module "crosstool" [system] { textual header "/usr/include/linux/netfilter/nfnetlink_cttimeout.h" textual header "/usr/include/linux/netfilter/nfnetlink.h" textual header "/usr/include/linux/netfilter/nfnetlink_log.h" + textual header "/usr/include/linux/netfilter/nfnetlink_osf.h" textual header "/usr/include/linux/netfilter/nfnetlink_queue.h" + textual header "/usr/include/linux/netfilter/nf_synproxy.h" textual header "/usr/include/linux/netfilter/nf_tables_compat.h" textual header "/usr/include/linux/netfilter/nf_tables.h" textual header "/usr/include/linux/netfilter/x_tables.h" @@ -1882,6 +1930,7 @@ module "crosstool" [system] { textual header "/usr/include/linux/net_namespace.h" textual header "/usr/include/linux/netrom.h" textual header "/usr/include/linux/net_tstamp.h" + textual header "/usr/include/linux/nexthop.h" textual header "/usr/include/linux/nfc.h" textual header "/usr/include/linux/nfs2.h" textual header "/usr/include/linux/nfs3.h" @@ -1939,8 +1988,10 @@ module "crosstool" [system] { textual header "/usr/include/linux/pr.h" textual header "/usr/include/linux/psample.h" textual header "/usr/include/linux/psci.h" + textual header "/usr/include/linux/psp-sev.h" textual header "/usr/include/linux/ptp_clock.h" textual header "/usr/include/linux/ptrace.h" + textual header "/usr/include/linux/qemu_fw_cfg.h" textual header "/usr/include/linux/qnx4_fs.h" textual header "/usr/include/linux/qnxtypes.h" textual header "/usr/include/linux/qrtr.h" @@ -1962,6 +2013,7 @@ module "crosstool" [system] { textual header "/usr/include/linux/rose.h" textual header "/usr/include/linux/route.h" textual header "/usr/include/linux/rpmsg.h" + textual header "/usr/include/linux/rseq.h" textual header "/usr/include/linux/rtc.h" textual header "/usr/include/linux/rtnetlink.h" textual header "/usr/include/linux/rxrpc.h" @@ -2018,11 +2070,14 @@ module "crosstool" [system] { textual header "/usr/include/linux/tc_act/tc_bpf.h" textual header "/usr/include/linux/tc_act/tc_connmark.h" textual header "/usr/include/linux/tc_act/tc_csum.h" + textual header "/usr/include/linux/tc_act/tc_ct.h" + textual header "/usr/include/linux/tc_act/tc_ctinfo.h" textual header "/usr/include/linux/tc_act/tc_defact.h" textual header "/usr/include/linux/tc_act/tc_gact.h" textual header "/usr/include/linux/tc_act/tc_ife.h" textual header "/usr/include/linux/tc_act/tc_ipt.h" textual header "/usr/include/linux/tc_act/tc_mirred.h" + textual header "/usr/include/linux/tc_act/tc_mpls.h" textual header "/usr/include/linux/tc_act/tc_nat.h" textual header "/usr/include/linux/tc_act/tc_pedit.h" textual header "/usr/include/linux/tc_act/tc_sample.h" @@ -2031,29 +2086,32 @@ module "crosstool" [system] { textual header "/usr/include/linux/tc_act/tc_tunnel_key.h" textual header "/usr/include/linux/tc_act/tc_vlan.h" textual header "/usr/include/linux/tc_ematch/tc_em_cmp.h" + textual header "/usr/include/linux/tc_ematch/tc_em_ipt.h" textual header "/usr/include/linux/tc_ematch/tc_em_meta.h" textual header "/usr/include/linux/tc_ematch/tc_em_nbyte.h" textual header "/usr/include/linux/tc_ematch/tc_em_text.h" textual header "/usr/include/linux/tcp.h" textual header "/usr/include/linux/tcp_metrics.h" textual header "/usr/include/linux/tee.h" - textual header "/usr/include/linux/telephony.h" textual header "/usr/include/linux/termios.h" textual header "/usr/include/linux/thermal.h" textual header "/usr/include/linux/time.h" textual header "/usr/include/linux/timerfd.h" textual header "/usr/include/linux/times.h" + textual header "/usr/include/linux/time_types.h" textual header "/usr/include/linux/timex.h" textual header "/usr/include/linux/tiocl.h" textual header "/usr/include/linux/tipc_config.h" textual header "/usr/include/linux/tipc.h" textual header "/usr/include/linux/tipc_netlink.h" + textual header "/usr/include/linux/tipc_sockets_diag.h" textual header "/usr/include/linux/tls.h" textual header "/usr/include/linux/toshiba.h" textual header "/usr/include/linux/tty_flags.h" textual header "/usr/include/linux/tty.h" textual header "/usr/include/linux/types.h" textual header "/usr/include/linux/udf_fs_i.h" + textual header "/usr/include/linux/udmabuf.h" textual header "/usr/include/linux/udp.h" textual header "/usr/include/linux/uhid.h" textual header "/usr/include/linux/uinput.h" @@ -2073,6 +2131,7 @@ module "crosstool" [system] { textual header "/usr/include/linux/usb/functionfs.h" textual header "/usr/include/linux/usb/gadgetfs.h" textual header "/usr/include/linux/usb/g_printer.h" + textual header "/usr/include/linux/usb/g_uvc.h" textual header "/usr/include/linux/usbip.h" textual header "/usr/include/linux/usb/midi.h" textual header "/usr/include/linux/usb/tmc.h" @@ -2088,11 +2147,15 @@ module "crosstool" [system] { textual header "/usr/include/linux/v4l2-dv-timings.h" textual header "/usr/include/linux/v4l2-mediabus.h" textual header "/usr/include/linux/v4l2-subdev.h" + textual header "/usr/include/linux/vbox_err.h" + textual header "/usr/include/linux/vboxguest.h" + textual header "/usr/include/linux/vbox_vmmdev_types.h" textual header "/usr/include/linux/version.h" textual header "/usr/include/linux/veth.h" textual header "/usr/include/linux/vfio_ccw.h" textual header "/usr/include/linux/vfio.h" textual header "/usr/include/linux/vhost.h" + textual header "/usr/include/linux/vhost_types.h" textual header "/usr/include/linux/videodev2.h" textual header "/usr/include/linux/virtio_9p.h" textual header "/usr/include/linux/virtio_balloon.h" @@ -2100,31 +2163,36 @@ module "crosstool" [system] { textual header "/usr/include/linux/virtio_config.h" textual header "/usr/include/linux/virtio_console.h" textual header "/usr/include/linux/virtio_crypto.h" + textual header "/usr/include/linux/virtio_fs.h" textual header "/usr/include/linux/virtio_gpu.h" textual header "/usr/include/linux/virtio_ids.h" textual header "/usr/include/linux/virtio_input.h" + textual header "/usr/include/linux/virtio_iommu.h" textual header "/usr/include/linux/virtio_mmio.h" textual header "/usr/include/linux/virtio_net.h" textual header "/usr/include/linux/virtio_pci.h" + textual header "/usr/include/linux/virtio_pmem.h" textual header "/usr/include/linux/virtio_ring.h" textual header "/usr/include/linux/virtio_rng.h" textual header "/usr/include/linux/virtio_scsi.h" textual header "/usr/include/linux/virtio_types.h" textual header "/usr/include/linux/virtio_vsock.h" + textual header "/usr/include/linux/vmcore.h" textual header "/usr/include/linux/vm_sockets_diag.h" textual header "/usr/include/linux/vm_sockets.h" textual header "/usr/include/linux/vsockmon.h" textual header "/usr/include/linux/vt.h" textual header "/usr/include/linux/vtpm_proxy.h" textual header "/usr/include/linux/wait.h" - textual header "/usr/include/linux/wanrouter.h" textual header "/usr/include/linux/watchdog.h" + textual header "/usr/include/linux/watch_queue.h" textual header "/usr/include/linux/wimax.h" textual header "/usr/include/linux/wimax/i2400m.h" textual header "/usr/include/linux/wireless.h" textual header "/usr/include/linux/wmi.h" textual header "/usr/include/linux/x25.h" textual header "/usr/include/linux/xattr.h" + textual header "/usr/include/linux/xdp_diag.h" textual header "/usr/include/linux/xfrm.h" textual header "/usr/include/linux/xilinx-v4l2-controls.h" textual header "/usr/include/linux/zorro.h" @@ -2136,7 +2204,10 @@ module "crosstool" [system] { textual header "/usr/include/memory.h" textual header "/usr/include/menu.h" textual header "/usr/include/misc/cxl.h" + textual header "/usr/include/misc/fastrpc.h" + textual header "/usr/include/misc/habanalabs.h" textual header "/usr/include/misc/ocxl.h" + textual header "/usr/include/misc/xilinx_sdfec.h" textual header "/usr/include/mntent.h" textual header "/usr/include/monetary.h" textual header "/usr/include/mqueue.h" @@ -2148,6 +2219,26 @@ module "crosstool" [system] { textual header "/usr/include/nc_tparm.h" textual header "/usr/include/ncurses_dll.h" textual header "/usr/include/ncurses.h" + textual header "/usr/include/ncursesw/cursesapp.h" + textual header "/usr/include/ncursesw/cursesf.h" + textual header "/usr/include/ncursesw/curses.h" + textual header "/usr/include/ncursesw/cursesm.h" + textual header "/usr/include/ncursesw/cursesp.h" + textual header "/usr/include/ncursesw/cursesw.h" + textual header "/usr/include/ncursesw/cursslk.h" + textual header "/usr/include/ncursesw/eti.h" + textual header "/usr/include/ncursesw/etip.h" + textual header "/usr/include/ncursesw/form.h" + textual header "/usr/include/ncursesw/menu.h" + textual header "/usr/include/ncursesw/nc_tparm.h" + textual header "/usr/include/ncursesw/ncurses_dll.h" + textual header "/usr/include/ncursesw/ncurses.h" + textual header "/usr/include/ncursesw/panel.h" + textual header "/usr/include/ncursesw/termcap.h" + textual header "/usr/include/ncursesw/term_entry.h" + textual header "/usr/include/ncursesw/term.h" + textual header "/usr/include/ncursesw/tic.h" + textual header "/usr/include/ncursesw/unctrl.h" textual header "/usr/include/netash/ash.h" textual header "/usr/include/netatalk/at.h" textual header "/usr/include/netax25/ax25.h" @@ -2185,6 +2276,109 @@ module "crosstool" [system] { textual header "/usr/include/nl_types.h" textual header "/usr/include/nss.h" textual header "/usr/include/obstack.h" + textual header "/usr/include/openssl/aes.h" + textual header "/usr/include/openssl/asn1err.h" + textual header "/usr/include/openssl/asn1.h" + textual header "/usr/include/openssl/asn1_mac.h" + textual header "/usr/include/openssl/asn1t.h" + textual header "/usr/include/openssl/asyncerr.h" + textual header "/usr/include/openssl/async.h" + textual header "/usr/include/openssl/bioerr.h" + textual header "/usr/include/openssl/bio.h" + textual header "/usr/include/openssl/blowfish.h" + textual header "/usr/include/openssl/bnerr.h" + textual header "/usr/include/openssl/bn.h" + textual header "/usr/include/openssl/buffererr.h" + textual header "/usr/include/openssl/buffer.h" + textual header "/usr/include/openssl/camellia.h" + textual header "/usr/include/openssl/cast.h" + textual header "/usr/include/openssl/cmac.h" + textual header "/usr/include/openssl/cmserr.h" + textual header "/usr/include/openssl/cms.h" + textual header "/usr/include/openssl/comperr.h" + textual header "/usr/include/openssl/comp.h" + textual header "/usr/include/openssl/conf_api.h" + textual header "/usr/include/openssl/conferr.h" + textual header "/usr/include/openssl/conf.h" + textual header "/usr/include/openssl/cryptoerr.h" + textual header "/usr/include/openssl/crypto.h" + textual header "/usr/include/openssl/cterr.h" + textual header "/usr/include/openssl/ct.h" + textual header "/usr/include/openssl/des.h" + textual header "/usr/include/openssl/dherr.h" + textual header "/usr/include/openssl/dh.h" + textual header "/usr/include/openssl/dsaerr.h" + textual header "/usr/include/openssl/dsa.h" + textual header "/usr/include/openssl/dtls1.h" + textual header "/usr/include/openssl/ebcdic.h" + textual header "/usr/include/openssl/ecdh.h" + textual header "/usr/include/openssl/ecdsa.h" + textual header "/usr/include/openssl/ecerr.h" + textual header "/usr/include/openssl/ec.h" + textual header "/usr/include/openssl/engineerr.h" + textual header "/usr/include/openssl/engine.h" + textual header "/usr/include/openssl/e_os2.h" + textual header "/usr/include/openssl/err.h" + textual header "/usr/include/openssl/evperr.h" + textual header "/usr/include/openssl/evp.h" + textual header "/usr/include/openssl/hmac.h" + textual header "/usr/include/openssl/idea.h" + textual header "/usr/include/openssl/kdferr.h" + textual header "/usr/include/openssl/kdf.h" + textual header "/usr/include/openssl/lhash.h" + textual header "/usr/include/openssl/md2.h" + textual header "/usr/include/openssl/md4.h" + textual header "/usr/include/openssl/md5.h" + textual header "/usr/include/openssl/mdc2.h" + textual header "/usr/include/openssl/modes.h" + textual header "/usr/include/openssl/objectserr.h" + textual header "/usr/include/openssl/objects.h" + textual header "/usr/include/openssl/obj_mac.h" + textual header "/usr/include/openssl/ocsperr.h" + textual header "/usr/include/openssl/ocsp.h" + textual header "/usr/include/openssl/opensslv.h" + textual header "/usr/include/openssl/ossl_typ.h" + textual header "/usr/include/openssl/pem2.h" + textual header "/usr/include/openssl/pemerr.h" + textual header "/usr/include/openssl/pem.h" + textual header "/usr/include/openssl/pkcs12err.h" + textual header "/usr/include/openssl/pkcs12.h" + textual header "/usr/include/openssl/pkcs7err.h" + textual header "/usr/include/openssl/pkcs7.h" + textual header "/usr/include/openssl/rand_drbg.h" + textual header "/usr/include/openssl/randerr.h" + textual header "/usr/include/openssl/rand.h" + textual header "/usr/include/openssl/rc2.h" + textual header "/usr/include/openssl/rc4.h" + textual header "/usr/include/openssl/rc5.h" + textual header "/usr/include/openssl/ripemd.h" + textual header "/usr/include/openssl/rsaerr.h" + textual header "/usr/include/openssl/rsa.h" + textual header "/usr/include/openssl/safestack.h" + textual header "/usr/include/openssl/seed.h" + textual header "/usr/include/openssl/sha.h" + textual header "/usr/include/openssl/srp.h" + textual header "/usr/include/openssl/srtp.h" + textual header "/usr/include/openssl/ssl2.h" + textual header "/usr/include/openssl/ssl3.h" + textual header "/usr/include/openssl/sslerr.h" + textual header "/usr/include/openssl/ssl.h" + textual header "/usr/include/openssl/stack.h" + textual header "/usr/include/openssl/storeerr.h" + textual header "/usr/include/openssl/store.h" + textual header "/usr/include/openssl/symhacks.h" + textual header "/usr/include/openssl/tls1.h" + textual header "/usr/include/openssl/tserr.h" + textual header "/usr/include/openssl/ts.h" + textual header "/usr/include/openssl/txt_db.h" + textual header "/usr/include/openssl/uierr.h" + textual header "/usr/include/openssl/ui.h" + textual header "/usr/include/openssl/whrlpool.h" + textual header "/usr/include/openssl/x509err.h" + textual header "/usr/include/openssl/x509.h" + textual header "/usr/include/openssl/x509v3err.h" + textual header "/usr/include/openssl/x509v3.h" + textual header "/usr/include/openssl/x509_vfy.h" textual header "/usr/include/panel.h" textual header "/usr/include/paths.h" textual header "/usr/include/poll.h" @@ -2197,190 +2391,33 @@ module "crosstool" [system] { textual header "/usr/include/pthread.h" textual header "/usr/include/pty.h" textual header "/usr/include/pwd.h" - textual header "/usr/include/python3.10/abstract.h" - textual header "/usr/include/python3.10/bltinmodule.h" - textual header "/usr/include/python3.10/boolobject.h" - textual header "/usr/include/python3.10/bytearrayobject.h" - textual header "/usr/include/python3.10/bytesobject.h" - textual header "/usr/include/python3.10/cellobject.h" - textual header "/usr/include/python3.10/ceval.h" - textual header "/usr/include/python3.10/classobject.h" - textual header "/usr/include/python3.10/codecs.h" - textual header "/usr/include/python3.10/code.h" - textual header "/usr/include/python3.10/compile.h" - textual header "/usr/include/python3.10/complexobject.h" - textual header "/usr/include/python3.10/context.h" - textual header "/usr/include/python3.10/cpython/abstract.h" - textual header "/usr/include/python3.10/cpython/bytearrayobject.h" - textual header "/usr/include/python3.10/cpython/bytesobject.h" - textual header "/usr/include/python3.10/cpython/ceval.h" - textual header "/usr/include/python3.10/cpython/code.h" - textual header "/usr/include/python3.10/cpython/compile.h" - textual header "/usr/include/python3.10/cpython/dictobject.h" - textual header "/usr/include/python3.10/cpython/fileobject.h" - textual header "/usr/include/python3.10/cpython/fileutils.h" - textual header "/usr/include/python3.10/cpython/frameobject.h" - textual header "/usr/include/python3.10/cpython/import.h" - textual header "/usr/include/python3.10/cpython/initconfig.h" - textual header "/usr/include/python3.10/cpython/interpreteridobject.h" - textual header "/usr/include/python3.10/cpython/listobject.h" - textual header "/usr/include/python3.10/cpython/methodobject.h" - textual header "/usr/include/python3.10/cpython/object.h" - textual header "/usr/include/python3.10/cpython/objimpl.h" - textual header "/usr/include/python3.10/cpython/odictobject.h" - textual header "/usr/include/python3.10/cpython/picklebufobject.h" - textual header "/usr/include/python3.10/cpython/pyctype.h" - textual header "/usr/include/python3.10/cpython/pydebug.h" - textual header "/usr/include/python3.10/cpython/pyerrors.h" - textual header "/usr/include/python3.10/cpython/pyfpe.h" - textual header "/usr/include/python3.10/cpython/pylifecycle.h" - textual header "/usr/include/python3.10/cpython/pymem.h" - textual header "/usr/include/python3.10/cpython/pystate.h" - textual header "/usr/include/python3.10/cpython/pythonrun.h" - textual header "/usr/include/python3.10/cpython/pytime.h" - textual header "/usr/include/python3.10/cpython/sysmodule.h" - textual header "/usr/include/python3.10/cpython/traceback.h" - textual header "/usr/include/python3.10/cpython/tupleobject.h" - textual header "/usr/include/python3.10/cpython/unicodeobject.h" - textual header "/usr/include/python3.10/datetime.h" - textual header "/usr/include/python3.10/descrobject.h" - textual header "/usr/include/python3.10/dictobject.h" - textual header "/usr/include/python3.10/dynamic_annotations.h" - textual header "/usr/include/python3.10/enumobject.h" - textual header "/usr/include/python3.10/errcode.h" - textual header "/usr/include/python3.10/eval.h" - textual header "/usr/include/python3.10/exports.h" - textual header "/usr/include/python3.10/fileobject.h" - textual header "/usr/include/python3.10/fileutils.h" - textual header "/usr/include/python3.10/floatobject.h" - textual header "/usr/include/python3.10/frameobject.h" - textual header "/usr/include/python3.10/funcobject.h" - textual header "/usr/include/python3.10/genericaliasobject.h" - textual header "/usr/include/python3.10/genobject.h" - textual header "/usr/include/python3.10/graminit.h" - textual header "/usr/include/python3.10/import.h" - textual header "/usr/include/python3.10/internal/pycore_abstract.h" - textual header "/usr/include/python3.10/internal/pycore_accu.h" - textual header "/usr/include/python3.10/internal/pycore_asdl.h" - textual header "/usr/include/python3.10/internal/pycore_ast.h" - textual header "/usr/include/python3.10/internal/pycore_ast_state.h" - textual header "/usr/include/python3.10/internal/pycore_atomic_funcs.h" - textual header "/usr/include/python3.10/internal/pycore_atomic.h" - textual header "/usr/include/python3.10/internal/pycore_bitutils.h" - textual header "/usr/include/python3.10/internal/pycore_blocks_output_buffer.h" - textual header "/usr/include/python3.10/internal/pycore_bytes_methods.h" - textual header "/usr/include/python3.10/internal/pycore_call.h" - textual header "/usr/include/python3.10/internal/pycore_ceval.h" - textual header "/usr/include/python3.10/internal/pycore_code.h" - textual header "/usr/include/python3.10/internal/pycore_compile.h" - textual header "/usr/include/python3.10/internal/pycore_condvar.h" - textual header "/usr/include/python3.10/internal/pycore_context.h" - textual header "/usr/include/python3.10/internal/pycore_dtoa.h" - textual header "/usr/include/python3.10/internal/pycore_fileutils.h" - textual header "/usr/include/python3.10/internal/pycore_format.h" - textual header "/usr/include/python3.10/internal/pycore_gc.h" - textual header "/usr/include/python3.10/internal/pycore_getopt.h" - textual header "/usr/include/python3.10/internal/pycore_gil.h" - textual header "/usr/include/python3.10/internal/pycore_hamt.h" - textual header "/usr/include/python3.10/internal/pycore_hashtable.h" - textual header "/usr/include/python3.10/internal/pycore_import.h" - textual header "/usr/include/python3.10/internal/pycore_initconfig.h" - textual header "/usr/include/python3.10/internal/pycore_interp.h" - textual header "/usr/include/python3.10/internal/pycore_list.h" - textual header "/usr/include/python3.10/internal/pycore_long.h" - textual header "/usr/include/python3.10/internal/pycore_moduleobject.h" - textual header "/usr/include/python3.10/internal/pycore_object.h" - textual header "/usr/include/python3.10/internal/pycore_parser.h" - textual header "/usr/include/python3.10/internal/pycore_pathconfig.h" - textual header "/usr/include/python3.10/internal/pycore_pyarena.h" - textual header "/usr/include/python3.10/internal/pycore_pyerrors.h" - textual header "/usr/include/python3.10/internal/pycore_pyhash.h" - textual header "/usr/include/python3.10/internal/pycore_pylifecycle.h" - textual header "/usr/include/python3.10/internal/pycore_pymem.h" - textual header "/usr/include/python3.10/internal/pycore_pystate.h" - textual header "/usr/include/python3.10/internal/pycore_runtime.h" - textual header "/usr/include/python3.10/internal/pycore_structseq.h" - textual header "/usr/include/python3.10/internal/pycore_symtable.h" - textual header "/usr/include/python3.10/internal/pycore_sysmodule.h" - textual header "/usr/include/python3.10/internal/pycore_traceback.h" - textual header "/usr/include/python3.10/internal/pycore_tuple.h" - textual header "/usr/include/python3.10/internal/pycore_ucnhash.h" - textual header "/usr/include/python3.10/internal/pycore_unionobject.h" - textual header "/usr/include/python3.10/internal/pycore_warnings.h" - textual header "/usr/include/python3.10/interpreteridobject.h" - textual header "/usr/include/python3.10/intrcheck.h" - textual header "/usr/include/python3.10/iterobject.h" - textual header "/usr/include/python3.10/listobject.h" - textual header "/usr/include/python3.10/longintrepr.h" - textual header "/usr/include/python3.10/longobject.h" - textual header "/usr/include/python3.10/marshal.h" - textual header "/usr/include/python3.10/memoryobject.h" - textual header "/usr/include/python3.10/methodobject.h" - textual header "/usr/include/python3.10/modsupport.h" - textual header "/usr/include/python3.10/moduleobject.h" - textual header "/usr/include/python3.10/namespaceobject.h" - textual header "/usr/include/python3.10/object.h" - textual header "/usr/include/python3.10/objimpl.h" - textual header "/usr/include/python3.10/opcode.h" - textual header "/usr/include/python3.10/osdefs.h" - textual header "/usr/include/python3.10/osmodule.h" - textual header "/usr/include/python3.10/patchlevel.h" - textual header "/usr/include/python3.10/pycapsule.h" - textual header "/usr/include/python3.10/pyconfig.h" - textual header "/usr/include/python3.10/py_curses.h" - textual header "/usr/include/python3.10/pydtrace.h" - textual header "/usr/include/python3.10/pyerrors.h" - textual header "/usr/include/python3.10/pyexpat.h" - textual header "/usr/include/python3.10/pyframe.h" - textual header "/usr/include/python3.10/pyhash.h" - textual header "/usr/include/python3.10/pylifecycle.h" - textual header "/usr/include/python3.10/pymacconfig.h" - textual header "/usr/include/python3.10/pymacro.h" - textual header "/usr/include/python3.10/pymath.h" - textual header "/usr/include/python3.10/pymem.h" - textual header "/usr/include/python3.10/pyport.h" - textual header "/usr/include/python3.10/pystate.h" - textual header "/usr/include/python3.10/pystrcmp.h" - textual header "/usr/include/python3.10/pystrhex.h" - textual header "/usr/include/python3.10/pystrtod.h" - textual header "/usr/include/python3.10/Python.h" - textual header "/usr/include/python3.10/pythonrun.h" - textual header "/usr/include/python3.10/pythread.h" - textual header "/usr/include/python3.10/rangeobject.h" - textual header "/usr/include/python3.10/setobject.h" - textual header "/usr/include/python3.10/sliceobject.h" - textual header "/usr/include/python3.10/structmember.h" - textual header "/usr/include/python3.10/structseq.h" - textual header "/usr/include/python3.10/sysmodule.h" - textual header "/usr/include/python3.10/token.h" - textual header "/usr/include/python3.10/traceback.h" - textual header "/usr/include/python3.10/tracemalloc.h" - textual header "/usr/include/python3.10/tupleobject.h" - textual header "/usr/include/python3.10/typeslots.h" - textual header "/usr/include/python3.10/unicodeobject.h" - textual header "/usr/include/python3.10/warnings.h" - textual header "/usr/include/python3.10/weakrefobject.h" textual header "/usr/include/rdma/bnxt_re-abi.h" textual header "/usr/include/rdma/cxgb3-abi.h" textual header "/usr/include/rdma/cxgb4-abi.h" + textual header "/usr/include/rdma/efa-abi.h" textual header "/usr/include/rdma/hfi/hfi1_ioctl.h" textual header "/usr/include/rdma/hfi/hfi1_user.h" textual header "/usr/include/rdma/hns-abi.h" - textual header "/usr/include/rdma/ib_user_cm.h" + textual header "/usr/include/rdma/i40iw-abi.h" + textual header "/usr/include/rdma/ib_user_ioctl_cmds.h" textual header "/usr/include/rdma/ib_user_ioctl_verbs.h" textual header "/usr/include/rdma/ib_user_mad.h" textual header "/usr/include/rdma/ib_user_sa.h" textual header "/usr/include/rdma/ib_user_verbs.h" textual header "/usr/include/rdma/mlx4-abi.h" textual header "/usr/include/rdma/mlx5-abi.h" + textual header "/usr/include/rdma/mlx5_user_ioctl_cmds.h" + textual header "/usr/include/rdma/mlx5_user_ioctl_verbs.h" textual header "/usr/include/rdma/mthca-abi.h" - textual header "/usr/include/rdma/nes-abi.h" textual header "/usr/include/rdma/ocrdma-abi.h" textual header "/usr/include/rdma/qedr-abi.h" textual header "/usr/include/rdma/rdma_netlink.h" textual header "/usr/include/rdma/rdma_user_cm.h" + textual header "/usr/include/rdma/rdma_user_ioctl_cmds.h" textual header "/usr/include/rdma/rdma_user_ioctl.h" textual header "/usr/include/rdma/rdma_user_rxe.h" + textual header "/usr/include/rdma/rvt-abi.h" + textual header "/usr/include/rdma/siw-abi.h" textual header "/usr/include/rdma/vmw_pvrdma-abi.h" textual header "/usr/include/re_comp.h" textual header "/usr/include/regex.h" @@ -2390,13 +2427,11 @@ module "crosstool" [system] { textual header "/usr/include/rpc/auth.h" textual header "/usr/include/rpc/auth_unix.h" textual header "/usr/include/rpc/clnt.h" - textual header "/usr/include/rpc/des_crypt.h" textual header "/usr/include/rpc/key_prot.h" textual header "/usr/include/rpc/netdb.h" textual header "/usr/include/rpc/pmap_clnt.h" textual header "/usr/include/rpc/pmap_prot.h" textual header "/usr/include/rpc/pmap_rmt.h" - textual header "/usr/include/rpc/rpc_des.h" textual header "/usr/include/rpc/rpc.h" textual header "/usr/include/rpc/rpc_msg.h" textual header "/usr/include/rpc/svc_auth.h" @@ -2449,6 +2484,7 @@ module "crosstool" [system] { textual header "/usr/include/scsi/fc/fc_gs.h" textual header "/usr/include/scsi/fc/fc_ns.h" textual header "/usr/include/scsi/scsi_bsg_fc.h" + textual header "/usr/include/scsi/scsi_bsg_ufs.h" textual header "/usr/include/scsi/scsi.h" textual header "/usr/include/scsi/scsi_ioctl.h" textual header "/usr/include/scsi/scsi_netlink_fc.h" @@ -2472,7 +2508,12 @@ module "crosstool" [system] { textual header "/usr/include/sound/hdspm.h" textual header "/usr/include/sound/sb16_csp.h" textual header "/usr/include/sound/sfnt_info.h" + textual header "/usr/include/sound/skl-tplg-interface.h" textual header "/usr/include/sound/snd_sst_tokens.h" + textual header "/usr/include/sound/sof/abi.h" + textual header "/usr/include/sound/sof/fw.h" + textual header "/usr/include/sound/sof/header.h" + textual header "/usr/include/sound/sof/tokens.h" textual header "/usr/include/sound/tlv.h" textual header "/usr/include/sound/usb_stream.h" textual header "/usr/include/spawn.h" @@ -2484,7 +2525,6 @@ module "crosstool" [system] { textual header "/usr/include/stdlib.h" textual header "/usr/include/string.h" textual header "/usr/include/strings.h" - textual header "/usr/include/stropts.h" textual header "/usr/include/sudo_plugin.h" textual header "/usr/include/syscall.h" textual header "/usr/include/sysexits.h" @@ -2497,6 +2537,7 @@ module "crosstool" [system] { textual header "/usr/include/termios.h" textual header "/usr/include/tgmath.h" textual header "/usr/include/thread_db.h" + textual header "/usr/include/threads.h" textual header "/usr/include/tic.h" textual header "/usr/include/time.h" textual header "/usr/include/ttyent.h" @@ -2505,7 +2546,6 @@ module "crosstool" [system] { textual header "/usr/include/ulimit.h" textual header "/usr/include/unctrl.h" textual header "/usr/include/unistd.h" - textual header "/usr/include/ustat.h" textual header "/usr/include/utime.h" textual header "/usr/include/utmp.h" textual header "/usr/include/utmpx.h" @@ -2531,7 +2571,6 @@ module "crosstool" [system] { textual header "/usr/include/x86_64-linux-gnu/asm/fcntl.h" textual header "/usr/include/x86_64-linux-gnu/asm/hw_breakpoint.h" textual header "/usr/include/x86_64-linux-gnu/asm/hwcap2.h" - textual header "/usr/include/x86_64-linux-gnu/asm/hyperv.h" textual header "/usr/include/x86_64-linux-gnu/asm/ioctl.h" textual header "/usr/include/x86_64-linux-gnu/asm/ioctls.h" textual header "/usr/include/x86_64-linux-gnu/asm/ipcbuf.h" @@ -2582,20 +2621,24 @@ module "crosstool" [system] { textual header "/usr/include/x86_64-linux-gnu/asm/vmx.h" textual header "/usr/include/x86_64-linux-gnu/asm/vsyscall.h" textual header "/usr/include/x86_64-linux-gnu/bits/a.out.h" + textual header "/usr/include/x86_64-linux-gnu/bits/argp-ldbl.h" textual header "/usr/include/x86_64-linux-gnu/bits/auxv.h" - textual header "/usr/include/x86_64-linux-gnu/bits/byteswap-16.h" textual header "/usr/include/x86_64-linux-gnu/bits/byteswap.h" textual header "/usr/include/x86_64-linux-gnu/bits/cmathcalls.h" textual header "/usr/include/x86_64-linux-gnu/bits/confname.h" textual header "/usr/include/x86_64-linux-gnu/bits/cpu-set.h" + textual header "/usr/include/x86_64-linux-gnu/bits/dirent_ext.h" textual header "/usr/include/x86_64-linux-gnu/bits/dirent.h" textual header "/usr/include/x86_64-linux-gnu/bits/dlfcn.h" textual header "/usr/include/x86_64-linux-gnu/bits/elfclass.h" textual header "/usr/include/x86_64-linux-gnu/bits/endian.h" + textual header "/usr/include/x86_64-linux-gnu/bits/endianness.h" textual header "/usr/include/x86_64-linux-gnu/bits/environments.h" textual header "/usr/include/x86_64-linux-gnu/bits/epoll.h" + textual header "/usr/include/x86_64-linux-gnu/bits/err-ldbl.h" textual header "/usr/include/x86_64-linux-gnu/bits/errno.h" textual header "/usr/include/x86_64-linux-gnu/bits/error.h" + textual header "/usr/include/x86_64-linux-gnu/bits/error-ldbl.h" textual header "/usr/include/x86_64-linux-gnu/bits/eventfd.h" textual header "/usr/include/x86_64-linux-gnu/bits/fcntl2.h" textual header "/usr/include/x86_64-linux-gnu/bits/fcntl.h" @@ -2607,22 +2650,21 @@ module "crosstool" [system] { textual header "/usr/include/x86_64-linux-gnu/bits/flt-eval-method.h" textual header "/usr/include/x86_64-linux-gnu/bits/fp-fast.h" textual header "/usr/include/x86_64-linux-gnu/bits/fp-logb.h" - textual header "/usr/include/x86_64-linux-gnu/bits/_G_config.h" textual header "/usr/include/x86_64-linux-gnu/bits/getopt_core.h" textual header "/usr/include/x86_64-linux-gnu/bits/getopt_ext.h" textual header "/usr/include/x86_64-linux-gnu/bits/getopt_posix.h" textual header "/usr/include/x86_64-linux-gnu/bits/hwcap.h" + textual header "/usr/include/x86_64-linux-gnu/bits/indirect-return.h" textual header "/usr/include/x86_64-linux-gnu/bits/in.h" textual header "/usr/include/x86_64-linux-gnu/bits/initspin.h" textual header "/usr/include/x86_64-linux-gnu/bits/inotify.h" textual header "/usr/include/x86_64-linux-gnu/bits/ioctls.h" textual header "/usr/include/x86_64-linux-gnu/bits/ioctl-types.h" textual header "/usr/include/x86_64-linux-gnu/bits/ipc.h" + textual header "/usr/include/x86_64-linux-gnu/bits/ipc-perm.h" textual header "/usr/include/x86_64-linux-gnu/bits/ipctypes.h" textual header "/usr/include/x86_64-linux-gnu/bits/iscanonical.h" textual header "/usr/include/x86_64-linux-gnu/bits/libc-header-start.h" - textual header "/usr/include/x86_64-linux-gnu/bits/libio.h" - textual header "/usr/include/x86_64-linux-gnu/bits/libio-ldbl.h" textual header "/usr/include/x86_64-linux-gnu/bits/libm-simd-decl-stubs.h" textual header "/usr/include/x86_64-linux-gnu/bits/link.h" textual header "/usr/include/x86_64-linux-gnu/bits/locale.h" @@ -2630,17 +2672,19 @@ module "crosstool" [system] { textual header "/usr/include/x86_64-linux-gnu/bits/long-double.h" textual header "/usr/include/x86_64-linux-gnu/bits/mathcalls.h" textual header "/usr/include/x86_64-linux-gnu/bits/mathcalls-helper-functions.h" + textual header "/usr/include/x86_64-linux-gnu/bits/mathcalls-narrow.h" textual header "/usr/include/x86_64-linux-gnu/bits/mathdef.h" - textual header "/usr/include/x86_64-linux-gnu/bits/math-finite.h" textual header "/usr/include/x86_64-linux-gnu/bits/mathinline.h" textual header "/usr/include/x86_64-linux-gnu/bits/math-vector.h" textual header "/usr/include/x86_64-linux-gnu/bits/mman.h" textual header "/usr/include/x86_64-linux-gnu/bits/mman-linux.h" + textual header "/usr/include/x86_64-linux-gnu/bits/mman-map-flags-generic.h" textual header "/usr/include/x86_64-linux-gnu/bits/mman-shared.h" textual header "/usr/include/x86_64-linux-gnu/bits/monetary-ldbl.h" textual header "/usr/include/x86_64-linux-gnu/bits/mqueue2.h" textual header "/usr/include/x86_64-linux-gnu/bits/mqueue.h" textual header "/usr/include/x86_64-linux-gnu/bits/msq.h" + textual header "/usr/include/x86_64-linux-gnu/bits/msq-pad.h" textual header "/usr/include/x86_64-linux-gnu/bits/netdb.h" textual header "/usr/include/x86_64-linux-gnu/bits/param.h" textual header "/usr/include/x86_64-linux-gnu/bits/poll2.h" @@ -2649,6 +2693,10 @@ module "crosstool" [system] { textual header "/usr/include/x86_64-linux-gnu/bits/posix2_lim.h" textual header "/usr/include/x86_64-linux-gnu/bits/posix_opt.h" textual header "/usr/include/x86_64-linux-gnu/bits/printf-ldbl.h" + textual header "/usr/include/x86_64-linux-gnu/bits/procfs-extra.h" + textual header "/usr/include/x86_64-linux-gnu/bits/procfs.h" + textual header "/usr/include/x86_64-linux-gnu/bits/procfs-id.h" + textual header "/usr/include/x86_64-linux-gnu/bits/procfs-prregset.h" textual header "/usr/include/x86_64-linux-gnu/bits/pthreadtypes-arch.h" textual header "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" textual header "/usr/include/x86_64-linux-gnu/bits/ptrace-shared.h" @@ -2658,15 +2706,19 @@ module "crosstool" [system] { textual header "/usr/include/x86_64-linux-gnu/bits/select.h" textual header "/usr/include/x86_64-linux-gnu/bits/semaphore.h" textual header "/usr/include/x86_64-linux-gnu/bits/sem.h" + textual header "/usr/include/x86_64-linux-gnu/bits/sem-pad.h" textual header "/usr/include/x86_64-linux-gnu/bits/setjmp2.h" textual header "/usr/include/x86_64-linux-gnu/bits/setjmp.h" textual header "/usr/include/x86_64-linux-gnu/bits/shm.h" + textual header "/usr/include/x86_64-linux-gnu/bits/shmlba.h" + textual header "/usr/include/x86_64-linux-gnu/bits/shm-pad.h" textual header "/usr/include/x86_64-linux-gnu/bits/sigaction.h" textual header "/usr/include/x86_64-linux-gnu/bits/sigcontext.h" textual header "/usr/include/x86_64-linux-gnu/bits/sigevent-consts.h" textual header "/usr/include/x86_64-linux-gnu/bits/siginfo-arch.h" textual header "/usr/include/x86_64-linux-gnu/bits/siginfo-consts-arch.h" textual header "/usr/include/x86_64-linux-gnu/bits/siginfo-consts.h" + textual header "/usr/include/x86_64-linux-gnu/bits/signal_ext.h" textual header "/usr/include/x86_64-linux-gnu/bits/signalfd.h" textual header "/usr/include/x86_64-linux-gnu/bits/signum-generic.h" textual header "/usr/include/x86_64-linux-gnu/bits/signum.h" @@ -2674,6 +2726,7 @@ module "crosstool" [system] { textual header "/usr/include/x86_64-linux-gnu/bits/sigthread.h" textual header "/usr/include/x86_64-linux-gnu/bits/sockaddr.h" textual header "/usr/include/x86_64-linux-gnu/bits/socket2.h" + textual header "/usr/include/x86_64-linux-gnu/bits/socket-constants.h" textual header "/usr/include/x86_64-linux-gnu/bits/socket.h" textual header "/usr/include/x86_64-linux-gnu/bits/socket_type.h" textual header "/usr/include/x86_64-linux-gnu/bits/ss_flags.h" @@ -2681,6 +2734,8 @@ module "crosstool" [system] { textual header "/usr/include/x86_64-linux-gnu/bits/statfs.h" textual header "/usr/include/x86_64-linux-gnu/bits/stat.h" textual header "/usr/include/x86_64-linux-gnu/bits/statvfs.h" + textual header "/usr/include/x86_64-linux-gnu/bits/statx-generic.h" + textual header "/usr/include/x86_64-linux-gnu/bits/statx.h" textual header "/usr/include/x86_64-linux-gnu/bits/stdint-intn.h" textual header "/usr/include/x86_64-linux-gnu/bits/stdint-uintn.h" textual header "/usr/include/x86_64-linux-gnu/bits/stdio2.h" @@ -2693,7 +2748,8 @@ module "crosstool" [system] { textual header "/usr/include/x86_64-linux-gnu/bits/stdlib-ldbl.h" textual header "/usr/include/x86_64-linux-gnu/bits/string_fortified.h" textual header "/usr/include/x86_64-linux-gnu/bits/strings_fortified.h" - textual header "/usr/include/x86_64-linux-gnu/bits/stropts.h" + textual header "/usr/include/x86_64-linux-gnu/bits/struct_mutex.h" + textual header "/usr/include/x86_64-linux-gnu/bits/struct_rwlock.h" textual header "/usr/include/x86_64-linux-gnu/bits/syscall.h" textual header "/usr/include/x86_64-linux-gnu/bits/sysctl.h" textual header "/usr/include/x86_64-linux-gnu/bits/sys_errlist.h" @@ -2701,15 +2757,30 @@ module "crosstool" [system] { textual header "/usr/include/x86_64-linux-gnu/bits/syslog-ldbl.h" textual header "/usr/include/x86_64-linux-gnu/bits/syslog-path.h" textual header "/usr/include/x86_64-linux-gnu/bits/sysmacros.h" + textual header "/usr/include/x86_64-linux-gnu/bits/termios-baud.h" + textual header "/usr/include/x86_64-linux-gnu/bits/termios-c_cc.h" + textual header "/usr/include/x86_64-linux-gnu/bits/termios-c_cflag.h" + textual header "/usr/include/x86_64-linux-gnu/bits/termios-c_iflag.h" + textual header "/usr/include/x86_64-linux-gnu/bits/termios-c_lflag.h" + textual header "/usr/include/x86_64-linux-gnu/bits/termios-c_oflag.h" textual header "/usr/include/x86_64-linux-gnu/bits/termios.h" + textual header "/usr/include/x86_64-linux-gnu/bits/termios-misc.h" + textual header "/usr/include/x86_64-linux-gnu/bits/termios-struct.h" + textual header "/usr/include/x86_64-linux-gnu/bits/termios-tcflow.h" textual header "/usr/include/x86_64-linux-gnu/bits/thread-shared-types.h" + textual header "/usr/include/x86_64-linux-gnu/bits/time64.h" textual header "/usr/include/x86_64-linux-gnu/bits/time.h" textual header "/usr/include/x86_64-linux-gnu/bits/timerfd.h" + textual header "/usr/include/x86_64-linux-gnu/bits/timesize.h" textual header "/usr/include/x86_64-linux-gnu/bits/timex.h" textual header "/usr/include/x86_64-linux-gnu/bits/types/clockid_t.h" textual header "/usr/include/x86_64-linux-gnu/bits/types/clock_t.h" + textual header "/usr/include/x86_64-linux-gnu/bits/types/cookie_io_functions_t.h" + textual header "/usr/include/x86_64-linux-gnu/bits/types/error_t.h" textual header "/usr/include/x86_64-linux-gnu/bits/types/__FILE.h" textual header "/usr/include/x86_64-linux-gnu/bits/types/FILE.h" + textual header "/usr/include/x86_64-linux-gnu/bits/types/__fpos64_t.h" + textual header "/usr/include/x86_64-linux-gnu/bits/types/__fpos_t.h" textual header "/usr/include/x86_64-linux-gnu/bits/types.h" textual header "/usr/include/x86_64-linux-gnu/bits/typesizes.h" textual header "/usr/include/x86_64-linux-gnu/bits/types/__locale_t.h" @@ -2725,11 +2796,15 @@ module "crosstool" [system] { textual header "/usr/include/x86_64-linux-gnu/bits/types/__sigval_t.h" textual header "/usr/include/x86_64-linux-gnu/bits/types/sigval_t.h" textual header "/usr/include/x86_64-linux-gnu/bits/types/stack_t.h" + textual header "/usr/include/x86_64-linux-gnu/bits/types/struct_FILE.h" textual header "/usr/include/x86_64-linux-gnu/bits/types/struct_iovec.h" textual header "/usr/include/x86_64-linux-gnu/bits/types/struct_itimerspec.h" textual header "/usr/include/x86_64-linux-gnu/bits/types/struct_osockaddr.h" textual header "/usr/include/x86_64-linux-gnu/bits/types/struct_rusage.h" + textual header "/usr/include/x86_64-linux-gnu/bits/types/struct_sched_param.h" textual header "/usr/include/x86_64-linux-gnu/bits/types/struct_sigstack.h" + textual header "/usr/include/x86_64-linux-gnu/bits/types/struct_statx.h" + textual header "/usr/include/x86_64-linux-gnu/bits/types/struct_statx_timestamp.h" textual header "/usr/include/x86_64-linux-gnu/bits/types/struct_timespec.h" textual header "/usr/include/x86_64-linux-gnu/bits/types/struct_timeval.h" textual header "/usr/include/x86_64-linux-gnu/bits/types/struct_tm.h" @@ -2739,8 +2814,8 @@ module "crosstool" [system] { textual header "/usr/include/x86_64-linux-gnu/bits/uintn-identity.h" textual header "/usr/include/x86_64-linux-gnu/bits/uio-ext.h" textual header "/usr/include/x86_64-linux-gnu/bits/uio_lim.h" + textual header "/usr/include/x86_64-linux-gnu/bits/unistd_ext.h" textual header "/usr/include/x86_64-linux-gnu/bits/unistd.h" - textual header "/usr/include/x86_64-linux-gnu/bits/ustat.h" textual header "/usr/include/x86_64-linux-gnu/bits/utmp.h" textual header "/usr/include/x86_64-linux-gnu/bits/utmpx.h" textual header "/usr/include/x86_64-linux-gnu/bits/utsname.h" @@ -2752,31 +2827,29 @@ module "crosstool" [system] { textual header "/usr/include/x86_64-linux-gnu/bits/wctype-wchar.h" textual header "/usr/include/x86_64-linux-gnu/bits/wordsize.h" textual header "/usr/include/x86_64-linux-gnu/bits/xopen_lim.h" - textual header "/usr/include/x86_64-linux-gnu/bits/xtitypes.h" - textual header "/usr/include/x86_64-linux-gnu/c++/9/bits/atomic_word.h" - textual header "/usr/include/x86_64-linux-gnu/c++/9/bits/basic_file.h" - textual header "/usr/include/x86_64-linux-gnu/c++/9/bits/c++allocator.h" - textual header "/usr/include/x86_64-linux-gnu/c++/9/bits/c++config.h" - textual header "/usr/include/x86_64-linux-gnu/c++/9/bits/c++io.h" - textual header "/usr/include/x86_64-linux-gnu/c++/9/bits/c++locale.h" - textual header "/usr/include/x86_64-linux-gnu/c++/9/bits/cpu_defines.h" - textual header "/usr/include/x86_64-linux-gnu/c++/9/bits/ctype_base.h" - textual header "/usr/include/x86_64-linux-gnu/c++/9/bits/ctype_inline.h" - textual header "/usr/include/x86_64-linux-gnu/c++/9/bits/cxxabi_tweaks.h" - textual header "/usr/include/x86_64-linux-gnu/c++/9/bits/error_constants.h" - textual header "/usr/include/x86_64-linux-gnu/c++/9/bits/extc++.h" - textual header "/usr/include/x86_64-linux-gnu/c++/9/bits/gthr-default.h" - textual header "/usr/include/x86_64-linux-gnu/c++/9/bits/gthr.h" - textual header "/usr/include/x86_64-linux-gnu/c++/9/bits/gthr-posix.h" - textual header "/usr/include/x86_64-linux-gnu/c++/9/bits/gthr-single.h" - textual header "/usr/include/x86_64-linux-gnu/c++/9/bits/messages_members.h" - textual header "/usr/include/x86_64-linux-gnu/c++/9/bits/opt_random.h" - textual header "/usr/include/x86_64-linux-gnu/c++/9/bits/os_defines.h" - textual header "/usr/include/x86_64-linux-gnu/c++/9/bits/stdc++.h" - textual header "/usr/include/x86_64-linux-gnu/c++/9/bits/stdtr1c++.h" - textual header "/usr/include/x86_64-linux-gnu/c++/9/bits/time_members.h" - textual header "/usr/include/x86_64-linux-gnu/c++/9/ext/opt_random.h" - textual header "/usr/include/x86_64-linux-gnu/expat_config.h" + textual header "/usr/include/x86_64-linux-gnu/c++/11/bits/atomic_word.h" + textual header "/usr/include/x86_64-linux-gnu/c++/11/bits/basic_file.h" + textual header "/usr/include/x86_64-linux-gnu/c++/11/bits/c++allocator.h" + textual header "/usr/include/x86_64-linux-gnu/c++/11/bits/c++config.h" + textual header "/usr/include/x86_64-linux-gnu/c++/11/bits/c++io.h" + textual header "/usr/include/x86_64-linux-gnu/c++/11/bits/c++locale.h" + textual header "/usr/include/x86_64-linux-gnu/c++/11/bits/cpu_defines.h" + textual header "/usr/include/x86_64-linux-gnu/c++/11/bits/ctype_base.h" + textual header "/usr/include/x86_64-linux-gnu/c++/11/bits/ctype_inline.h" + textual header "/usr/include/x86_64-linux-gnu/c++/11/bits/cxxabi_tweaks.h" + textual header "/usr/include/x86_64-linux-gnu/c++/11/bits/error_constants.h" + textual header "/usr/include/x86_64-linux-gnu/c++/11/bits/extc++.h" + textual header "/usr/include/x86_64-linux-gnu/c++/11/bits/gthr-default.h" + textual header "/usr/include/x86_64-linux-gnu/c++/11/bits/gthr.h" + textual header "/usr/include/x86_64-linux-gnu/c++/11/bits/gthr-posix.h" + textual header "/usr/include/x86_64-linux-gnu/c++/11/bits/gthr-single.h" + textual header "/usr/include/x86_64-linux-gnu/c++/11/bits/messages_members.h" + textual header "/usr/include/x86_64-linux-gnu/c++/11/bits/opt_random.h" + textual header "/usr/include/x86_64-linux-gnu/c++/11/bits/os_defines.h" + textual header "/usr/include/x86_64-linux-gnu/c++/11/bits/stdc++.h" + textual header "/usr/include/x86_64-linux-gnu/c++/11/bits/stdtr1c++.h" + textual header "/usr/include/x86_64-linux-gnu/c++/11/bits/time_members.h" + textual header "/usr/include/x86_64-linux-gnu/c++/11/ext/opt_random.h" textual header "/usr/include/x86_64-linux-gnu/ffi.h" textual header "/usr/include/x86_64-linux-gnu/ffitarget.h" textual header "/usr/include/x86_64-linux-gnu/fpu_control.h" @@ -2786,7 +2859,7 @@ module "crosstool" [system] { textual header "/usr/include/x86_64-linux-gnu/gnu/stubs-64.h" textual header "/usr/include/x86_64-linux-gnu/gnu/stubs.h" textual header "/usr/include/x86_64-linux-gnu/ieee754.h" - textual header "/usr/include/x86_64-linux-gnu/python3.10/pyconfig.h" + textual header "/usr/include/x86_64-linux-gnu/openssl/opensslconf.h" textual header "/usr/include/x86_64-linux-gnu/sys/acct.h" textual header "/usr/include/x86_64-linux-gnu/sys/auxv.h" textual header "/usr/include/x86_64-linux-gnu/sys/bitypes.h" @@ -2841,7 +2914,6 @@ module "crosstool" [system] { textual header "/usr/include/x86_64-linux-gnu/sys/statfs.h" textual header "/usr/include/x86_64-linux-gnu/sys/stat.h" textual header "/usr/include/x86_64-linux-gnu/sys/statvfs.h" - textual header "/usr/include/x86_64-linux-gnu/sys/stropts.h" textual header "/usr/include/x86_64-linux-gnu/sys/swap.h" textual header "/usr/include/x86_64-linux-gnu/sys/syscall.h" textual header "/usr/include/x86_64-linux-gnu/sys/sysctl.h" @@ -2862,7 +2934,6 @@ module "crosstool" [system] { textual header "/usr/include/x86_64-linux-gnu/sys/un.h" textual header "/usr/include/x86_64-linux-gnu/sys/unistd.h" textual header "/usr/include/x86_64-linux-gnu/sys/user.h" - textual header "/usr/include/x86_64-linux-gnu/sys/ustat.h" textual header "/usr/include/x86_64-linux-gnu/sys/utsname.h" textual header "/usr/include/x86_64-linux-gnu/sys/vfs.h" textual header "/usr/include/x86_64-linux-gnu/sys/vlimit.h" @@ -2880,801 +2951,810 @@ module "crosstool" [system] { textual header "/opt/llvm/lib/clang/14.0.0/share/dfsan_abilist.txt" textual header "/opt/llvm/lib/clang/14.0.0/share/hwasan_ignorelist.txt" textual header "/opt/llvm/lib/clang/14.0.0/share/msan_ignorelist.txt" - textual header "/usr/include/c++/9/algorithm" - textual header "/usr/include/c++/9/any" - textual header "/usr/include/c++/9/array" - textual header "/usr/include/c++/9/atomic" - textual header "/usr/include/c++/9/backward/auto_ptr.h" - textual header "/usr/include/c++/9/backward/backward_warning.h" - textual header "/usr/include/c++/9/backward/binders.h" - textual header "/usr/include/c++/9/backward/hash_fun.h" - textual header "/usr/include/c++/9/backward/hash_map" - textual header "/usr/include/c++/9/backward/hash_set" - textual header "/usr/include/c++/9/backward/hashtable.h" - textual header "/usr/include/c++/9/backward/strstream" - textual header "/usr/include/c++/9/bit" - textual header "/usr/include/c++/9/bits/algorithmfwd.h" - textual header "/usr/include/c++/9/bits/allocated_ptr.h" - textual header "/usr/include/c++/9/bits/allocator.h" - textual header "/usr/include/c++/9/bits/alloc_traits.h" - textual header "/usr/include/c++/9/bits/atomic_base.h" - textual header "/usr/include/c++/9/bits/atomic_futex.h" - textual header "/usr/include/c++/9/bits/atomic_lockfree_defines.h" - textual header "/usr/include/c++/9/bits/basic_ios.h" - textual header "/usr/include/c++/9/bits/basic_ios.tcc" - textual header "/usr/include/c++/9/bits/basic_string.h" - textual header "/usr/include/c++/9/bits/basic_string.tcc" - textual header "/usr/include/c++/9/bits/boost_concept_check.h" - textual header "/usr/include/c++/9/bits/c++0x_warning.h" - textual header "/usr/include/c++/9/bits/char_traits.h" - textual header "/usr/include/c++/9/bits/codecvt.h" - textual header "/usr/include/c++/9/bits/concept_check.h" - textual header "/usr/include/c++/9/bits/cpp_type_traits.h" - textual header "/usr/include/c++/9/bits/cxxabi_forced.h" - textual header "/usr/include/c++/9/bits/cxxabi_init_exception.h" - textual header "/usr/include/c++/9/bits/deque.tcc" - textual header "/usr/include/c++/9/bits/enable_special_members.h" - textual header "/usr/include/c++/9/bits/erase_if.h" - textual header "/usr/include/c++/9/bitset" - textual header "/usr/include/c++/9/bits/exception_defines.h" - textual header "/usr/include/c++/9/bits/exception.h" - textual header "/usr/include/c++/9/bits/exception_ptr.h" - textual header "/usr/include/c++/9/bits/forward_list.h" - textual header "/usr/include/c++/9/bits/forward_list.tcc" - textual header "/usr/include/c++/9/bits/fs_dir.h" - textual header "/usr/include/c++/9/bits/fs_fwd.h" - textual header "/usr/include/c++/9/bits/fs_ops.h" - textual header "/usr/include/c++/9/bits/fs_path.h" - textual header "/usr/include/c++/9/bits/fstream.tcc" - textual header "/usr/include/c++/9/bits/functexcept.h" - textual header "/usr/include/c++/9/bits/functional_hash.h" - textual header "/usr/include/c++/9/bits/gslice_array.h" - textual header "/usr/include/c++/9/bits/gslice.h" - textual header "/usr/include/c++/9/bits/hash_bytes.h" - textual header "/usr/include/c++/9/bits/hashtable.h" - textual header "/usr/include/c++/9/bits/hashtable_policy.h" - textual header "/usr/include/c++/9/bits/indirect_array.h" - textual header "/usr/include/c++/9/bits/invoke.h" - textual header "/usr/include/c++/9/bits/ios_base.h" - textual header "/usr/include/c++/9/bits/istream.tcc" - textual header "/usr/include/c++/9/bits/list.tcc" - textual header "/usr/include/c++/9/bits/locale_classes.h" - textual header "/usr/include/c++/9/bits/locale_classes.tcc" - textual header "/usr/include/c++/9/bits/locale_conv.h" - textual header "/usr/include/c++/9/bits/locale_facets.h" - textual header "/usr/include/c++/9/bits/locale_facets_nonio.h" - textual header "/usr/include/c++/9/bits/locale_facets_nonio.tcc" - textual header "/usr/include/c++/9/bits/locale_facets.tcc" - textual header "/usr/include/c++/9/bits/localefwd.h" - textual header "/usr/include/c++/9/bits/mask_array.h" - textual header "/usr/include/c++/9/bits/memoryfwd.h" - textual header "/usr/include/c++/9/bits/move.h" - textual header "/usr/include/c++/9/bits/nested_exception.h" - textual header "/usr/include/c++/9/bits/node_handle.h" - textual header "/usr/include/c++/9/bits/ostream_insert.h" - textual header "/usr/include/c++/9/bits/ostream.tcc" - textual header "/usr/include/c++/9/bits/parse_numbers.h" - textual header "/usr/include/c++/9/bits/postypes.h" - textual header "/usr/include/c++/9/bits/predefined_ops.h" - textual header "/usr/include/c++/9/bits/ptr_traits.h" - textual header "/usr/include/c++/9/bits/quoted_string.h" - textual header "/usr/include/c++/9/bits/random.h" - textual header "/usr/include/c++/9/bits/random.tcc" - textual header "/usr/include/c++/9/bits/range_access.h" - textual header "/usr/include/c++/9/bits/refwrap.h" - textual header "/usr/include/c++/9/bits/regex_automaton.h" - textual header "/usr/include/c++/9/bits/regex_automaton.tcc" - textual header "/usr/include/c++/9/bits/regex_compiler.h" - textual header "/usr/include/c++/9/bits/regex_compiler.tcc" - textual header "/usr/include/c++/9/bits/regex_constants.h" - textual header "/usr/include/c++/9/bits/regex_error.h" - textual header "/usr/include/c++/9/bits/regex_executor.h" - textual header "/usr/include/c++/9/bits/regex_executor.tcc" - textual header "/usr/include/c++/9/bits/regex.h" - textual header "/usr/include/c++/9/bits/regex_scanner.h" - textual header "/usr/include/c++/9/bits/regex_scanner.tcc" - textual header "/usr/include/c++/9/bits/regex.tcc" - textual header "/usr/include/c++/9/bits/shared_ptr_atomic.h" - textual header "/usr/include/c++/9/bits/shared_ptr_base.h" - textual header "/usr/include/c++/9/bits/shared_ptr.h" - textual header "/usr/include/c++/9/bits/slice_array.h" - textual header "/usr/include/c++/9/bits/specfun.h" - textual header "/usr/include/c++/9/bits/sstream.tcc" - textual header "/usr/include/c++/9/bits/std_abs.h" - textual header "/usr/include/c++/9/bits/std_function.h" - textual header "/usr/include/c++/9/bits/std_mutex.h" - textual header "/usr/include/c++/9/bits/stl_algobase.h" - textual header "/usr/include/c++/9/bits/stl_algo.h" - textual header "/usr/include/c++/9/bits/stl_bvector.h" - textual header "/usr/include/c++/9/bits/stl_construct.h" - textual header "/usr/include/c++/9/bits/stl_deque.h" - textual header "/usr/include/c++/9/bits/stl_function.h" - textual header "/usr/include/c++/9/bits/stl_heap.h" - textual header "/usr/include/c++/9/bits/stl_iterator_base_funcs.h" - textual header "/usr/include/c++/9/bits/stl_iterator_base_types.h" - textual header "/usr/include/c++/9/bits/stl_iterator.h" - textual header "/usr/include/c++/9/bits/stl_list.h" - textual header "/usr/include/c++/9/bits/stl_map.h" - textual header "/usr/include/c++/9/bits/stl_multimap.h" - textual header "/usr/include/c++/9/bits/stl_multiset.h" - textual header "/usr/include/c++/9/bits/stl_numeric.h" - textual header "/usr/include/c++/9/bits/stl_pair.h" - textual header "/usr/include/c++/9/bits/stl_queue.h" - textual header "/usr/include/c++/9/bits/stl_raw_storage_iter.h" - textual header "/usr/include/c++/9/bits/stl_relops.h" - textual header "/usr/include/c++/9/bits/stl_set.h" - textual header "/usr/include/c++/9/bits/stl_stack.h" - textual header "/usr/include/c++/9/bits/stl_tempbuf.h" - textual header "/usr/include/c++/9/bits/stl_tree.h" - textual header "/usr/include/c++/9/bits/stl_uninitialized.h" - textual header "/usr/include/c++/9/bits/stl_vector.h" - textual header "/usr/include/c++/9/bits/streambuf_iterator.h" - textual header "/usr/include/c++/9/bits/streambuf.tcc" - textual header "/usr/include/c++/9/bits/stream_iterator.h" - textual header "/usr/include/c++/9/bits/stringfwd.h" - textual header "/usr/include/c++/9/bits/string_view.tcc" - textual header "/usr/include/c++/9/bits/uniform_int_dist.h" - textual header "/usr/include/c++/9/bits/unique_lock.h" - textual header "/usr/include/c++/9/bits/unique_ptr.h" - textual header "/usr/include/c++/9/bits/unordered_map.h" - textual header "/usr/include/c++/9/bits/unordered_set.h" - textual header "/usr/include/c++/9/bits/uses_allocator.h" - textual header "/usr/include/c++/9/bits/valarray_after.h" - textual header "/usr/include/c++/9/bits/valarray_array.h" - textual header "/usr/include/c++/9/bits/valarray_array.tcc" - textual header "/usr/include/c++/9/bits/valarray_before.h" - textual header "/usr/include/c++/9/bits/vector.tcc" - textual header "/usr/include/c++/9/cassert" - textual header "/usr/include/c++/9/ccomplex" - textual header "/usr/include/c++/9/cctype" - textual header "/usr/include/c++/9/cerrno" - textual header "/usr/include/c++/9/cfenv" - textual header "/usr/include/c++/9/cfloat" - textual header "/usr/include/c++/9/charconv" - textual header "/usr/include/c++/9/chrono" - textual header "/usr/include/c++/9/cinttypes" - textual header "/usr/include/c++/9/ciso646" - textual header "/usr/include/c++/9/climits" - textual header "/usr/include/c++/9/clocale" - textual header "/usr/include/c++/9/cmath" - textual header "/usr/include/c++/9/codecvt" - textual header "/usr/include/c++/9/complex" - textual header "/usr/include/c++/9/complex.h" - textual header "/usr/include/c++/9/condition_variable" - textual header "/usr/include/c++/9/csetjmp" - textual header "/usr/include/c++/9/csignal" - textual header "/usr/include/c++/9/cstdalign" - textual header "/usr/include/c++/9/cstdarg" - textual header "/usr/include/c++/9/cstdbool" - textual header "/usr/include/c++/9/cstddef" - textual header "/usr/include/c++/9/cstdint" - textual header "/usr/include/c++/9/cstdio" - textual header "/usr/include/c++/9/cstdlib" - textual header "/usr/include/c++/9/cstring" - textual header "/usr/include/c++/9/ctgmath" - textual header "/usr/include/c++/9/ctime" - textual header "/usr/include/c++/9/cuchar" - textual header "/usr/include/c++/9/cwchar" - textual header "/usr/include/c++/9/cwctype" - textual header "/usr/include/c++/9/cxxabi.h" - textual header "/usr/include/c++/9/debug/array" - textual header "/usr/include/c++/9/debug/assertions.h" - textual header "/usr/include/c++/9/debug/bitset" - textual header "/usr/include/c++/9/debug/debug.h" - textual header "/usr/include/c++/9/debug/deque" - textual header "/usr/include/c++/9/debug/formatter.h" - textual header "/usr/include/c++/9/debug/forward_list" - textual header "/usr/include/c++/9/debug/functions.h" - textual header "/usr/include/c++/9/debug/helper_functions.h" - textual header "/usr/include/c++/9/debug/list" - textual header "/usr/include/c++/9/debug/macros.h" - textual header "/usr/include/c++/9/debug/map" - textual header "/usr/include/c++/9/debug/map.h" - textual header "/usr/include/c++/9/debug/multimap.h" - textual header "/usr/include/c++/9/debug/multiset.h" - textual header "/usr/include/c++/9/debug/safe_base.h" - textual header "/usr/include/c++/9/debug/safe_container.h" - textual header "/usr/include/c++/9/debug/safe_iterator.h" - textual header "/usr/include/c++/9/debug/safe_iterator.tcc" - textual header "/usr/include/c++/9/debug/safe_local_iterator.h" - textual header "/usr/include/c++/9/debug/safe_local_iterator.tcc" - textual header "/usr/include/c++/9/debug/safe_sequence.h" - textual header "/usr/include/c++/9/debug/safe_sequence.tcc" - textual header "/usr/include/c++/9/debug/safe_unordered_base.h" - textual header "/usr/include/c++/9/debug/safe_unordered_container.h" - textual header "/usr/include/c++/9/debug/safe_unordered_container.tcc" - textual header "/usr/include/c++/9/debug/set" - textual header "/usr/include/c++/9/debug/set.h" - textual header "/usr/include/c++/9/debug/stl_iterator.h" - textual header "/usr/include/c++/9/debug/string" - textual header "/usr/include/c++/9/debug/unordered_map" - textual header "/usr/include/c++/9/debug/unordered_set" - textual header "/usr/include/c++/9/debug/vector" - textual header "/usr/include/c++/9/decimal/decimal" - textual header "/usr/include/c++/9/decimal/decimal.h" - textual header "/usr/include/c++/9/deque" - textual header "/usr/include/c++/9/exception" - textual header "/usr/include/c++/9/execution" - textual header "/usr/include/c++/9/experimental/algorithm" - textual header "/usr/include/c++/9/experimental/any" - textual header "/usr/include/c++/9/experimental/array" - textual header "/usr/include/c++/9/experimental/bits/fs_dir.h" - textual header "/usr/include/c++/9/experimental/bits/fs_fwd.h" - textual header "/usr/include/c++/9/experimental/bits/fs_ops.h" - textual header "/usr/include/c++/9/experimental/bits/fs_path.h" - textual header "/usr/include/c++/9/experimental/bits/lfts_config.h" - textual header "/usr/include/c++/9/experimental/bits/net.h" - textual header "/usr/include/c++/9/experimental/bits/shared_ptr.h" - textual header "/usr/include/c++/9/experimental/bits/string_view.tcc" - textual header "/usr/include/c++/9/experimental/buffer" - textual header "/usr/include/c++/9/experimental/chrono" - textual header "/usr/include/c++/9/experimental/deque" - textual header "/usr/include/c++/9/experimental/executor" - textual header "/usr/include/c++/9/experimental/filesystem" - textual header "/usr/include/c++/9/experimental/forward_list" - textual header "/usr/include/c++/9/experimental/functional" - textual header "/usr/include/c++/9/experimental/internet" - textual header "/usr/include/c++/9/experimental/io_context" - textual header "/usr/include/c++/9/experimental/iterator" - textual header "/usr/include/c++/9/experimental/list" - textual header "/usr/include/c++/9/experimental/map" - textual header "/usr/include/c++/9/experimental/memory" - textual header "/usr/include/c++/9/experimental/memory_resource" - textual header "/usr/include/c++/9/experimental/net" - textual header "/usr/include/c++/9/experimental/netfwd" - textual header "/usr/include/c++/9/experimental/numeric" - textual header "/usr/include/c++/9/experimental/optional" - textual header "/usr/include/c++/9/experimental/propagate_const" - textual header "/usr/include/c++/9/experimental/random" - textual header "/usr/include/c++/9/experimental/ratio" - textual header "/usr/include/c++/9/experimental/regex" - textual header "/usr/include/c++/9/experimental/set" - textual header "/usr/include/c++/9/experimental/socket" - textual header "/usr/include/c++/9/experimental/source_location" - textual header "/usr/include/c++/9/experimental/string" - textual header "/usr/include/c++/9/experimental/string_view" - textual header "/usr/include/c++/9/experimental/system_error" - textual header "/usr/include/c++/9/experimental/timer" - textual header "/usr/include/c++/9/experimental/tuple" - textual header "/usr/include/c++/9/experimental/type_traits" - textual header "/usr/include/c++/9/experimental/unordered_map" - textual header "/usr/include/c++/9/experimental/unordered_set" - textual header "/usr/include/c++/9/experimental/utility" - textual header "/usr/include/c++/9/experimental/vector" - textual header "/usr/include/c++/9/ext/algorithm" - textual header "/usr/include/c++/9/ext/aligned_buffer.h" - textual header "/usr/include/c++/9/ext/alloc_traits.h" - textual header "/usr/include/c++/9/ext/array_allocator.h" - textual header "/usr/include/c++/9/ext/atomicity.h" - textual header "/usr/include/c++/9/ext/bitmap_allocator.h" - textual header "/usr/include/c++/9/ext/cast.h" - textual header "/usr/include/c++/9/ext/cmath" - textual header "/usr/include/c++/9/ext/codecvt_specializations.h" - textual header "/usr/include/c++/9/ext/concurrence.h" - textual header "/usr/include/c++/9/ext/debug_allocator.h" - textual header "/usr/include/c++/9/ext/enc_filebuf.h" - textual header "/usr/include/c++/9/ext/extptr_allocator.h" - textual header "/usr/include/c++/9/ext/functional" - textual header "/usr/include/c++/9/ext/hash_map" - textual header "/usr/include/c++/9/ext/hash_set" - textual header "/usr/include/c++/9/ext/iterator" - textual header "/usr/include/c++/9/ext/malloc_allocator.h" - textual header "/usr/include/c++/9/ext/memory" - textual header "/usr/include/c++/9/ext/mt_allocator.h" - textual header "/usr/include/c++/9/ext/new_allocator.h" - textual header "/usr/include/c++/9/ext/numeric" - textual header "/usr/include/c++/9/ext/numeric_traits.h" - textual header "/usr/include/c++/9/ext/pb_ds/assoc_container.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/binary_heap_/binary_heap_.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/binary_heap_/const_iterator.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/binary_heap_/constructors_destructor_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/binary_heap_/debug_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/binary_heap_/entry_cmp.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/binary_heap_/entry_pred.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/binary_heap_/erase_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/binary_heap_/find_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/binary_heap_/info_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/binary_heap_/insert_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/binary_heap_/iterators_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/binary_heap_/point_const_iterator.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/binary_heap_/policy_access_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/binary_heap_/resize_policy.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/binary_heap_/split_join_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/binary_heap_/trace_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/binomial_heap_base_/binomial_heap_base_.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/binomial_heap_base_/constructors_destructor_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/binomial_heap_base_/debug_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/binomial_heap_base_/erase_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/binomial_heap_base_/find_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/binomial_heap_base_/insert_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/binomial_heap_base_/split_join_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/binomial_heap_/binomial_heap_.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/binomial_heap_/constructors_destructor_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/binomial_heap_/debug_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/bin_search_tree_/bin_search_tree_.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/bin_search_tree_/constructors_destructor_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/bin_search_tree_/debug_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/bin_search_tree_/erase_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/bin_search_tree_/find_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/bin_search_tree_/info_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/bin_search_tree_/insert_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/bin_search_tree_/iterators_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/bin_search_tree_/node_iterators.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/bin_search_tree_/point_iterators.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/bin_search_tree_/policy_access_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/bin_search_tree_/r_erase_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/bin_search_tree_/rotate_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/bin_search_tree_/split_join_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/bin_search_tree_/traits.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/branch_policy/branch_policy.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/branch_policy/null_node_metadata.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/branch_policy/traits.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/cc_hash_table_map_/cc_ht_map_.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/cc_hash_table_map_/cmp_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/cc_hash_table_map_/cond_key_dtor_entry_dealtor.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/cc_hash_table_map_/constructor_destructor_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/cc_hash_table_map_/constructor_destructor_no_store_hash_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/cc_hash_table_map_/constructor_destructor_store_hash_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/cc_hash_table_map_/debug_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/cc_hash_table_map_/debug_no_store_hash_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/cc_hash_table_map_/debug_store_hash_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/cc_hash_table_map_/entry_list_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/cc_hash_table_map_/erase_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/cc_hash_table_map_/erase_no_store_hash_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/cc_hash_table_map_/erase_store_hash_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/cc_hash_table_map_/find_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/cc_hash_table_map_/find_store_hash_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/cc_hash_table_map_/info_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/cc_hash_table_map_/insert_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/cc_hash_table_map_/insert_no_store_hash_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/cc_hash_table_map_/insert_store_hash_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/cc_hash_table_map_/iterators_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/cc_hash_table_map_/policy_access_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/cc_hash_table_map_/resize_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/cc_hash_table_map_/resize_no_store_hash_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/cc_hash_table_map_/resize_store_hash_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/cc_hash_table_map_/size_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/cc_hash_table_map_/trace_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/cond_dealtor.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/container_base_dispatch.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/debug_map_base.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/eq_fn/eq_by_less.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/eq_fn/hash_eq_fn.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/gp_hash_table_map_/constructor_destructor_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/gp_hash_table_map_/constructor_destructor_no_store_hash_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/gp_hash_table_map_/constructor_destructor_store_hash_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/gp_hash_table_map_/debug_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/gp_hash_table_map_/debug_no_store_hash_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/gp_hash_table_map_/debug_store_hash_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/gp_hash_table_map_/erase_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/gp_hash_table_map_/erase_no_store_hash_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/gp_hash_table_map_/erase_store_hash_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/gp_hash_table_map_/find_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/gp_hash_table_map_/find_no_store_hash_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/gp_hash_table_map_/find_store_hash_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/gp_hash_table_map_/gp_ht_map_.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/gp_hash_table_map_/info_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/gp_hash_table_map_/insert_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/gp_hash_table_map_/insert_no_store_hash_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/gp_hash_table_map_/insert_store_hash_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/gp_hash_table_map_/iterator_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/gp_hash_table_map_/policy_access_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/gp_hash_table_map_/resize_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/gp_hash_table_map_/resize_no_store_hash_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/gp_hash_table_map_/resize_store_hash_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/gp_hash_table_map_/trace_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/hash_fn/direct_mask_range_hashing_imp.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/hash_fn/direct_mod_range_hashing_imp.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/hash_fn/linear_probe_fn_imp.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/hash_fn/mask_based_range_hashing.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/hash_fn/mod_based_range_hashing.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/hash_fn/probe_fn_base.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/hash_fn/quadratic_probe_fn_imp.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/hash_fn/ranged_hash_fn.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/hash_fn/ranged_probe_fn.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/hash_fn/sample_probe_fn.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/hash_fn/sample_ranged_hash_fn.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/hash_fn/sample_ranged_probe_fn.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/hash_fn/sample_range_hashing.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/left_child_next_sibling_heap_/const_iterator.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/left_child_next_sibling_heap_/constructors_destructor_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/left_child_next_sibling_heap_/debug_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/left_child_next_sibling_heap_/erase_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/left_child_next_sibling_heap_/info_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/left_child_next_sibling_heap_/insert_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/left_child_next_sibling_heap_/iterators_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/left_child_next_sibling_heap_/left_child_next_sibling_heap_.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/left_child_next_sibling_heap_/node.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/left_child_next_sibling_heap_/point_const_iterator.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/left_child_next_sibling_heap_/policy_access_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/left_child_next_sibling_heap_/trace_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/list_update_map_/constructor_destructor_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/list_update_map_/debug_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/list_update_map_/entry_metadata_base.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/list_update_map_/erase_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/list_update_map_/find_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/list_update_map_/info_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/list_update_map_/insert_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/list_update_map_/iterators_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/list_update_map_/lu_map_.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/list_update_map_/trace_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/list_update_policy/lu_counter_metadata.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/list_update_policy/sample_update_policy.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/ov_tree_map_/constructors_destructor_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/ov_tree_map_/debug_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/ov_tree_map_/erase_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/ov_tree_map_/info_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/ov_tree_map_/insert_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/ov_tree_map_/iterators_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/ov_tree_map_/node_iterators.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/ov_tree_map_/ov_tree_map_.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/ov_tree_map_/policy_access_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/ov_tree_map_/split_join_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/ov_tree_map_/traits.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/pairing_heap_/constructors_destructor_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/pairing_heap_/debug_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/pairing_heap_/erase_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/pairing_heap_/find_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/pairing_heap_/insert_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/pairing_heap_/pairing_heap_.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/pairing_heap_/split_join_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/pat_trie_/constructors_destructor_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/pat_trie_/debug_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/pat_trie_/erase_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/pat_trie_/find_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/pat_trie_/info_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/pat_trie_/insert_join_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/pat_trie_/iterators_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/pat_trie_/pat_trie_base.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/pat_trie_/pat_trie_.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/pat_trie_/policy_access_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/pat_trie_/r_erase_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/pat_trie_/rotate_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/pat_trie_/split_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/pat_trie_/synth_access_traits.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/pat_trie_/trace_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/pat_trie_/traits.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/pat_trie_/update_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/priority_queue_base_dispatch.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/rb_tree_map_/constructors_destructor_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/rb_tree_map_/debug_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/rb_tree_map_/erase_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/rb_tree_map_/find_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/rb_tree_map_/info_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/rb_tree_map_/insert_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/rb_tree_map_/node.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/rb_tree_map_/rb_tree_.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/rb_tree_map_/split_join_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/rb_tree_map_/traits.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/rc_binomial_heap_/constructors_destructor_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/rc_binomial_heap_/debug_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/rc_binomial_heap_/erase_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/rc_binomial_heap_/insert_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/rc_binomial_heap_/rc_binomial_heap_.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/rc_binomial_heap_/rc.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/rc_binomial_heap_/split_join_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/rc_binomial_heap_/trace_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/resize_policy/cc_hash_max_collision_check_resize_trigger_imp.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/resize_policy/hash_exponential_size_policy_imp.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/resize_policy/hash_load_check_resize_trigger_imp.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/resize_policy/hash_load_check_resize_trigger_size_base.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/resize_policy/hash_prime_size_policy_imp.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/resize_policy/hash_standard_resize_policy_imp.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/resize_policy/sample_resize_policy.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/resize_policy/sample_resize_trigger.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/resize_policy/sample_size_policy.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/splay_tree_/constructors_destructor_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/splay_tree_/debug_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/splay_tree_/erase_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/splay_tree_/find_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/splay_tree_/info_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/splay_tree_/insert_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/splay_tree_/node.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/splay_tree_/splay_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/splay_tree_/splay_tree_.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/splay_tree_/split_join_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/splay_tree_/traits.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/standard_policies.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/thin_heap_/constructors_destructor_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/thin_heap_/debug_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/thin_heap_/erase_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/thin_heap_/find_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/thin_heap_/insert_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/thin_heap_/split_join_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/thin_heap_/thin_heap_.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/thin_heap_/trace_fn_imps.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/tree_policy/node_metadata_selector.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/tree_policy/order_statistics_imp.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/tree_policy/sample_tree_node_update.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/tree_trace_base.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/trie_policy/node_metadata_selector.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/trie_policy/order_statistics_imp.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/trie_policy/prefix_search_node_update_imp.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/trie_policy/sample_trie_access_traits.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/trie_policy/sample_trie_node_update.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/trie_policy/trie_policy_base.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/trie_policy/trie_string_access_traits_imp.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/types_traits.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/type_utils.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/unordered_iterator/const_iterator.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/unordered_iterator/iterator.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/unordered_iterator/point_const_iterator.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/detail/unordered_iterator/point_iterator.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/exception.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/hash_policy.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/list_update_policy.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/priority_queue.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/tag_and_trait.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/tree_policy.hpp" - textual header "/usr/include/c++/9/ext/pb_ds/trie_policy.hpp" - textual header "/usr/include/c++/9/ext/pod_char_traits.h" - textual header "/usr/include/c++/9/ext/pointer.h" - textual header "/usr/include/c++/9/ext/pool_allocator.h" - textual header "/usr/include/c++/9/ext/random" - textual header "/usr/include/c++/9/ext/random.tcc" - textual header "/usr/include/c++/9/ext/rb_tree" - textual header "/usr/include/c++/9/ext/rc_string_base.h" - textual header "/usr/include/c++/9/ext/rope" - textual header "/usr/include/c++/9/ext/ropeimpl.h" - textual header "/usr/include/c++/9/ext/slist" - textual header "/usr/include/c++/9/ext/sso_string_base.h" - textual header "/usr/include/c++/9/ext/stdio_filebuf.h" - textual header "/usr/include/c++/9/ext/stdio_sync_filebuf.h" - textual header "/usr/include/c++/9/ext/string_conversions.h" - textual header "/usr/include/c++/9/ext/throw_allocator.h" - textual header "/usr/include/c++/9/ext/typelist.h" - textual header "/usr/include/c++/9/ext/type_traits.h" - textual header "/usr/include/c++/9/ext/vstring_fwd.h" - textual header "/usr/include/c++/9/ext/vstring.h" - textual header "/usr/include/c++/9/ext/vstring.tcc" - textual header "/usr/include/c++/9/ext/vstring_util.h" - textual header "/usr/include/c++/9/fenv.h" - textual header "/usr/include/c++/9/filesystem" - textual header "/usr/include/c++/9/forward_list" - textual header "/usr/include/c++/9/fstream" - textual header "/usr/include/c++/9/functional" - textual header "/usr/include/c++/9/future" - textual header "/usr/include/c++/9/initializer_list" - textual header "/usr/include/c++/9/iomanip" - textual header "/usr/include/c++/9/ios" - textual header "/usr/include/c++/9/iosfwd" - textual header "/usr/include/c++/9/iostream" - textual header "/usr/include/c++/9/istream" - textual header "/usr/include/c++/9/iterator" - textual header "/usr/include/c++/9/limits" - textual header "/usr/include/c++/9/list" - textual header "/usr/include/c++/9/locale" - textual header "/usr/include/c++/9/map" - textual header "/usr/include/c++/9/math.h" - textual header "/usr/include/c++/9/memory" - textual header "/usr/include/c++/9/memory_resource" - textual header "/usr/include/c++/9/mutex" - textual header "/usr/include/c++/9/new" - textual header "/usr/include/c++/9/numeric" - textual header "/usr/include/c++/9/optional" - textual header "/usr/include/c++/9/ostream" - textual header "/usr/include/c++/9/parallel/algobase.h" - textual header "/usr/include/c++/9/parallel/algo.h" - textual header "/usr/include/c++/9/parallel/algorithm" - textual header "/usr/include/c++/9/parallel/algorithmfwd.h" - textual header "/usr/include/c++/9/parallel/balanced_quicksort.h" - textual header "/usr/include/c++/9/parallel/base.h" - textual header "/usr/include/c++/9/parallel/basic_iterator.h" - textual header "/usr/include/c++/9/parallel/checkers.h" - textual header "/usr/include/c++/9/parallel/compatibility.h" - textual header "/usr/include/c++/9/parallel/compiletime_settings.h" - textual header "/usr/include/c++/9/parallel/equally_split.h" - textual header "/usr/include/c++/9/parallel/features.h" - textual header "/usr/include/c++/9/parallel/find.h" - textual header "/usr/include/c++/9/parallel/find_selectors.h" - textual header "/usr/include/c++/9/parallel/for_each.h" - textual header "/usr/include/c++/9/parallel/for_each_selectors.h" - textual header "/usr/include/c++/9/parallel/iterator.h" - textual header "/usr/include/c++/9/parallel/list_partition.h" - textual header "/usr/include/c++/9/parallel/losertree.h" - textual header "/usr/include/c++/9/parallel/merge.h" - textual header "/usr/include/c++/9/parallel/multiseq_selection.h" - textual header "/usr/include/c++/9/parallel/multiway_merge.h" - textual header "/usr/include/c++/9/parallel/multiway_mergesort.h" - textual header "/usr/include/c++/9/parallel/numeric" - textual header "/usr/include/c++/9/parallel/numericfwd.h" - textual header "/usr/include/c++/9/parallel/omp_loop.h" - textual header "/usr/include/c++/9/parallel/omp_loop_static.h" - textual header "/usr/include/c++/9/parallel/parallel.h" - textual header "/usr/include/c++/9/parallel/par_loop.h" - textual header "/usr/include/c++/9/parallel/partial_sum.h" - textual header "/usr/include/c++/9/parallel/partition.h" - textual header "/usr/include/c++/9/parallel/queue.h" - textual header "/usr/include/c++/9/parallel/quicksort.h" - textual header "/usr/include/c++/9/parallel/random_number.h" - textual header "/usr/include/c++/9/parallel/random_shuffle.h" - textual header "/usr/include/c++/9/parallel/search.h" - textual header "/usr/include/c++/9/parallel/set_operations.h" - textual header "/usr/include/c++/9/parallel/settings.h" - textual header "/usr/include/c++/9/parallel/sort.h" - textual header "/usr/include/c++/9/parallel/tags.h" - textual header "/usr/include/c++/9/parallel/types.h" - textual header "/usr/include/c++/9/parallel/unique_copy.h" - textual header "/usr/include/c++/9/parallel/workstealing.h" - textual header "/usr/include/c++/9/profile/array" - textual header "/usr/include/c++/9/profile/base.h" - textual header "/usr/include/c++/9/profile/bitset" - textual header "/usr/include/c++/9/profile/deque" - textual header "/usr/include/c++/9/profile/forward_list" - textual header "/usr/include/c++/9/profile/impl/profiler_algos.h" - textual header "/usr/include/c++/9/profile/impl/profiler_container_size.h" - textual header "/usr/include/c++/9/profile/impl/profiler.h" - textual header "/usr/include/c++/9/profile/impl/profiler_hash_func.h" - textual header "/usr/include/c++/9/profile/impl/profiler_hashtable_size.h" - textual header "/usr/include/c++/9/profile/impl/profiler_list_to_slist.h" - textual header "/usr/include/c++/9/profile/impl/profiler_list_to_vector.h" - textual header "/usr/include/c++/9/profile/impl/profiler_map_to_unordered_map.h" - textual header "/usr/include/c++/9/profile/impl/profiler_node.h" - textual header "/usr/include/c++/9/profile/impl/profiler_state.h" - textual header "/usr/include/c++/9/profile/impl/profiler_trace.h" - textual header "/usr/include/c++/9/profile/impl/profiler_vector_size.h" - textual header "/usr/include/c++/9/profile/impl/profiler_vector_to_list.h" - textual header "/usr/include/c++/9/profile/iterator_tracker.h" - textual header "/usr/include/c++/9/profile/list" - textual header "/usr/include/c++/9/profile/map" - textual header "/usr/include/c++/9/profile/map.h" - textual header "/usr/include/c++/9/profile/multimap.h" - textual header "/usr/include/c++/9/profile/multiset.h" - textual header "/usr/include/c++/9/profile/ordered_base.h" - textual header "/usr/include/c++/9/profile/set" - textual header "/usr/include/c++/9/profile/set.h" - textual header "/usr/include/c++/9/profile/unordered_base.h" - textual header "/usr/include/c++/9/profile/unordered_map" - textual header "/usr/include/c++/9/profile/unordered_set" - textual header "/usr/include/c++/9/profile/vector" - textual header "/usr/include/c++/9/pstl/algorithm_fwd.h" - textual header "/usr/include/c++/9/pstl/algorithm_impl.h" - textual header "/usr/include/c++/9/pstl/execution_defs.h" - textual header "/usr/include/c++/9/pstl/execution_impl.h" - textual header "/usr/include/c++/9/pstl/glue_algorithm_defs.h" - textual header "/usr/include/c++/9/pstl/glue_algorithm_impl.h" - textual header "/usr/include/c++/9/pstl/glue_execution_defs.h" - textual header "/usr/include/c++/9/pstl/glue_memory_defs.h" - textual header "/usr/include/c++/9/pstl/glue_memory_impl.h" - textual header "/usr/include/c++/9/pstl/glue_numeric_defs.h" - textual header "/usr/include/c++/9/pstl/glue_numeric_impl.h" - textual header "/usr/include/c++/9/pstl/memory_impl.h" - textual header "/usr/include/c++/9/pstl/numeric_fwd.h" - textual header "/usr/include/c++/9/pstl/numeric_impl.h" - textual header "/usr/include/c++/9/pstl/parallel_backend.h" - textual header "/usr/include/c++/9/pstl/parallel_backend_tbb.h" - textual header "/usr/include/c++/9/pstl/parallel_backend_utils.h" - textual header "/usr/include/c++/9/pstl/parallel_impl.h" - textual header "/usr/include/c++/9/pstl/pstl_config.h" - textual header "/usr/include/c++/9/pstl/unseq_backend_simd.h" - textual header "/usr/include/c++/9/pstl/utils.h" - textual header "/usr/include/c++/9/queue" - textual header "/usr/include/c++/9/random" - textual header "/usr/include/c++/9/ratio" - textual header "/usr/include/c++/9/regex" - textual header "/usr/include/c++/9/scoped_allocator" - textual header "/usr/include/c++/9/set" - textual header "/usr/include/c++/9/shared_mutex" - textual header "/usr/include/c++/9/sstream" - textual header "/usr/include/c++/9/stack" - textual header "/usr/include/c++/9/stdexcept" - textual header "/usr/include/c++/9/stdlib.h" - textual header "/usr/include/c++/9/streambuf" - textual header "/usr/include/c++/9/string" - textual header "/usr/include/c++/9/string_view" - textual header "/usr/include/c++/9/system_error" - textual header "/usr/include/c++/9/tgmath.h" - textual header "/usr/include/c++/9/thread" - textual header "/usr/include/c++/9/tr1/array" - textual header "/usr/include/c++/9/tr1/bessel_function.tcc" - textual header "/usr/include/c++/9/tr1/beta_function.tcc" - textual header "/usr/include/c++/9/tr1/ccomplex" - textual header "/usr/include/c++/9/tr1/cctype" - textual header "/usr/include/c++/9/tr1/cfenv" - textual header "/usr/include/c++/9/tr1/cfloat" - textual header "/usr/include/c++/9/tr1/cinttypes" - textual header "/usr/include/c++/9/tr1/climits" - textual header "/usr/include/c++/9/tr1/cmath" - textual header "/usr/include/c++/9/tr1/complex" - textual header "/usr/include/c++/9/tr1/complex.h" - textual header "/usr/include/c++/9/tr1/cstdarg" - textual header "/usr/include/c++/9/tr1/cstdbool" - textual header "/usr/include/c++/9/tr1/cstdint" - textual header "/usr/include/c++/9/tr1/cstdio" - textual header "/usr/include/c++/9/tr1/cstdlib" - textual header "/usr/include/c++/9/tr1/ctgmath" - textual header "/usr/include/c++/9/tr1/ctime" - textual header "/usr/include/c++/9/tr1/ctype.h" - textual header "/usr/include/c++/9/tr1/cwchar" - textual header "/usr/include/c++/9/tr1/cwctype" - textual header "/usr/include/c++/9/tr1/ell_integral.tcc" - textual header "/usr/include/c++/9/tr1/exp_integral.tcc" - textual header "/usr/include/c++/9/tr1/fenv.h" - textual header "/usr/include/c++/9/tr1/float.h" - textual header "/usr/include/c++/9/tr1/functional" - textual header "/usr/include/c++/9/tr1/functional_hash.h" - textual header "/usr/include/c++/9/tr1/gamma.tcc" - textual header "/usr/include/c++/9/tr1/hashtable.h" - textual header "/usr/include/c++/9/tr1/hashtable_policy.h" - textual header "/usr/include/c++/9/tr1/hypergeometric.tcc" - textual header "/usr/include/c++/9/tr1/inttypes.h" - textual header "/usr/include/c++/9/tr1/legendre_function.tcc" - textual header "/usr/include/c++/9/tr1/limits.h" - textual header "/usr/include/c++/9/tr1/math.h" - textual header "/usr/include/c++/9/tr1/memory" - textual header "/usr/include/c++/9/tr1/modified_bessel_func.tcc" - textual header "/usr/include/c++/9/tr1/poly_hermite.tcc" - textual header "/usr/include/c++/9/tr1/poly_laguerre.tcc" - textual header "/usr/include/c++/9/tr1/random" - textual header "/usr/include/c++/9/tr1/random.h" - textual header "/usr/include/c++/9/tr1/random.tcc" - textual header "/usr/include/c++/9/tr1/regex" - textual header "/usr/include/c++/9/tr1/riemann_zeta.tcc" - textual header "/usr/include/c++/9/tr1/shared_ptr.h" - textual header "/usr/include/c++/9/tr1/special_function_util.h" - textual header "/usr/include/c++/9/tr1/stdarg.h" - textual header "/usr/include/c++/9/tr1/stdbool.h" - textual header "/usr/include/c++/9/tr1/stdint.h" - textual header "/usr/include/c++/9/tr1/stdio.h" - textual header "/usr/include/c++/9/tr1/stdlib.h" - textual header "/usr/include/c++/9/tr1/tgmath.h" - textual header "/usr/include/c++/9/tr1/tuple" - textual header "/usr/include/c++/9/tr1/type_traits" - textual header "/usr/include/c++/9/tr1/unordered_map" - textual header "/usr/include/c++/9/tr1/unordered_map.h" - textual header "/usr/include/c++/9/tr1/unordered_set" - textual header "/usr/include/c++/9/tr1/unordered_set.h" - textual header "/usr/include/c++/9/tr1/utility" - textual header "/usr/include/c++/9/tr1/wchar.h" - textual header "/usr/include/c++/9/tr1/wctype.h" - textual header "/usr/include/c++/9/tr2/bool_set" - textual header "/usr/include/c++/9/tr2/bool_set.tcc" - textual header "/usr/include/c++/9/tr2/dynamic_bitset" - textual header "/usr/include/c++/9/tr2/dynamic_bitset.tcc" - textual header "/usr/include/c++/9/tr2/ratio" - textual header "/usr/include/c++/9/tr2/type_traits" - textual header "/usr/include/c++/9/tuple" - textual header "/usr/include/c++/9/typeindex" - textual header "/usr/include/c++/9/typeinfo" - textual header "/usr/include/c++/9/type_traits" - textual header "/usr/include/c++/9/unordered_map" - textual header "/usr/include/c++/9/unordered_set" - textual header "/usr/include/c++/9/utility" - textual header "/usr/include/c++/9/valarray" - textual header "/usr/include/c++/9/variant" - textual header "/usr/include/c++/9/vector" - textual header "/usr/include/c++/9/version" - textual header "/usr/include/x86_64-linux-gnu/c++/9/bits/atomic_word.h" - textual header "/usr/include/x86_64-linux-gnu/c++/9/bits/basic_file.h" - textual header "/usr/include/x86_64-linux-gnu/c++/9/bits/c++allocator.h" - textual header "/usr/include/x86_64-linux-gnu/c++/9/bits/c++config.h" - textual header "/usr/include/x86_64-linux-gnu/c++/9/bits/c++io.h" - textual header "/usr/include/x86_64-linux-gnu/c++/9/bits/c++locale.h" - textual header "/usr/include/x86_64-linux-gnu/c++/9/bits/cpu_defines.h" - textual header "/usr/include/x86_64-linux-gnu/c++/9/bits/ctype_base.h" - textual header "/usr/include/x86_64-linux-gnu/c++/9/bits/ctype_inline.h" - textual header "/usr/include/x86_64-linux-gnu/c++/9/bits/cxxabi_tweaks.h" - textual header "/usr/include/x86_64-linux-gnu/c++/9/bits/error_constants.h" - textual header "/usr/include/x86_64-linux-gnu/c++/9/bits/extc++.h" - textual header "/usr/include/x86_64-linux-gnu/c++/9/bits/gthr-default.h" - textual header "/usr/include/x86_64-linux-gnu/c++/9/bits/gthr.h" - textual header "/usr/include/x86_64-linux-gnu/c++/9/bits/gthr-posix.h" - textual header "/usr/include/x86_64-linux-gnu/c++/9/bits/gthr-single.h" - textual header "/usr/include/x86_64-linux-gnu/c++/9/bits/messages_members.h" - textual header "/usr/include/x86_64-linux-gnu/c++/9/bits/opt_random.h" - textual header "/usr/include/x86_64-linux-gnu/c++/9/bits/os_defines.h" - textual header "/usr/include/x86_64-linux-gnu/c++/9/bits/stdc++.h" - textual header "/usr/include/x86_64-linux-gnu/c++/9/bits/stdtr1c++.h" - textual header "/usr/include/x86_64-linux-gnu/c++/9/bits/time_members.h" - textual header "/usr/include/x86_64-linux-gnu/c++/9/ext/opt_random.h" - textual header "/usr/include/c++/9/backward/auto_ptr.h" - textual header "/usr/include/c++/9/backward/backward_warning.h" - textual header "/usr/include/c++/9/backward/binders.h" - textual header "/usr/include/c++/9/backward/hash_fun.h" - textual header "/usr/include/c++/9/backward/hash_map" - textual header "/usr/include/c++/9/backward/hash_set" - textual header "/usr/include/c++/9/backward/hashtable.h" - textual header "/usr/include/c++/9/backward/strstream" + textual header "/usr/include/c++/11/algorithm" + textual header "/usr/include/c++/11/any" + textual header "/usr/include/c++/11/array" + textual header "/usr/include/c++/11/atomic" + textual header "/usr/include/c++/11/backward/auto_ptr.h" + textual header "/usr/include/c++/11/backward/backward_warning.h" + textual header "/usr/include/c++/11/backward/binders.h" + textual header "/usr/include/c++/11/backward/hash_fun.h" + textual header "/usr/include/c++/11/backward/hash_map" + textual header "/usr/include/c++/11/backward/hash_set" + textual header "/usr/include/c++/11/backward/hashtable.h" + textual header "/usr/include/c++/11/backward/strstream" + textual header "/usr/include/c++/11/barrier" + textual header "/usr/include/c++/11/bit" + textual header "/usr/include/c++/11/bits/algorithmfwd.h" + textual header "/usr/include/c++/11/bits/align.h" + textual header "/usr/include/c++/11/bits/allocated_ptr.h" + textual header "/usr/include/c++/11/bits/allocator.h" + textual header "/usr/include/c++/11/bits/alloc_traits.h" + textual header "/usr/include/c++/11/bits/atomic_base.h" + textual header "/usr/include/c++/11/bits/atomic_futex.h" + textual header "/usr/include/c++/11/bits/atomic_lockfree_defines.h" + textual header "/usr/include/c++/11/bits/atomic_timed_wait.h" + textual header "/usr/include/c++/11/bits/atomic_wait.h" + textual header "/usr/include/c++/11/bits/basic_ios.h" + textual header "/usr/include/c++/11/bits/basic_ios.tcc" + textual header "/usr/include/c++/11/bits/basic_string.h" + textual header "/usr/include/c++/11/bits/basic_string.tcc" + textual header "/usr/include/c++/11/bits/boost_concept_check.h" + textual header "/usr/include/c++/11/bits/c++0x_warning.h" + textual header "/usr/include/c++/11/bits/charconv.h" + textual header "/usr/include/c++/11/bits/char_traits.h" + textual header "/usr/include/c++/11/bits/codecvt.h" + textual header "/usr/include/c++/11/bits/concept_check.h" + textual header "/usr/include/c++/11/bits/cpp_type_traits.h" + textual header "/usr/include/c++/11/bits/cxxabi_forced.h" + textual header "/usr/include/c++/11/bits/cxxabi_init_exception.h" + textual header "/usr/include/c++/11/bits/deque.tcc" + textual header "/usr/include/c++/11/bits/enable_special_members.h" + textual header "/usr/include/c++/11/bits/erase_if.h" + textual header "/usr/include/c++/11/bitset" + textual header "/usr/include/c++/11/bits/exception_defines.h" + textual header "/usr/include/c++/11/bits/exception.h" + textual header "/usr/include/c++/11/bits/exception_ptr.h" + textual header "/usr/include/c++/11/bits/forward_list.h" + textual header "/usr/include/c++/11/bits/forward_list.tcc" + textual header "/usr/include/c++/11/bits/fs_dir.h" + textual header "/usr/include/c++/11/bits/fs_fwd.h" + textual header "/usr/include/c++/11/bits/fs_ops.h" + textual header "/usr/include/c++/11/bits/fs_path.h" + textual header "/usr/include/c++/11/bits/fstream.tcc" + textual header "/usr/include/c++/11/bits/functexcept.h" + textual header "/usr/include/c++/11/bits/functional_hash.h" + textual header "/usr/include/c++/11/bits/gslice_array.h" + textual header "/usr/include/c++/11/bits/gslice.h" + textual header "/usr/include/c++/11/bits/hash_bytes.h" + textual header "/usr/include/c++/11/bits/hashtable.h" + textual header "/usr/include/c++/11/bits/hashtable_policy.h" + textual header "/usr/include/c++/11/bits/indirect_array.h" + textual header "/usr/include/c++/11/bits/invoke.h" + textual header "/usr/include/c++/11/bits/ios_base.h" + textual header "/usr/include/c++/11/bits/istream.tcc" + textual header "/usr/include/c++/11/bits/iterator_concepts.h" + textual header "/usr/include/c++/11/bits/list.tcc" + textual header "/usr/include/c++/11/bits/locale_classes.h" + textual header "/usr/include/c++/11/bits/locale_classes.tcc" + textual header "/usr/include/c++/11/bits/locale_conv.h" + textual header "/usr/include/c++/11/bits/locale_facets.h" + textual header "/usr/include/c++/11/bits/locale_facets_nonio.h" + textual header "/usr/include/c++/11/bits/locale_facets_nonio.tcc" + textual header "/usr/include/c++/11/bits/locale_facets.tcc" + textual header "/usr/include/c++/11/bits/localefwd.h" + textual header "/usr/include/c++/11/bits/mask_array.h" + textual header "/usr/include/c++/11/bits/max_size_type.h" + textual header "/usr/include/c++/11/bits/memoryfwd.h" + textual header "/usr/include/c++/11/bits/move.h" + textual header "/usr/include/c++/11/bits/nested_exception.h" + textual header "/usr/include/c++/11/bits/node_handle.h" + textual header "/usr/include/c++/11/bits/ostream_insert.h" + textual header "/usr/include/c++/11/bits/ostream.tcc" + textual header "/usr/include/c++/11/bits/parse_numbers.h" + textual header "/usr/include/c++/11/bits/postypes.h" + textual header "/usr/include/c++/11/bits/predefined_ops.h" + textual header "/usr/include/c++/11/bits/ptr_traits.h" + textual header "/usr/include/c++/11/bits/quoted_string.h" + textual header "/usr/include/c++/11/bits/random.h" + textual header "/usr/include/c++/11/bits/random.tcc" + textual header "/usr/include/c++/11/bits/range_access.h" + textual header "/usr/include/c++/11/bits/ranges_algobase.h" + textual header "/usr/include/c++/11/bits/ranges_algo.h" + textual header "/usr/include/c++/11/bits/ranges_base.h" + textual header "/usr/include/c++/11/bits/ranges_cmp.h" + textual header "/usr/include/c++/11/bits/ranges_uninitialized.h" + textual header "/usr/include/c++/11/bits/ranges_util.h" + textual header "/usr/include/c++/11/bits/refwrap.h" + textual header "/usr/include/c++/11/bits/regex_automaton.h" + textual header "/usr/include/c++/11/bits/regex_automaton.tcc" + textual header "/usr/include/c++/11/bits/regex_compiler.h" + textual header "/usr/include/c++/11/bits/regex_compiler.tcc" + textual header "/usr/include/c++/11/bits/regex_constants.h" + textual header "/usr/include/c++/11/bits/regex_error.h" + textual header "/usr/include/c++/11/bits/regex_executor.h" + textual header "/usr/include/c++/11/bits/regex_executor.tcc" + textual header "/usr/include/c++/11/bits/regex.h" + textual header "/usr/include/c++/11/bits/regex_scanner.h" + textual header "/usr/include/c++/11/bits/regex_scanner.tcc" + textual header "/usr/include/c++/11/bits/regex.tcc" + textual header "/usr/include/c++/11/bits/semaphore_base.h" + textual header "/usr/include/c++/11/bits/shared_ptr_atomic.h" + textual header "/usr/include/c++/11/bits/shared_ptr_base.h" + textual header "/usr/include/c++/11/bits/shared_ptr.h" + textual header "/usr/include/c++/11/bits/slice_array.h" + textual header "/usr/include/c++/11/bits/specfun.h" + textual header "/usr/include/c++/11/bits/sstream.tcc" + textual header "/usr/include/c++/11/bits/std_abs.h" + textual header "/usr/include/c++/11/bits/std_function.h" + textual header "/usr/include/c++/11/bits/std_mutex.h" + textual header "/usr/include/c++/11/bits/std_thread.h" + textual header "/usr/include/c++/11/bits/stl_algobase.h" + textual header "/usr/include/c++/11/bits/stl_algo.h" + textual header "/usr/include/c++/11/bits/stl_bvector.h" + textual header "/usr/include/c++/11/bits/stl_construct.h" + textual header "/usr/include/c++/11/bits/stl_deque.h" + textual header "/usr/include/c++/11/bits/stl_function.h" + textual header "/usr/include/c++/11/bits/stl_heap.h" + textual header "/usr/include/c++/11/bits/stl_iterator_base_funcs.h" + textual header "/usr/include/c++/11/bits/stl_iterator_base_types.h" + textual header "/usr/include/c++/11/bits/stl_iterator.h" + textual header "/usr/include/c++/11/bits/stl_list.h" + textual header "/usr/include/c++/11/bits/stl_map.h" + textual header "/usr/include/c++/11/bits/stl_multimap.h" + textual header "/usr/include/c++/11/bits/stl_multiset.h" + textual header "/usr/include/c++/11/bits/stl_numeric.h" + textual header "/usr/include/c++/11/bits/stl_pair.h" + textual header "/usr/include/c++/11/bits/stl_queue.h" + textual header "/usr/include/c++/11/bits/stl_raw_storage_iter.h" + textual header "/usr/include/c++/11/bits/stl_relops.h" + textual header "/usr/include/c++/11/bits/stl_set.h" + textual header "/usr/include/c++/11/bits/stl_stack.h" + textual header "/usr/include/c++/11/bits/stl_tempbuf.h" + textual header "/usr/include/c++/11/bits/stl_tree.h" + textual header "/usr/include/c++/11/bits/stl_uninitialized.h" + textual header "/usr/include/c++/11/bits/stl_vector.h" + textual header "/usr/include/c++/11/bits/streambuf_iterator.h" + textual header "/usr/include/c++/11/bits/streambuf.tcc" + textual header "/usr/include/c++/11/bits/stream_iterator.h" + textual header "/usr/include/c++/11/bits/stringfwd.h" + textual header "/usr/include/c++/11/bits/string_view.tcc" + textual header "/usr/include/c++/11/bits/this_thread_sleep.h" + textual header "/usr/include/c++/11/bits/uniform_int_dist.h" + textual header "/usr/include/c++/11/bits/unique_lock.h" + textual header "/usr/include/c++/11/bits/unique_ptr.h" + textual header "/usr/include/c++/11/bits/unordered_map.h" + textual header "/usr/include/c++/11/bits/unordered_set.h" + textual header "/usr/include/c++/11/bits/uses_allocator_args.h" + textual header "/usr/include/c++/11/bits/uses_allocator.h" + textual header "/usr/include/c++/11/bits/valarray_after.h" + textual header "/usr/include/c++/11/bits/valarray_array.h" + textual header "/usr/include/c++/11/bits/valarray_array.tcc" + textual header "/usr/include/c++/11/bits/valarray_before.h" + textual header "/usr/include/c++/11/bits/vector.tcc" + textual header "/usr/include/c++/11/cassert" + textual header "/usr/include/c++/11/ccomplex" + textual header "/usr/include/c++/11/cctype" + textual header "/usr/include/c++/11/cerrno" + textual header "/usr/include/c++/11/cfenv" + textual header "/usr/include/c++/11/cfloat" + textual header "/usr/include/c++/11/charconv" + textual header "/usr/include/c++/11/chrono" + textual header "/usr/include/c++/11/cinttypes" + textual header "/usr/include/c++/11/ciso646" + textual header "/usr/include/c++/11/climits" + textual header "/usr/include/c++/11/clocale" + textual header "/usr/include/c++/11/cmath" + textual header "/usr/include/c++/11/codecvt" + textual header "/usr/include/c++/11/compare" + textual header "/usr/include/c++/11/complex" + textual header "/usr/include/c++/11/complex.h" + textual header "/usr/include/c++/11/concepts" + textual header "/usr/include/c++/11/condition_variable" + textual header "/usr/include/c++/11/coroutine" + textual header "/usr/include/c++/11/csetjmp" + textual header "/usr/include/c++/11/csignal" + textual header "/usr/include/c++/11/cstdalign" + textual header "/usr/include/c++/11/cstdarg" + textual header "/usr/include/c++/11/cstdbool" + textual header "/usr/include/c++/11/cstddef" + textual header "/usr/include/c++/11/cstdint" + textual header "/usr/include/c++/11/cstdio" + textual header "/usr/include/c++/11/cstdlib" + textual header "/usr/include/c++/11/cstring" + textual header "/usr/include/c++/11/ctgmath" + textual header "/usr/include/c++/11/ctime" + textual header "/usr/include/c++/11/cuchar" + textual header "/usr/include/c++/11/cwchar" + textual header "/usr/include/c++/11/cwctype" + textual header "/usr/include/c++/11/cxxabi.h" + textual header "/usr/include/c++/11/debug/assertions.h" + textual header "/usr/include/c++/11/debug/bitset" + textual header "/usr/include/c++/11/debug/debug.h" + textual header "/usr/include/c++/11/debug/deque" + textual header "/usr/include/c++/11/debug/formatter.h" + textual header "/usr/include/c++/11/debug/forward_list" + textual header "/usr/include/c++/11/debug/functions.h" + textual header "/usr/include/c++/11/debug/helper_functions.h" + textual header "/usr/include/c++/11/debug/list" + textual header "/usr/include/c++/11/debug/macros.h" + textual header "/usr/include/c++/11/debug/map" + textual header "/usr/include/c++/11/debug/map.h" + textual header "/usr/include/c++/11/debug/multimap.h" + textual header "/usr/include/c++/11/debug/multiset.h" + textual header "/usr/include/c++/11/debug/safe_base.h" + textual header "/usr/include/c++/11/debug/safe_container.h" + textual header "/usr/include/c++/11/debug/safe_iterator.h" + textual header "/usr/include/c++/11/debug/safe_iterator.tcc" + textual header "/usr/include/c++/11/debug/safe_local_iterator.h" + textual header "/usr/include/c++/11/debug/safe_local_iterator.tcc" + textual header "/usr/include/c++/11/debug/safe_sequence.h" + textual header "/usr/include/c++/11/debug/safe_sequence.tcc" + textual header "/usr/include/c++/11/debug/safe_unordered_base.h" + textual header "/usr/include/c++/11/debug/safe_unordered_container.h" + textual header "/usr/include/c++/11/debug/safe_unordered_container.tcc" + textual header "/usr/include/c++/11/debug/set" + textual header "/usr/include/c++/11/debug/set.h" + textual header "/usr/include/c++/11/debug/stl_iterator.h" + textual header "/usr/include/c++/11/debug/string" + textual header "/usr/include/c++/11/debug/unordered_map" + textual header "/usr/include/c++/11/debug/unordered_set" + textual header "/usr/include/c++/11/debug/vector" + textual header "/usr/include/c++/11/decimal/decimal" + textual header "/usr/include/c++/11/decimal/decimal.h" + textual header "/usr/include/c++/11/deque" + textual header "/usr/include/c++/11/exception" + textual header "/usr/include/c++/11/execution" + textual header "/usr/include/c++/11/experimental/algorithm" + textual header "/usr/include/c++/11/experimental/any" + textual header "/usr/include/c++/11/experimental/array" + textual header "/usr/include/c++/11/experimental/bits/fs_dir.h" + textual header "/usr/include/c++/11/experimental/bits/fs_fwd.h" + textual header "/usr/include/c++/11/experimental/bits/fs_ops.h" + textual header "/usr/include/c++/11/experimental/bits/fs_path.h" + textual header "/usr/include/c++/11/experimental/bits/lfts_config.h" + textual header "/usr/include/c++/11/experimental/bits/net.h" + textual header "/usr/include/c++/11/experimental/bits/numeric_traits.h" + textual header "/usr/include/c++/11/experimental/bits/shared_ptr.h" + textual header "/usr/include/c++/11/experimental/bits/simd_builtin.h" + textual header "/usr/include/c++/11/experimental/bits/simd_converter.h" + textual header "/usr/include/c++/11/experimental/bits/simd_detail.h" + textual header "/usr/include/c++/11/experimental/bits/simd_fixed_size.h" + textual header "/usr/include/c++/11/experimental/bits/simd.h" + textual header "/usr/include/c++/11/experimental/bits/simd_math.h" + textual header "/usr/include/c++/11/experimental/bits/simd_neon.h" + textual header "/usr/include/c++/11/experimental/bits/simd_ppc.h" + textual header "/usr/include/c++/11/experimental/bits/simd_scalar.h" + textual header "/usr/include/c++/11/experimental/bits/simd_x86_conversions.h" + textual header "/usr/include/c++/11/experimental/bits/simd_x86.h" + textual header "/usr/include/c++/11/experimental/bits/string_view.tcc" + textual header "/usr/include/c++/11/experimental/buffer" + textual header "/usr/include/c++/11/experimental/chrono" + textual header "/usr/include/c++/11/experimental/deque" + textual header "/usr/include/c++/11/experimental/executor" + textual header "/usr/include/c++/11/experimental/filesystem" + textual header "/usr/include/c++/11/experimental/forward_list" + textual header "/usr/include/c++/11/experimental/functional" + textual header "/usr/include/c++/11/experimental/internet" + textual header "/usr/include/c++/11/experimental/io_context" + textual header "/usr/include/c++/11/experimental/iterator" + textual header "/usr/include/c++/11/experimental/list" + textual header "/usr/include/c++/11/experimental/map" + textual header "/usr/include/c++/11/experimental/memory" + textual header "/usr/include/c++/11/experimental/memory_resource" + textual header "/usr/include/c++/11/experimental/net" + textual header "/usr/include/c++/11/experimental/netfwd" + textual header "/usr/include/c++/11/experimental/numeric" + textual header "/usr/include/c++/11/experimental/optional" + textual header "/usr/include/c++/11/experimental/propagate_const" + textual header "/usr/include/c++/11/experimental/random" + textual header "/usr/include/c++/11/experimental/ratio" + textual header "/usr/include/c++/11/experimental/regex" + textual header "/usr/include/c++/11/experimental/set" + textual header "/usr/include/c++/11/experimental/simd" + textual header "/usr/include/c++/11/experimental/socket" + textual header "/usr/include/c++/11/experimental/source_location" + textual header "/usr/include/c++/11/experimental/string" + textual header "/usr/include/c++/11/experimental/string_view" + textual header "/usr/include/c++/11/experimental/system_error" + textual header "/usr/include/c++/11/experimental/timer" + textual header "/usr/include/c++/11/experimental/tuple" + textual header "/usr/include/c++/11/experimental/type_traits" + textual header "/usr/include/c++/11/experimental/unordered_map" + textual header "/usr/include/c++/11/experimental/unordered_set" + textual header "/usr/include/c++/11/experimental/utility" + textual header "/usr/include/c++/11/experimental/vector" + textual header "/usr/include/c++/11/ext/algorithm" + textual header "/usr/include/c++/11/ext/aligned_buffer.h" + textual header "/usr/include/c++/11/ext/alloc_traits.h" + textual header "/usr/include/c++/11/ext/atomicity.h" + textual header "/usr/include/c++/11/ext/bitmap_allocator.h" + textual header "/usr/include/c++/11/ext/cast.h" + textual header "/usr/include/c++/11/ext/cmath" + textual header "/usr/include/c++/11/ext/codecvt_specializations.h" + textual header "/usr/include/c++/11/ext/concurrence.h" + textual header "/usr/include/c++/11/ext/debug_allocator.h" + textual header "/usr/include/c++/11/ext/enc_filebuf.h" + textual header "/usr/include/c++/11/ext/extptr_allocator.h" + textual header "/usr/include/c++/11/ext/functional" + textual header "/usr/include/c++/11/ext/hash_map" + textual header "/usr/include/c++/11/ext/hash_set" + textual header "/usr/include/c++/11/ext/iterator" + textual header "/usr/include/c++/11/ext/malloc_allocator.h" + textual header "/usr/include/c++/11/ext/memory" + textual header "/usr/include/c++/11/ext/mt_allocator.h" + textual header "/usr/include/c++/11/ext/new_allocator.h" + textual header "/usr/include/c++/11/ext/numeric" + textual header "/usr/include/c++/11/ext/numeric_traits.h" + textual header "/usr/include/c++/11/ext/pb_ds/assoc_container.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/binary_heap_/binary_heap_.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/binary_heap_/const_iterator.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/binary_heap_/constructors_destructor_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/binary_heap_/debug_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/binary_heap_/entry_cmp.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/binary_heap_/entry_pred.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/binary_heap_/erase_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/binary_heap_/find_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/binary_heap_/info_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/binary_heap_/insert_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/binary_heap_/iterators_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/binary_heap_/point_const_iterator.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/binary_heap_/policy_access_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/binary_heap_/resize_policy.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/binary_heap_/split_join_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/binary_heap_/trace_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/binomial_heap_base_/binomial_heap_base_.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/binomial_heap_base_/constructors_destructor_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/binomial_heap_base_/debug_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/binomial_heap_base_/erase_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/binomial_heap_base_/find_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/binomial_heap_base_/insert_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/binomial_heap_base_/split_join_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/binomial_heap_/binomial_heap_.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/binomial_heap_/constructors_destructor_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/binomial_heap_/debug_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/bin_search_tree_/bin_search_tree_.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/bin_search_tree_/constructors_destructor_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/bin_search_tree_/debug_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/bin_search_tree_/erase_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/bin_search_tree_/find_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/bin_search_tree_/info_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/bin_search_tree_/insert_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/bin_search_tree_/iterators_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/bin_search_tree_/node_iterators.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/bin_search_tree_/point_iterators.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/bin_search_tree_/policy_access_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/bin_search_tree_/r_erase_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/bin_search_tree_/rotate_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/bin_search_tree_/split_join_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/bin_search_tree_/traits.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/branch_policy/branch_policy.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/branch_policy/null_node_metadata.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/branch_policy/traits.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/cc_hash_table_map_/cc_ht_map_.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/cc_hash_table_map_/cmp_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/cc_hash_table_map_/cond_key_dtor_entry_dealtor.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/cc_hash_table_map_/constructor_destructor_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/cc_hash_table_map_/constructor_destructor_no_store_hash_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/cc_hash_table_map_/constructor_destructor_store_hash_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/cc_hash_table_map_/debug_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/cc_hash_table_map_/debug_no_store_hash_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/cc_hash_table_map_/debug_store_hash_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/cc_hash_table_map_/entry_list_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/cc_hash_table_map_/erase_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/cc_hash_table_map_/erase_no_store_hash_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/cc_hash_table_map_/erase_store_hash_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/cc_hash_table_map_/find_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/cc_hash_table_map_/find_store_hash_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/cc_hash_table_map_/info_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/cc_hash_table_map_/insert_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/cc_hash_table_map_/insert_no_store_hash_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/cc_hash_table_map_/insert_store_hash_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/cc_hash_table_map_/iterators_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/cc_hash_table_map_/policy_access_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/cc_hash_table_map_/resize_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/cc_hash_table_map_/resize_no_store_hash_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/cc_hash_table_map_/resize_store_hash_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/cc_hash_table_map_/size_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/cc_hash_table_map_/trace_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/cond_dealtor.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/container_base_dispatch.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/debug_map_base.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/eq_fn/eq_by_less.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/eq_fn/hash_eq_fn.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/gp_hash_table_map_/constructor_destructor_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/gp_hash_table_map_/constructor_destructor_no_store_hash_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/gp_hash_table_map_/constructor_destructor_store_hash_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/gp_hash_table_map_/debug_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/gp_hash_table_map_/debug_no_store_hash_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/gp_hash_table_map_/debug_store_hash_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/gp_hash_table_map_/erase_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/gp_hash_table_map_/erase_no_store_hash_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/gp_hash_table_map_/erase_store_hash_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/gp_hash_table_map_/find_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/gp_hash_table_map_/find_no_store_hash_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/gp_hash_table_map_/find_store_hash_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/gp_hash_table_map_/gp_ht_map_.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/gp_hash_table_map_/info_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/gp_hash_table_map_/insert_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/gp_hash_table_map_/insert_no_store_hash_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/gp_hash_table_map_/insert_store_hash_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/gp_hash_table_map_/iterator_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/gp_hash_table_map_/policy_access_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/gp_hash_table_map_/resize_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/gp_hash_table_map_/resize_no_store_hash_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/gp_hash_table_map_/resize_store_hash_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/gp_hash_table_map_/trace_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/hash_fn/direct_mask_range_hashing_imp.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/hash_fn/direct_mod_range_hashing_imp.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/hash_fn/linear_probe_fn_imp.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/hash_fn/mask_based_range_hashing.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/hash_fn/mod_based_range_hashing.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/hash_fn/probe_fn_base.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/hash_fn/quadratic_probe_fn_imp.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/hash_fn/ranged_hash_fn.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/hash_fn/ranged_probe_fn.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/hash_fn/sample_probe_fn.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/hash_fn/sample_ranged_hash_fn.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/hash_fn/sample_ranged_probe_fn.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/hash_fn/sample_range_hashing.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/left_child_next_sibling_heap_/const_iterator.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/left_child_next_sibling_heap_/constructors_destructor_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/left_child_next_sibling_heap_/debug_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/left_child_next_sibling_heap_/erase_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/left_child_next_sibling_heap_/info_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/left_child_next_sibling_heap_/insert_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/left_child_next_sibling_heap_/iterators_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/left_child_next_sibling_heap_/left_child_next_sibling_heap_.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/left_child_next_sibling_heap_/node.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/left_child_next_sibling_heap_/point_const_iterator.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/left_child_next_sibling_heap_/policy_access_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/left_child_next_sibling_heap_/trace_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/list_update_map_/constructor_destructor_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/list_update_map_/debug_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/list_update_map_/entry_metadata_base.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/list_update_map_/erase_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/list_update_map_/find_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/list_update_map_/info_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/list_update_map_/insert_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/list_update_map_/iterators_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/list_update_map_/lu_map_.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/list_update_map_/trace_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/list_update_policy/lu_counter_metadata.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/list_update_policy/sample_update_policy.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/ov_tree_map_/constructors_destructor_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/ov_tree_map_/debug_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/ov_tree_map_/erase_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/ov_tree_map_/info_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/ov_tree_map_/insert_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/ov_tree_map_/iterators_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/ov_tree_map_/node_iterators.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/ov_tree_map_/ov_tree_map_.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/ov_tree_map_/policy_access_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/ov_tree_map_/split_join_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/ov_tree_map_/traits.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/pairing_heap_/constructors_destructor_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/pairing_heap_/debug_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/pairing_heap_/erase_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/pairing_heap_/find_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/pairing_heap_/insert_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/pairing_heap_/pairing_heap_.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/pairing_heap_/split_join_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/pat_trie_/constructors_destructor_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/pat_trie_/debug_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/pat_trie_/erase_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/pat_trie_/find_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/pat_trie_/info_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/pat_trie_/insert_join_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/pat_trie_/iterators_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/pat_trie_/pat_trie_base.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/pat_trie_/pat_trie_.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/pat_trie_/policy_access_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/pat_trie_/r_erase_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/pat_trie_/rotate_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/pat_trie_/split_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/pat_trie_/synth_access_traits.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/pat_trie_/trace_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/pat_trie_/traits.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/pat_trie_/update_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/priority_queue_base_dispatch.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/rb_tree_map_/constructors_destructor_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/rb_tree_map_/debug_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/rb_tree_map_/erase_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/rb_tree_map_/find_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/rb_tree_map_/info_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/rb_tree_map_/insert_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/rb_tree_map_/node.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/rb_tree_map_/rb_tree_.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/rb_tree_map_/split_join_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/rb_tree_map_/traits.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/rc_binomial_heap_/constructors_destructor_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/rc_binomial_heap_/debug_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/rc_binomial_heap_/erase_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/rc_binomial_heap_/insert_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/rc_binomial_heap_/rc_binomial_heap_.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/rc_binomial_heap_/rc.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/rc_binomial_heap_/split_join_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/rc_binomial_heap_/trace_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/resize_policy/cc_hash_max_collision_check_resize_trigger_imp.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/resize_policy/hash_exponential_size_policy_imp.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/resize_policy/hash_load_check_resize_trigger_imp.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/resize_policy/hash_load_check_resize_trigger_size_base.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/resize_policy/hash_prime_size_policy_imp.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/resize_policy/hash_standard_resize_policy_imp.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/resize_policy/sample_resize_policy.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/resize_policy/sample_resize_trigger.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/resize_policy/sample_size_policy.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/splay_tree_/constructors_destructor_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/splay_tree_/debug_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/splay_tree_/erase_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/splay_tree_/find_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/splay_tree_/info_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/splay_tree_/insert_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/splay_tree_/node.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/splay_tree_/splay_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/splay_tree_/splay_tree_.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/splay_tree_/split_join_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/splay_tree_/traits.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/standard_policies.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/thin_heap_/constructors_destructor_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/thin_heap_/debug_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/thin_heap_/erase_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/thin_heap_/find_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/thin_heap_/insert_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/thin_heap_/split_join_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/thin_heap_/thin_heap_.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/thin_heap_/trace_fn_imps.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/tree_policy/node_metadata_selector.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/tree_policy/order_statistics_imp.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/tree_policy/sample_tree_node_update.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/tree_trace_base.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/trie_policy/node_metadata_selector.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/trie_policy/order_statistics_imp.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/trie_policy/prefix_search_node_update_imp.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/trie_policy/sample_trie_access_traits.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/trie_policy/sample_trie_node_update.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/trie_policy/trie_policy_base.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/trie_policy/trie_string_access_traits_imp.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/types_traits.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/type_utils.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/unordered_iterator/const_iterator.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/unordered_iterator/iterator.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/unordered_iterator/point_const_iterator.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/detail/unordered_iterator/point_iterator.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/exception.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/hash_policy.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/list_update_policy.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/priority_queue.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/tag_and_trait.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/tree_policy.hpp" + textual header "/usr/include/c++/11/ext/pb_ds/trie_policy.hpp" + textual header "/usr/include/c++/11/ext/pod_char_traits.h" + textual header "/usr/include/c++/11/ext/pointer.h" + textual header "/usr/include/c++/11/ext/pool_allocator.h" + textual header "/usr/include/c++/11/ext/random" + textual header "/usr/include/c++/11/ext/random.tcc" + textual header "/usr/include/c++/11/ext/rb_tree" + textual header "/usr/include/c++/11/ext/rc_string_base.h" + textual header "/usr/include/c++/11/ext/rope" + textual header "/usr/include/c++/11/ext/ropeimpl.h" + textual header "/usr/include/c++/11/ext/slist" + textual header "/usr/include/c++/11/ext/sso_string_base.h" + textual header "/usr/include/c++/11/ext/stdio_filebuf.h" + textual header "/usr/include/c++/11/ext/stdio_sync_filebuf.h" + textual header "/usr/include/c++/11/ext/string_conversions.h" + textual header "/usr/include/c++/11/ext/throw_allocator.h" + textual header "/usr/include/c++/11/ext/typelist.h" + textual header "/usr/include/c++/11/ext/type_traits.h" + textual header "/usr/include/c++/11/ext/vstring_fwd.h" + textual header "/usr/include/c++/11/ext/vstring.h" + textual header "/usr/include/c++/11/ext/vstring.tcc" + textual header "/usr/include/c++/11/ext/vstring_util.h" + textual header "/usr/include/c++/11/fenv.h" + textual header "/usr/include/c++/11/filesystem" + textual header "/usr/include/c++/11/forward_list" + textual header "/usr/include/c++/11/fstream" + textual header "/usr/include/c++/11/functional" + textual header "/usr/include/c++/11/future" + textual header "/usr/include/c++/11/initializer_list" + textual header "/usr/include/c++/11/iomanip" + textual header "/usr/include/c++/11/ios" + textual header "/usr/include/c++/11/iosfwd" + textual header "/usr/include/c++/11/iostream" + textual header "/usr/include/c++/11/istream" + textual header "/usr/include/c++/11/iterator" + textual header "/usr/include/c++/11/latch" + textual header "/usr/include/c++/11/limits" + textual header "/usr/include/c++/11/list" + textual header "/usr/include/c++/11/locale" + textual header "/usr/include/c++/11/map" + textual header "/usr/include/c++/11/math.h" + textual header "/usr/include/c++/11/memory" + textual header "/usr/include/c++/11/memory_resource" + textual header "/usr/include/c++/11/mutex" + textual header "/usr/include/c++/11/new" + textual header "/usr/include/c++/11/numbers" + textual header "/usr/include/c++/11/numeric" + textual header "/usr/include/c++/11/optional" + textual header "/usr/include/c++/11/ostream" + textual header "/usr/include/c++/11/parallel/algobase.h" + textual header "/usr/include/c++/11/parallel/algo.h" + textual header "/usr/include/c++/11/parallel/algorithm" + textual header "/usr/include/c++/11/parallel/algorithmfwd.h" + textual header "/usr/include/c++/11/parallel/balanced_quicksort.h" + textual header "/usr/include/c++/11/parallel/base.h" + textual header "/usr/include/c++/11/parallel/basic_iterator.h" + textual header "/usr/include/c++/11/parallel/checkers.h" + textual header "/usr/include/c++/11/parallel/compatibility.h" + textual header "/usr/include/c++/11/parallel/compiletime_settings.h" + textual header "/usr/include/c++/11/parallel/equally_split.h" + textual header "/usr/include/c++/11/parallel/features.h" + textual header "/usr/include/c++/11/parallel/find.h" + textual header "/usr/include/c++/11/parallel/find_selectors.h" + textual header "/usr/include/c++/11/parallel/for_each.h" + textual header "/usr/include/c++/11/parallel/for_each_selectors.h" + textual header "/usr/include/c++/11/parallel/iterator.h" + textual header "/usr/include/c++/11/parallel/list_partition.h" + textual header "/usr/include/c++/11/parallel/losertree.h" + textual header "/usr/include/c++/11/parallel/merge.h" + textual header "/usr/include/c++/11/parallel/multiseq_selection.h" + textual header "/usr/include/c++/11/parallel/multiway_merge.h" + textual header "/usr/include/c++/11/parallel/multiway_mergesort.h" + textual header "/usr/include/c++/11/parallel/numeric" + textual header "/usr/include/c++/11/parallel/numericfwd.h" + textual header "/usr/include/c++/11/parallel/omp_loop.h" + textual header "/usr/include/c++/11/parallel/omp_loop_static.h" + textual header "/usr/include/c++/11/parallel/parallel.h" + textual header "/usr/include/c++/11/parallel/par_loop.h" + textual header "/usr/include/c++/11/parallel/partial_sum.h" + textual header "/usr/include/c++/11/parallel/partition.h" + textual header "/usr/include/c++/11/parallel/queue.h" + textual header "/usr/include/c++/11/parallel/quicksort.h" + textual header "/usr/include/c++/11/parallel/random_number.h" + textual header "/usr/include/c++/11/parallel/random_shuffle.h" + textual header "/usr/include/c++/11/parallel/search.h" + textual header "/usr/include/c++/11/parallel/set_operations.h" + textual header "/usr/include/c++/11/parallel/settings.h" + textual header "/usr/include/c++/11/parallel/sort.h" + textual header "/usr/include/c++/11/parallel/tags.h" + textual header "/usr/include/c++/11/parallel/types.h" + textual header "/usr/include/c++/11/parallel/unique_copy.h" + textual header "/usr/include/c++/11/parallel/workstealing.h" + textual header "/usr/include/c++/11/pstl/algorithm_fwd.h" + textual header "/usr/include/c++/11/pstl/algorithm_impl.h" + textual header "/usr/include/c++/11/pstl/execution_defs.h" + textual header "/usr/include/c++/11/pstl/execution_impl.h" + textual header "/usr/include/c++/11/pstl/glue_algorithm_defs.h" + textual header "/usr/include/c++/11/pstl/glue_algorithm_impl.h" + textual header "/usr/include/c++/11/pstl/glue_execution_defs.h" + textual header "/usr/include/c++/11/pstl/glue_memory_defs.h" + textual header "/usr/include/c++/11/pstl/glue_memory_impl.h" + textual header "/usr/include/c++/11/pstl/glue_numeric_defs.h" + textual header "/usr/include/c++/11/pstl/glue_numeric_impl.h" + textual header "/usr/include/c++/11/pstl/memory_impl.h" + textual header "/usr/include/c++/11/pstl/numeric_fwd.h" + textual header "/usr/include/c++/11/pstl/numeric_impl.h" + textual header "/usr/include/c++/11/pstl/parallel_backend.h" + textual header "/usr/include/c++/11/pstl/parallel_backend_serial.h" + textual header "/usr/include/c++/11/pstl/parallel_backend_tbb.h" + textual header "/usr/include/c++/11/pstl/parallel_backend_utils.h" + textual header "/usr/include/c++/11/pstl/parallel_impl.h" + textual header "/usr/include/c++/11/pstl/pstl_config.h" + textual header "/usr/include/c++/11/pstl/unseq_backend_simd.h" + textual header "/usr/include/c++/11/pstl/utils.h" + textual header "/usr/include/c++/11/queue" + textual header "/usr/include/c++/11/random" + textual header "/usr/include/c++/11/ranges" + textual header "/usr/include/c++/11/ratio" + textual header "/usr/include/c++/11/regex" + textual header "/usr/include/c++/11/scoped_allocator" + textual header "/usr/include/c++/11/semaphore" + textual header "/usr/include/c++/11/set" + textual header "/usr/include/c++/11/shared_mutex" + textual header "/usr/include/c++/11/source_location" + textual header "/usr/include/c++/11/span" + textual header "/usr/include/c++/11/sstream" + textual header "/usr/include/c++/11/stack" + textual header "/usr/include/c++/11/stdexcept" + textual header "/usr/include/c++/11/stdlib.h" + textual header "/usr/include/c++/11/stop_token" + textual header "/usr/include/c++/11/streambuf" + textual header "/usr/include/c++/11/string" + textual header "/usr/include/c++/11/string_view" + textual header "/usr/include/c++/11/syncstream" + textual header "/usr/include/c++/11/system_error" + textual header "/usr/include/c++/11/tgmath.h" + textual header "/usr/include/c++/11/thread" + textual header "/usr/include/c++/11/tr1/array" + textual header "/usr/include/c++/11/tr1/bessel_function.tcc" + textual header "/usr/include/c++/11/tr1/beta_function.tcc" + textual header "/usr/include/c++/11/tr1/ccomplex" + textual header "/usr/include/c++/11/tr1/cctype" + textual header "/usr/include/c++/11/tr1/cfenv" + textual header "/usr/include/c++/11/tr1/cfloat" + textual header "/usr/include/c++/11/tr1/cinttypes" + textual header "/usr/include/c++/11/tr1/climits" + textual header "/usr/include/c++/11/tr1/cmath" + textual header "/usr/include/c++/11/tr1/complex" + textual header "/usr/include/c++/11/tr1/complex.h" + textual header "/usr/include/c++/11/tr1/cstdarg" + textual header "/usr/include/c++/11/tr1/cstdbool" + textual header "/usr/include/c++/11/tr1/cstdint" + textual header "/usr/include/c++/11/tr1/cstdio" + textual header "/usr/include/c++/11/tr1/cstdlib" + textual header "/usr/include/c++/11/tr1/ctgmath" + textual header "/usr/include/c++/11/tr1/ctime" + textual header "/usr/include/c++/11/tr1/ctype.h" + textual header "/usr/include/c++/11/tr1/cwchar" + textual header "/usr/include/c++/11/tr1/cwctype" + textual header "/usr/include/c++/11/tr1/ell_integral.tcc" + textual header "/usr/include/c++/11/tr1/exp_integral.tcc" + textual header "/usr/include/c++/11/tr1/fenv.h" + textual header "/usr/include/c++/11/tr1/float.h" + textual header "/usr/include/c++/11/tr1/functional" + textual header "/usr/include/c++/11/tr1/functional_hash.h" + textual header "/usr/include/c++/11/tr1/gamma.tcc" + textual header "/usr/include/c++/11/tr1/hashtable.h" + textual header "/usr/include/c++/11/tr1/hashtable_policy.h" + textual header "/usr/include/c++/11/tr1/hypergeometric.tcc" + textual header "/usr/include/c++/11/tr1/inttypes.h" + textual header "/usr/include/c++/11/tr1/legendre_function.tcc" + textual header "/usr/include/c++/11/tr1/limits.h" + textual header "/usr/include/c++/11/tr1/math.h" + textual header "/usr/include/c++/11/tr1/memory" + textual header "/usr/include/c++/11/tr1/modified_bessel_func.tcc" + textual header "/usr/include/c++/11/tr1/poly_hermite.tcc" + textual header "/usr/include/c++/11/tr1/poly_laguerre.tcc" + textual header "/usr/include/c++/11/tr1/random" + textual header "/usr/include/c++/11/tr1/random.h" + textual header "/usr/include/c++/11/tr1/random.tcc" + textual header "/usr/include/c++/11/tr1/regex" + textual header "/usr/include/c++/11/tr1/riemann_zeta.tcc" + textual header "/usr/include/c++/11/tr1/shared_ptr.h" + textual header "/usr/include/c++/11/tr1/special_function_util.h" + textual header "/usr/include/c++/11/tr1/stdarg.h" + textual header "/usr/include/c++/11/tr1/stdbool.h" + textual header "/usr/include/c++/11/tr1/stdint.h" + textual header "/usr/include/c++/11/tr1/stdio.h" + textual header "/usr/include/c++/11/tr1/stdlib.h" + textual header "/usr/include/c++/11/tr1/tgmath.h" + textual header "/usr/include/c++/11/tr1/tuple" + textual header "/usr/include/c++/11/tr1/type_traits" + textual header "/usr/include/c++/11/tr1/unordered_map" + textual header "/usr/include/c++/11/tr1/unordered_map.h" + textual header "/usr/include/c++/11/tr1/unordered_set" + textual header "/usr/include/c++/11/tr1/unordered_set.h" + textual header "/usr/include/c++/11/tr1/utility" + textual header "/usr/include/c++/11/tr1/wchar.h" + textual header "/usr/include/c++/11/tr1/wctype.h" + textual header "/usr/include/c++/11/tr2/bool_set" + textual header "/usr/include/c++/11/tr2/bool_set.tcc" + textual header "/usr/include/c++/11/tr2/dynamic_bitset" + textual header "/usr/include/c++/11/tr2/dynamic_bitset.tcc" + textual header "/usr/include/c++/11/tr2/ratio" + textual header "/usr/include/c++/11/tr2/type_traits" + textual header "/usr/include/c++/11/tuple" + textual header "/usr/include/c++/11/typeindex" + textual header "/usr/include/c++/11/typeinfo" + textual header "/usr/include/c++/11/type_traits" + textual header "/usr/include/c++/11/unordered_map" + textual header "/usr/include/c++/11/unordered_set" + textual header "/usr/include/c++/11/utility" + textual header "/usr/include/c++/11/valarray" + textual header "/usr/include/c++/11/variant" + textual header "/usr/include/c++/11/vector" + textual header "/usr/include/c++/11/version" + textual header "/usr/include/x86_64-linux-gnu/c++/11/bits/atomic_word.h" + textual header "/usr/include/x86_64-linux-gnu/c++/11/bits/basic_file.h" + textual header "/usr/include/x86_64-linux-gnu/c++/11/bits/c++allocator.h" + textual header "/usr/include/x86_64-linux-gnu/c++/11/bits/c++config.h" + textual header "/usr/include/x86_64-linux-gnu/c++/11/bits/c++io.h" + textual header "/usr/include/x86_64-linux-gnu/c++/11/bits/c++locale.h" + textual header "/usr/include/x86_64-linux-gnu/c++/11/bits/cpu_defines.h" + textual header "/usr/include/x86_64-linux-gnu/c++/11/bits/ctype_base.h" + textual header "/usr/include/x86_64-linux-gnu/c++/11/bits/ctype_inline.h" + textual header "/usr/include/x86_64-linux-gnu/c++/11/bits/cxxabi_tweaks.h" + textual header "/usr/include/x86_64-linux-gnu/c++/11/bits/error_constants.h" + textual header "/usr/include/x86_64-linux-gnu/c++/11/bits/extc++.h" + textual header "/usr/include/x86_64-linux-gnu/c++/11/bits/gthr-default.h" + textual header "/usr/include/x86_64-linux-gnu/c++/11/bits/gthr.h" + textual header "/usr/include/x86_64-linux-gnu/c++/11/bits/gthr-posix.h" + textual header "/usr/include/x86_64-linux-gnu/c++/11/bits/gthr-single.h" + textual header "/usr/include/x86_64-linux-gnu/c++/11/bits/messages_members.h" + textual header "/usr/include/x86_64-linux-gnu/c++/11/bits/opt_random.h" + textual header "/usr/include/x86_64-linux-gnu/c++/11/bits/os_defines.h" + textual header "/usr/include/x86_64-linux-gnu/c++/11/bits/stdc++.h" + textual header "/usr/include/x86_64-linux-gnu/c++/11/bits/stdtr1c++.h" + textual header "/usr/include/x86_64-linux-gnu/c++/11/bits/time_members.h" + textual header "/usr/include/x86_64-linux-gnu/c++/11/ext/opt_random.h" + textual header "/usr/include/c++/11/backward/auto_ptr.h" + textual header "/usr/include/c++/11/backward/backward_warning.h" + textual header "/usr/include/c++/11/backward/binders.h" + textual header "/usr/include/c++/11/backward/hash_fun.h" + textual header "/usr/include/c++/11/backward/hash_map" + textual header "/usr/include/c++/11/backward/hash_set" + textual header "/usr/include/c++/11/backward/hashtable.h" + textual header "/usr/include/c++/11/backward/strstream" textual header "/opt/llvm/include/x86_64-unknown-linux-gnu/c++/v1/__config_site" textual header "/opt/llvm/include/c++/v1/algorithm" textual header "/opt/llvm/include/c++/v1/__algorithm/adjacent_find.h" From bb22882dc51b9e41ad1b1fc78e1258c17df3e3ec Mon Sep 17 00:00:00 2001 From: Greg Greenway Date: Fri, 20 Sep 2024 16:15:29 -0700 Subject: [PATCH 49/65] http2: fix reported protocol error from graceful upstream close (#36205) Risk Level: Medium Testing: Added new tests Release Notes: added Runtime guard: envoy.reloadable_features.http2_no_protocol_error_upon_clean_close Fixes #21522 --------- Signed-off-by: Greg Greenway --- changelogs/current.yaml | 6 + source/common/http/codec_client.cc | 13 +- source/common/http/http2/codec_impl.cc | 6 +- source/common/http/status.cc | 12 ++ source/common/http/status.h | 7 ++ source/common/runtime/runtime_features.cc | 1 + .../multiplexed_integration_test.cc | 112 ++++++++++++++++++ 7 files changed, 152 insertions(+), 5 deletions(-) diff --git a/changelogs/current.yaml b/changelogs/current.yaml index 5fd9945a3a..9d61bc5641 100644 --- a/changelogs/current.yaml +++ b/changelogs/current.yaml @@ -132,6 +132,12 @@ bug_fixes: change: | RBAC will now allow stat prefixes configured in per-route config to override the base config's stat prefix. +- area: http2 + change: | + Fixed bug where an upstream that sent a GOAWAY and gracefully closed a connection would result in an increment of + the cluster stat ``upstream_cx_protocol_error`` and setting the ``UpstreamProtocolError`` response flag. This behavior + can be reverted by setting the runtime guard ``envoy.reloadable_features.http2_no_protocol_error_upon_clean_close`` + to false. - area: http3 change: | Fixed a bug where an empty trailers block could be sent. This would occur if a filter removed diff --git a/source/common/http/codec_client.cc b/source/common/http/codec_client.cc index 4c0cee0828..2f74974d98 100644 --- a/source/common/http/codec_client.cc +++ b/source/common/http/codec_client.cc @@ -170,10 +170,15 @@ void CodecClient::onData(Buffer::Instance& data) { if (!status.ok()) { ENVOY_CONN_LOG(debug, "Error dispatching received data: {}", *connection_, status.message()); - // Don't count 408 responses where we have no active requests as protocol errors - if (!isPrematureResponseError(status) || - (!active_requests_.empty() || - getPrematureResponseHttpCode(status) != Code::RequestTimeout)) { + // Don't count 408 responses where we have no active requests as protocol errors. + // Don't count graceful GOAWAY closes. + const bool not_408 = + !isPrematureResponseError(status) || + (!active_requests_.empty() || getPrematureResponseHttpCode(status) != Code::RequestTimeout); + const bool is_goaway = isGoAwayGracefulCloseError(status); + if (not_408 && + (!is_goaway || !Runtime::runtimeFeatureEnabled( + "envoy.reloadable_features.http2_no_protocol_error_upon_clean_close"))) { host_->cluster().trafficStats()->upstream_cx_protocol_error_.inc(); protocol_error_ = true; } diff --git a/source/common/http/http2/codec_impl.cc b/source/common/http/http2/codec_impl.cc index 9171d60a88..92ce356540 100644 --- a/source/common/http/http2/codec_impl.cc +++ b/source/common/http/http2/codec_impl.cc @@ -1704,7 +1704,11 @@ int ConnectionImpl::setAndCheckCodecCallbackStatus(Status&& status) { // error statuses are silently discarded. codec_callback_status_.Update(std::move(status)); if (codec_callback_status_.ok() && connection_.state() != Network::Connection::State::Open) { - codec_callback_status_ = codecProtocolError("Connection was closed while dispatching frames"); + if (!active_streams_.empty() || !raised_goaway_) { + codec_callback_status_ = codecProtocolError("Connection was closed while dispatching frames"); + } else { + codec_callback_status_ = goAwayGracefulCloseError(); + } } return codec_callback_status_.ok() ? 0 : ERR_CALLBACK_FAILURE; diff --git a/source/common/http/status.cc b/source/common/http/status.cc index 86117912c2..2ae3d69bb3 100644 --- a/source/common/http/status.cc +++ b/source/common/http/status.cc @@ -27,6 +27,8 @@ absl::string_view statusCodeToString(StatusCode code) { return "InboundFramesWithEmptyPayloadError"; case StatusCode::EnvoyOverloadError: return "EnvoyOverloadError"; + case StatusCode::GoAwayGracefulClose: + return "GoAwayGracefulClose"; } return ""; } @@ -124,6 +126,12 @@ Status envoyOverloadError(absl::string_view message) { return status; } +Status goAwayGracefulCloseError() { + absl::Status status(absl::StatusCode::kInternal, {}); + storePayload(status, EnvoyStatusPayload(StatusCode::GoAwayGracefulClose)); + return status; +} + // Methods for checking and extracting error information StatusCode getStatusCode(const Status& status) { return status.ok() ? StatusCode::Ok : getPayload(status).status_code_; @@ -160,5 +168,9 @@ bool isEnvoyOverloadError(const Status& status) { return getStatusCode(status) == StatusCode::EnvoyOverloadError; } +bool isGoAwayGracefulCloseError(const Status& status) { + return getStatusCode(status) == StatusCode::GoAwayGracefulClose; +} + } // namespace Http } // namespace Envoy diff --git a/source/common/http/status.h b/source/common/http/status.h index 858311b1d9..94c451a640 100644 --- a/source/common/http/status.h +++ b/source/common/http/status.h @@ -79,6 +79,11 @@ enum class StatusCode : int { * Indicates that Envoy is overloaded and may shed load. */ EnvoyOverloadError = 6, + + /** + * Indicates the connection was gracefully closed due to GOAWAY. + */ + GoAwayGracefulClose = 7, }; using Status = absl::Status; @@ -100,6 +105,7 @@ Status prematureResponseError(absl::string_view message, Http::Code http_code); Status codecClientError(absl::string_view message); Status inboundFramesWithEmptyPayloadError(); Status envoyOverloadError(absl::string_view message); +Status goAwayGracefulCloseError(); /** * Returns Envoy::StatusCode of the given status object. @@ -116,6 +122,7 @@ ABSL_MUST_USE_RESULT bool isPrematureResponseError(const Status& status); ABSL_MUST_USE_RESULT bool isCodecClientError(const Status& status); ABSL_MUST_USE_RESULT bool isInboundFramesWithEmptyPayloadError(const Status& status); ABSL_MUST_USE_RESULT bool isEnvoyOverloadError(const Status& status); +ABSL_MUST_USE_RESULT bool isGoAwayGracefulCloseError(const Status& status); /** * Returns Http::Code value of the PrematureResponseError status. diff --git a/source/common/runtime/runtime_features.cc b/source/common/runtime/runtime_features.cc index 650205fcc8..085a986b26 100644 --- a/source/common/runtime/runtime_features.cc +++ b/source/common/runtime/runtime_features.cc @@ -55,6 +55,7 @@ RUNTIME_GUARD(envoy_reloadable_features_http1_balsa_disallow_lone_cr_in_chunk_ex // Ignore the automated "remove this flag" issue: we should keep this for 1 year. RUNTIME_GUARD(envoy_reloadable_features_http1_use_balsa_parser); RUNTIME_GUARD(envoy_reloadable_features_http2_discard_host_header); +RUNTIME_GUARD(envoy_reloadable_features_http2_no_protocol_error_upon_clean_close); // Ignore the automated "remove this flag" issue: we should keep this for 1 year. RUNTIME_GUARD(envoy_reloadable_features_http2_use_visitor_for_data); RUNTIME_GUARD(envoy_reloadable_features_http3_happy_eyeballs); diff --git a/test/integration/multiplexed_integration_test.cc b/test/integration/multiplexed_integration_test.cc index ff133982bd..a47d6e7161 100644 --- a/test/integration/multiplexed_integration_test.cc +++ b/test/integration/multiplexed_integration_test.cc @@ -2147,6 +2147,9 @@ TEST_P(Http2FrameIntegrationTest, AdjustUpstreamSettingsMaxStreams) { } TEST_P(Http2FrameIntegrationTest, UpstreamSettingsMaxStreamsAfterGoAway) { + config_helper_.addRuntimeOverride( + "envoy.reloadable_features.http2_no_protocol_error_upon_clean_close", "true"); + beginSession(); FakeRawConnectionPtr fake_upstream_connection; @@ -2170,6 +2173,115 @@ TEST_P(Http2FrameIntegrationTest, UpstreamSettingsMaxStreamsAfterGoAway) { std::string(settings_max_connections_frame)))); test_server_->waitForCounterGe("cluster.cluster_0.upstream_cx_close_notify", 1); + EXPECT_EQ(0, test_server_->counter("cluster.cluster_0.upstream_cx_protocol_error")->value()); + + // Cleanup. + tcp_client_->close(); +} + +TEST_P(Http2FrameIntegrationTest, UpstreamGoAway) { + config_helper_.addRuntimeOverride( + "envoy.reloadable_features.http2_no_protocol_error_upon_clean_close", "true"); + + beginSession(); + FakeRawConnectionPtr fake_upstream_connection; + + const uint32_t client_stream_idx = 1; + // Start a request and wait for it to reach the upstream. + sendFrame(Http2Frame::makePostRequest(client_stream_idx, "host", "/path/to/long/url")); + ASSERT_TRUE(fake_upstreams_[0]->waitForRawConnection(fake_upstream_connection)); + const Http2Frame settings_frame = Http2Frame::makeEmptySettingsFrame(); + ASSERT_TRUE(fake_upstream_connection->write(std::string(settings_frame))); + test_server_->waitForGaugeEq("cluster.cluster_0.upstream_rq_active", 1); + + const Http2Frame rst_stream = + Http2Frame::makeResetStreamFrame(client_stream_idx, Http2Frame::ErrorCode::FlowControlError); + const Http2Frame go_away_frame = + Http2Frame::makeEmptyGoAwayFrame(12345, Http2Frame::ErrorCode::NoError); + ASSERT_TRUE(fake_upstream_connection->write( + absl::StrCat(std::string(rst_stream), std::string(go_away_frame)))); + ASSERT_TRUE(fake_upstream_connection->close()); + + test_server_->waitForCounterGe("cluster.cluster_0.upstream_cx_close_notify", 1); + EXPECT_EQ(0, test_server_->counter("cluster.cluster_0.upstream_cx_protocol_error")->value()); + + // Cleanup. + tcp_client_->close(); +} + +TEST_P(Http2FrameIntegrationTest, UpstreamGoAwayLegacy) { + config_helper_.addRuntimeOverride( + "envoy.reloadable_features.http2_no_protocol_error_upon_clean_close", "false"); + + beginSession(); + FakeRawConnectionPtr fake_upstream_connection; + + const uint32_t client_stream_idx = 1; + // Start a request and wait for it to reach the upstream. + sendFrame(Http2Frame::makePostRequest(client_stream_idx, "host", "/path/to/long/url")); + ASSERT_TRUE(fake_upstreams_[0]->waitForRawConnection(fake_upstream_connection)); + const Http2Frame settings_frame = Http2Frame::makeEmptySettingsFrame(); + ASSERT_TRUE(fake_upstream_connection->write(std::string(settings_frame))); + test_server_->waitForGaugeEq("cluster.cluster_0.upstream_rq_active", 1); + + const Http2Frame rst_stream = + Http2Frame::makeResetStreamFrame(client_stream_idx, Http2Frame::ErrorCode::FlowControlError); + const Http2Frame go_away_frame = + Http2Frame::makeEmptyGoAwayFrame(12345, Http2Frame::ErrorCode::NoError); + ASSERT_TRUE(fake_upstream_connection->write( + absl::StrCat(std::string(rst_stream), std::string(go_away_frame)))); + ASSERT_TRUE(fake_upstream_connection->close()); + + test_server_->waitForCounterGe("cluster.cluster_0.upstream_cx_close_notify", 1); + test_server_->waitForCounterGe("cluster.cluster_0.upstream_cx_protocol_error", 1); + + // Cleanup. + tcp_client_->close(); +} + +// Test that sending an invalid frame results in `upstream_cx_protocol_error`. +TEST_P(Http2FrameIntegrationTest, UpstreamProtocolError) { + config_helper_.addRuntimeOverride( + "envoy.reloadable_features.http2_no_protocol_error_upon_clean_close", "true"); + + beginSession(); + FakeRawConnectionPtr fake_upstream_connection; + + const uint32_t client_stream_idx = 1; + // Start a request and wait for it to reach the upstream. + sendFrame(Http2Frame::makePostRequest(client_stream_idx, "host", "/path/to/long/url")); + ASSERT_TRUE(fake_upstreams_[0]->waitForRawConnection(fake_upstream_connection)); + const Http2Frame settings_frame = Http2Frame::makeEmptySettingsFrame(); + ASSERT_TRUE(fake_upstream_connection->write(std::string(settings_frame))); + test_server_->waitForGaugeEq("cluster.cluster_0.upstream_rq_active", 1); + + ASSERT_TRUE(fake_upstream_connection->write("abcdefg this is not a valid h2 frame")); + + test_server_->waitForCounterGe("cluster.cluster_0.upstream_cx_protocol_error", 1); + + // Cleanup. + tcp_client_->close(); +} + +// Test that sending an invalid frame results in `upstream_cx_protocol_error`. +TEST_P(Http2FrameIntegrationTest, UpstreamProtocolErrorLegacy) { + config_helper_.addRuntimeOverride( + "envoy.reloadable_features.http2_no_protocol_error_upon_clean_close", "false"); + + beginSession(); + FakeRawConnectionPtr fake_upstream_connection; + + const uint32_t client_stream_idx = 1; + // Start a request and wait for it to reach the upstream. + sendFrame(Http2Frame::makePostRequest(client_stream_idx, "host", "/path/to/long/url")); + ASSERT_TRUE(fake_upstreams_[0]->waitForRawConnection(fake_upstream_connection)); + const Http2Frame settings_frame = Http2Frame::makeEmptySettingsFrame(); + ASSERT_TRUE(fake_upstream_connection->write(std::string(settings_frame))); + test_server_->waitForGaugeEq("cluster.cluster_0.upstream_rq_active", 1); + + ASSERT_TRUE(fake_upstream_connection->write("abcdefg this is not a valid h2 frame")); + + test_server_->waitForCounterGe("cluster.cluster_0.upstream_cx_protocol_error", 1); // Cleanup. tcp_client_->close(); From f575d26b90fb8dccbce9aa9ae924b8f20bf09ab6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20R=2E=20Sede=C3=B1o?= Date: Fri, 20 Sep 2024 19:16:09 -0400 Subject: [PATCH 50/65] bump grpc-httpjson-transcoding (#36229) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Updating to a version which is more amenable to future protobuf updates. Risk Level: low Testing: ``` $ bazel test \ //test/extensions/filters/http/grpc_json_transcoder/... \ //test/extensions/filters/http/grpc_field_extraction/... \ //test/extensions/filters/http/proto_message_extraction/... ``` Signed-off-by: Alejandro R SedeƱo --- bazel/repository_locations.bzl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/bazel/repository_locations.bzl b/bazel/repository_locations.bzl index 2405fb248b..6080c1b3c6 100644 --- a/bazel/repository_locations.bzl +++ b/bazel/repository_locations.bzl @@ -948,13 +948,13 @@ REPOSITORY_LOCATIONS_SPEC = dict( project_name = "grpc-httpjson-transcoding", project_desc = "Library that supports transcoding so that HTTP/JSON can be converted to gRPC", project_url = "https://github.com/grpc-ecosystem/grpc-httpjson-transcoding", - version = "20e58e7ef9c3878ae9fc89123b9aba36d6f98a7f", - sha256 = "2f0ea248c59f51e5376f23590a986813b96076531ffe27a805f7a37407a81a87", + version = "8f0d092ecf60470f504f506e2851173a8033a62c", + sha256 = "11f6316192c5fbd967796e46ab2872964cb4f0a2396126c9e7b961295d4768af", strip_prefix = "grpc-httpjson-transcoding-{version}", urls = ["https://github.com/grpc-ecosystem/grpc-httpjson-transcoding/archive/{version}.tar.gz"], use_category = ["dataplane_ext"], extensions = ["envoy.filters.http.grpc_json_transcoder", "envoy.filters.http.grpc_field_extraction", "envoy.filters.http.proto_message_extraction"], - release_date = "2024-08-30", + release_date = "2024-09-19", cpe = "N/A", license = "Apache-2.0", license_url = "https://github.com/grpc-ecosystem/grpc-httpjson-transcoding/blob/{version}/LICENSE", From decbb66be1e3d71fc673553775bb5c1c8f83b784 Mon Sep 17 00:00:00 2001 From: Raven Black Date: Fri, 20 Sep 2024 19:16:59 -0400 Subject: [PATCH 51/65] Refactor cache_filter to expect caches to post cb (#36184) Refactor cache_filter to expect caches to post cb Additional Description: This is a bit of an unintuitive change in that it moves some work from the common class to the plugin, meaning that work will be duplicated. However, there's a good reason for this - if the cache class needs to use a dispatcher to get back onto its own thread, having cache_filter also post means that actions end up being queued in the dispatcher twice. A different possible solution would be to have the cache_filter callbacks only post if the callback comes in on the wrong thread, but there's a wrinkle in that model too - if the callback executes immediately, on the same thread, as was the case with the simple_http_cache, it executes too soon, trying to resume a connection that hasn't yet stopped, which is an error. That, too, could be covered with *another* workaround, either intercepting when that happens and posting the resume, or intercepting when that happens and replacing the resume with returning `Continue` instead, but both of those options make the cache filter itself more complicated (and therefore error prone). Having just one consistent path, where the cache implementation always posts the callback (and never calls it if cancelled), and the cache always performs the callback outside of the initial call's context and on its own thread, is the least complexity, and avoids the performance impact of posting twice, at a cost of a bit more verbosity in the simple cache implementation. This PR also wraps the UpdateHeadersCallback into a declared type, and makes it an `AnyInvocable` instead of a `std::function`, which enforces that callbacks are called only once and that they're moved not copied, avoiding accidental performance drains. Risk Level: Low; WIP filter, existing tests still pass. Testing: Existing tests should be covering all cases. Added tests to enforce that all cache implementations' `LookupContext` correctly posts callback actions, and correctly cancels calling the callback if the context is deleted before the post resolves. Docs Changes: Code-comments only. Release Notes: Maybe? Platform Specific Features: n/a --------- Signed-off-by: Raven Black --- .../filters/http/cache/cache_filter.cc | 69 ++----- .../filters/http/cache/cache_filter.h | 2 + .../filters/http/cache/cache_insert_queue.cc | 114 +++++------ .../filters/http/cache/cache_insert_queue.h | 2 +- .../filters/http/cache/http_cache.h | 40 ++-- .../file_system_http_cache.cc | 17 +- .../file_system_http_cache.h | 3 +- .../file_system_http_cache/insert_context.cc | 11 +- .../file_system_http_cache/insert_context.h | 1 - .../file_system_http_cache/lookup_context.cc | 4 +- .../simple_http_cache/simple_http_cache.cc | 98 ++++++--- .../simple_http_cache/simple_http_cache.h | 3 +- .../filters/http/cache/cache_filter_test.cc | 189 +++++++++++++----- .../http_cache_implementation_test_common.cc | 56 ++++++ .../http_cache_implementation_test_common.h | 3 + test/extensions/filters/http/cache/mocks.h | 2 +- 16 files changed, 382 insertions(+), 232 deletions(-) diff --git a/source/extensions/filters/http/cache/cache_filter.cc b/source/extensions/filters/http/cache/cache_filter.cc index 2e9c073a66..88aed69f9f 100644 --- a/source/extensions/filters/http/cache/cache_filter.cc +++ b/source/extensions/filters/http/cache/cache_filter.cc @@ -303,38 +303,19 @@ CacheFilter::resolveLookupStatus(absl::optional cache_entry_st void CacheFilter::getHeaders(Http::RequestHeaderMap& request_headers) { ASSERT(lookup_, "CacheFilter is trying to call getHeaders with no LookupContext"); - - // If the cache posts a callback to the dispatcher then the CacheFilter is destroyed for any - // reason (e.g client disconnected and HTTP stream terminated), then there is no guarantee that - // the posted callback will run before the filter is deleted. Hence, a weak_ptr to the CacheFilter - // is captured and used to make sure the CacheFilter is still alive before accessing it in the - // posted callback. - // TODO(yosrym93): Look into other options for handling this (also in getBody and getTrailers) as - // they arise, e.g. cancellable posts, guaranteed ordering of posted callbacks and deletions, etc. - CacheFilterWeakPtr self = weak_from_this(); - - // The dispatcher needs to be captured because there's no guarantee that - // decoder_callbacks_->dispatcher() is thread-safe. - lookup_->getHeaders([self, &request_headers, &dispatcher = decoder_callbacks_->dispatcher()]( + callback_called_directly_ = true; + lookup_->getHeaders([this, &request_headers, &dispatcher = decoder_callbacks_->dispatcher()]( LookupResult&& result, bool end_stream) { - // The callback is posted to the dispatcher to make sure it is called on the worker thread. - dispatcher.post([self, &request_headers, result = std::move(result), end_stream]() mutable { - if (CacheFilterSharedPtr cache_filter = self.lock()) { - cache_filter->onHeaders(std::move(result), request_headers, end_stream); - } - }); + ASSERT(!callback_called_directly_ && dispatcher.isThreadSafe(), + "caches must post the callback to the filter's dispatcher"); + onHeaders(std::move(result), request_headers, end_stream); }); + callback_called_directly_ = false; } void CacheFilter::getBody() { ASSERT(lookup_, "CacheFilter is trying to call getBody with no LookupContext"); ASSERT(!remaining_ranges_.empty(), "No reason to call getBody when there's no body to get."); - // If the cache posts a callback to the dispatcher then the CacheFilter is destroyed for any - // reason (e.g client disconnected and HTTP stream terminated), then there is no guarantee that - // the posted callback will run before the filter is deleted. Hence, a weak_ptr to the CacheFilter - // is captured and used to make sure the CacheFilter is still alive before accessing it in the - // posted callback. - CacheFilterWeakPtr self = weak_from_this(); // We don't want to request more than a buffer-size at a time from the cache. uint64_t fetch_size_limit = encoder_callbacks_->encoderBufferLimit(); @@ -347,41 +328,27 @@ void CacheFilter::getBody() { ? (remaining_ranges_[0].begin() + fetch_size_limit) : remaining_ranges_[0].end()}; - // The dispatcher needs to be captured because there's no guarantee that - // decoder_callbacks_->dispatcher() is thread-safe. - lookup_->getBody(fetch_range, [self, &dispatcher = decoder_callbacks_->dispatcher()]( + callback_called_directly_ = true; + lookup_->getBody(fetch_range, [this, &dispatcher = decoder_callbacks_->dispatcher()]( Buffer::InstancePtr&& body, bool end_stream) { - // The callback is posted to the dispatcher to make sure it is called on the worker thread. - dispatcher.post([self, body = std::move(body), end_stream]() mutable { - if (CacheFilterSharedPtr cache_filter = self.lock()) { - cache_filter->onBody(std::move(body), end_stream); - } - }); + ASSERT(!callback_called_directly_ && dispatcher.isThreadSafe(), + "caches must post the callback to the filter's dispatcher"); + onBody(std::move(body), end_stream); }); + callback_called_directly_ = false; } void CacheFilter::getTrailers() { ASSERT(lookup_, "CacheFilter is trying to call getTrailers with no LookupContext"); - // If the cache posts a callback to the dispatcher then the CacheFilter is destroyed for any - // reason (e.g client disconnected and HTTP stream terminated), then there is no guarantee that - // the posted callback will run before the filter is deleted. Hence, a weak_ptr to the CacheFilter - // is captured and used to make sure the CacheFilter is still alive before accessing it in the - // posted callback. - CacheFilterWeakPtr self = weak_from_this(); - - // The dispatcher needs to be captured because there's no guarantee that - // decoder_callbacks_->dispatcher() is thread-safe. - lookup_->getTrailers([self, &dispatcher = decoder_callbacks_->dispatcher()]( + callback_called_directly_ = true; + lookup_->getTrailers([this, &dispatcher = decoder_callbacks_->dispatcher()]( Http::ResponseTrailerMapPtr&& trailers) { - // The callback is posted to the dispatcher to make sure it is called on the worker thread. - // The lambda must be mutable as it captures trailers as a unique_ptr. - dispatcher.post([self, trailers = std::move(trailers)]() mutable { - if (CacheFilterSharedPtr cache_filter = self.lock()) { - cache_filter->onTrailers(std::move(trailers)); - } - }); + ASSERT(!callback_called_directly_ && dispatcher.isThreadSafe(), + "caches must post the callback to the filter's dispatcher"); + onTrailers(std::move(trailers)); }); + callback_called_directly_ = false; } void CacheFilter::onHeaders(LookupResult&& result, Http::RequestHeaderMap& request_headers, diff --git a/source/extensions/filters/http/cache/cache_filter.h b/source/extensions/filters/http/cache/cache_filter.h index 3641797b5c..923a1cf197 100644 --- a/source/extensions/filters/http/cache/cache_filter.h +++ b/source/extensions/filters/http/cache/cache_filter.h @@ -164,6 +164,8 @@ class CacheFilter : public Http::PassThroughFilter, FilterState filter_state_ = FilterState::Initial; bool is_head_request_ = false; + // This toggle is used to detect callbacks being called directly and not posted. + bool callback_called_directly_ = false; // The status of the insert operation or header update, or decision not to insert or update. // If it's too early to determine the final status, this is empty. absl::optional insert_status_; diff --git a/source/extensions/filters/http/cache/cache_insert_queue.cc b/source/extensions/filters/http/cache/cache_insert_queue.cc index 66cb9d41ea..80de4b6128 100644 --- a/source/extensions/filters/http/cache/cache_insert_queue.cc +++ b/source/extensions/filters/http/cache/cache_insert_queue.cc @@ -14,7 +14,7 @@ class CacheInsertFragment { // on_complete is called when the cache completes the operation. virtual void send(InsertContext& context, - std::function on_complete) PURE; + absl::AnyInvocable on_complete) PURE; virtual ~CacheInsertFragment() = default; }; @@ -27,14 +27,14 @@ class CacheInsertFragmentBody : public CacheInsertFragment { CacheInsertFragmentBody(const Buffer::Instance& buffer, bool end_stream) : buffer_(buffer), end_stream_(end_stream) {} - void - send(InsertContext& context, - std::function on_complete) override { + void send(InsertContext& context, + absl::AnyInvocable on_complete) + override { size_t sz = buffer_.length(); context.insertBody( std::move(buffer_), - [on_complete, end_stream = end_stream_, sz](bool cache_success) { - on_complete(cache_success, end_stream, sz); + [cb = std::move(on_complete), end_stream = end_stream_, sz](bool cache_success) mutable { + std::move(cb)(cache_success, end_stream, sz); }, end_stream_); } @@ -52,14 +52,15 @@ class CacheInsertFragmentTrailers : public CacheInsertFragment { Http::ResponseTrailerMapImpl::copyFrom(*trailers_, trailers); } - void - send(InsertContext& context, - std::function on_complete) override { + void send(InsertContext& context, + absl::AnyInvocable on_complete) + override { // While zero isn't technically true for the size of trailers, it doesn't // matter at this point because watermarks after the stream is complete // aren't useful. - context.insertTrailers( - *trailers_, [on_complete](bool cache_success) { on_complete(cache_success, true, 0); }); + context.insertTrailers(*trailers_, [cb = std::move(on_complete)](bool cache_success) mutable { + std::move(cb)(cache_success, true, 0); + }); } private: @@ -72,7 +73,7 @@ CacheInsertQueue::CacheInsertQueue(std::shared_ptr cache, : dispatcher_(encoder_callbacks.dispatcher()), insert_context_(std::move(insert_context)), low_watermark_bytes_(encoder_callbacks.encoderBufferLimit() / 2), high_watermark_bytes_(encoder_callbacks.encoderBufferLimit()), - encoder_callbacks_(encoder_callbacks), abort_callback_(abort), cache_(cache) {} + encoder_callbacks_(encoder_callbacks), abort_callback_(std::move(abort)), cache_(cache) {} void CacheInsertQueue::insertHeaders(const Http::ResponseHeaderMap& response_headers, const ResponseMetadata& metadata, bool end_stream) { @@ -123,59 +124,54 @@ void CacheInsertQueue::insertTrailers(const Http::ResponseTrailerMap& trailers) } void CacheInsertQueue::onFragmentComplete(bool cache_success, bool end_stream, size_t sz) { - // If the cache implementation is asynchronous, this may be called from whatever - // thread that cache implementation runs on. Therefore, we post it to the - // dispatcher to be certain any callbacks and updates are called on the filter's - // thread (and therefore we don't have to mutex-guard anything). - dispatcher_.post([this, cache_success, end_stream, sz]() { - fragment_in_flight_ = false; - if (aborting_) { - // Parent filter was destroyed, so we can quit this operation. - fragments_.clear(); - self_ownership_.reset(); - return; + ASSERT(dispatcher_.isThreadSafe()); + fragment_in_flight_ = false; + if (aborting_) { + // Parent filter was destroyed, so we can quit this operation. + fragments_.clear(); + self_ownership_.reset(); + return; + } + ASSERT(queue_size_bytes_ >= sz, "queue can't be emptied by more than its size"); + queue_size_bytes_ -= sz; + if (watermarked_ && queue_size_bytes_ <= low_watermark_bytes_) { + if (encoder_callbacks_.has_value()) { + encoder_callbacks_.value().get().onEncoderFilterBelowWriteBufferLowWatermark(); } - ASSERT(queue_size_bytes_ >= sz, "queue can't be emptied by more than its size"); - queue_size_bytes_ -= sz; - if (watermarked_ && queue_size_bytes_ <= low_watermark_bytes_) { + watermarked_ = false; + } + if (!cache_success) { + // canceled by cache; unwatermark if necessary, inform the filter if + // it's still around, and delete the queue. + if (watermarked_) { if (encoder_callbacks_.has_value()) { encoder_callbacks_.value().get().onEncoderFilterBelowWriteBufferLowWatermark(); } watermarked_ = false; } - if (!cache_success) { - // canceled by cache; unwatermark if necessary, inform the filter if - // it's still around, and delete the queue. - if (watermarked_) { - if (encoder_callbacks_.has_value()) { - encoder_callbacks_.value().get().onEncoderFilterBelowWriteBufferLowWatermark(); - } - watermarked_ = false; - } - fragments_.clear(); - // Clearing self-ownership might provoke the destructor, so take a copy of the - // abort callback to avoid reading from 'this' after it may be deleted. - auto abort_callback = abort_callback_; - self_ownership_.reset(); - abort_callback(); - return; - } - if (end_stream) { - ASSERT(fragments_.empty(), "ending a stream with the queue not empty is a bug"); - ASSERT(!watermarked_, "being over the high watermark when the queue is empty makes no sense"); - self_ownership_.reset(); - return; - } - if (!fragments_.empty()) { - // If there's more in the queue, push the next fragment to the cache. - auto fragment = std::move(fragments_.front()); - fragments_.pop_front(); - fragment_in_flight_ = true; - fragment->send(*insert_context_, [this](bool cache_success, bool end_stream, size_t sz) { - onFragmentComplete(cache_success, end_stream, sz); - }); - } - }); + fragments_.clear(); + // Clearing self-ownership might provoke the destructor, so take a copy of the + // abort callback to avoid reading from 'this' after it may be deleted. + auto abort_callback = std::move(abort_callback_); + self_ownership_.reset(); + std::move(abort_callback)(); + return; + } + if (end_stream) { + ASSERT(fragments_.empty(), "ending a stream with the queue not empty is a bug"); + ASSERT(!watermarked_, "being over the high watermark when the queue is empty makes no sense"); + self_ownership_.reset(); + return; + } + if (!fragments_.empty()) { + // If there's more in the queue, push the next fragment to the cache. + auto fragment = std::move(fragments_.front()); + fragments_.pop_front(); + fragment_in_flight_ = true; + fragment->send(*insert_context_, [this](bool cache_success, bool end_stream, size_t sz) { + onFragmentComplete(cache_success, end_stream, sz); + }); + } } void CacheInsertQueue::setSelfOwned(std::unique_ptr self) { diff --git a/source/extensions/filters/http/cache/cache_insert_queue.h b/source/extensions/filters/http/cache/cache_insert_queue.h index feae50414a..22297a70a5 100644 --- a/source/extensions/filters/http/cache/cache_insert_queue.h +++ b/source/extensions/filters/http/cache/cache_insert_queue.h @@ -12,7 +12,7 @@ namespace Cache { using OverHighWatermarkCallback = std::function; using UnderLowWatermarkCallback = std::function; -using AbortInsertCallback = std::function; +using AbortInsertCallback = absl::AnyInvocable; class CacheInsertFragment; // This queue acts as an intermediary between CacheFilter and the cache diff --git a/source/extensions/filters/http/cache/http_cache.h b/source/extensions/filters/http/cache/http_cache.h index 59face7598..e01fbf7d16 100644 --- a/source/extensions/filters/http/cache/http_cache.h +++ b/source/extensions/filters/http/cache/http_cache.h @@ -122,19 +122,20 @@ struct CacheInfo { bool supports_range_requests_ = false; }; -using LookupBodyCallback = std::function; -using LookupHeadersCallback = std::function; -using LookupTrailersCallback = std::function; -using InsertCallback = std::function; +using LookupBodyCallback = absl::AnyInvocable; +using LookupHeadersCallback = absl::AnyInvocable; +using LookupTrailersCallback = absl::AnyInvocable; +using InsertCallback = absl::AnyInvocable; +using UpdateHeadersCallback = absl::AnyInvocable; // Manages the lifetime of an insertion. class InsertContext { public: // Accepts response_headers for caching. Only called once. // - // Implementations MUST call insert_complete(true) on success, or - // insert_complete(false) to attempt to abort the insertion. This - // call may be made asynchronously, but any async operation that can + // Implementations MUST post to the filter's dispatcher insert_complete(true) + // on success, or insert_complete(false) to attempt to abort the insertion. + // This call may be made asynchronously, but any async operation that can // potentially silently fail must include a timeout, to avoid memory leaks. virtual void insertHeaders(const Http::ResponseHeaderMap& response_headers, const ResponseMetadata& metadata, InsertCallback insert_complete, @@ -149,17 +150,17 @@ class InsertContext { // InsertContextPtr. A cache can abort the insertion by passing 'false' into // ready_for_next_fragment. // - // The cache implementation MUST call ready_for_next_fragment. This call may be - // made asynchronously, but any async operation that can potentially silently - // fail must include a timeout, to avoid memory leaks. + // The cache implementation MUST post ready_for_next_fragment to the filter's + // dispatcher. This post may be made asynchronously, but any async operation + // that can potentially silently fail must include a timeout, to avoid memory leaks. virtual void insertBody(const Buffer::Instance& fragment, InsertCallback ready_for_next_fragment, bool end_stream) PURE; // Inserts trailers into the cache. // - // The cache implementation MUST call insert_complete. This call may be - // made asynchronously, but any async operation that can potentially silently - // fail must include a timeout, to avoid memory leaks. + // The cache implementation MUST post insert_complete to the filter's dispatcher. + // This call may be made asynchronously, but any async operation that can + // potentially silently fail must include a timeout, to avoid memory leaks. virtual void insertTrailers(const Http::ResponseTrailerMap& trailers, InsertCallback insert_complete) PURE; @@ -199,6 +200,9 @@ class LookupContext { // implementation should wait until that is known before calling the callback, // and must pass a LookupResult with range_details_->satisfiable_ = false // if the request is invalid. + // + // A cache that posts the callback must wrap it such that if the LookupContext is + // destroyed before the callback is executed, the callback is not executed. virtual void getHeaders(LookupHeadersCallback&& cb) PURE; // Reads the next fragment from the cache, calling cb when the fragment is ready. @@ -228,11 +232,17 @@ class LookupContext { // getBody requests bytes 0-23 .......... callback with bytes 0-9 // getBody requests bytes 10-23 .......... callback with bytes 10-19 // getBody requests bytes 20-23 .......... callback with bytes 20-23 + // + // A cache that posts the callback must wrap it such that if the LookupContext is + // destroyed before the callback is executed, the callback is not executed. virtual void getBody(const AdjustedByteRange& range, LookupBodyCallback&& cb) PURE; // Get the trailers from the cache. Only called if the request reached the end of // the body and LookupBodyCallback did not pass true for end_stream. The // Http::ResponseTrailerMapPtr passed to cb must not be null. + // + // A cache that posts the callback must wrap it such that if the LookupContext is + // destroyed before the callback is executed, the callback is not executed. virtual void getTrailers(LookupTrailersCallback&& cb) PURE; // This routine is called prior to a LookupContext being destroyed. LookupContext is responsible @@ -248,7 +258,7 @@ class LookupContext { // 5. [Other thread] RPC completes and calls RPCLookupContext::onRPCDone. // --> RPCLookupContext's destructor and onRpcDone cause a data race in RPCLookupContext. // onDestroy() should cancel any outstanding async operations and, if necessary, - // it should block on that cancellation to avoid data races. InsertContext must not invoke any + // it should block on that cancellation to avoid data races. LookupContext must not invoke any // callbacks to the CacheFilter after having onDestroy() invoked. virtual void onDestroy() PURE; @@ -289,7 +299,7 @@ class HttpCache { virtual void updateHeaders(const LookupContext& lookup_context, const Http::ResponseHeaderMap& response_headers, const ResponseMetadata& metadata, - std::function on_complete) PURE; + UpdateHeadersCallback on_complete) PURE; // Returns statically known information about a cache. virtual CacheInfo cacheInfo() const PURE; diff --git a/source/extensions/http/cache/file_system_http_cache/file_system_http_cache.cc b/source/extensions/http/cache/file_system_http_cache/file_system_http_cache.cc index 1e5a49c6c6..5e220e2b45 100644 --- a/source/extensions/http/cache/file_system_http_cache/file_system_http_cache.cc +++ b/source/extensions/http/cache/file_system_http_cache/file_system_http_cache.cc @@ -127,13 +127,13 @@ class HeaderUpdateContext : public Logger::Loggable { HeaderUpdateContext(Event::Dispatcher& dispatcher, const FileSystemHttpCache& cache, const Key& key, std::shared_ptr cleanup, const Http::ResponseHeaderMap& response_headers, - const ResponseMetadata& metadata, std::function on_complete) + const ResponseMetadata& metadata, UpdateHeadersCallback on_complete) : dispatcher_(dispatcher), filepath_(absl::StrCat(cache.cachePath(), cache.generateFilename(key))), cache_path_(cache.cachePath()), cleanup_(cleanup), async_file_manager_(cache.asyncFileManager()), response_headers_(Http::createHeaderMap(response_headers)), - response_metadata_(metadata), on_complete_(on_complete) {} + response_metadata_(metadata), on_complete_(std::move(on_complete)) {} void begin(std::shared_ptr ctx) { async_file_manager_->openExistingFile( @@ -278,14 +278,14 @@ class HeaderUpdateContext : public Logger::Loggable { fail("failed to link new cache file", link_result); return; } - on_complete_(true); + std::move(on_complete_)(true); }); ASSERT(queued.ok()); } void fail(absl::string_view msg, absl::Status status) { ENVOY_LOG(warn, "file_system_http_cache: {} for update cache file {}: {}", msg, filepath_, status); - on_complete_(false); + std::move(on_complete_)(false); } Event::Dispatcher* dispatcher() { return &dispatcher_; } Event::Dispatcher& dispatcher_; @@ -300,13 +300,13 @@ class HeaderUpdateContext : public Logger::Loggable { CacheFileHeader header_proto_; AsyncFileHandle read_handle_; AsyncFileHandle write_handle_; - std::function on_complete_; + UpdateHeadersCallback on_complete_; }; void FileSystemHttpCache::updateHeaders(const LookupContext& base_lookup_context, const Http::ResponseHeaderMap& response_headers, const ResponseMetadata& metadata, - std::function on_complete) { + UpdateHeadersCallback on_complete) { const FileLookupContext& lookup_context = dynamic_cast(base_lookup_context); const Key& key = lookup_context.key(); @@ -314,8 +314,9 @@ void FileSystemHttpCache::updateHeaders(const LookupContext& base_lookup_context if (!cleanup) { return; } - auto ctx = std::make_shared( - *lookup_context.dispatcher(), *this, key, cleanup, response_headers, metadata, on_complete); + auto ctx = + std::make_shared(*lookup_context.dispatcher(), *this, key, cleanup, + response_headers, metadata, std::move(on_complete)); ctx->begin(ctx); } diff --git a/source/extensions/http/cache/file_system_http_cache/file_system_http_cache.h b/source/extensions/http/cache/file_system_http_cache/file_system_http_cache.h index 9e81bf0410..be4c594024 100644 --- a/source/extensions/http/cache/file_system_http_cache/file_system_http_cache.h +++ b/source/extensions/http/cache/file_system_http_cache/file_system_http_cache.h @@ -79,8 +79,7 @@ class FileSystemHttpCache : public HttpCache, */ void updateHeaders(const LookupContext& lookup_context, const Http::ResponseHeaderMap& response_headers, - const ResponseMetadata& metadata, - std::function on_complete) override; + const ResponseMetadata& metadata, UpdateHeadersCallback on_complete) override; /** * The config of this cache. Used by the factory to ensure there aren't incompatible diff --git a/source/extensions/http/cache/file_system_http_cache/insert_context.cc b/source/extensions/http/cache/file_system_http_cache/insert_context.cc index 98e0565773..55503ef6dd 100644 --- a/source/extensions/http/cache/file_system_http_cache/insert_context.cc +++ b/source/extensions/http/cache/file_system_http_cache/insert_context.cc @@ -32,7 +32,7 @@ void FileInsertContext::insertHeaders(const Http::ResponseHeaderMap& response_he const ResponseMetadata& metadata, InsertCallback insert_complete, bool end_stream) { ASSERT(dispatcher()->isThreadSafe()); - callback_in_flight_ = insert_complete; + callback_in_flight_ = std::move(insert_complete); const VaryAllowList& vary_allow_list = lookup_context_->lookup().varyAllowList(); const Http::RequestHeaderMap& request_headers = lookup_context_->lookup().requestHeaders(); if (VaryHeaderUtils::hasVary(response_headers)) { @@ -59,7 +59,6 @@ void FileInsertContext::insertHeaders(const Http::ResponseHeaderMap& response_he } cache_file_header_proto_ = makeCacheFileHeaderProto(key_, response_headers, metadata); end_stream_after_headers_ = end_stream; - on_insert_complete_ = std::move(insert_complete); createFile(); } @@ -140,10 +139,10 @@ void FileInsertContext::insertBody(const Buffer::Instance& fragment, ASSERT(!callback_in_flight_); if (!cleanup_) { // Already cancelled, do nothing, return failure. - ready_for_next_fragment(false); + std::move(ready_for_next_fragment)(false); return; } - callback_in_flight_ = ready_for_next_fragment; + callback_in_flight_ = std::move(ready_for_next_fragment); size_t sz = fragment.length(); Buffer::OwnedImpl consumable_fragment(fragment); auto queued = file_handle_->write( @@ -172,10 +171,10 @@ void FileInsertContext::insertTrailers(const Http::ResponseTrailerMap& trailers, ASSERT(!callback_in_flight_); if (!cleanup_) { // Already cancelled, do nothing, return failure. - insert_complete(false); + std::move(insert_complete)(false); return; } - callback_in_flight_ = insert_complete; + callback_in_flight_ = std::move(insert_complete); CacheFileTrailer file_trailer = makeCacheFileTrailerProto(trailers); Buffer::OwnedImpl consumable_buffer = bufferFromProto(file_trailer); size_t sz = consumable_buffer.length(); diff --git a/source/extensions/http/cache/file_system_http_cache/insert_context.h b/source/extensions/http/cache/file_system_http_cache/insert_context.h index 1f8e666533..a70fbbae1d 100644 --- a/source/extensions/http/cache/file_system_http_cache/insert_context.h +++ b/source/extensions/http/cache/file_system_http_cache/insert_context.h @@ -88,7 +88,6 @@ class FileInsertContext : public InsertContext, public Logger::Loggable lookup_context_; Key key_; std::shared_ptr cache_; diff --git a/source/extensions/http/cache/file_system_http_cache/lookup_context.cc b/source/extensions/http/cache/file_system_http_cache/lookup_context.cc index a58b13a441..9f3d7e028f 100644 --- a/source/extensions/http/cache/file_system_http_cache/lookup_context.cc +++ b/source/extensions/http/cache/file_system_http_cache/lookup_context.cc @@ -140,7 +140,7 @@ void FileLookupContext::getBody(const AdjustedByteRange& range, LookupBodyCallba ASSERT(file_handle_); auto queued = file_handle_->read( dispatcher(), header_block_.offsetToBody() + range.begin(), range.length(), - [this, cb = std::move(cb), range](absl::StatusOr read_result) { + [this, cb = std::move(cb), range](absl::StatusOr read_result) mutable { ASSERT(dispatcher()->isThreadSafe()); cancel_action_in_flight_ = nullptr; if (!read_result.ok() || read_result.value()->length() != range.length()) { @@ -164,7 +164,7 @@ void FileLookupContext::getTrailers(LookupTrailersCallback&& cb) { ASSERT(file_handle_); auto queued = file_handle_->read( dispatcher(), header_block_.offsetToTrailers(), header_block_.trailerSize(), - [this, cb = std::move(cb)](absl::StatusOr read_result) { + [this, cb = std::move(cb)](absl::StatusOr read_result) mutable { ASSERT(dispatcher()->isThreadSafe()); cancel_action_in_flight_ = nullptr; if (!read_result.ok() || read_result.value()->length() != header_block_.trailerSize()) { diff --git a/source/extensions/http/cache/simple_http_cache/simple_http_cache.cc b/source/extensions/http/cache/simple_http_cache/simple_http_cache.cc index a2be23281c..04c70bba9d 100644 --- a/source/extensions/http/cache/simple_http_cache/simple_http_cache.cc +++ b/source/extensions/http/cache/simple_http_cache/simple_http_cache.cc @@ -33,35 +33,57 @@ absl::optional variedRequestKey(const LookupRequest& request, class SimpleLookupContext : public LookupContext { public: - SimpleLookupContext(SimpleHttpCache& cache, LookupRequest&& request) - : cache_(cache), request_(std::move(request)) {} + SimpleLookupContext(Event::Dispatcher& dispatcher, SimpleHttpCache& cache, + LookupRequest&& request) + : dispatcher_(dispatcher), cache_(cache), request_(std::move(request)) {} void getHeaders(LookupHeadersCallback&& cb) override { auto entry = cache_.lookup(request_); body_ = std::move(entry.body_); trailers_ = std::move(entry.trailers_); - cb(entry.response_headers_ ? request_.makeLookupResult(std::move(entry.response_headers_), - std::move(entry.metadata_), body_.size()) - : LookupResult{}, - body_.empty() && trailers_ == nullptr); + LookupResult result = entry.response_headers_ + ? request_.makeLookupResult(std::move(entry.response_headers_), + std::move(entry.metadata_), body_.size()) + : LookupResult{}; + bool end_stream = body_.empty() && trailers_ == nullptr; + dispatcher_.post([result = std::move(result), cb = std::move(cb), end_stream, + cancelled = cancelled_]() mutable { + if (!*cancelled) { + std::move(cb)(std::move(result), end_stream); + } + }); } void getBody(const AdjustedByteRange& range, LookupBodyCallback&& cb) override { ASSERT(range.end() <= body_.length(), "Attempt to read past end of body."); - cb(std::make_unique(&body_[range.begin()], range.length()), - trailers_ == nullptr && range.end() == body_.length()); + auto result = std::make_unique(&body_[range.begin()], range.length()); + bool end_stream = trailers_ == nullptr && range.end() == body_.length(); + dispatcher_.post([result = std::move(result), cb = std::move(cb), end_stream, + cancelled = cancelled_]() mutable { + if (!*cancelled) { + std::move(cb)(std::move(result), end_stream); + } + }); } // The cache must call cb with the cached trailers. void getTrailers(LookupTrailersCallback&& cb) override { ASSERT(trailers_); - cb(std::move(trailers_)); + dispatcher_.post( + [cb = std::move(cb), trailers = std::move(trailers_), cancelled = cancelled_]() mutable { + if (!*cancelled) { + std::move(cb)(std::move(trailers)); + } + }); } const LookupRequest& request() const { return request_; } - void onDestroy() override {} + void onDestroy() override { *cancelled_ = true; } + Event::Dispatcher& dispatcher() const { return dispatcher_; } private: + Event::Dispatcher& dispatcher_; + std::shared_ptr cancelled_ = std::make_shared(false); SimpleHttpCache& cache_; const LookupRequest request_; std::string body_; @@ -70,13 +92,18 @@ class SimpleLookupContext : public LookupContext { class SimpleInsertContext : public InsertContext { public: - SimpleInsertContext(LookupContext& lookup_context, SimpleHttpCache& cache) - : key_(dynamic_cast(lookup_context).request().key()), - request_headers_( - dynamic_cast(lookup_context).request().requestHeaders()), - vary_allow_list_( - dynamic_cast(lookup_context).request().varyAllowList()), - cache_(cache) {} + SimpleInsertContext(SimpleLookupContext& lookup_context, SimpleHttpCache& cache) + : dispatcher_(lookup_context.dispatcher()), key_(lookup_context.request().key()), + request_headers_(lookup_context.request().requestHeaders()), + vary_allow_list_(lookup_context.request().varyAllowList()), cache_(cache) {} + + void post(InsertCallback cb, bool result) { + dispatcher_.post([cb = std::move(cb), result = result, cancelled = cancelled_]() mutable { + if (!*cancelled) { + std::move(cb)(result); + } + }); + } void insertHeaders(const Http::ResponseHeaderMap& response_headers, const ResponseMetadata& metadata, InsertCallback insert_success, @@ -85,9 +112,9 @@ class SimpleInsertContext : public InsertContext { response_headers_ = Http::createHeaderMap(response_headers); metadata_ = metadata; if (end_stream) { - insert_success(commit()); + post(std::move(insert_success), commit()); } else { - insert_success(true); + post(std::move(insert_success), true); } } @@ -98,9 +125,9 @@ class SimpleInsertContext : public InsertContext { body_.add(chunk); if (end_stream) { - ready_for_next_chunk(commit()); + post(std::move(ready_for_next_chunk), commit()); } else { - ready_for_next_chunk(true); + post(std::move(ready_for_next_chunk), true); } } @@ -108,10 +135,10 @@ class SimpleInsertContext : public InsertContext { InsertCallback insert_complete) override { ASSERT(!committed_); trailers_ = Http::createHeaderMap(trailers); - insert_complete(commit()); + post(std::move(insert_complete), commit()); } - void onDestroy() override {} + void onDestroy() override { *cancelled_ = true; } private: bool commit() { @@ -126,6 +153,8 @@ class SimpleInsertContext : public InsertContext { } } + Event::Dispatcher& dispatcher_; + std::shared_ptr cancelled_ = std::make_shared(false); Key key_; const Http::RequestHeaderMap& request_headers_; const VaryAllowList& vary_allow_list_; @@ -139,32 +168,38 @@ class SimpleInsertContext : public InsertContext { } // namespace LookupContextPtr SimpleHttpCache::makeLookupContext(LookupRequest&& request, - Http::StreamDecoderFilterCallbacks&) { - return std::make_unique(*this, std::move(request)); + Http::StreamDecoderFilterCallbacks& callbacks) { + return std::make_unique(callbacks.dispatcher(), *this, std::move(request)); } void SimpleHttpCache::updateHeaders(const LookupContext& lookup_context, const Http::ResponseHeaderMap& response_headers, const ResponseMetadata& metadata, - std::function on_complete) { + UpdateHeadersCallback on_complete) { const auto& simple_lookup_context = static_cast(lookup_context); const Key& key = simple_lookup_context.request().key(); absl::WriterMutexLock lock(&mutex_); auto iter = map_.find(key); + auto post_complete = [on_complete = std::move(on_complete), + &dispatcher = simple_lookup_context.dispatcher()](bool result) mutable { + dispatcher.post([on_complete = std::move(on_complete), result]() mutable { + std::move(on_complete)(result); + }); + }; if (iter == map_.end() || !iter->second.response_headers_) { - on_complete(false); + std::move(post_complete)(false); return; } if (VaryHeaderUtils::hasVary(*iter->second.response_headers_)) { absl::optional varied_key = variedRequestKey(simple_lookup_context.request(), *iter->second.response_headers_); if (!varied_key.has_value()) { - on_complete(false); + std::move(post_complete)(false); return; } iter = map_.find(varied_key.value()); if (iter == map_.end() || !iter->second.response_headers_) { - on_complete(false); + std::move(post_complete)(false); return; } } @@ -172,7 +207,7 @@ void SimpleHttpCache::updateHeaders(const LookupContext& lookup_context, applyHeaderUpdate(response_headers, *entry.response_headers_); entry.metadata_ = metadata; - on_complete(true); + std::move(post_complete)(true); } SimpleHttpCache::Entry SimpleHttpCache::lookup(const LookupRequest& request) { @@ -278,7 +313,8 @@ bool SimpleHttpCache::varyInsert(const Key& request_key, InsertContextPtr SimpleHttpCache::makeInsertContext(LookupContextPtr&& lookup_context, Http::StreamEncoderFilterCallbacks&) { ASSERT(lookup_context != nullptr); - return std::make_unique(*lookup_context, *this); + return std::make_unique(dynamic_cast(*lookup_context), + *this); } constexpr absl::string_view Name = "envoy.extensions.http.cache.simple"; diff --git a/source/extensions/http/cache/simple_http_cache/simple_http_cache.h b/source/extensions/http/cache/simple_http_cache/simple_http_cache.h index bfad38d9fd..515ccc5f01 100644 --- a/source/extensions/http/cache/simple_http_cache/simple_http_cache.h +++ b/source/extensions/http/cache/simple_http_cache/simple_http_cache.h @@ -40,8 +40,7 @@ class SimpleHttpCache : public HttpCache, public Singleton::Instance { Http::StreamEncoderFilterCallbacks& callbacks) override; void updateHeaders(const LookupContext& lookup_context, const Http::ResponseHeaderMap& response_headers, - const ResponseMetadata& metadata, - std::function on_complete) override; + const ResponseMetadata& metadata, UpdateHeadersCallback on_complete) override; CacheInfo cacheInfo() const override; Entry lookup(const LookupRequest& request); diff --git a/test/extensions/filters/http/cache/cache_filter_test.cc b/test/extensions/filters/http/cache/cache_filter_test.cc index 27bd88716b..14edc705c3 100644 --- a/test/extensions/filters/http/cache/cache_filter_test.cc +++ b/test/extensions/filters/http/cache/cache_filter_test.cc @@ -291,6 +291,40 @@ TEST_F(CacheFilterTest, CacheMissWithTrailers) { dispatcher_->run(Event::Dispatcher::RunType::Block); } +TEST_F(CacheFilterTest, CacheMissWithTrailersWhenCacheRespondsQuickerThanUpstream) { + request_headers_.setHost("CacheMissWithTrailers"); + const std::string body = "abc"; + Buffer::OwnedImpl body_buffer(body); + Http::TestResponseTrailerMapImpl trailers; + + for (int request = 1; request <= 2; request++) { + // Each iteration a request is sent to a different host, therefore the second one is a miss + request_headers_.setHost("CacheMissWithTrailers" + std::to_string(request)); + + // Create filter for request 1 + CacheFilterSharedPtr filter = makeFilter(simple_cache_); + + testDecodeRequestMiss(filter); + + // Encode response header + EXPECT_EQ(filter->encodeHeaders(response_headers_, false), Http::FilterHeadersStatus::Continue); + // Resolve cache response + dispatcher_->run(Event::Dispatcher::RunType::Block); + EXPECT_EQ(filter->encodeData(body_buffer, false), Http::FilterDataStatus::Continue); + // Resolve cache response + dispatcher_->run(Event::Dispatcher::RunType::Block); + EXPECT_EQ(filter->encodeTrailers(trailers), Http::FilterTrailersStatus::Continue); + // Resolve cache response + dispatcher_->run(Event::Dispatcher::RunType::Block); + + filter->onStreamComplete(); + EXPECT_THAT(lookupStatus(), IsOkAndHolds(LookupStatus::CacheMiss)); + EXPECT_THAT(insertStatus(), IsOkAndHolds(InsertStatus::InsertSucceeded)); + } + // Clear events off the dispatcher. + dispatcher_->run(Event::Dispatcher::RunType::Block); +} + TEST_F(CacheFilterTest, CacheHitNoBody) { request_headers_.setHost("CacheHitNoBody"); @@ -372,22 +406,25 @@ TEST_F(CacheFilterTest, WatermarkEventsAreSentIfCacheBlocksStreamAndLimitExceede return std::move(mock_insert_context); }); EXPECT_CALL(*mock_lookup_context, getHeaders(_)).WillOnce([&](LookupHeadersCallback&& cb) { - cb(LookupResult{}, false); + dispatcher_->post([cb = std::move(cb)]() mutable { std::move(cb)(LookupResult{}, false); }); }); EXPECT_CALL(*mock_insert_context, insertHeaders(_, _, _, false)) .WillOnce([&](const Http::ResponseHeaderMap&, const ResponseMetadata&, - InsertCallback insert_complete, bool) { insert_complete(true); }); + InsertCallback insert_complete, bool) { + dispatcher_->post([cb = std::move(insert_complete)]() mutable { std::move(cb)(true); }); + }); InsertCallback captured_insert_body_callback; // The first time insertBody is called, block until the test is ready to call it. // For completion chunk, complete immediately. EXPECT_CALL(*mock_insert_context, insertBody(_, _, false)) .WillOnce([&](const Buffer::Instance&, InsertCallback ready_for_next_chunk, bool) { EXPECT_THAT(captured_insert_body_callback, IsNull()); - captured_insert_body_callback = ready_for_next_chunk; + captured_insert_body_callback = std::move(ready_for_next_chunk); }); EXPECT_CALL(*mock_insert_context, insertBody(_, _, true)) .WillOnce([&](const Buffer::Instance&, InsertCallback ready_for_next_chunk, bool) { - ready_for_next_chunk(true); + dispatcher_->post( + [cb = std::move(ready_for_next_chunk)]() mutable { std::move(cb)(true); }); }); EXPECT_CALL(*mock_insert_context, onDestroy()); EXPECT_CALL(*mock_lookup_context, onDestroy()); @@ -444,18 +481,20 @@ TEST_F(CacheFilterTest, FilterDestroyedWhileWatermarkedSendsLowWatermarkEvent) { return std::move(mock_insert_context); }); EXPECT_CALL(*mock_lookup_context, getHeaders(_)).WillOnce([&](LookupHeadersCallback&& cb) { - cb(LookupResult{}, false); + dispatcher_->post([cb = std::move(cb)]() mutable { std::move(cb)(LookupResult{}, false); }); }); EXPECT_CALL(*mock_insert_context, insertHeaders(_, _, _, false)) .WillOnce([&](const Http::ResponseHeaderMap&, const ResponseMetadata&, - InsertCallback insert_complete, bool) { insert_complete(true); }); + InsertCallback insert_complete, bool) { + dispatcher_->post([cb = std::move(insert_complete)]() mutable { std::move(cb)(true); }); + }); InsertCallback captured_insert_body_callback; // The first time insertBody is called, block until the test is ready to call it. // Cache aborts, so there is no second call. EXPECT_CALL(*mock_insert_context, insertBody(_, _, false)) .WillOnce([&](const Buffer::Instance&, InsertCallback ready_for_next_chunk, bool) { EXPECT_THAT(captured_insert_body_callback, IsNull()); - captured_insert_body_callback = ready_for_next_chunk; + captured_insert_body_callback = std::move(ready_for_next_chunk); }); EXPECT_CALL(*mock_insert_context, onDestroy()); EXPECT_CALL(*mock_lookup_context, onDestroy()); @@ -477,15 +516,15 @@ TEST_F(CacheFilterTest, FilterDestroyedWhileWatermarkedSendsLowWatermarkEvent) { Buffer::OwnedImpl body1buf(body1); Buffer::OwnedImpl body2buf(body2); EXPECT_EQ(filter->encodeData(body1buf, false), Http::FilterDataStatus::Continue); + dispatcher_->run(Event::Dispatcher::RunType::Block); EXPECT_EQ(filter->encodeData(body2buf, true), Http::FilterDataStatus::Continue); + dispatcher_->run(Event::Dispatcher::RunType::Block); ASSERT_THAT(captured_insert_body_callback, NotNull()); // When the filter is destroyed, a low watermark event should be sent. EXPECT_CALL(encoder_callbacks_, onEncoderFilterBelowWriteBufferLowWatermark()); filter->onDestroy(); filter.reset(); captured_insert_body_callback(false); - // The cache insertBody callback should be posted to the dispatcher. - // Run events on the dispatcher so that the callback is invoked. dispatcher_->run(Event::Dispatcher::RunType::Block); } } @@ -507,19 +546,28 @@ TEST_F(CacheFilterTest, CacheEntryStreamedWithTrailersAndNoContentLengthCanDeliv }); // response_headers_ intentionally has no content length, LookupResult also has no content length. EXPECT_CALL(*mock_lookup_context, getHeaders(_)).WillOnce([&](LookupHeadersCallback&& cb) { - cb(LookupResult{CacheEntryStatus::Ok, - std::make_unique(response_headers_), - absl::nullopt, absl::nullopt}, - /* end_stream = */ false); + dispatcher_->post([cb = std::move(cb), this]() mutable { + std::move(cb)( + LookupResult{CacheEntryStatus::Ok, + std::make_unique(response_headers_), + absl::nullopt, absl::nullopt}, + /* end_stream = */ false); + }); }); EXPECT_CALL(*mock_lookup_context, getBody(RangeMatcher(0, Gt(5)), _)) .WillOnce([&](AdjustedByteRange, LookupBodyCallback&& cb) { - cb(std::make_unique(body), false); + dispatcher_->post([cb = std::move(cb), &body]() mutable { + std::move(cb)(std::make_unique(body), false); + }); }); EXPECT_CALL(*mock_lookup_context, getBody(RangeMatcher(5, Gt(5)), _)) - .WillOnce([&](AdjustedByteRange, LookupBodyCallback&& cb) { cb(nullptr, false); }); + .WillOnce([&](AdjustedByteRange, LookupBodyCallback&& cb) { + dispatcher_->post([cb = std::move(cb)]() mutable { std::move(cb)(nullptr, false); }); + }); EXPECT_CALL(*mock_lookup_context, getTrailers(_)).WillOnce([&](LookupTrailersCallback&& cb) { - cb(std::make_unique()); + dispatcher_->post([cb = std::move(cb)]() mutable { + std::move(cb)(std::make_unique()); + }); }); EXPECT_CALL(*mock_lookup_context, onDestroy()); { @@ -558,7 +606,11 @@ TEST_F(CacheFilterTest, OnDestroyBeforeOnHeadersAbortsAction) { EXPECT_CALL(*mock_lookup_context, getHeaders(_)).WillOnce([&](LookupHeadersCallback&& cb) { std::unique_ptr response_headers = std::make_unique(response_headers_); - cb(LookupResult{CacheEntryStatus::Ok, std::move(response_headers), 8, absl::nullopt}, false); + dispatcher_->post([cb = std::move(cb), + response_headers = std::move(response_headers)]() mutable { + std::move(cb)( + LookupResult{CacheEntryStatus::Ok, std::move(response_headers), 8, absl::nullopt}, false); + }); }); auto filter = makeFilter(mock_http_cache, false); EXPECT_EQ(filter->decodeHeaders(request_headers_, true), @@ -581,19 +633,27 @@ TEST_F(CacheFilterTest, OnDestroyBeforeOnBodyAbortsAction) { EXPECT_CALL(*mock_lookup_context, getHeaders(_)).WillOnce([&](LookupHeadersCallback&& cb) { std::unique_ptr response_headers = std::make_unique(response_headers_); - cb(LookupResult{CacheEntryStatus::Ok, std::move(response_headers), 5, absl::nullopt}, false); + dispatcher_->post([cb = std::move(cb), + response_headers = std::move(response_headers)]() mutable { + std::move(cb)( + LookupResult{CacheEntryStatus::Ok, std::move(response_headers), 5, absl::nullopt}, false); + }); }); LookupBodyCallback body_callback; EXPECT_CALL(*mock_lookup_context, getBody(RangeMatcher(0, 5), _)) - .WillOnce([&](const AdjustedByteRange&, LookupBodyCallback&& cb) { body_callback = cb; }); + .WillOnce([&](const AdjustedByteRange&, LookupBodyCallback&& cb) { + body_callback = std::move(cb); + }); + EXPECT_CALL(*mock_lookup_context, onDestroy()); auto filter = makeFilter(mock_http_cache, false); EXPECT_EQ(filter->decodeHeaders(request_headers_, true), Http::FilterHeadersStatus::StopAllIterationAndWatermark); dispatcher_->run(Event::Dispatcher::RunType::NonBlock); filter->onDestroy(); - // onBody should do nothing because the filter was destroyed. - body_callback(std::make_unique("abcde"), true); - dispatcher_->run(Event::Dispatcher::RunType::NonBlock); + ::testing::Mock::VerifyAndClearExpectations(mock_lookup_context.get()); + EXPECT_THAT(body_callback, NotNull()); + // body_callback should not be called because LookupContext::onDestroy, + // correctly implemented, should have aborted it. } TEST_F(CacheFilterTest, OnDestroyBeforeOnTrailersAbortsAction) { @@ -608,15 +668,21 @@ TEST_F(CacheFilterTest, OnDestroyBeforeOnTrailersAbortsAction) { EXPECT_CALL(*mock_lookup_context, getHeaders(_)).WillOnce([&](LookupHeadersCallback&& cb) { std::unique_ptr response_headers = std::make_unique(response_headers_); - cb(LookupResult{CacheEntryStatus::Ok, std::move(response_headers), 5, absl::nullopt}, false); + dispatcher_->post([cb = std::move(cb), + response_headers = std::move(response_headers)]() mutable { + std::move(cb)( + LookupResult{CacheEntryStatus::Ok, std::move(response_headers), 5, absl::nullopt}, false); + }); }); EXPECT_CALL(*mock_lookup_context, getBody(RangeMatcher(0, 5), _)) .WillOnce([&](const AdjustedByteRange&, LookupBodyCallback&& cb) { - cb(std::make_unique("abcde"), false); + dispatcher_->post([cb = std::move(cb)]() mutable { + std::move(cb)(std::make_unique("abcde"), false); + }); }); LookupTrailersCallback trailers_callback; EXPECT_CALL(*mock_lookup_context, getTrailers(_)).WillOnce([&](LookupTrailersCallback&& cb) { - trailers_callback = cb; + trailers_callback = std::move(cb); }); auto filter = makeFilter(mock_http_cache, false); EXPECT_EQ(filter->decodeHeaders(request_headers_, true), @@ -643,15 +709,23 @@ TEST_F(CacheFilterTest, BodyReadFromCacheLimitedToBufferSizeChunks) { EXPECT_CALL(*mock_lookup_context, getHeaders(_)).WillOnce([&](LookupHeadersCallback&& cb) { std::unique_ptr response_headers = std::make_unique(response_headers_); - cb(LookupResult{CacheEntryStatus::Ok, std::move(response_headers), 8, absl::nullopt}, false); + dispatcher_->post([cb = std::move(cb), + response_headers = std::move(response_headers)]() mutable { + std::move(cb)( + LookupResult{CacheEntryStatus::Ok, std::move(response_headers), 8, absl::nullopt}, false); + }); }); EXPECT_CALL(*mock_lookup_context, getBody(RangeMatcher(0, 5), _)) .WillOnce([&](const AdjustedByteRange&, LookupBodyCallback&& cb) { - cb(std::make_unique("abcde"), false); + dispatcher_->post([cb = std::move(cb)]() mutable { + std::move(cb)(std::make_unique("abcde"), false); + }); }); EXPECT_CALL(*mock_lookup_context, getBody(RangeMatcher(5, 8), _)) .WillOnce([&](const AdjustedByteRange&, LookupBodyCallback&& cb) { - cb(std::make_unique("fgh"), true); + dispatcher_->post([cb = std::move(cb)]() mutable { + std::move(cb)(std::make_unique("fgh"), true); + }); }); EXPECT_CALL(*mock_lookup_context, onDestroy()); @@ -703,14 +777,17 @@ TEST_F(CacheFilterTest, CacheInsertAbortedByCache) { return std::move(mock_insert_context); }); EXPECT_CALL(*mock_lookup_context, getHeaders(_)).WillOnce([&](LookupHeadersCallback&& cb) { - cb(LookupResult{}, false); + dispatcher_->post([cb = std::move(cb)]() mutable { std::move(cb)(LookupResult{}, false); }); }); EXPECT_CALL(*mock_insert_context, insertHeaders(_, _, _, false)) .WillOnce([&](const Http::ResponseHeaderMap&, const ResponseMetadata&, - InsertCallback insert_complete, bool) { insert_complete(true); }); + InsertCallback insert_complete, bool) { + dispatcher_->post([cb = std::move(insert_complete)]() mutable { std::move(cb)(true); }); + }); EXPECT_CALL(*mock_insert_context, insertBody(_, _, true)) .WillOnce([&](const Buffer::Instance&, InsertCallback ready_for_next_chunk, bool) { - ready_for_next_chunk(false); + dispatcher_->post( + [cb = std::move(ready_for_next_chunk)]() mutable { std::move(cb)(false); }); }); EXPECT_CALL(*mock_insert_context, onDestroy()); EXPECT_CALL(*mock_lookup_context, onDestroy()); @@ -753,13 +830,13 @@ TEST_F(CacheFilterTest, FilterDeletedWhileIncompleteCacheWriteInQueueShouldAband return std::move(mock_insert_context); }); EXPECT_CALL(*mock_lookup_context, getHeaders(_)).WillOnce([&](LookupHeadersCallback&& cb) { - cb(LookupResult{}, false); + dispatcher_->post([cb = std::move(cb)]() mutable { std::move(cb)(LookupResult{}, false); }); }); InsertCallback captured_insert_header_callback; EXPECT_CALL(*mock_insert_context, insertHeaders(_, _, _, false)) .WillOnce([&](const Http::ResponseHeaderMap&, const ResponseMetadata&, InsertCallback insert_complete, - bool) { captured_insert_header_callback = insert_complete; }); + bool) { captured_insert_header_callback = std::move(insert_complete); }); EXPECT_CALL(*mock_insert_context, onDestroy()); EXPECT_CALL(*mock_lookup_context, onDestroy()); { @@ -772,16 +849,14 @@ TEST_F(CacheFilterTest, FilterDeletedWhileIncompleteCacheWriteInQueueShouldAband // Encode header of response. response_headers_.setContentLength(body.size()); EXPECT_EQ(filter->encodeHeaders(response_headers_, false), Http::FilterHeadersStatus::Continue); - // Destroy the filter prematurely. + // Destroy the filter prematurely (it goes out of scope). } ASSERT_THAT(captured_insert_header_callback, NotNull()); EXPECT_THAT(weak_cache_pointer.lock(), NotNull()) << "cache instance was unexpectedly destroyed when filter was destroyed"; + // The callback should now do nothing visible, because the filter has been destroyed. + // Calling it allows the CacheInsertQueue to discard its self-ownership. captured_insert_header_callback(true); - // The callback should be posted to the dispatcher. - // Run events on the dispatcher so that the callback is invoked, - // where it should now do nothing due to the filter being destroyed. - dispatcher_->run(Event::Dispatcher::RunType::Block); } TEST_F(CacheFilterTest, FilterDeletedWhileCompleteCacheWriteInQueueShouldContinueWrite) { @@ -801,17 +876,17 @@ TEST_F(CacheFilterTest, FilterDeletedWhileCompleteCacheWriteInQueueShouldContinu return std::move(mock_insert_context); }); EXPECT_CALL(*mock_lookup_context, getHeaders(_)).WillOnce([&](LookupHeadersCallback&& cb) { - cb(LookupResult{}, false); + dispatcher_->post([cb = std::move(cb)]() mutable { std::move(cb)(LookupResult{}, false); }); }); InsertCallback captured_insert_header_callback; InsertCallback captured_insert_body_callback; EXPECT_CALL(*mock_insert_context, insertHeaders(_, _, _, false)) .WillOnce([&](const Http::ResponseHeaderMap&, const ResponseMetadata&, InsertCallback insert_complete, - bool) { captured_insert_header_callback = insert_complete; }); + bool) { captured_insert_header_callback = std::move(insert_complete); }); EXPECT_CALL(*mock_insert_context, insertBody(_, _, true)) .WillOnce([&](const Buffer::Instance&, InsertCallback ready_for_next_chunk, bool) { - captured_insert_body_callback = ready_for_next_chunk; + captured_insert_body_callback = std::move(ready_for_next_chunk); }); EXPECT_CALL(*mock_insert_context, onDestroy()); EXPECT_CALL(*mock_lookup_context, onDestroy()); @@ -1391,12 +1466,15 @@ TEST_F(CacheFilterDeathTest, BadRangeRequestLookup) { return std::move(mock_lookup_context); }); EXPECT_CALL(*mock_lookup_context, getHeaders(_)).WillOnce([&](LookupHeadersCallback&& cb) { - // LookupResult with unknown length and an unsatisfiable RangeDetails is invalid. - cb(LookupResult{CacheEntryStatus::Ok, - std::make_unique(response_headers_), - absl::nullopt, - RangeDetails{/*satisfiable_ = */ false, {AdjustedByteRange{0, 5}}}}, - false); + dispatcher_->post([cb = std::move(cb), this]() mutable { + // LookupResult with unknown length and an unsatisfiable RangeDetails is invalid. + std::move(cb)( + LookupResult{CacheEntryStatus::Ok, + std::make_unique(response_headers_), + absl::nullopt, + RangeDetails{/*satisfiable_ = */ false, {AdjustedByteRange{0, 5}}}}, + false); + }); }); EXPECT_CALL(*mock_lookup_context, onDestroy()); { @@ -1429,15 +1507,20 @@ TEST_F(CacheFilterTest, RangeRequestSatisfiedBeforeLengthKnown) { }); EXPECT_CALL(*mock_lookup_context, getHeaders(_)).WillOnce([&](LookupHeadersCallback&& cb) { // LookupResult with unknown length and an unsatisfiable RangeDetails is invalid. - cb(LookupResult{CacheEntryStatus::Ok, - std::make_unique(response_headers_), - absl::nullopt, - RangeDetails{/*satisfiable_ = */ true, {AdjustedByteRange{0, 5}}}}, - false); + dispatcher_->post([cb = std::move(cb), this]() mutable { + std::move(cb)( + LookupResult{CacheEntryStatus::Ok, + std::make_unique(response_headers_), + absl::nullopt, + RangeDetails{/*satisfiable_ = */ true, {AdjustedByteRange{0, 5}}}}, + false); + }); }); EXPECT_CALL(*mock_lookup_context, getBody(RangeMatcher(0, 5), _)) .WillOnce([&](AdjustedByteRange, LookupBodyCallback&& cb) { - cb(std::make_unique(body), false); + dispatcher_->post([cb = std::move(cb), &body]() mutable { + cb(std::make_unique(body), false); + }); }); EXPECT_CALL(*mock_lookup_context, onDestroy()); { diff --git a/test/extensions/filters/http/cache/http_cache_implementation_test_common.cc b/test/extensions/filters/http/cache/http_cache_implementation_test_common.cc index c5df0fa728..d4c6bb578b 100644 --- a/test/extensions/filters/http/cache/http_cache_implementation_test_common.cc +++ b/test/extensions/filters/http/cache/http_cache_implementation_test_common.cc @@ -153,6 +153,20 @@ absl::Status HttpCacheImplementationTest::insert( return absl::OkStatus(); } +LookupContextPtr HttpCacheImplementationTest::lookupContextWithAllParts() { + absl::string_view path = "/common"; + Http::TestResponseHeaderMapImpl response_headers{ + {":status", "200"}, + {"date", formatter_.fromTime(time_system_.systemTime())}, + {"cache-control", "public,max-age=3600"}}; + Http::TestResponseTrailerMapImpl response_trailers{ + {"common-trailer", "irrelevant value"}, + }; + EXPECT_THAT(insert(lookup(path), response_headers, "commonbody", response_trailers), IsOk()); + LookupRequest request = makeLookupRequest(path); + return cache()->makeLookupContext(std::move(request), decoder_callbacks_); +} + absl::Status HttpCacheImplementationTest::insert(absl::string_view request_path, const Http::TestResponseHeaderMapImpl& headers, const absl::string_view body) { @@ -777,6 +791,48 @@ TEST_P(HttpCacheImplementationTest, EmptyTrailers) { EXPECT_TRUE(expectLookupSuccessWithBodyAndTrailers(name_lookup_context.get(), body1)); } +TEST_P(HttpCacheImplementationTest, DoesNotRunHeadersCallbackWhenCancelledAfterPosted) { + bool was_called = false; + { + LookupContextPtr context = lookupContextWithAllParts(); + context->getHeaders([&was_called](LookupResult&&, bool) { was_called = true; }); + pumpIntoDispatcher(); + context->onDestroy(); + } + pumpDispatcher(); + EXPECT_FALSE(was_called); +} + +TEST_P(HttpCacheImplementationTest, DoesNotRunBodyCallbackWhenCancelledAfterPosted) { + bool was_called = false; + { + LookupContextPtr context = lookupContextWithAllParts(); + context->getHeaders([](LookupResult&&, bool) {}); + pumpDispatcher(); + context->getBody({0, 10}, [&was_called](Buffer::InstancePtr&&, bool) { was_called = true; }); + pumpIntoDispatcher(); + context->onDestroy(); + } + pumpDispatcher(); + EXPECT_FALSE(was_called); +} + +TEST_P(HttpCacheImplementationTest, DoesNotRunTrailersCallbackWhenCancelledAfterPosted) { + bool was_called = false; + { + LookupContextPtr context = lookupContextWithAllParts(); + context->getHeaders([](LookupResult&&, bool) {}); + pumpDispatcher(); + context->getBody({0, 10}, [](Buffer::InstancePtr&&, bool) {}); + pumpDispatcher(); + context->getTrailers([&was_called](Http::ResponseTrailerMapPtr&&) { was_called = true; }); + pumpIntoDispatcher(); + context->onDestroy(); + } + pumpDispatcher(); + EXPECT_FALSE(was_called); +} + } // namespace Cache } // namespace HttpFilters } // namespace Extensions diff --git a/test/extensions/filters/http/cache/http_cache_implementation_test_common.h b/test/extensions/filters/http/cache/http_cache_implementation_test_common.h index 497bfcad81..26f20312fd 100644 --- a/test/extensions/filters/http/cache/http_cache_implementation_test_common.h +++ b/test/extensions/filters/http/cache/http_cache_implementation_test_common.h @@ -63,6 +63,7 @@ class HttpCacheImplementationTest std::shared_ptr cache() const { return delegate_->cache(); } bool validationEnabled() const { return delegate_->validationEnabled(); } + void pumpIntoDispatcher() { delegate_->beforePumpingDispatcher(); } void pumpDispatcher() { delegate_->pumpDispatcher(); } LookupContextPtr lookup(absl::string_view request_path); @@ -91,6 +92,8 @@ class HttpCacheImplementationTest LookupRequest makeLookupRequest(absl::string_view request_path); + LookupContextPtr lookupContextWithAllParts(); + testing::AssertionResult expectLookupSuccessWithHeaders(LookupContext* lookup_context, const Http::TestResponseHeaderMapImpl& headers); diff --git a/test/extensions/filters/http/cache/mocks.h b/test/extensions/filters/http/cache/mocks.h index 0a243fab19..d1739f9584 100644 --- a/test/extensions/filters/http/cache/mocks.h +++ b/test/extensions/filters/http/cache/mocks.h @@ -17,7 +17,7 @@ class MockHttpCache : public HttpCache { (LookupContextPtr && lookup_context, Http::StreamEncoderFilterCallbacks& callbacks)); MOCK_METHOD(void, updateHeaders, (const LookupContext& lookup_context, const Http::ResponseHeaderMap& response_headers, - const ResponseMetadata& metadata, std::function on_complete)); + const ResponseMetadata& metadata, absl::AnyInvocable on_complete)); MOCK_METHOD(CacheInfo, cacheInfo, (), (const)); }; From 4d99ab1627a9b847b6cd5fba3e4a816b1f5b883c Mon Sep 17 00:00:00 2001 From: Sunay Dagli Date: Fri, 20 Sep 2024 19:57:44 -0700 Subject: [PATCH 52/65] Change filter and access logger order in access_log_handlers_ (#35959) Commit Message: Change filter and access logger order in access_log_handlers_ Additional Description: Risk Level: Testing: Docs Changes: Release Notes: Platform Specific Features: Runtime guard: envoy.reloadable_features.http_separate_config_and_filter_access_loggers Fixes: #30859 The effect of this change is to iterate the filter loggers first in order for wasm filters to fully write out dynamic metadata before any access loggers use the data, therefore fixing #30859. Thank you to @wbpcode for the suggestion! This change overrides #35924 and related PRs. --------- Signed-off-by: Sunay Dagli Co-authored-by: sunaydagli --- changelogs/current.yaml | 7 ++ source/common/http/conn_manager_impl.cc | 34 ++++++++-- source/common/http/conn_manager_impl.h | 15 ++++- source/common/http/filter_manager.h | 10 +-- source/common/runtime/runtime_features.cc | 1 + test/common/http/conn_manager_impl_test.cc | 76 ++++++++++++++++++++++ 6 files changed, 126 insertions(+), 17 deletions(-) diff --git a/changelogs/current.yaml b/changelogs/current.yaml index 9d61bc5641..256fd4a98f 100644 --- a/changelogs/current.yaml +++ b/changelogs/current.yaml @@ -47,6 +47,13 @@ behavior_changes: ` See the config examples from the above ``internal_address_config`` link. This default no trust internal address can be turned on by setting runtime guard ``envoy.reloadable_features.explicit_internal_address_config`` to ``true``. +- area: http + change: | + The access log handlers that added by the filters will be evaluated before the access + log handlers that configured in the :ref:`access_log configuration + `. + This change can be disabled by setting the runtime guard flag + ``envoy.reloadable_features.filter_access_loggers_first`` to ``false``. minor_behavior_changes: # *Changes that may cause incompatibilities for some users, but should not for most* diff --git a/source/common/http/conn_manager_impl.cc b/source/common/http/conn_manager_impl.cc index ef4bb44f46..e06bca9c6a 100644 --- a/source/common/http/conn_manager_impl.cc +++ b/source/common/http/conn_manager_impl.cc @@ -357,7 +357,7 @@ void ConnectionManagerImpl::doDeferredStreamDestroy(ActiveStream& stream) { stream.deferHeadersAndTrailers(); } else { // For HTTP/1 and HTTP/2, log here as usual. - stream.filter_manager_.log(AccessLog::AccessLogType::DownstreamEnd); + stream.log(AccessLog::AccessLogType::DownstreamEnd); } stream.filter_manager_.destroyFilters(); @@ -827,9 +827,6 @@ ConnectionManagerImpl::ActiveStream::ActiveStream(ConnectionManagerImpl& connect "Either routeConfigProvider or (scopedRouteConfigProvider and scopeKeyBuilder) should be " "set in " "ConnectionManagerImpl."); - for (const AccessLog::InstanceSharedPtr& access_log : connection_manager_.config_->accessLogs()) { - filter_manager_.addAccessLogHandler(access_log); - } filter_manager_.streamInfo().setStreamIdProvider( std::make_shared(*this)); @@ -900,7 +897,7 @@ ConnectionManagerImpl::ActiveStream::ActiveStream(ConnectionManagerImpl& connect // If the request is complete, we've already done the stream-end access-log, and shouldn't // do the periodic log. if (!streamInfo().requestComplete().has_value()) { - filter_manager_.log(AccessLog::AccessLogType::DownstreamPeriodic); + log(AccessLog::AccessLogType::DownstreamPeriodic); refreshAccessLogFlushTimer(); } const SystemTime now = connection_manager_.timeSource().systemTime(); @@ -918,6 +915,29 @@ ConnectionManagerImpl::ActiveStream::ActiveStream(ConnectionManagerImpl& connect } } +void ConnectionManagerImpl::ActiveStream::log(AccessLog::AccessLogType type) { + const Formatter::HttpFormatterContext log_context{ + request_headers_.get(), response_headers_.get(), response_trailers_.get(), {}, type, + active_span_.get()}; + + const bool filter_access_loggers_first = + Runtime::runtimeFeatureEnabled("envoy.reloadable_features.filter_access_loggers_first"); + + if (!filter_access_loggers_first) { + for (const auto& access_logger : connection_manager_.config_->accessLogs()) { + access_logger->log(log_context, filter_manager_.streamInfo()); + } + } + + filter_manager_.log(log_context); + + if (filter_access_loggers_first) { + for (const auto& access_logger : connection_manager_.config_->accessLogs()) { + access_logger->log(log_context, filter_manager_.streamInfo()); + } + } +} + void ConnectionManagerImpl::ActiveStream::completeRequest() { filter_manager_.streamInfo().onRequestComplete(); @@ -1370,7 +1390,7 @@ void ConnectionManagerImpl::ActiveStream::decodeHeaders(RequestHeaderMapSharedPt const bool upgrade_rejected = filter_manager_.createFilterChain() == false; if (connection_manager_.config_->flushAccessLogOnNewRequest()) { - filter_manager_.log(AccessLog::AccessLogType::DownstreamStart); + log(AccessLog::AccessLogType::DownstreamStart); } // TODO if there are no filters when starting a filter iteration, the connection manager @@ -1846,7 +1866,7 @@ void ConnectionManagerImpl::ActiveStream::encodeHeaders(ResponseHeaderMap& heade if (state_.is_tunneling_ && connection_manager_.config_->flushAccessLogOnTunnelSuccessfullyEstablished()) { - filter_manager_.log(AccessLog::AccessLogType::DownstreamTunnelSuccessfullyEstablished); + log(AccessLog::AccessLogType::DownstreamTunnelSuccessfullyEstablished); } ENVOY_STREAM_LOG(debug, "encoding headers via codec (end_stream={}):\n{}", *this, end_stream, headers); diff --git a/source/common/http/conn_manager_impl.h b/source/common/http/conn_manager_impl.h index d5c9a32928..aef542307f 100644 --- a/source/common/http/conn_manager_impl.h +++ b/source/common/http/conn_manager_impl.h @@ -157,6 +157,7 @@ class ConnectionManagerImpl : Logger::Loggable, still_alive_.reset(); } + void log(AccessLog::AccessLogType type); void completeRequest(); const Network::Connection* connection(); @@ -190,7 +191,19 @@ class ConnectionManagerImpl : Logger::Loggable, return filter_manager_.sendLocalReply(code, body, modify_headers, grpc_status, details); } std::list accessLogHandlers() override { - return filter_manager_.accessLogHandlers(); + std::list combined_log_handlers( + filter_manager_.accessLogHandlers()); + std::list config_log_handlers_( + connection_manager_.config_->accessLogs()); + if (!Runtime::runtimeFeatureEnabled( + "envoy.reloadable_features.filter_access_loggers_first")) { + combined_log_handlers.insert(combined_log_handlers.begin(), config_log_handlers_.begin(), + config_log_handlers_.end()); + } else { + combined_log_handlers.insert(combined_log_handlers.end(), config_log_handlers_.begin(), + config_log_handlers_.end()); + } + return combined_log_handlers; } // Hand off headers/trailers and stream info to the codec's response encoder, for logging later // (i.e. possibly after this stream has been destroyed). diff --git a/source/common/http/filter_manager.h b/source/common/http/filter_manager.h index 1051685851..f1698144b3 100644 --- a/source/common/http/filter_manager.h +++ b/source/common/http/filter_manager.h @@ -696,15 +696,7 @@ class FilterManager : public ScopeTrackedObject, // FilterChainManager void applyFilterFactoryCb(FilterContext context, FilterFactoryCb& factory) override; - void log(AccessLog::AccessLogType access_log_type) { - const Formatter::HttpFormatterContext log_context{ - filter_manager_callbacks_.requestHeaders().ptr(), - filter_manager_callbacks_.responseHeaders().ptr(), - filter_manager_callbacks_.responseTrailers().ptr(), - {}, - access_log_type, - &filter_manager_callbacks_.activeSpan()}; - + void log(const Formatter::HttpFormatterContext log_context) { for (const auto& log_handler : access_log_handlers_) { log_handler->log(log_context, streamInfo()); } diff --git a/source/common/runtime/runtime_features.cc b/source/common/runtime/runtime_features.cc index 085a986b26..7b28eebbb2 100644 --- a/source/common/runtime/runtime_features.cc +++ b/source/common/runtime/runtime_features.cc @@ -47,6 +47,7 @@ RUNTIME_GUARD(envoy_reloadable_features_enable_include_histograms); RUNTIME_GUARD(envoy_reloadable_features_exclude_host_in_eds_status_draining); RUNTIME_GUARD(envoy_reloadable_features_ext_proc_timeout_error); RUNTIME_GUARD(envoy_reloadable_features_extend_h3_accept_untrusted); +RUNTIME_GUARD(envoy_reloadable_features_filter_access_loggers_first); RUNTIME_GUARD(envoy_reloadable_features_gcp_authn_use_fixed_url); RUNTIME_GUARD(envoy_reloadable_features_getaddrinfo_num_retries); RUNTIME_GUARD(envoy_reloadable_features_grpc_side_stream_flow_control); diff --git a/test/common/http/conn_manager_impl_test.cc b/test/common/http/conn_manager_impl_test.cc index d98b1008e2..44a1dacf48 100644 --- a/test/common/http/conn_manager_impl_test.cc +++ b/test/common/http/conn_manager_impl_test.cc @@ -4493,5 +4493,81 @@ TEST_F(ProxyStatusTest, PopulateProxyStatusAppendToPreviousValue) { "SomeCDN, custom_server_name; error=http_response_timeout; details=\"baz; UT\""); } +TEST_F(HttpConnectionManagerImplTest, TestFilterAccessLogBeforeConfigAccessLog) { + log_handler_ = std::make_shared>(); // filter log handler + std::shared_ptr handler( + new NiceMock()); // config log handler + access_logs_ = {handler}; + setup(); + setupFilterChain(1, 0); + + EXPECT_CALL(*decoder_filters_[0], decodeHeaders(_, false)) + .WillOnce(Return(FilterHeadersStatus::StopIteration)); + startRequest(); + + { + InSequence s; // Create an InSequence object to enforce order + + EXPECT_CALL(*log_handler_, log(_, _)) + .WillOnce(Invoke([](const Formatter::HttpFormatterContext& log_context, + const StreamInfo::StreamInfo& stream_info) { + EXPECT_EQ(AccessLog::AccessLogType::DownstreamEnd, log_context.accessLogType()); + EXPECT_FALSE(stream_info.hasAnyResponseFlag()); + })); + + EXPECT_CALL(*handler, log(_, _)) + .WillOnce(Invoke([](const Formatter::HttpFormatterContext& log_context, + const StreamInfo::StreamInfo& stream_info) { + // First call to log() is made when a new HTTP request has been received + // On the first call it is expected that there is no response code. + EXPECT_EQ(AccessLog::AccessLogType::DownstreamEnd, log_context.accessLogType()); + EXPECT_TRUE(stream_info.responseCode()); + })); + } + + ResponseHeaderMapPtr response_headers{new TestResponseHeaderMapImpl{{":status", "200"}}}; + decoder_filters_[0]->callbacks_->streamInfo().setResponseCodeDetails(""); + decoder_filters_[0]->callbacks_->encodeHeaders(std::move(response_headers), true, "details"); +} + +TEST_F(HttpConnectionManagerImplTest, TestFilterAccessLogBeforeConfigAccessLogFeatureFalse) { + TestScopedRuntime scoped_runtime; + scoped_runtime.mergeValues({{"envoy.reloadable_features.filter_access_loggers_first", "false"}}); + log_handler_ = std::make_shared>(); // filter log handler + std::shared_ptr handler( + new NiceMock()); // config log handler + access_logs_ = {handler}; + setup(); + setupFilterChain(1, 0); + + EXPECT_CALL(*decoder_filters_[0], decodeHeaders(_, false)) + .WillOnce(Return(FilterHeadersStatus::StopIteration)); + startRequest(); + + { + InSequence s; // Create an InSequence object to enforce order + + EXPECT_CALL(*handler, log(_, _)) + .WillOnce(Invoke([](const Formatter::HttpFormatterContext& log_context, + const StreamInfo::StreamInfo& stream_info) { + // First call to log() is made when a new HTTP request has been received + // On the first call it is expected that there is no response code. + EXPECT_EQ(AccessLog::AccessLogType::DownstreamEnd, log_context.accessLogType()); + EXPECT_TRUE(stream_info.responseCode()); + })); + + EXPECT_CALL(*log_handler_, log(_, _)) + .WillOnce(Invoke([](const Formatter::HttpFormatterContext& log_context, + const StreamInfo::StreamInfo& stream_info) { + EXPECT_EQ(AccessLog::AccessLogType::DownstreamEnd, log_context.accessLogType()); + EXPECT_FALSE(stream_info.hasAnyResponseFlag()); + })); + } + + ResponseHeaderMapPtr response_headers{new TestResponseHeaderMapImpl{{":status", "200"}}}; + decoder_filters_[0]->callbacks_->streamInfo().setResponseCodeDetails(""); + decoder_filters_[0]->callbacks_->encodeHeaders(std::move(response_headers), true, "details"); +} + } // namespace Http } // namespace Envoy From 0e7fdf5f23e3147a998c24a0cf8e3192797e80c5 Mon Sep 17 00:00:00 2001 From: Jeongseok Son Date: Sun, 22 Sep 2024 22:36:17 -0700 Subject: [PATCH 53/65] http: fix issues in CONNECT-UDP forwarding mode. (#36174) Commit Message: When Envoy operates as a CONNECT-UDP forwarding proxy, it was resetting the upstream stream because it received HTTP Datagrams before receiving the SETTINGS frame. A new enum has been added in QUICHE to distinguish this case, so I added handling logic for this and made Envoy drop the datagrams instead of resetting the stream. Also, Envoy was dropping Datagrams because the default maximum packet length for QUIC connections in QUICHE is not large enough for tunneling use cases such as CONNECT-UDP. I added a new QUIC protocol option called `max_packet_length` to allow users to adjust the maximum packet length for upstream QUIC connections to fix this issue. Additional Description: Risk Level: Low, this change is only relevant if CONNECT-UDP is enabled with the forwarding mode. Testing: Added more unit tests. Docs Changes: Added the `max_packet_length` QUIC protocol option and its explanation. Release Notes: Added notes about fixing the CONNECT-UDP forwarding mode and adding the new QUIC protocol option. Platform Specific Features: N/A [Optional Fixes #Issue]: #34836 --------- Signed-off-by: Jeongseok Son --- api/envoy/config/core/v3/protocol.proto | 6 +++++- changelogs/current.yaml | 9 +++++++++ configs/proxy_connect_udp_http3_downstream.yaml | 4 ++++ .../common/quic/client_connection_factory_impl.cc | 15 ++++++++++++--- .../common/quic/client_connection_factory_impl.h | 6 +++++- source/common/quic/http_datagram_handler.cc | 3 ++- test/common/quic/http_datagram_handler_test.cc | 11 ++++++++++- 7 files changed, 47 insertions(+), 7 deletions(-) diff --git a/api/envoy/config/core/v3/protocol.proto b/api/envoy/config/core/v3/protocol.proto index 6dbff8c48f..eda87d9408 100644 --- a/api/envoy/config/core/v3/protocol.proto +++ b/api/envoy/config/core/v3/protocol.proto @@ -56,7 +56,7 @@ message QuicKeepAliveSettings { } // QUIC protocol options which apply to both downstream and upstream connections. -// [#next-free-field: 9] +// [#next-free-field: 10] message QuicProtocolOptions { // Maximum number of streams that the client can negotiate per connection. 100 // if not specified. @@ -111,6 +111,10 @@ message QuicProtocolOptions { lte {seconds: 600} gte {seconds: 1} }]; + + // Maximum packet length for QUIC connections. It refers to the largest size of a QUIC packet that can be transmitted over the connection. + // If not specified, one of the `default values in QUICHE `_ is used. + google.protobuf.UInt64Value max_packet_length = 9; } message UpstreamHttpProtocolOptions { diff --git a/changelogs/current.yaml b/changelogs/current.yaml index 256fd4a98f..34bfdd97fd 100644 --- a/changelogs/current.yaml +++ b/changelogs/current.yaml @@ -180,6 +180,11 @@ bug_fixes: - area: http_async_client change: | Fixed the local reply and destroy order crashes when using the http async client for websocket handshake. +- area: http3 + change: | + Fixed a bug in the CONNECT-UDP forwarding mode where Envoy reset the upstream stream when it + received HTTP/3 datagrams before receiving the SETTINGS frame from the upstream peer. Envoy now + drops the datagrams in this case instead of resetting the stream. removed_config_or_runtime: # *Normally occurs at the end of the* :ref:`deprecation period ` @@ -395,5 +400,9 @@ new_features: Added support to provide an override :ref:`authentication_header ` to load Basic Auth credential. +- area: quic + change: | + Added ``max_packet_length`` to the QUIC protocol options to allow users to change the largest + size of a QUIC packet that can be transmitted over the QUIC connection. deprecated: diff --git a/configs/proxy_connect_udp_http3_downstream.yaml b/configs/proxy_connect_udp_http3_downstream.yaml index 24967e488e..4455eb6844 100644 --- a/configs/proxy_connect_udp_http3_downstream.yaml +++ b/configs/proxy_connect_udp_http3_downstream.yaml @@ -58,6 +58,10 @@ static_resources: explicit_http_config: http3_protocol_options: allow_extended_connect: true + quic_protocol_options: + # Increase the max packet length for tunneling. + # The example value matches the default value used by the MASQUE client in QUICHE. + max_packet_length: 1350 load_assignment: cluster_name: cluster_0 endpoints: diff --git a/source/common/quic/client_connection_factory_impl.cc b/source/common/quic/client_connection_factory_impl.cc index 17802078a1..f0f1a91b02 100644 --- a/source/common/quic/client_connection_factory_impl.cc +++ b/source/common/quic/client_connection_factory_impl.cc @@ -5,9 +5,10 @@ namespace Envoy { namespace Quic { -PersistentQuicInfoImpl::PersistentQuicInfoImpl(Event::Dispatcher& dispatcher, uint32_t buffer_limit) +PersistentQuicInfoImpl::PersistentQuicInfoImpl(Event::Dispatcher& dispatcher, uint32_t buffer_limit, + quic::QuicByteCount max_packet_length) : conn_helper_(dispatcher), alarm_factory_(dispatcher, *conn_helper_.GetClock()), - buffer_limit_(buffer_limit) { + buffer_limit_(buffer_limit), max_packet_length_(max_packet_length) { quiche::FlagRegistry::getInstance(); } @@ -16,7 +17,9 @@ createPersistentQuicInfoForCluster(Event::Dispatcher& dispatcher, const Upstream::ClusterInfo& cluster) { auto quic_info = std::make_unique( dispatcher, cluster.perConnectionBufferLimitBytes()); - Quic::convertQuicConfig(cluster.http3Options().quic_protocol_options(), quic_info->quic_config_); + const envoy::config::core::v3::QuicProtocolOptions& quic_config = + cluster.http3Options().quic_protocol_options(); + Quic::convertQuicConfig(quic_config, quic_info->quic_config_); quic::QuicTime::Delta crypto_timeout = quic::QuicTime::Delta::FromMilliseconds(cluster.connectTimeout().count()); @@ -25,6 +28,8 @@ createPersistentQuicInfoForCluster(Event::Dispatcher& dispatcher, quic_info->quic_config_.max_idle_time_before_crypto_handshake()) { quic_info->quic_config_.set_max_idle_time_before_crypto_handshake(crypto_timeout); } + quic_info->max_packet_length_ = + PROTOBUF_GET_WRAPPED_OR_DEFAULT(quic_config, max_packet_length, 0); return quic_info; } @@ -50,6 +55,10 @@ std::unique_ptr createQuicNetworkConnection( quic::QuicUtils::CreateRandomConnectionId(), server_addr, info_impl->conn_helper_, info_impl->alarm_factory_, quic_versions, local_addr, dispatcher, options, generator, Runtime::runtimeFeatureEnabled("envoy.reloadable_features.prefer_quic_client_udp_gro")); + // Override the max packet length of the QUIC connection if the option value is not 0. + if (info_impl->max_packet_length_ > 0) { + connection->SetMaxPacketLength(info_impl->max_packet_length_); + } // TODO (danzh) move this temporary config and initial RTT configuration to h3 pool. quic::QuicConfig config = info_impl->quic_config_; diff --git a/source/common/quic/client_connection_factory_impl.h b/source/common/quic/client_connection_factory_impl.h index 9e47687ac1..7d955602c4 100644 --- a/source/common/quic/client_connection_factory_impl.h +++ b/source/common/quic/client_connection_factory_impl.h @@ -21,7 +21,8 @@ namespace Quic { // TODO(danzh) considering exposing these QUICHE interfaces via base class virtual methods, so that // down casting can be avoided while passing around this object. struct PersistentQuicInfoImpl : public Http::PersistentQuicInfo { - PersistentQuicInfoImpl(Event::Dispatcher& dispatcher, uint32_t buffer_limit); + PersistentQuicInfoImpl(Event::Dispatcher& dispatcher, uint32_t buffer_limit, + quic::QuicByteCount max_packet_length = 0); EnvoyQuicConnectionHelper conn_helper_; EnvoyQuicAlarmFactory alarm_factory_; @@ -30,6 +31,9 @@ struct PersistentQuicInfoImpl : public Http::PersistentQuicInfo { const uint32_t buffer_limit_; // Hard code with the default crypto stream as there's no pluggable crypto for upstream Envoy. EnvoyQuicCryptoClientStreamFactoryImpl crypto_stream_factory_; + // Override the maximum packet length of connections for tunneling. Use the default length in + // QUICHE if this is set to 0. + quic::QuicByteCount max_packet_length_; }; std::unique_ptr diff --git a/source/common/quic/http_datagram_handler.cc b/source/common/quic/http_datagram_handler.cc index 929e848209..0c2fbe8912 100644 --- a/source/common/quic/http_datagram_handler.cc +++ b/source/common/quic/http_datagram_handler.cc @@ -56,7 +56,8 @@ bool HttpDatagramHandler::OnCapsule(const quiche::Capsule& capsule) { quic::MessageStatusToString(status))); return true; } - if (status == quic::MessageStatus::MESSAGE_STATUS_TOO_LARGE) { + if (status == quic::MessageStatus::MESSAGE_STATUS_TOO_LARGE || + status == quic::MessageStatus::MESSAGE_STATUS_SETTINGS_NOT_RECEIVED) { ENVOY_LOG(warn, fmt::format("SendHttpH3Datagram failed: status = {}, drops the Datagram.", quic::MessageStatusToString(status))); return true; diff --git a/test/common/quic/http_datagram_handler_test.cc b/test/common/quic/http_datagram_handler_test.cc index 19c7e9869c..1efeeb8f07 100644 --- a/test/common/quic/http_datagram_handler_test.cc +++ b/test/common/quic/http_datagram_handler_test.cc @@ -100,12 +100,21 @@ TEST_F(HttpDatagramHandlerTest, SendCapsulesWithUnknownType) { /*end_stream=*/false)); } -TEST_F(HttpDatagramHandlerTest, SendHttp3DatagramError) { +TEST_F(HttpDatagramHandlerTest, SendHttp3DatagramInternalError) { EXPECT_CALL(stream_, SendHttp3Datagram(_)) .WillOnce(testing::Return(quic::MessageStatus::MESSAGE_STATUS_INTERNAL_ERROR)); EXPECT_FALSE( http_datagram_handler_.encodeCapsuleFragment(capsule_fragment_, /*end_stream*/ false)); } +TEST_F(HttpDatagramHandlerTest, SendHttp3DatagramTooEarly) { + // If SendHttp3Datagram is called before receiving SETTINGS from a peer, HttpDatagramHandler + // drops the datagram without resetting the stream. + EXPECT_CALL(stream_, SendHttp3Datagram(_)) + .WillOnce(testing::Return(quic::MessageStatus::MESSAGE_STATUS_SETTINGS_NOT_RECEIVED)); + EXPECT_TRUE( + http_datagram_handler_.encodeCapsuleFragment(capsule_fragment_, /*end_stream*/ false)); +} + } // namespace Quic } // namespace Envoy From 61992631763eb67a6f78ca9242f88518b8490060 Mon Sep 17 00:00:00 2001 From: phlax Date: Mon, 23 Sep 2024 08:35:32 +0100 Subject: [PATCH 54/65] tools/python: Update all deps (#36267) this should reduce dependabot noise - also the release branches need something similar so will ~backport this Signed-off-by: Ryan Northey --- tools/base/requirements.txt | 166 ++++++++++++++++++------------------ 1 file changed, 83 insertions(+), 83 deletions(-) diff --git a/tools/base/requirements.txt b/tools/base/requirements.txt index f2b74091a5..a5e34dba82 100644 --- a/tools/base/requirements.txt +++ b/tools/base/requirements.txt @@ -88,9 +88,9 @@ aiofiles==24.1.0 \ --hash=sha256:22a075c9e5a3810f0c2e48f3008c94d68c65d763b9b03857924c99e57355166c \ --hash=sha256:b4ec55f4195e3eb5d7abd1bf7e061763e864dd4954231fb8539a0ef8bb8260e5 # via envoy-github-release -aiohappyeyeballs==2.3.5 \ - --hash=sha256:4d6dea59215537dbc746e93e779caea8178c866856a721c9c660d7a5a7b8be03 \ - --hash=sha256:6fa48b9f1317254f122a07a131a86b71ca6946ca989ce6326fff54a99a920105 +aiohappyeyeballs==2.4.0 \ + --hash=sha256:55a1714f084e63d49639800f95716da97a1f173d46a16dfcfda0016abb93b6b2 \ + --hash=sha256:7ce92076e249169a13c2f49320d1967425eaf1f407522d707d59cac7628d62bd # via aiohttp aiohttp==3.10.5 \ --hash=sha256:02594361128f780eecc2a29939d9dfc870e17b45178a867bf61a11b2a4367277 \ @@ -230,31 +230,31 @@ alabaster==0.7.16 \ --hash=sha256:75a8b99c28a5dad50dd7f8ccdd447a121ddb3892da9e53d1ca5cca3106d58d65 \ --hash=sha256:b46733c07dce03ae4e150330b975c75737fa60f0a7c591b6c8bf4928a28e2c92 # via sphinx -argcomplete==3.4.0 \ - --hash=sha256:69a79e083a716173e5532e0fa3bef45f793f4e61096cf52b5a42c0211c8b8aa5 \ - --hash=sha256:c2abcdfe1be8ace47ba777d4fce319eb13bf8ad9dace8d085dcad6eded88057f +argcomplete==3.5.0 \ + --hash=sha256:4349400469dccfb7950bb60334a680c58d88699bff6159df61251878dc6bf74b \ + --hash=sha256:d4bcf3ff544f51e16e54228a7ac7f486ed70ebf2ecfe49a63a91171c76bf029b # via gsutil -attrs==23.2.0 \ - --hash=sha256:935dc3b529c262f6cf76e50877d35a4bd3c1de194fd41f47a2b7ae8f19971f30 \ - --hash=sha256:99b87a485a5820b23b879f04c2305b44b951b502fd64be915879d77a7e8fc6f1 +attrs==24.2.0 \ + --hash=sha256:5cfb1b9148b5b086569baec03f20d7b6bf3bcacc9a42bebf87ffaaca362f6346 \ + --hash=sha256:81921eb96de3191c8258c199618104dd27ac608d9366f5e35d011eae1867ede2 # via # aiohttp # service-identity -babel==2.15.0 \ - --hash=sha256:08706bdad8d0a3413266ab61bd6c34d0c28d6e1e7badf40a2cebe67644e2e1fb \ - --hash=sha256:8daf0e265d05768bc6c7a314cf1321e9a123afc328cc635c18622a2f30a04413 +babel==2.16.0 \ + --hash=sha256:368b5b98b37c06b7daf6696391c3240c938b37767d4584413e8438c5c435fa8b \ + --hash=sha256:d1f3554ca26605fe173f3de0c65f750f5a42f924499bf134de6423582298e316 # via sphinx boto==2.49.0 \ --hash=sha256:147758d41ae7240dc989f0039f27da8ca0d53734be0eb869ef16e3adcfa462e8 \ --hash=sha256:ea0d3b40a2d852767be77ca343b58a9e3a4b00d9db440efb8da74b4e58025e5a # via gcs-oauth2-boto-plugin -cachetools==5.4.0 \ - --hash=sha256:3ae3b49a3d5e28a77a0be2b37dbcb89005058959cb2323858c2657c4a8cab474 \ - --hash=sha256:b8adc2e7c07f105ced7bc56dbb6dfbe7c4a00acce20e2227b3f355be89bc6827 +cachetools==5.5.0 \ + --hash=sha256:02134e8439cdc2ffb62023ce1debca2944c3f289d66bb17ead3ab3dede74b292 \ + --hash=sha256:2cc24fb4cbe39633fb7badd9db9ca6295d766d9c2995f245725a46715d050f2a # via google-auth -certifi==2024.7.4 \ - --hash=sha256:5a1e7645bc0ec61a09e26c36f6106dd4cf40c6db3a1fb6352b0244e7fb057c7b \ - --hash=sha256:c198e21b1289c2ab85ee4e67bb4b4ef3ead0892059901a8d5b622f24a1101e90 +certifi==2024.8.30 \ + --hash=sha256:922820b53db7a7257ffbda3f597266d435245903d80737e34f8a45ff3e3230d8 \ + --hash=sha256:bec941d2aa8195e248a60b31ff9f0558284cf01a52591ceda73ea9afffd69fd9 # via # aioquic # requests @@ -768,9 +768,9 @@ icalendar==5.0.13 \ --hash=sha256:5ded5415e2e1edef5ab230024a75878a7a81d518a3b1ae4f34bf20b173c84dc2 \ --hash=sha256:92799fde8cce0b61daa8383593836d1e19136e504fa1671f471f98be9b029706 # via -r requirements.in -idna==3.7 \ - --hash=sha256:028ff3aadf0609c1fd278d8ea3089299412a7a8b9bd005dd08b9f8285bcb5cfc \ - --hash=sha256:82fee1fc78add43492d3a1898bfa6d8a904cc97d8427f683ed8e798d07761aa0 +idna==3.10 \ + --hash=sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9 \ + --hash=sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3 # via # requests # yarl @@ -778,9 +778,9 @@ imagesize==1.4.1 \ --hash=sha256:0d8d18d08f840c19d0ee7ca1fd82490fdc3729b7ac93f49870406ddde8ef8d8b \ --hash=sha256:69150444affb9cb0d5cc5a92b3676f0b2fb7cd9ae39e947a5e11a36b4497cd4a # via sphinx -importlib-metadata==8.0.0 \ - --hash=sha256:15584cf2b1bf449d98ff8a6ff1abef57bf20f3ac6454f431736cd3e660921b2f \ - --hash=sha256:188bd24e4c346d3f0a933f275c2fec67050326a856b9a359881d7c2a697e8812 +importlib-metadata==8.5.0 \ + --hash=sha256:45e54197d28b7a7f1559e60b95e7c567032b602131fbd588f1497f47880aa68b \ + --hash=sha256:71522656f0abace1d072b9e5481a48f07c138e00f079c38c8f883823f9c26bd7 # via yapf jinja2==3.1.4 \ --hash=sha256:4a3aee7acbbe7303aede8e9648d13b8bf88a429282aa6122a993f0ac800cb369 \ @@ -1049,9 +1049,9 @@ pep8-naming==0.14.1 \ --hash=sha256:1ef228ae80875557eb6c1549deafed4dabbf3261cfcafa12f773fe0db9be8a36 \ --hash=sha256:63f514fc777d715f935faf185dedd679ab99526a7f2f503abb61587877f7b1c5 # via -r requirements.in -platformdirs==4.2.2 \ - --hash=sha256:2d7a1657e36a80ea911db832a8a6ece5ee53d8de21edd5cc5879af6530b1bfee \ - --hash=sha256:38b7b51f512eed9e84a22788b4bce1de17c0adb134d6becb09836e37d8654cd3 +platformdirs==4.3.6 \ + --hash=sha256:357fb2acbc885b0419afd3ce3ed34564c13c9b95c89360cd9563f73aa5e2b907 \ + --hash=sha256:73e575e1408ab8103900836b97580d5307456908a03e92031bab39e4554cc3fb # via yapf ply==3.11 \ --hash=sha256:00c7c1aaa88358b9c765b6d3000c6eec0ba42abca5351b095321aef446081da3 \ @@ -1073,24 +1073,24 @@ protobuf==5.28.2 \ # -r requirements.in # envoy-base-utils # envoy-docs-sphinx-runner -pyasn1==0.6.0 \ - --hash=sha256:3a35ab2c4b5ef98e17dfdec8ab074046fbda76e281c5a706ccd82328cfc8f64c \ - --hash=sha256:cca4bb0f2df5504f02f6f8a775b6e416ff9b0b3b16f7ee80b5a3153d9b804473 +pyasn1==0.6.1 \ + --hash=sha256:0d632f46f2ba09143da3a8afe9e33fb6f92fa2320ab7e886e2d0f7672af84629 \ + --hash=sha256:6f580d2bdd84365380830acf45550f2511469f673cb4a5ae3857a3170128b034 # via # oauth2client # pyasn1-modules # rsa # service-identity -pyasn1-modules==0.4.0 \ - --hash=sha256:831dbcea1b177b28c9baddf4c6d1013c24c3accd14a1873fffaa6a2e905f17b6 \ - --hash=sha256:be04f15b66c206eed667e0bb5ab27e2b1855ea54a842e5037738099e8ca4ae0b +pyasn1-modules==0.4.1 \ + --hash=sha256:49bfa96b45a292b711e986f222502c1c9a5e1f4e568fc30e2574a6c7d07838fd \ + --hash=sha256:c28e2dbf9c06ad61c71a075c7e0f9fd0f1b0bb2d2ad4377f240d33ac2ab60a7c # via # google-auth # oauth2client # service-identity -pycodestyle==2.12.0 \ - --hash=sha256:442f950141b4f43df752dd303511ffded3a04c2b6fb7f65980574f0c31e6e79c \ - --hash=sha256:949a39f6b86c3e1515ba1787c2022131d165a8ad271b11370a8819aa070269e4 +pycodestyle==2.12.1 \ + --hash=sha256:46f0fb92069a7c28ab7bb558f05bfc0110dac69a0cd23c61ea0040283a9d78b3 \ + --hash=sha256:6838eae08bbce4f6accd5d5572075c63626a15ee3e6f842df996bf62f6d73521 # via flake8 pycparser==2.22 \ --hash=sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6 \ @@ -1110,9 +1110,9 @@ pygments==2.18.0 \ # via # envoy-docs-sphinx-runner # sphinx -pyjwt[crypto]==2.8.0 \ - --hash=sha256:57e28d156e3d5c10088e0c68abb90bfac3df82b40a71bd0daa20c65ccd5c23de \ - --hash=sha256:59127c392cc44c2da5bb3192169a91f429924e17aff6534d70fdc02ab3e04320 +pyjwt[crypto]==2.9.0 \ + --hash=sha256:3b02fb0f44517787776cf48f2ae25d8e14f300e6d7545a4315cee571a415e850 \ + --hash=sha256:7e1e5b56cc735432a7369cbfa0efe50fa113ebecdc04ae6922deba8b84582d0c # via # gidgethub # pygithub @@ -1156,9 +1156,9 @@ pyopenssl==24.2.1 \ # aioquic # gcs-oauth2-boto-plugin # gsutil -pyparsing==3.1.2 \ - --hash=sha256:a1bac0ce561155ecc3ed78ca94d3c9378656ad4c94c1270de543f621420f94ad \ - --hash=sha256:f9db75911801ed778fe61bb643079ff86601aca99fcae6345aa67292038fb742 +pyparsing==3.1.4 \ + --hash=sha256:a6a7ee4235a3f944aa1fa2249307708f893fe5717dc603503c6c7969c070fb7c \ + --hash=sha256:f86ec8d1a83f11977c9a6ea7598e8c27fc5cddfa5b07ea2241edbbde1d7bc032 # via httplib2 pyreadline==2.1 \ --hash=sha256:4530592fc2e85b25b1a9f79664433da09237c1a270e4d78ea5aa3a2c7229e2d1 @@ -1173,9 +1173,9 @@ python-gnupg==0.5.2 \ # via # envoy-base-utils # envoy-gpg-identity -pytz==2024.1 \ - --hash=sha256:2a29735ea9c18baf14b448846bde5a48030ed267578472d8955cd0e7443a9812 \ - --hash=sha256:328171f4e3623139da4983451950b28e95ac706e13f3f2630a879749e7a8b319 +pytz==2024.2 \ + --hash=sha256:2aa355083c50a0f93fa581709deac0c9ad65cca8a9e9beac660adcbd493c798a \ + --hash=sha256:31c7c1817eb7fae7ca4b8c7ee50c72f93aa2dd863de768e1ef4245d426aa0725 # via # aio-core # envoy-base-utils @@ -1384,44 +1384,44 @@ uritemplate==4.1.1 \ --hash=sha256:4346edfc5c3b79f694bccd6d6099a322bbeb628dbf2cd86eea55a456ce5124f0 \ --hash=sha256:830c08b8d99bdd312ea4ead05994a38e8936266f84b9a7878232db50b044e02e # via gidgethub -urllib3==2.2.2 \ - --hash=sha256:a448b2f64d686155468037e1ace9f2d2199776e17f0a46610480d311f73e3472 \ - --hash=sha256:dd505485549a7a552833da5e6063639d0d177c04f23bc3864e41e5dc5f612168 +urllib3==2.2.3 \ + --hash=sha256:ca899ca043dcb1bafa3e262d73aa25c465bfb49e0bd9dd5d59f1d0acba2f8fac \ + --hash=sha256:e7d814a81dad81e6caf2ec9fdedb284ecc9c73076b62654547cc64ccdcae26e9 # via # pygithub # requests -uvloop==0.19.0 \ - --hash=sha256:0246f4fd1bf2bf702e06b0d45ee91677ee5c31242f39aab4ea6fe0c51aedd0fd \ - --hash=sha256:02506dc23a5d90e04d4f65c7791e65cf44bd91b37f24cfc3ef6cf2aff05dc7ec \ - --hash=sha256:13dfdf492af0aa0a0edf66807d2b465607d11c4fa48f4a1fd41cbea5b18e8e8b \ - --hash=sha256:2693049be9d36fef81741fddb3f441673ba12a34a704e7b4361efb75cf30befc \ - --hash=sha256:271718e26b3e17906b28b67314c45d19106112067205119dddbd834c2b7ce797 \ - --hash=sha256:2df95fca285a9f5bfe730e51945ffe2fa71ccbfdde3b0da5772b4ee4f2e770d5 \ - --hash=sha256:31e672bb38b45abc4f26e273be83b72a0d28d074d5b370fc4dcf4c4eb15417d2 \ - --hash=sha256:34175c9fd2a4bc3adc1380e1261f60306344e3407c20a4d684fd5f3be010fa3d \ - --hash=sha256:45bf4c24c19fb8a50902ae37c5de50da81de4922af65baf760f7c0c42e1088be \ - --hash=sha256:472d61143059c84947aa8bb74eabbace30d577a03a1805b77933d6bd13ddebbd \ - --hash=sha256:47bf3e9312f63684efe283f7342afb414eea4d3011542155c7e625cd799c3b12 \ - --hash=sha256:492e2c32c2af3f971473bc22f086513cedfc66a130756145a931a90c3958cb17 \ - --hash=sha256:4ce6b0af8f2729a02a5d1575feacb2a94fc7b2e983868b009d51c9a9d2149bef \ - --hash=sha256:5138821e40b0c3e6c9478643b4660bd44372ae1e16a322b8fc07478f92684e24 \ - --hash=sha256:5588bd21cf1fcf06bded085f37e43ce0e00424197e7c10e77afd4bbefffef428 \ - --hash=sha256:570fc0ed613883d8d30ee40397b79207eedd2624891692471808a95069a007c1 \ - --hash=sha256:5a05128d315e2912791de6088c34136bfcdd0c7cbc1cf85fd6fd1bb321b7c849 \ - --hash=sha256:5daa304d2161d2918fa9a17d5635099a2f78ae5b5960e742b2fcfbb7aefaa593 \ - --hash=sha256:5f17766fb6da94135526273080f3455a112f82570b2ee5daa64d682387fe0dcd \ - --hash=sha256:6e3d4e85ac060e2342ff85e90d0c04157acb210b9ce508e784a944f852a40e67 \ - --hash=sha256:7010271303961c6f0fe37731004335401eb9075a12680738731e9c92ddd96ad6 \ - --hash=sha256:7207272c9520203fea9b93843bb775d03e1cf88a80a936ce760f60bb5add92f3 \ - --hash=sha256:78ab247f0b5671cc887c31d33f9b3abfb88d2614b84e4303f1a63b46c046c8bd \ - --hash=sha256:7b1fd71c3843327f3bbc3237bedcdb6504fd50368ab3e04d0410e52ec293f5b8 \ - --hash=sha256:8ca4956c9ab567d87d59d49fa3704cf29e37109ad348f2d5223c9bf761a332e7 \ - --hash=sha256:91ab01c6cd00e39cde50173ba4ec68a1e578fee9279ba64f5221810a9e786533 \ - --hash=sha256:cd81bdc2b8219cb4b2556eea39d2e36bfa375a2dd021404f90a62e44efaaf957 \ - --hash=sha256:da8435a3bd498419ee8c13c34b89b5005130a476bda1d6ca8cfdde3de35cd650 \ - --hash=sha256:de4313d7f575474c8f5a12e163f6d89c0a878bc49219641d49e6f1444369a90e \ - --hash=sha256:e27f100e1ff17f6feeb1f33968bc185bf8ce41ca557deee9d9bbbffeb72030b7 \ - --hash=sha256:f467a5fd23b4fc43ed86342641f3936a68ded707f4627622fa3f82a120e18256 +uvloop==0.20.0 \ + --hash=sha256:265a99a2ff41a0fd56c19c3838b29bf54d1d177964c300dad388b27e84fd7847 \ + --hash=sha256:2beee18efd33fa6fdb0976e18475a4042cd31c7433c866e8a09ab604c7c22ff2 \ + --hash=sha256:35968fc697b0527a06e134999eef859b4034b37aebca537daeb598b9d45a137b \ + --hash=sha256:36c530d8fa03bfa7085af54a48f2ca16ab74df3ec7108a46ba82fd8b411a2315 \ + --hash=sha256:3a609780e942d43a275a617c0839d85f95c334bad29c4c0918252085113285b5 \ + --hash=sha256:4603ca714a754fc8d9b197e325db25b2ea045385e8a3ad05d3463de725fdf469 \ + --hash=sha256:4b75f2950ddb6feed85336412b9a0c310a2edbcf4cf931aa5cfe29034829676d \ + --hash=sha256:4f44af67bf39af25db4c1ac27e82e9665717f9c26af2369c404be865c8818dcf \ + --hash=sha256:6462c95f48e2d8d4c993a2950cd3d31ab061864d1c226bbf0ee2f1a8f36674b9 \ + --hash=sha256:649c33034979273fa71aa25d0fe120ad1777c551d8c4cd2c0c9851d88fcb13ab \ + --hash=sha256:746242cd703dc2b37f9d8b9f173749c15e9a918ddb021575a0205ec29a38d31e \ + --hash=sha256:77fbc69c287596880ecec2d4c7a62346bef08b6209749bf6ce8c22bbaca0239e \ + --hash=sha256:80dc1b139516be2077b3e57ce1cb65bfed09149e1d175e0478e7a987863b68f0 \ + --hash=sha256:82edbfd3df39fb3d108fc079ebc461330f7c2e33dbd002d146bf7c445ba6e756 \ + --hash=sha256:89e8d33bb88d7263f74dc57d69f0063e06b5a5ce50bb9a6b32f5fcbe655f9e73 \ + --hash=sha256:94707205efbe809dfa3a0d09c08bef1352f5d3d6612a506f10a319933757c006 \ + --hash=sha256:95720bae002ac357202e0d866128eb1ac82545bcf0b549b9abe91b5178d9b541 \ + --hash=sha256:9b04d96188d365151d1af41fa2d23257b674e7ead68cfd61c725a422764062ae \ + --hash=sha256:9d0fba61846f294bce41eb44d60d58136090ea2b5b99efd21cbdf4e21927c56a \ + --hash=sha256:9ebafa0b96c62881d5cafa02d9da2e44c23f9f0cd829f3a32a6aff771449c996 \ + --hash=sha256:a0fac7be202596c7126146660725157d4813aa29a4cc990fe51346f75ff8fde7 \ + --hash=sha256:aea15c78e0d9ad6555ed201344ae36db5c63d428818b4b2a42842b3870127c00 \ + --hash=sha256:b10c2956efcecb981bf9cfb8184d27d5d64b9033f917115a960b83f11bfa0d6b \ + --hash=sha256:b16696f10e59d7580979b420eedf6650010a4a9c3bd8113f24a103dfdb770b10 \ + --hash=sha256:d8c36fdf3e02cec92aed2d44f63565ad1522a499c654f07935c8f9d04db69e95 \ + --hash=sha256:e237f9c1e8a00e7d9ddaa288e535dc337a39bcbf679f290aee9d26df9e72bce9 \ + --hash=sha256:e50289c101495e0d1bb0bfcb4a60adde56e32f4449a67216a1ab2750aa84f037 \ + --hash=sha256:e7d61fe8e8d9335fac1bf8d5d82820b4808dd7a43020c149b63a1ada953d48a6 \ + --hash=sha256:e97152983442b499d7a71e44f29baa75b3b02e65d9c44ba53b10338e98dedb66 \ + --hash=sha256:f0e94b221295b5e69de57a1bd4aeb0b3a29f61be6e1b478bb8a69a73377db7ba \ + --hash=sha256:fee6044b64c965c425b65a4e17719953b96e065c5b7e09b599ff332bb2744bdf # via aio-run-runner verboselogs==1.7 \ --hash=sha256:d63f23bf568295b95d3530c6864a0b580cec70e7ff974177dead1e4ffbc6ff49 \ @@ -1611,9 +1611,9 @@ yarl==1.11.1 \ # via # -r requirements.in # aiohttp -zipp==3.19.2 \ - --hash=sha256:bf1dcf6450f873a13e952a29504887c89e6de7506209e5b1bcc3460135d4de19 \ - --hash=sha256:f091755f667055f2d02b32c53771a7a6c8b47e1fdbc4b72a8b9072b3eef8015c +zipp==3.20.2 \ + --hash=sha256:a817ac80d6cf4b23bf7f2828b7cabf326f15a001bea8b1f9b49631780ba28350 \ + --hash=sha256:bc9eb26f4506fda01b81bcde0ca78103b6e62f991b381fec825435c836edbc29 # via importlib-metadata zstandard==0.23.0 \ --hash=sha256:034b88913ecc1b097f528e42b539453fa82c3557e414b3de9d5632c80439a473 \ From 6bccf47f6c3a99ee06a9c68897b70bc771aa4da9 Mon Sep 17 00:00:00 2001 From: Takeshi Yoneda Date: Tue, 24 Sep 2024 00:33:55 +0900 Subject: [PATCH 55/65] dynamic_modules: switch to crate_universe to remove manual bindgen (#36240) Signed-off-by: Takeshi Yoneda --- WORKSPACE | 4 + bazel/dependency_imports.bzl | 12 + bazel/dependency_imports_extra.bzl | 5 + bazel/repository_locations.bzl | 8 +- source/extensions/dynamic_modules/abi.h | 4 - .../extensions/dynamic_modules/abi_version.h | 2 +- .../extensions/dynamic_modules/sdk/README.md | 4 - .../extensions/dynamic_modules/sdk/rust/BUILD | 19 + .../dynamic_modules/sdk/rust/Cargo.Bazel.lock | 2300 +++++++++++++++++ .../dynamic_modules/sdk/rust/Cargo.lock | 279 ++ .../dynamic_modules/sdk/rust/Cargo.toml | 3 + .../dynamic_modules/sdk/rust/README.md | 10 +- .../dynamic_modules/sdk/rust/build.rs | 17 + .../dynamic_modules/sdk/rust/src/abi.rs | 17 - .../dynamic_modules/sdk/rust/src/lib.rs | 11 +- .../dynamic_modules/dynamic_modules_test.cc | 3 +- .../test_data/c/program_init_fail.c | 2 + 17 files changed, 2662 insertions(+), 38 deletions(-) create mode 100644 bazel/dependency_imports_extra.bzl delete mode 100644 source/extensions/dynamic_modules/sdk/README.md create mode 100644 source/extensions/dynamic_modules/sdk/rust/Cargo.Bazel.lock create mode 100644 source/extensions/dynamic_modules/sdk/rust/build.rs delete mode 100644 source/extensions/dynamic_modules/sdk/rust/src/abi.rs diff --git a/WORKSPACE b/WORKSPACE index 9819ecb5ac..e4460bfc54 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -27,3 +27,7 @@ envoy_python_dependencies() load("//bazel:dependency_imports.bzl", "envoy_dependency_imports") envoy_dependency_imports() + +load("//bazel:dependency_imports_extra.bzl", "envoy_dependency_imports_extra") + +envoy_dependency_imports_extra() diff --git a/bazel/dependency_imports.bzl b/bazel/dependency_imports.bzl index 476ca5b9d2..c68eb4bf3e 100644 --- a/bazel/dependency_imports.bzl +++ b/bazel/dependency_imports.bzl @@ -14,6 +14,8 @@ load("@rules_foreign_cc//foreign_cc:repositories.bzl", "rules_foreign_cc_depende load("@rules_fuzzing//fuzzing:repositories.bzl", "rules_fuzzing_dependencies") load("@rules_pkg//:deps.bzl", "rules_pkg_dependencies") load("@rules_proto_grpc//:repositories.bzl", "rules_proto_grpc_toolchains") +load("@rules_rust//crate_universe:defs.bzl", "crates_repository") +load("@rules_rust//crate_universe:repositories.bzl", "crate_universe_dependencies") load("@rules_rust//rust:defs.bzl", "rust_common") load("@rules_rust//rust:repositories.bzl", "rules_rust_dependencies", "rust_register_toolchains", "rust_repository_set") @@ -51,6 +53,8 @@ def envoy_dependency_imports(go_version = GO_VERSION, jq_version = JQ_VERSION, y "wasm32-wasi", ], ) + crate_universe_dependencies() + crates_repositories() shellcheck_dependencies() proxy_wasm_rust_sdk_dependencies() rules_fuzzing_dependencies( @@ -196,3 +200,11 @@ def envoy_download_go_sdks(go_version): goarch = "arm64", version = go_version, ) + +def crates_repositories(): + crates_repository( + name = "dynamic_modules_rust_sdk_crate_index", + cargo_lockfile = "//source/extensions/dynamic_modules/sdk/rust:Cargo.lock", + lockfile = Label("//source/extensions/dynamic_modules/sdk/rust:Cargo.Bazel.lock"), + manifests = ["//source/extensions/dynamic_modules/sdk/rust:Cargo.toml"], + ) diff --git a/bazel/dependency_imports_extra.bzl b/bazel/dependency_imports_extra.bzl new file mode 100644 index 0000000000..de302800d2 --- /dev/null +++ b/bazel/dependency_imports_extra.bzl @@ -0,0 +1,5 @@ +load("@dynamic_modules_rust_sdk_crate_index//:defs.bzl", "crate_repositories") + +# Dependencies that rely on a first stage of envoy_dependency_imports() in dependency_imports.bzl. +def envoy_dependency_imports_extra(): + crate_repositories() diff --git a/bazel/repository_locations.bzl b/bazel/repository_locations.bzl index 6080c1b3c6..5eada04195 100644 --- a/bazel/repository_locations.bzl +++ b/bazel/repository_locations.bzl @@ -1453,9 +1453,11 @@ REPOSITORY_LOCATIONS_SPEC = dict( project_desc = "Bazel rust rules (used by Wasm)", project_url = "https://github.com/bazelbuild/rules_rust", version = "0.51.0", - strip_prefix = "rules_rust-{version}", - sha256 = "44ffa703f95fe693c15fefb58432ad009379848d24012338a3c2eb9951b371e7", - urls = ["https://github.com/bazelbuild/rules_rust/archive/{version}.tar.gz"], + sha256 = "042acfb73469b2d1848fe148d81c3422c61ea47a9e1900f1c9ec36f51e8e7193", + # Note: rules_rust should point to the releases, not archive to avoid the hassle of bootstrapping in crate_universe. + # This is described in https://bazelbuild.github.io/rules_rust/crate_universe.html#setup, otherwise bootstrap + # is required which in turn requires a system CC toolchains, not the bazel controlled ones. + urls = ["https://github.com/bazelbuild/rules_rust/releases/download/{version}/rules_rust-v{version}.tar.gz"], use_category = [ "controlplane", "dataplane_core", diff --git a/source/extensions/dynamic_modules/abi.h b/source/extensions/dynamic_modules/abi.h index 460dc00cef..badf6b962e 100644 --- a/source/extensions/dynamic_modules/abi.h +++ b/source/extensions/dynamic_modules/abi.h @@ -14,11 +14,7 @@ // same version of the ABI. #ifdef __cplusplus -#include - extern "C" { -#else -#include #endif // ----------------------------------------------------------------------------- diff --git a/source/extensions/dynamic_modules/abi_version.h b/source/extensions/dynamic_modules/abi_version.h index 6262f9b54b..1e17a9a938 100644 --- a/source/extensions/dynamic_modules/abi_version.h +++ b/source/extensions/dynamic_modules/abi_version.h @@ -6,7 +6,7 @@ namespace DynamicModules { #endif // This is the ABI version calculated as a sha256 hash of the ABI header files. When the ABI // changes, this value must change, and the correctness of this value is checked by the test. -const char* kAbiVersion = "749b1e6bf97309b7d171009700a80e651ac61e35f9770c24a63460d765895a51"; +const char* kAbiVersion = "4293760426255b24c25b97a18d9fd31b4d1956f10ba0ff2f723580a46ee8fa21"; #ifdef __cplusplus } // namespace DynamicModules diff --git a/source/extensions/dynamic_modules/sdk/README.md b/source/extensions/dynamic_modules/sdk/README.md deleted file mode 100644 index 64d61baa62..0000000000 --- a/source/extensions/dynamic_modules/sdk/README.md +++ /dev/null @@ -1,4 +0,0 @@ -## Dynamic Modules SDKs - -This directory contains the SDKs for the Dynamic Modules feature. Each SDK passes the same set of tests and -is guaranteed to provide the same functionality. diff --git a/source/extensions/dynamic_modules/sdk/rust/BUILD b/source/extensions/dynamic_modules/sdk/rust/BUILD index 480a9432eb..b3eecb438d 100644 --- a/source/extensions/dynamic_modules/sdk/rust/BUILD +++ b/source/extensions/dynamic_modules/sdk/rust/BUILD @@ -1,3 +1,5 @@ +load("@dynamic_modules_rust_sdk_crate_index//:defs.bzl", "all_crate_deps") +load("@rules_rust//cargo:defs.bzl", "cargo_build_script") load("@rules_rust//rust:defs.bzl", "rust_library") load( "//bazel:envoy_build_system.bzl", @@ -8,8 +10,25 @@ licenses(["notice"]) # Apache 2 envoy_extension_package() +cargo_build_script( + name = "build_script", + srcs = ["build.rs"], + data = [ + "//source/extensions/dynamic_modules:abi.h", + "//source/extensions/dynamic_modules:abi_version.h", + ], + edition = "2021", + deps = all_crate_deps( + build = True, + normal = True, + ), +) + rust_library( name = "envoy_proxy_dynamic_modules_rust_sdk", srcs = glob(["src/**/*.rs"]), edition = "2021", + deps = all_crate_deps( + normal = True, + ) + [":build_script"], ) diff --git a/source/extensions/dynamic_modules/sdk/rust/Cargo.Bazel.lock b/source/extensions/dynamic_modules/sdk/rust/Cargo.Bazel.lock new file mode 100644 index 0000000000..fa6012f406 --- /dev/null +++ b/source/extensions/dynamic_modules/sdk/rust/Cargo.Bazel.lock @@ -0,0 +1,2300 @@ +{ + "checksum": "96b309ddded40cf6f46a62829d15a02d7253b4cc94af2ac1890e492f9c07e93f", + "crates": { + "aho-corasick 1.1.3": { + "name": "aho-corasick", + "version": "1.1.3", + "package_url": "https://github.com/BurntSushi/aho-corasick", + "repository": { + "Http": { + "url": "https://static.crates.io/crates/aho-corasick/1.1.3/download", + "sha256": "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" + } + }, + "targets": [ + { + "Library": { + "crate_name": "aho_corasick", + "crate_root": "src/lib.rs", + "srcs": { + "allow_empty": true, + "include": [ + "**/*.rs" + ] + } + } + } + ], + "library_target_name": "aho_corasick", + "common_attrs": { + "compile_data_glob": [ + "**" + ], + "edition": "2021", + "version": "1.1.3" + }, + "license": "Unlicense OR MIT", + "license_ids": [ + "MIT", + "Unlicense" + ], + "license_file": "LICENSE-MIT" + }, + "bindgen 0.70.1": { + "name": "bindgen", + "version": "0.70.1", + "package_url": "https://github.com/rust-lang/rust-bindgen", + "repository": { + "Http": { + "url": "https://static.crates.io/crates/bindgen/0.70.1/download", + "sha256": "f49d8fed880d473ea71efb9bf597651e77201bdd4893efe54c9e5d65ae04ce6f" + } + }, + "targets": [ + { + "Library": { + "crate_name": "bindgen", + "crate_root": "lib.rs", + "srcs": { + "allow_empty": true, + "include": [ + "**/*.rs" + ] + } + } + }, + { + "BuildScript": { + "crate_name": "build_script_build", + "crate_root": "build.rs", + "srcs": { + "allow_empty": true, + "include": [ + "**/*.rs" + ] + } + } + } + ], + "library_target_name": "bindgen", + "common_attrs": { + "compile_data_glob": [ + "**" + ], + "crate_features": { + "common": [ + "default", + "logging", + "prettyplease", + "runtime" + ], + "selects": {} + }, + "deps": { + "common": [ + { + "id": "bindgen 0.70.1", + "target": "build_script_build" + }, + { + "id": "bitflags 2.6.0", + "target": "bitflags" + }, + { + "id": "cexpr 0.6.0", + "target": "cexpr" + }, + { + "id": "clang-sys 1.8.1", + "target": "clang_sys" + }, + { + "id": "itertools 0.13.0", + "target": "itertools" + }, + { + "id": "log 0.4.22", + "target": "log" + }, + { + "id": "prettyplease 0.2.22", + "target": "prettyplease" + }, + { + "id": "proc-macro2 1.0.86", + "target": "proc_macro2" + }, + { + "id": "quote 1.0.37", + "target": "quote" + }, + { + "id": "regex 1.10.6", + "target": "regex" + }, + { + "id": "rustc-hash 1.1.0", + "target": "rustc_hash" + }, + { + "id": "shlex 1.3.0", + "target": "shlex" + }, + { + "id": "syn 2.0.77", + "target": "syn" + } + ], + "selects": {} + }, + "edition": "2018", + "version": "0.70.1" + }, + "build_script_attrs": { + "compile_data_glob": [ + "**" + ], + "data_glob": [ + "**" + ], + "link_deps": { + "common": [ + { + "id": "clang-sys 1.8.1", + "target": "clang_sys" + }, + { + "id": "prettyplease 0.2.22", + "target": "prettyplease" + } + ], + "selects": {} + } + }, + "license": "BSD-3-Clause", + "license_ids": [ + "BSD-3-Clause" + ], + "license_file": "LICENSE" + }, + "bitflags 2.6.0": { + "name": "bitflags", + "version": "2.6.0", + "package_url": "https://github.com/bitflags/bitflags", + "repository": { + "Http": { + "url": "https://static.crates.io/crates/bitflags/2.6.0/download", + "sha256": "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" + } + }, + "targets": [ + { + "Library": { + "crate_name": "bitflags", + "crate_root": "src/lib.rs", + "srcs": { + "allow_empty": true, + "include": [ + "**/*.rs" + ] + } + } + } + ], + "library_target_name": "bitflags", + "common_attrs": { + "compile_data_glob": [ + "**" + ], + "edition": "2021", + "version": "2.6.0" + }, + "license": "MIT OR Apache-2.0", + "license_ids": [ + "Apache-2.0", + "MIT" + ], + "license_file": "LICENSE-APACHE" + }, + "cexpr 0.6.0": { + "name": "cexpr", + "version": "0.6.0", + "package_url": "https://github.com/jethrogb/rust-cexpr", + "repository": { + "Http": { + "url": "https://static.crates.io/crates/cexpr/0.6.0/download", + "sha256": "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" + } + }, + "targets": [ + { + "Library": { + "crate_name": "cexpr", + "crate_root": "src/lib.rs", + "srcs": { + "allow_empty": true, + "include": [ + "**/*.rs" + ] + } + } + } + ], + "library_target_name": "cexpr", + "common_attrs": { + "compile_data_glob": [ + "**" + ], + "deps": { + "common": [ + { + "id": "nom 7.1.3", + "target": "nom" + } + ], + "selects": {} + }, + "edition": "2018", + "version": "0.6.0" + }, + "license": "Apache-2.0/MIT", + "license_ids": [ + "Apache-2.0", + "MIT" + ], + "license_file": "LICENSE-APACHE" + }, + "cfg-if 1.0.0": { + "name": "cfg-if", + "version": "1.0.0", + "package_url": "https://github.com/alexcrichton/cfg-if", + "repository": { + "Http": { + "url": "https://static.crates.io/crates/cfg-if/1.0.0/download", + "sha256": "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + } + }, + "targets": [ + { + "Library": { + "crate_name": "cfg_if", + "crate_root": "src/lib.rs", + "srcs": { + "allow_empty": true, + "include": [ + "**/*.rs" + ] + } + } + } + ], + "library_target_name": "cfg_if", + "common_attrs": { + "compile_data_glob": [ + "**" + ], + "edition": "2018", + "version": "1.0.0" + }, + "license": "MIT/Apache-2.0", + "license_ids": [ + "Apache-2.0", + "MIT" + ], + "license_file": "LICENSE-APACHE" + }, + "clang-sys 1.8.1": { + "name": "clang-sys", + "version": "1.8.1", + "package_url": "https://github.com/KyleMayes/clang-sys", + "repository": { + "Http": { + "url": "https://static.crates.io/crates/clang-sys/1.8.1/download", + "sha256": "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4" + } + }, + "targets": [ + { + "Library": { + "crate_name": "clang_sys", + "crate_root": "src/lib.rs", + "srcs": { + "allow_empty": true, + "include": [ + "**/*.rs" + ] + } + } + }, + { + "BuildScript": { + "crate_name": "build_script_build", + "crate_root": "build.rs", + "srcs": { + "allow_empty": true, + "include": [ + "**/*.rs" + ] + } + } + } + ], + "library_target_name": "clang_sys", + "common_attrs": { + "compile_data_glob": [ + "**" + ], + "crate_features": { + "common": [ + "clang_3_5", + "clang_3_6", + "clang_3_7", + "clang_3_8", + "clang_3_9", + "clang_4_0", + "clang_5_0", + "clang_6_0", + "libloading", + "runtime" + ], + "selects": {} + }, + "deps": { + "common": [ + { + "id": "clang-sys 1.8.1", + "target": "build_script_build" + }, + { + "id": "glob 0.3.1", + "target": "glob" + }, + { + "id": "libc 0.2.158", + "target": "libc" + }, + { + "id": "libloading 0.8.5", + "target": "libloading" + } + ], + "selects": {} + }, + "edition": "2021", + "version": "1.8.1" + }, + "build_script_attrs": { + "compile_data_glob": [ + "**" + ], + "data_glob": [ + "**" + ], + "deps": { + "common": [ + { + "id": "glob 0.3.1", + "target": "glob" + } + ], + "selects": {} + }, + "links": "clang" + }, + "license": "Apache-2.0", + "license_ids": [ + "Apache-2.0" + ], + "license_file": "LICENSE.txt" + }, + "either 1.13.0": { + "name": "either", + "version": "1.13.0", + "package_url": "https://github.com/rayon-rs/either", + "repository": { + "Http": { + "url": "https://static.crates.io/crates/either/1.13.0/download", + "sha256": "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" + } + }, + "targets": [ + { + "Library": { + "crate_name": "either", + "crate_root": "src/lib.rs", + "srcs": { + "allow_empty": true, + "include": [ + "**/*.rs" + ] + } + } + } + ], + "library_target_name": "either", + "common_attrs": { + "compile_data_glob": [ + "**" + ], + "edition": "2018", + "version": "1.13.0" + }, + "license": "MIT OR Apache-2.0", + "license_ids": [ + "Apache-2.0", + "MIT" + ], + "license_file": "LICENSE-APACHE" + }, + "envoy-proxy-dynamic-modules-rust-sdk 0.1.0": { + "name": "envoy-proxy-dynamic-modules-rust-sdk", + "version": "0.1.0", + "package_url": "https://github.com/envoyproxy/envoy", + "repository": null, + "targets": [ + { + "Library": { + "crate_name": "envoy_proxy_dynamic_modules_rust_sdk", + "crate_root": "src/lib.rs", + "srcs": { + "allow_empty": true, + "include": [ + "**/*.rs" + ] + } + } + }, + { + "BuildScript": { + "crate_name": "build_script_build", + "crate_root": "build.rs", + "srcs": { + "allow_empty": true, + "include": [ + "**/*.rs" + ] + } + } + } + ], + "library_target_name": "envoy_proxy_dynamic_modules_rust_sdk", + "common_attrs": { + "compile_data_glob": [ + "**" + ], + "deps": { + "common": [ + { + "id": "envoy-proxy-dynamic-modules-rust-sdk 0.1.0", + "target": "build_script_build" + } + ], + "selects": {} + }, + "edition": "2021", + "version": "0.1.0" + }, + "build_script_attrs": { + "compile_data_glob": [ + "**" + ], + "data_glob": [ + "**" + ], + "deps": { + "common": [ + { + "id": "bindgen 0.70.1", + "target": "bindgen" + } + ], + "selects": {} + } + }, + "license": "Apache-2.0", + "license_ids": [ + "Apache-2.0" + ], + "license_file": null + }, + "glob 0.3.1": { + "name": "glob", + "version": "0.3.1", + "package_url": "https://github.com/rust-lang/glob", + "repository": { + "Http": { + "url": "https://static.crates.io/crates/glob/0.3.1/download", + "sha256": "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" + } + }, + "targets": [ + { + "Library": { + "crate_name": "glob", + "crate_root": "src/lib.rs", + "srcs": { + "allow_empty": true, + "include": [ + "**/*.rs" + ] + } + } + } + ], + "library_target_name": "glob", + "common_attrs": { + "compile_data_glob": [ + "**" + ], + "edition": "2015", + "version": "0.3.1" + }, + "license": "MIT OR Apache-2.0", + "license_ids": [ + "Apache-2.0", + "MIT" + ], + "license_file": "LICENSE-APACHE" + }, + "itertools 0.13.0": { + "name": "itertools", + "version": "0.13.0", + "package_url": "https://github.com/rust-itertools/itertools", + "repository": { + "Http": { + "url": "https://static.crates.io/crates/itertools/0.13.0/download", + "sha256": "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" + } + }, + "targets": [ + { + "Library": { + "crate_name": "itertools", + "crate_root": "src/lib.rs", + "srcs": { + "allow_empty": true, + "include": [ + "**/*.rs" + ] + } + } + } + ], + "library_target_name": "itertools", + "common_attrs": { + "compile_data_glob": [ + "**" + ], + "deps": { + "common": [ + { + "id": "either 1.13.0", + "target": "either" + } + ], + "selects": {} + }, + "edition": "2018", + "version": "0.13.0" + }, + "license": "MIT OR Apache-2.0", + "license_ids": [ + "Apache-2.0", + "MIT" + ], + "license_file": "LICENSE-APACHE" + }, + "libc 0.2.158": { + "name": "libc", + "version": "0.2.158", + "package_url": "https://github.com/rust-lang/libc", + "repository": { + "Http": { + "url": "https://static.crates.io/crates/libc/0.2.158/download", + "sha256": "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439" + } + }, + "targets": [ + { + "Library": { + "crate_name": "libc", + "crate_root": "src/lib.rs", + "srcs": { + "allow_empty": true, + "include": [ + "**/*.rs" + ] + } + } + }, + { + "BuildScript": { + "crate_name": "build_script_build", + "crate_root": "build.rs", + "srcs": { + "allow_empty": true, + "include": [ + "**/*.rs" + ] + } + } + } + ], + "library_target_name": "libc", + "common_attrs": { + "compile_data_glob": [ + "**" + ], + "deps": { + "common": [ + { + "id": "libc 0.2.158", + "target": "build_script_build" + } + ], + "selects": {} + }, + "edition": "2015", + "version": "0.2.158" + }, + "build_script_attrs": { + "compile_data_glob": [ + "**" + ], + "data_glob": [ + "**" + ] + }, + "license": "MIT OR Apache-2.0", + "license_ids": [ + "Apache-2.0", + "MIT" + ], + "license_file": "LICENSE-APACHE" + }, + "libloading 0.8.5": { + "name": "libloading", + "version": "0.8.5", + "package_url": "https://github.com/nagisa/rust_libloading/", + "repository": { + "Http": { + "url": "https://static.crates.io/crates/libloading/0.8.5/download", + "sha256": "4979f22fdb869068da03c9f7528f8297c6fd2606bc3a4affe42e6a823fdb8da4" + } + }, + "targets": [ + { + "Library": { + "crate_name": "libloading", + "crate_root": "src/lib.rs", + "srcs": { + "allow_empty": true, + "include": [ + "**/*.rs" + ] + } + } + } + ], + "library_target_name": "libloading", + "common_attrs": { + "compile_data_glob": [ + "**" + ], + "deps": { + "common": [], + "selects": { + "cfg(unix)": [ + { + "id": "cfg-if 1.0.0", + "target": "cfg_if" + } + ], + "cfg(windows)": [ + { + "id": "windows-targets 0.52.6", + "target": "windows_targets" + } + ] + } + }, + "edition": "2015", + "version": "0.8.5" + }, + "license": "ISC", + "license_ids": [ + "ISC" + ], + "license_file": "LICENSE" + }, + "log 0.4.22": { + "name": "log", + "version": "0.4.22", + "package_url": "https://github.com/rust-lang/log", + "repository": { + "Http": { + "url": "https://static.crates.io/crates/log/0.4.22/download", + "sha256": "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" + } + }, + "targets": [ + { + "Library": { + "crate_name": "log", + "crate_root": "src/lib.rs", + "srcs": { + "allow_empty": true, + "include": [ + "**/*.rs" + ] + } + } + } + ], + "library_target_name": "log", + "common_attrs": { + "compile_data_glob": [ + "**" + ], + "edition": "2021", + "version": "0.4.22" + }, + "license": "MIT OR Apache-2.0", + "license_ids": [ + "Apache-2.0", + "MIT" + ], + "license_file": "LICENSE-APACHE" + }, + "memchr 2.7.4": { + "name": "memchr", + "version": "2.7.4", + "package_url": "https://github.com/BurntSushi/memchr", + "repository": { + "Http": { + "url": "https://static.crates.io/crates/memchr/2.7.4/download", + "sha256": "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + } + }, + "targets": [ + { + "Library": { + "crate_name": "memchr", + "crate_root": "src/lib.rs", + "srcs": { + "allow_empty": true, + "include": [ + "**/*.rs" + ] + } + } + } + ], + "library_target_name": "memchr", + "common_attrs": { + "compile_data_glob": [ + "**" + ], + "crate_features": { + "common": [ + "alloc", + "std" + ], + "selects": {} + }, + "edition": "2021", + "version": "2.7.4" + }, + "license": "Unlicense OR MIT", + "license_ids": [ + "MIT", + "Unlicense" + ], + "license_file": "LICENSE-MIT" + }, + "minimal-lexical 0.2.1": { + "name": "minimal-lexical", + "version": "0.2.1", + "package_url": "https://github.com/Alexhuszagh/minimal-lexical", + "repository": { + "Http": { + "url": "https://static.crates.io/crates/minimal-lexical/0.2.1/download", + "sha256": "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + } + }, + "targets": [ + { + "Library": { + "crate_name": "minimal_lexical", + "crate_root": "src/lib.rs", + "srcs": { + "allow_empty": true, + "include": [ + "**/*.rs" + ] + } + } + } + ], + "library_target_name": "minimal_lexical", + "common_attrs": { + "compile_data_glob": [ + "**" + ], + "crate_features": { + "common": [ + "std" + ], + "selects": {} + }, + "edition": "2018", + "version": "0.2.1" + }, + "license": "MIT/Apache-2.0", + "license_ids": [ + "Apache-2.0", + "MIT" + ], + "license_file": "LICENSE-APACHE" + }, + "nom 7.1.3": { + "name": "nom", + "version": "7.1.3", + "package_url": "https://github.com/Geal/nom", + "repository": { + "Http": { + "url": "https://static.crates.io/crates/nom/7.1.3/download", + "sha256": "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" + } + }, + "targets": [ + { + "Library": { + "crate_name": "nom", + "crate_root": "src/lib.rs", + "srcs": { + "allow_empty": true, + "include": [ + "**/*.rs" + ] + } + } + } + ], + "library_target_name": "nom", + "common_attrs": { + "compile_data_glob": [ + "**" + ], + "crate_features": { + "common": [ + "alloc", + "std" + ], + "selects": {} + }, + "deps": { + "common": [ + { + "id": "memchr 2.7.4", + "target": "memchr" + }, + { + "id": "minimal-lexical 0.2.1", + "target": "minimal_lexical" + } + ], + "selects": {} + }, + "edition": "2018", + "version": "7.1.3" + }, + "license": "MIT", + "license_ids": [ + "MIT" + ], + "license_file": "LICENSE" + }, + "prettyplease 0.2.22": { + "name": "prettyplease", + "version": "0.2.22", + "package_url": "https://github.com/dtolnay/prettyplease", + "repository": { + "Http": { + "url": "https://static.crates.io/crates/prettyplease/0.2.22/download", + "sha256": "479cf940fbbb3426c32c5d5176f62ad57549a0bb84773423ba8be9d089f5faba" + } + }, + "targets": [ + { + "Library": { + "crate_name": "prettyplease", + "crate_root": "src/lib.rs", + "srcs": { + "allow_empty": true, + "include": [ + "**/*.rs" + ] + } + } + }, + { + "BuildScript": { + "crate_name": "build_script_build", + "crate_root": "build.rs", + "srcs": { + "allow_empty": true, + "include": [ + "**/*.rs" + ] + } + } + } + ], + "library_target_name": "prettyplease", + "common_attrs": { + "compile_data_glob": [ + "**" + ], + "crate_features": { + "common": [ + "verbatim" + ], + "selects": {} + }, + "deps": { + "common": [ + { + "id": "prettyplease 0.2.22", + "target": "build_script_build" + }, + { + "id": "proc-macro2 1.0.86", + "target": "proc_macro2" + }, + { + "id": "syn 2.0.77", + "target": "syn" + } + ], + "selects": {} + }, + "edition": "2021", + "version": "0.2.22" + }, + "build_script_attrs": { + "compile_data_glob": [ + "**" + ], + "data_glob": [ + "**" + ], + "links": "prettyplease02" + }, + "license": "MIT OR Apache-2.0", + "license_ids": [ + "Apache-2.0", + "MIT" + ], + "license_file": "LICENSE-APACHE" + }, + "proc-macro2 1.0.86": { + "name": "proc-macro2", + "version": "1.0.86", + "package_url": "https://github.com/dtolnay/proc-macro2", + "repository": { + "Http": { + "url": "https://static.crates.io/crates/proc-macro2/1.0.86/download", + "sha256": "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" + } + }, + "targets": [ + { + "Library": { + "crate_name": "proc_macro2", + "crate_root": "src/lib.rs", + "srcs": { + "allow_empty": true, + "include": [ + "**/*.rs" + ] + } + } + }, + { + "BuildScript": { + "crate_name": "build_script_build", + "crate_root": "build.rs", + "srcs": { + "allow_empty": true, + "include": [ + "**/*.rs" + ] + } + } + } + ], + "library_target_name": "proc_macro2", + "common_attrs": { + "compile_data_glob": [ + "**" + ], + "crate_features": { + "common": [ + "proc-macro" + ], + "selects": {} + }, + "deps": { + "common": [ + { + "id": "proc-macro2 1.0.86", + "target": "build_script_build" + }, + { + "id": "unicode-ident 1.0.13", + "target": "unicode_ident" + } + ], + "selects": {} + }, + "edition": "2021", + "version": "1.0.86" + }, + "build_script_attrs": { + "compile_data_glob": [ + "**" + ], + "data_glob": [ + "**" + ] + }, + "license": "MIT OR Apache-2.0", + "license_ids": [ + "Apache-2.0", + "MIT" + ], + "license_file": "LICENSE-APACHE" + }, + "quote 1.0.37": { + "name": "quote", + "version": "1.0.37", + "package_url": "https://github.com/dtolnay/quote", + "repository": { + "Http": { + "url": "https://static.crates.io/crates/quote/1.0.37/download", + "sha256": "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" + } + }, + "targets": [ + { + "Library": { + "crate_name": "quote", + "crate_root": "src/lib.rs", + "srcs": { + "allow_empty": true, + "include": [ + "**/*.rs" + ] + } + } + } + ], + "library_target_name": "quote", + "common_attrs": { + "compile_data_glob": [ + "**" + ], + "crate_features": { + "common": [ + "proc-macro" + ], + "selects": {} + }, + "deps": { + "common": [ + { + "id": "proc-macro2 1.0.86", + "target": "proc_macro2" + } + ], + "selects": {} + }, + "edition": "2018", + "version": "1.0.37" + }, + "license": "MIT OR Apache-2.0", + "license_ids": [ + "Apache-2.0", + "MIT" + ], + "license_file": "LICENSE-APACHE" + }, + "regex 1.10.6": { + "name": "regex", + "version": "1.10.6", + "package_url": "https://github.com/rust-lang/regex", + "repository": { + "Http": { + "url": "https://static.crates.io/crates/regex/1.10.6/download", + "sha256": "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619" + } + }, + "targets": [ + { + "Library": { + "crate_name": "regex", + "crate_root": "src/lib.rs", + "srcs": { + "allow_empty": true, + "include": [ + "**/*.rs" + ] + } + } + } + ], + "library_target_name": "regex", + "common_attrs": { + "compile_data_glob": [ + "**" + ], + "crate_features": { + "common": [ + "std", + "unicode-perl" + ], + "selects": {} + }, + "deps": { + "common": [ + { + "id": "regex-automata 0.4.7", + "target": "regex_automata" + }, + { + "id": "regex-syntax 0.8.4", + "target": "regex_syntax" + } + ], + "selects": {} + }, + "edition": "2021", + "version": "1.10.6" + }, + "license": "MIT OR Apache-2.0", + "license_ids": [ + "Apache-2.0", + "MIT" + ], + "license_file": "LICENSE-APACHE" + }, + "regex-automata 0.4.7": { + "name": "regex-automata", + "version": "0.4.7", + "package_url": "https://github.com/rust-lang/regex/tree/master/regex-automata", + "repository": { + "Http": { + "url": "https://static.crates.io/crates/regex-automata/0.4.7/download", + "sha256": "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" + } + }, + "targets": [ + { + "Library": { + "crate_name": "regex_automata", + "crate_root": "src/lib.rs", + "srcs": { + "allow_empty": true, + "include": [ + "**/*.rs" + ] + } + } + } + ], + "library_target_name": "regex_automata", + "common_attrs": { + "compile_data_glob": [ + "**" + ], + "crate_features": { + "common": [ + "alloc", + "meta", + "nfa-pikevm", + "nfa-thompson", + "std", + "syntax", + "unicode-perl", + "unicode-word-boundary" + ], + "selects": {} + }, + "deps": { + "common": [ + { + "id": "regex-syntax 0.8.4", + "target": "regex_syntax" + } + ], + "selects": {} + }, + "edition": "2021", + "version": "0.4.7" + }, + "license": "MIT OR Apache-2.0", + "license_ids": [ + "Apache-2.0", + "MIT" + ], + "license_file": "LICENSE-APACHE" + }, + "regex-syntax 0.8.4": { + "name": "regex-syntax", + "version": "0.8.4", + "package_url": "https://github.com/rust-lang/regex/tree/master/regex-syntax", + "repository": { + "Http": { + "url": "https://static.crates.io/crates/regex-syntax/0.8.4/download", + "sha256": "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" + } + }, + "targets": [ + { + "Library": { + "crate_name": "regex_syntax", + "crate_root": "src/lib.rs", + "srcs": { + "allow_empty": true, + "include": [ + "**/*.rs" + ] + } + } + } + ], + "library_target_name": "regex_syntax", + "common_attrs": { + "compile_data_glob": [ + "**" + ], + "crate_features": { + "common": [ + "std", + "unicode-perl" + ], + "selects": {} + }, + "edition": "2021", + "version": "0.8.4" + }, + "license": "MIT OR Apache-2.0", + "license_ids": [ + "Apache-2.0", + "MIT" + ], + "license_file": "LICENSE-APACHE" + }, + "rustc-hash 1.1.0": { + "name": "rustc-hash", + "version": "1.1.0", + "package_url": "https://github.com/rust-lang-nursery/rustc-hash", + "repository": { + "Http": { + "url": "https://static.crates.io/crates/rustc-hash/1.1.0/download", + "sha256": "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + } + }, + "targets": [ + { + "Library": { + "crate_name": "rustc_hash", + "crate_root": "src/lib.rs", + "srcs": { + "allow_empty": true, + "include": [ + "**/*.rs" + ] + } + } + } + ], + "library_target_name": "rustc_hash", + "common_attrs": { + "compile_data_glob": [ + "**" + ], + "crate_features": { + "common": [ + "default", + "std" + ], + "selects": {} + }, + "edition": "2015", + "version": "1.1.0" + }, + "license": "Apache-2.0/MIT", + "license_ids": [ + "Apache-2.0", + "MIT" + ], + "license_file": "LICENSE-APACHE" + }, + "shlex 1.3.0": { + "name": "shlex", + "version": "1.3.0", + "package_url": "https://github.com/comex/rust-shlex", + "repository": { + "Http": { + "url": "https://static.crates.io/crates/shlex/1.3.0/download", + "sha256": "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + } + }, + "targets": [ + { + "Library": { + "crate_name": "shlex", + "crate_root": "src/lib.rs", + "srcs": { + "allow_empty": true, + "include": [ + "**/*.rs" + ] + } + } + } + ], + "library_target_name": "shlex", + "common_attrs": { + "compile_data_glob": [ + "**" + ], + "crate_features": { + "common": [ + "default", + "std" + ], + "selects": {} + }, + "edition": "2015", + "version": "1.3.0" + }, + "license": "MIT OR Apache-2.0", + "license_ids": [ + "Apache-2.0", + "MIT" + ], + "license_file": "LICENSE-APACHE" + }, + "syn 2.0.77": { + "name": "syn", + "version": "2.0.77", + "package_url": "https://github.com/dtolnay/syn", + "repository": { + "Http": { + "url": "https://static.crates.io/crates/syn/2.0.77/download", + "sha256": "9f35bcdf61fd8e7be6caf75f429fdca8beb3ed76584befb503b1569faee373ed" + } + }, + "targets": [ + { + "Library": { + "crate_name": "syn", + "crate_root": "src/lib.rs", + "srcs": { + "allow_empty": true, + "include": [ + "**/*.rs" + ] + } + } + } + ], + "library_target_name": "syn", + "common_attrs": { + "compile_data_glob": [ + "**" + ], + "crate_features": { + "common": [ + "clone-impls", + "default", + "derive", + "extra-traits", + "full", + "parsing", + "printing", + "proc-macro", + "visit-mut" + ], + "selects": {} + }, + "deps": { + "common": [ + { + "id": "proc-macro2 1.0.86", + "target": "proc_macro2" + }, + { + "id": "quote 1.0.37", + "target": "quote" + }, + { + "id": "unicode-ident 1.0.13", + "target": "unicode_ident" + } + ], + "selects": {} + }, + "edition": "2021", + "version": "2.0.77" + }, + "license": "MIT OR Apache-2.0", + "license_ids": [ + "Apache-2.0", + "MIT" + ], + "license_file": "LICENSE-APACHE" + }, + "unicode-ident 1.0.13": { + "name": "unicode-ident", + "version": "1.0.13", + "package_url": "https://github.com/dtolnay/unicode-ident", + "repository": { + "Http": { + "url": "https://static.crates.io/crates/unicode-ident/1.0.13/download", + "sha256": "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" + } + }, + "targets": [ + { + "Library": { + "crate_name": "unicode_ident", + "crate_root": "src/lib.rs", + "srcs": { + "allow_empty": true, + "include": [ + "**/*.rs" + ] + } + } + } + ], + "library_target_name": "unicode_ident", + "common_attrs": { + "compile_data_glob": [ + "**" + ], + "edition": "2018", + "version": "1.0.13" + }, + "license": "(MIT OR Apache-2.0) AND Unicode-DFS-2016", + "license_ids": [ + "Apache-2.0", + "MIT", + "Unicode-DFS-2016" + ], + "license_file": "LICENSE-APACHE" + }, + "windows-targets 0.52.6": { + "name": "windows-targets", + "version": "0.52.6", + "package_url": "https://github.com/microsoft/windows-rs", + "repository": { + "Http": { + "url": "https://static.crates.io/crates/windows-targets/0.52.6/download", + "sha256": "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" + } + }, + "targets": [ + { + "Library": { + "crate_name": "windows_targets", + "crate_root": "src/lib.rs", + "srcs": { + "allow_empty": true, + "include": [ + "**/*.rs" + ] + } + } + } + ], + "library_target_name": "windows_targets", + "common_attrs": { + "compile_data_glob": [ + "**" + ], + "deps": { + "common": [], + "selects": { + "aarch64-pc-windows-gnullvm": [ + { + "id": "windows_aarch64_gnullvm 0.52.6", + "target": "windows_aarch64_gnullvm" + } + ], + "cfg(all(any(target_arch = \"x86_64\", target_arch = \"arm64ec\"), target_env = \"msvc\", not(windows_raw_dylib)))": [ + { + "id": "windows_x86_64_msvc 0.52.6", + "target": "windows_x86_64_msvc" + } + ], + "cfg(all(target_arch = \"aarch64\", target_env = \"msvc\", not(windows_raw_dylib)))": [ + { + "id": "windows_aarch64_msvc 0.52.6", + "target": "windows_aarch64_msvc" + } + ], + "cfg(all(target_arch = \"x86\", target_env = \"gnu\", not(target_abi = \"llvm\"), not(windows_raw_dylib)))": [ + { + "id": "windows_i686_gnu 0.52.6", + "target": "windows_i686_gnu" + } + ], + "cfg(all(target_arch = \"x86\", target_env = \"msvc\", not(windows_raw_dylib)))": [ + { + "id": "windows_i686_msvc 0.52.6", + "target": "windows_i686_msvc" + } + ], + "cfg(all(target_arch = \"x86_64\", target_env = \"gnu\", not(target_abi = \"llvm\"), not(windows_raw_dylib)))": [ + { + "id": "windows_x86_64_gnu 0.52.6", + "target": "windows_x86_64_gnu" + } + ], + "i686-pc-windows-gnullvm": [ + { + "id": "windows_i686_gnullvm 0.52.6", + "target": "windows_i686_gnullvm" + } + ], + "x86_64-pc-windows-gnullvm": [ + { + "id": "windows_x86_64_gnullvm 0.52.6", + "target": "windows_x86_64_gnullvm" + } + ] + } + }, + "edition": "2021", + "version": "0.52.6" + }, + "license": "MIT OR Apache-2.0", + "license_ids": [ + "Apache-2.0", + "MIT" + ], + "license_file": "license-apache-2.0" + }, + "windows_aarch64_gnullvm 0.52.6": { + "name": "windows_aarch64_gnullvm", + "version": "0.52.6", + "package_url": "https://github.com/microsoft/windows-rs", + "repository": { + "Http": { + "url": "https://static.crates.io/crates/windows_aarch64_gnullvm/0.52.6/download", + "sha256": "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + } + }, + "targets": [ + { + "Library": { + "crate_name": "windows_aarch64_gnullvm", + "crate_root": "src/lib.rs", + "srcs": { + "allow_empty": true, + "include": [ + "**/*.rs" + ] + } + } + }, + { + "BuildScript": { + "crate_name": "build_script_build", + "crate_root": "build.rs", + "srcs": { + "allow_empty": true, + "include": [ + "**/*.rs" + ] + } + } + } + ], + "library_target_name": "windows_aarch64_gnullvm", + "common_attrs": { + "compile_data_glob": [ + "**" + ], + "deps": { + "common": [ + { + "id": "windows_aarch64_gnullvm 0.52.6", + "target": "build_script_build" + } + ], + "selects": {} + }, + "edition": "2021", + "version": "0.52.6" + }, + "build_script_attrs": { + "compile_data_glob": [ + "**" + ], + "data_glob": [ + "**" + ] + }, + "license": "MIT OR Apache-2.0", + "license_ids": [ + "Apache-2.0", + "MIT" + ], + "license_file": "license-apache-2.0" + }, + "windows_aarch64_msvc 0.52.6": { + "name": "windows_aarch64_msvc", + "version": "0.52.6", + "package_url": "https://github.com/microsoft/windows-rs", + "repository": { + "Http": { + "url": "https://static.crates.io/crates/windows_aarch64_msvc/0.52.6/download", + "sha256": "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + } + }, + "targets": [ + { + "Library": { + "crate_name": "windows_aarch64_msvc", + "crate_root": "src/lib.rs", + "srcs": { + "allow_empty": true, + "include": [ + "**/*.rs" + ] + } + } + }, + { + "BuildScript": { + "crate_name": "build_script_build", + "crate_root": "build.rs", + "srcs": { + "allow_empty": true, + "include": [ + "**/*.rs" + ] + } + } + } + ], + "library_target_name": "windows_aarch64_msvc", + "common_attrs": { + "compile_data_glob": [ + "**" + ], + "deps": { + "common": [ + { + "id": "windows_aarch64_msvc 0.52.6", + "target": "build_script_build" + } + ], + "selects": {} + }, + "edition": "2021", + "version": "0.52.6" + }, + "build_script_attrs": { + "compile_data_glob": [ + "**" + ], + "data_glob": [ + "**" + ] + }, + "license": "MIT OR Apache-2.0", + "license_ids": [ + "Apache-2.0", + "MIT" + ], + "license_file": "license-apache-2.0" + }, + "windows_i686_gnu 0.52.6": { + "name": "windows_i686_gnu", + "version": "0.52.6", + "package_url": "https://github.com/microsoft/windows-rs", + "repository": { + "Http": { + "url": "https://static.crates.io/crates/windows_i686_gnu/0.52.6/download", + "sha256": "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + } + }, + "targets": [ + { + "Library": { + "crate_name": "windows_i686_gnu", + "crate_root": "src/lib.rs", + "srcs": { + "allow_empty": true, + "include": [ + "**/*.rs" + ] + } + } + }, + { + "BuildScript": { + "crate_name": "build_script_build", + "crate_root": "build.rs", + "srcs": { + "allow_empty": true, + "include": [ + "**/*.rs" + ] + } + } + } + ], + "library_target_name": "windows_i686_gnu", + "common_attrs": { + "compile_data_glob": [ + "**" + ], + "deps": { + "common": [ + { + "id": "windows_i686_gnu 0.52.6", + "target": "build_script_build" + } + ], + "selects": {} + }, + "edition": "2021", + "version": "0.52.6" + }, + "build_script_attrs": { + "compile_data_glob": [ + "**" + ], + "data_glob": [ + "**" + ] + }, + "license": "MIT OR Apache-2.0", + "license_ids": [ + "Apache-2.0", + "MIT" + ], + "license_file": "license-apache-2.0" + }, + "windows_i686_gnullvm 0.52.6": { + "name": "windows_i686_gnullvm", + "version": "0.52.6", + "package_url": "https://github.com/microsoft/windows-rs", + "repository": { + "Http": { + "url": "https://static.crates.io/crates/windows_i686_gnullvm/0.52.6/download", + "sha256": "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + } + }, + "targets": [ + { + "Library": { + "crate_name": "windows_i686_gnullvm", + "crate_root": "src/lib.rs", + "srcs": { + "allow_empty": true, + "include": [ + "**/*.rs" + ] + } + } + }, + { + "BuildScript": { + "crate_name": "build_script_build", + "crate_root": "build.rs", + "srcs": { + "allow_empty": true, + "include": [ + "**/*.rs" + ] + } + } + } + ], + "library_target_name": "windows_i686_gnullvm", + "common_attrs": { + "compile_data_glob": [ + "**" + ], + "deps": { + "common": [ + { + "id": "windows_i686_gnullvm 0.52.6", + "target": "build_script_build" + } + ], + "selects": {} + }, + "edition": "2021", + "version": "0.52.6" + }, + "build_script_attrs": { + "compile_data_glob": [ + "**" + ], + "data_glob": [ + "**" + ] + }, + "license": "MIT OR Apache-2.0", + "license_ids": [ + "Apache-2.0", + "MIT" + ], + "license_file": "license-apache-2.0" + }, + "windows_i686_msvc 0.52.6": { + "name": "windows_i686_msvc", + "version": "0.52.6", + "package_url": "https://github.com/microsoft/windows-rs", + "repository": { + "Http": { + "url": "https://static.crates.io/crates/windows_i686_msvc/0.52.6/download", + "sha256": "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + } + }, + "targets": [ + { + "Library": { + "crate_name": "windows_i686_msvc", + "crate_root": "src/lib.rs", + "srcs": { + "allow_empty": true, + "include": [ + "**/*.rs" + ] + } + } + }, + { + "BuildScript": { + "crate_name": "build_script_build", + "crate_root": "build.rs", + "srcs": { + "allow_empty": true, + "include": [ + "**/*.rs" + ] + } + } + } + ], + "library_target_name": "windows_i686_msvc", + "common_attrs": { + "compile_data_glob": [ + "**" + ], + "deps": { + "common": [ + { + "id": "windows_i686_msvc 0.52.6", + "target": "build_script_build" + } + ], + "selects": {} + }, + "edition": "2021", + "version": "0.52.6" + }, + "build_script_attrs": { + "compile_data_glob": [ + "**" + ], + "data_glob": [ + "**" + ] + }, + "license": "MIT OR Apache-2.0", + "license_ids": [ + "Apache-2.0", + "MIT" + ], + "license_file": "license-apache-2.0" + }, + "windows_x86_64_gnu 0.52.6": { + "name": "windows_x86_64_gnu", + "version": "0.52.6", + "package_url": "https://github.com/microsoft/windows-rs", + "repository": { + "Http": { + "url": "https://static.crates.io/crates/windows_x86_64_gnu/0.52.6/download", + "sha256": "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + } + }, + "targets": [ + { + "Library": { + "crate_name": "windows_x86_64_gnu", + "crate_root": "src/lib.rs", + "srcs": { + "allow_empty": true, + "include": [ + "**/*.rs" + ] + } + } + }, + { + "BuildScript": { + "crate_name": "build_script_build", + "crate_root": "build.rs", + "srcs": { + "allow_empty": true, + "include": [ + "**/*.rs" + ] + } + } + } + ], + "library_target_name": "windows_x86_64_gnu", + "common_attrs": { + "compile_data_glob": [ + "**" + ], + "deps": { + "common": [ + { + "id": "windows_x86_64_gnu 0.52.6", + "target": "build_script_build" + } + ], + "selects": {} + }, + "edition": "2021", + "version": "0.52.6" + }, + "build_script_attrs": { + "compile_data_glob": [ + "**" + ], + "data_glob": [ + "**" + ] + }, + "license": "MIT OR Apache-2.0", + "license_ids": [ + "Apache-2.0", + "MIT" + ], + "license_file": "license-apache-2.0" + }, + "windows_x86_64_gnullvm 0.52.6": { + "name": "windows_x86_64_gnullvm", + "version": "0.52.6", + "package_url": "https://github.com/microsoft/windows-rs", + "repository": { + "Http": { + "url": "https://static.crates.io/crates/windows_x86_64_gnullvm/0.52.6/download", + "sha256": "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + } + }, + "targets": [ + { + "Library": { + "crate_name": "windows_x86_64_gnullvm", + "crate_root": "src/lib.rs", + "srcs": { + "allow_empty": true, + "include": [ + "**/*.rs" + ] + } + } + }, + { + "BuildScript": { + "crate_name": "build_script_build", + "crate_root": "build.rs", + "srcs": { + "allow_empty": true, + "include": [ + "**/*.rs" + ] + } + } + } + ], + "library_target_name": "windows_x86_64_gnullvm", + "common_attrs": { + "compile_data_glob": [ + "**" + ], + "deps": { + "common": [ + { + "id": "windows_x86_64_gnullvm 0.52.6", + "target": "build_script_build" + } + ], + "selects": {} + }, + "edition": "2021", + "version": "0.52.6" + }, + "build_script_attrs": { + "compile_data_glob": [ + "**" + ], + "data_glob": [ + "**" + ] + }, + "license": "MIT OR Apache-2.0", + "license_ids": [ + "Apache-2.0", + "MIT" + ], + "license_file": "license-apache-2.0" + }, + "windows_x86_64_msvc 0.52.6": { + "name": "windows_x86_64_msvc", + "version": "0.52.6", + "package_url": "https://github.com/microsoft/windows-rs", + "repository": { + "Http": { + "url": "https://static.crates.io/crates/windows_x86_64_msvc/0.52.6/download", + "sha256": "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + } + }, + "targets": [ + { + "Library": { + "crate_name": "windows_x86_64_msvc", + "crate_root": "src/lib.rs", + "srcs": { + "allow_empty": true, + "include": [ + "**/*.rs" + ] + } + } + }, + { + "BuildScript": { + "crate_name": "build_script_build", + "crate_root": "build.rs", + "srcs": { + "allow_empty": true, + "include": [ + "**/*.rs" + ] + } + } + } + ], + "library_target_name": "windows_x86_64_msvc", + "common_attrs": { + "compile_data_glob": [ + "**" + ], + "deps": { + "common": [ + { + "id": "windows_x86_64_msvc 0.52.6", + "target": "build_script_build" + } + ], + "selects": {} + }, + "edition": "2021", + "version": "0.52.6" + }, + "build_script_attrs": { + "compile_data_glob": [ + "**" + ], + "data_glob": [ + "**" + ] + }, + "license": "MIT OR Apache-2.0", + "license_ids": [ + "Apache-2.0", + "MIT" + ], + "license_file": "license-apache-2.0" + } + }, + "binary_crates": [], + "workspace_members": { + "envoy-proxy-dynamic-modules-rust-sdk 0.1.0": "source/extensions/dynamic_modules/sdk/rust" + }, + "conditions": { + "aarch64-apple-darwin": [ + "aarch64-apple-darwin" + ], + "aarch64-apple-ios": [ + "aarch64-apple-ios" + ], + "aarch64-apple-ios-sim": [ + "aarch64-apple-ios-sim" + ], + "aarch64-fuchsia": [ + "aarch64-fuchsia" + ], + "aarch64-linux-android": [ + "aarch64-linux-android" + ], + "aarch64-pc-windows-gnullvm": [], + "aarch64-pc-windows-msvc": [ + "aarch64-pc-windows-msvc" + ], + "aarch64-unknown-linux-gnu": [ + "aarch64-unknown-linux-gnu" + ], + "aarch64-unknown-nixos-gnu": [ + "aarch64-unknown-nixos-gnu" + ], + "aarch64-unknown-nto-qnx710": [ + "aarch64-unknown-nto-qnx710" + ], + "arm-unknown-linux-gnueabi": [ + "arm-unknown-linux-gnueabi" + ], + "armv7-linux-androideabi": [ + "armv7-linux-androideabi" + ], + "armv7-unknown-linux-gnueabi": [ + "armv7-unknown-linux-gnueabi" + ], + "cfg(all(any(target_arch = \"x86_64\", target_arch = \"arm64ec\"), target_env = \"msvc\", not(windows_raw_dylib)))": [ + "x86_64-pc-windows-msvc" + ], + "cfg(all(target_arch = \"aarch64\", target_env = \"msvc\", not(windows_raw_dylib)))": [ + "aarch64-pc-windows-msvc" + ], + "cfg(all(target_arch = \"x86\", target_env = \"gnu\", not(target_abi = \"llvm\"), not(windows_raw_dylib)))": [ + "i686-unknown-linux-gnu" + ], + "cfg(all(target_arch = \"x86\", target_env = \"msvc\", not(windows_raw_dylib)))": [ + "i686-pc-windows-msvc" + ], + "cfg(all(target_arch = \"x86_64\", target_env = \"gnu\", not(target_abi = \"llvm\"), not(windows_raw_dylib)))": [ + "x86_64-unknown-linux-gnu", + "x86_64-unknown-nixos-gnu" + ], + "cfg(unix)": [ + "aarch64-apple-darwin", + "aarch64-apple-ios", + "aarch64-apple-ios-sim", + "aarch64-fuchsia", + "aarch64-linux-android", + "aarch64-unknown-linux-gnu", + "aarch64-unknown-nixos-gnu", + "aarch64-unknown-nto-qnx710", + "arm-unknown-linux-gnueabi", + "armv7-linux-androideabi", + "armv7-unknown-linux-gnueabi", + "i686-apple-darwin", + "i686-linux-android", + "i686-unknown-freebsd", + "i686-unknown-linux-gnu", + "powerpc-unknown-linux-gnu", + "s390x-unknown-linux-gnu", + "x86_64-apple-darwin", + "x86_64-apple-ios", + "x86_64-fuchsia", + "x86_64-linux-android", + "x86_64-unknown-freebsd", + "x86_64-unknown-linux-gnu", + "x86_64-unknown-nixos-gnu" + ], + "cfg(windows)": [ + "aarch64-pc-windows-msvc", + "i686-pc-windows-msvc", + "x86_64-pc-windows-msvc" + ], + "i686-apple-darwin": [ + "i686-apple-darwin" + ], + "i686-linux-android": [ + "i686-linux-android" + ], + "i686-pc-windows-gnullvm": [], + "i686-pc-windows-msvc": [ + "i686-pc-windows-msvc" + ], + "i686-unknown-freebsd": [ + "i686-unknown-freebsd" + ], + "i686-unknown-linux-gnu": [ + "i686-unknown-linux-gnu" + ], + "powerpc-unknown-linux-gnu": [ + "powerpc-unknown-linux-gnu" + ], + "riscv32imc-unknown-none-elf": [ + "riscv32imc-unknown-none-elf" + ], + "riscv64gc-unknown-none-elf": [ + "riscv64gc-unknown-none-elf" + ], + "s390x-unknown-linux-gnu": [ + "s390x-unknown-linux-gnu" + ], + "thumbv7em-none-eabi": [ + "thumbv7em-none-eabi" + ], + "thumbv8m.main-none-eabi": [ + "thumbv8m.main-none-eabi" + ], + "wasm32-unknown-unknown": [ + "wasm32-unknown-unknown" + ], + "wasm32-wasi": [ + "wasm32-wasi" + ], + "x86_64-apple-darwin": [ + "x86_64-apple-darwin" + ], + "x86_64-apple-ios": [ + "x86_64-apple-ios" + ], + "x86_64-fuchsia": [ + "x86_64-fuchsia" + ], + "x86_64-linux-android": [ + "x86_64-linux-android" + ], + "x86_64-pc-windows-gnullvm": [], + "x86_64-pc-windows-msvc": [ + "x86_64-pc-windows-msvc" + ], + "x86_64-unknown-freebsd": [ + "x86_64-unknown-freebsd" + ], + "x86_64-unknown-linux-gnu": [ + "x86_64-unknown-linux-gnu" + ], + "x86_64-unknown-nixos-gnu": [ + "x86_64-unknown-nixos-gnu" + ], + "x86_64-unknown-none": [ + "x86_64-unknown-none" + ] + }, + "direct_deps": [ + "bindgen 0.70.1" + ], + "direct_dev_deps": [] +} diff --git a/source/extensions/dynamic_modules/sdk/rust/Cargo.lock b/source/extensions/dynamic_modules/sdk/rust/Cargo.lock index f6f126e020..8c86727781 100644 --- a/source/extensions/dynamic_modules/sdk/rust/Cargo.lock +++ b/source/extensions/dynamic_modules/sdk/rust/Cargo.lock @@ -2,6 +2,285 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + +[[package]] +name = "bindgen" +version = "0.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f49d8fed880d473ea71efb9bf597651e77201bdd4893efe54c9e5d65ae04ce6f" +dependencies = [ + "bitflags", + "cexpr", + "clang-sys", + "itertools", + "log", + "prettyplease", + "proc-macro2", + "quote", + "regex", + "rustc-hash", + "shlex", + "syn", +] + +[[package]] +name = "bitflags" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" + +[[package]] +name = "cexpr" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" +dependencies = [ + "nom", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "clang-sys" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4" +dependencies = [ + "glob", + "libc", + "libloading", +] + +[[package]] +name = "either" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" + [[package]] name = "envoy-proxy-dynamic-modules-rust-sdk" version = "0.1.0" +dependencies = [ + "bindgen", +] + +[[package]] +name = "glob" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" + +[[package]] +name = "itertools" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" +dependencies = [ + "either", +] + +[[package]] +name = "libc" +version = "0.2.158" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439" + +[[package]] +name = "libloading" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4979f22fdb869068da03c9f7528f8297c6fd2606bc3a4affe42e6a823fdb8da4" +dependencies = [ + "cfg-if", + "windows-targets", +] + +[[package]] +name = "log" +version = "0.4.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" + +[[package]] +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + +[[package]] +name = "prettyplease" +version = "0.2.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "479cf940fbbb3426c32c5d5176f62ad57549a0bb84773423ba8be9d089f5faba" +dependencies = [ + "proc-macro2", + "syn", +] + +[[package]] +name = "proc-macro2" +version = "1.0.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "regex" +version = "1.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" + +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "syn" +version = "2.0.77" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f35bcdf61fd8e7be6caf75f429fdca8beb3ed76584befb503b1569faee373ed" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "unicode-ident" +version = "1.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" diff --git a/source/extensions/dynamic_modules/sdk/rust/Cargo.toml b/source/extensions/dynamic_modules/sdk/rust/Cargo.toml index 3874a8a330..14a1faf635 100644 --- a/source/extensions/dynamic_modules/sdk/rust/Cargo.toml +++ b/source/extensions/dynamic_modules/sdk/rust/Cargo.toml @@ -9,4 +9,7 @@ repository = "https://github.com/envoyproxy/envoy" [dependencies] +[build-dependencies] +bindgen = "0.70.1" + [lib] diff --git a/source/extensions/dynamic_modules/sdk/rust/README.md b/source/extensions/dynamic_modules/sdk/rust/README.md index 9470ff7b65..ffce6dbae4 100644 --- a/source/extensions/dynamic_modules/sdk/rust/README.md +++ b/source/extensions/dynamic_modules/sdk/rust/README.md @@ -1,7 +1,11 @@ # Envoy Dynamic Modules Rust SDK -This directory contains the Rust SDK for the Dynamic Modules feature. The SDK passes the same set of tests and is guaranteed to provide the same functionality as the other SDKs. This directory is organized in the way that it can be used as a standalone Rust crate. The SDK is basically the high-level abstraction layer for the Dynamic Modules ABI defined in the [abi.h](../../abi.h). +This directory contains the Rust SDK for the Dynamic Modules feature. This directory is organized in the way that it can be used as a standalone Rust crate. The SDK is basically the high-level abstraction layer for the Dynamic Modules ABI defined in the [abi.h](../../abi.h). -Currently, the ABI binding ([src/abi.rs](./src/abi.rs)) is manually generated by [`bindgen`](https://github.com/rust-lang/rust-bindgen) for the ABI header. Ideally, we should be able to do the bindgen in the build.rs file. +Note that this crate references the local ABI header files, so this is intended to be used as +``` +[dependencies] +envoy-proxy-dynamic-modules-rust-sdk = { git = "https://github.com/envoyproxy/envoy", tag = "v1.50.1" } +``` -TODO(@mathetake): figure out how to properly setup the bindgen in build.rs with rules_rust. The most recommended way is to use [crate_universe](https://bazelbuild.github.io/rules_rust/crate_universe.html#setup) and use bindgen as a dev-dependency. However, it seems that crate_universe tries to use the underlying gcc system linker which we cannot assume always available. +instead of `envoy-proxy-dynamic-modules-rust-sdk = "X.Y.Z"`. diff --git a/source/extensions/dynamic_modules/sdk/rust/build.rs b/source/extensions/dynamic_modules/sdk/rust/build.rs new file mode 100644 index 0000000000..d3ad0d987e --- /dev/null +++ b/source/extensions/dynamic_modules/sdk/rust/build.rs @@ -0,0 +1,17 @@ +use std::env; +use std::path::PathBuf; + +fn main() { + println!("cargo:rerun-if-changed=abi.h"); + let bindings = bindgen::Builder::default() + .header("../../abi.h") + .header("../../abi_version.h") + .parse_callbacks(Box::new(bindgen::CargoCallbacks::new())) + .generate() + .expect("Unable to generate bindings"); + + let out_path = PathBuf::from(env::var("OUT_DIR").unwrap()); + bindings + .write_to_file(out_path.join("bindings.rs")) + .expect("Couldn't write bindings"); +} diff --git a/source/extensions/dynamic_modules/sdk/rust/src/abi.rs b/source/extensions/dynamic_modules/sdk/rust/src/abi.rs deleted file mode 100644 index d673d5b2c5..0000000000 --- a/source/extensions/dynamic_modules/sdk/rust/src/abi.rs +++ /dev/null @@ -1,17 +0,0 @@ -/* automatically generated by rust-bindgen 0.70.1 */ - -pub type wchar_t = ::std::os::raw::c_int; -#[repr(C)] -#[repr(align(16))] -#[derive(Debug, Copy, Clone)] -pub struct max_align_t { - pub __clang_max_align_nonce1: ::std::os::raw::c_longlong, - pub __bindgen_padding_0: u64, - pub __clang_max_align_nonce2: u128, -} -#[doc = " envoy_dynamic_module_type_abi_version represents a null-terminated string that contains the ABI\n version of the dynamic module. This is used to ensure that the dynamic module is built against\n the compatible version of the ABI."] -pub type envoy_dynamic_module_type_abi_version = *const ::std::os::raw::c_char; -extern "C" { - #[doc = " envoy_dynamic_module_on_program_init is called by the main thread exactly when the module is\n loaded. The function returns the ABI version of the dynamic module. If null is returned, the\n module will be unloaded immediately.\n\n For Envoy, the return value will be used to check the compatibility of the dynamic module.\n\n For dynamic modules, this is useful when they need to perform some process-wide\n initialization or check if the module is compatible with the platform, such as CPU features.\n Note that initialization routines of a dynamic module can also be performed without this function\n through constructor functions in an object file. However, normal constructors cannot be used\n to check compatibility and gracefully fail the initialization because there is no way to\n report an error to Envoy.\n\n @return envoy_dynamic_module_type_abi_version is the ABI version of the dynamic module. Null\n means the error and the module will be unloaded immediately."] - pub fn envoy_dynamic_module_on_program_init() -> envoy_dynamic_module_type_abi_version; -} diff --git a/source/extensions/dynamic_modules/sdk/rust/src/lib.rs b/source/extensions/dynamic_modules/sdk/rust/src/lib.rs index e8aa578d6c..5796d12fe9 100644 --- a/source/extensions/dynamic_modules/sdk/rust/src/lib.rs +++ b/source/extensions/dynamic_modules/sdk/rust/src/lib.rs @@ -3,7 +3,12 @@ #![allow(non_snake_case)] #![allow(dead_code)] -mod abi; +/// This module contains the generated bindings for the envoy dynamic modules ABI. +/// +/// This is not meant to be used directly. +pub mod abi { + include!(concat!(env!("OUT_DIR"), "/bindings.rs")); +} /// Declare the init function for the dynamic module. This function is called when the dynamic module is loaded. /// The function must return true on success, and false on failure. When it returns false, @@ -28,9 +33,7 @@ macro_rules! declare_program_init { #[no_mangle] pub extern "C" fn envoy_dynamic_module_on_program_init() -> *const ::std::os::raw::c_char { if ($f()) { - // This magic number is sha256 of the ABI headers which must match the - // value in abi_version.h - b"749b1e6bf97309b7d171009700a80e651ac61e35f9770c24a63460d765895a51\0".as_ptr() + envoy_proxy_dynamic_modules_rust_sdk::abi::kAbiVersion.as_ptr() as *const ::std::os::raw::c_char } else { ::std::ptr::null() diff --git a/test/extensions/dynamic_modules/dynamic_modules_test.cc b/test/extensions/dynamic_modules/dynamic_modules_test.cc index 7368af924a..2177a45db7 100644 --- a/test/extensions/dynamic_modules/dynamic_modules_test.cc +++ b/test/extensions/dynamic_modules/dynamic_modules_test.cc @@ -36,8 +36,7 @@ class DynamicModuleTestLanguages : public ::testing::TestWithParam }; }; -INSTANTIATE_TEST_SUITE_P(LanguageTests, DynamicModuleTestLanguages, - testing::Values("c", "rust"), // TODO: add Go. +INSTANTIATE_TEST_SUITE_P(LanguageTests, DynamicModuleTestLanguages, testing::Values("c", "rust"), DynamicModuleTestLanguages::languageParamToTestName); TEST_P(DynamicModuleTestLanguages, DoNotClose) { diff --git a/test/extensions/dynamic_modules/test_data/c/program_init_fail.c b/test/extensions/dynamic_modules/test_data/c/program_init_fail.c index 62c903ac2d..0a00ce7d43 100644 --- a/test/extensions/dynamic_modules/test_data/c/program_init_fail.c +++ b/test/extensions/dynamic_modules/test_data/c/program_init_fail.c @@ -1,3 +1,5 @@ +#include + #include "source/extensions/dynamic_modules/abi.h" envoy_dynamic_module_type_abi_version envoy_dynamic_module_on_program_init() { return NULL; } From 6307e4a6ac6007e9be464ef9018b92f43703ae14 Mon Sep 17 00:00:00 2001 From: Kuat Date: Mon, 23 Sep 2024 10:08:40 -0700 Subject: [PATCH 56/65] admin: add allocation profiler (#36136) add `/allocprofiler` admin handler to record the tcmalloc allocation profile. I used this to chase down some excessive heap memory use (which turned out to be tcmalloc caches). Risk Level: low Testing: done Docs Changes: yes Release Notes: none Change-Id: I79629537ab83c54b655de7ef1010b29665d30541 Signed-off-by: Kuat Yessenov --- docs/root/operations/admin.rst | 5 +++ source/common/common/BUILD | 1 + source/common/common/thread.h | 1 + source/common/profiler/BUILD | 1 + source/common/profiler/profiler.cc | 38 +++++++++++++++++++++ source/common/profiler/profiler.h | 3 ++ source/server/admin/admin.cc | 7 ++++ source/server/admin/profiling_handler.cc | 29 ++++++++++++++++ source/server/admin/profiling_handler.h | 3 ++ test/server/admin/admin_test.cc | 2 ++ test/server/admin/profiling_handler_test.cc | 20 +++++++++++ 11 files changed, 110 insertions(+) diff --git a/docs/root/operations/admin.rst b/docs/root/operations/admin.rst index 99f61fe6bf..a70d89f129 100644 --- a/docs/root/operations/admin.rst +++ b/docs/root/operations/admin.rst @@ -250,6 +250,11 @@ modify different aspects of the server: Dump current heap profile of Envoy process. The output content is parsable binary by the ``pprof`` tool. Requires compiling with tcmalloc (default). +.. http:post:: /allocprofiler + + Enable or disable the allocation profiler. The output content is parsable binary by the ``pprof`` tool. + Requires compiling with tcmalloc (default). + .. _operations_admin_interface_healthcheck_fail: .. http:post:: /healthcheck/fail diff --git a/source/common/common/BUILD b/source/common/common/BUILD index e2f26a09a2..89a95df0a1 100644 --- a/source/common/common/BUILD +++ b/source/common/common/BUILD @@ -413,6 +413,7 @@ envoy_cc_library( srcs = ["thread.cc"], hdrs = ["thread.h"], deps = envoy_cc_platform_dep("thread_impl_lib") + [ + ":assert_lib", ":macros", ":non_copyable", "@com_google_absl//absl/synchronization", diff --git a/source/common/common/thread.h b/source/common/common/thread.h index 5403a29b0c..105f95ae89 100644 --- a/source/common/common/thread.h +++ b/source/common/common/thread.h @@ -7,6 +7,7 @@ #include "envoy/thread/thread.h" +#include "source/common/common/assert.h" #include "source/common/common/non_copyable.h" #include "absl/synchronization/mutex.h" diff --git a/source/common/profiler/BUILD b/source/common/profiler/BUILD index 1757fd696f..d5990ff866 100644 --- a/source/common/profiler/BUILD +++ b/source/common/profiler/BUILD @@ -14,6 +14,7 @@ envoy_cc_library( hdrs = ["profiler.h"], tcmalloc_dep = 1, deps = [ + "//source/common/common:thread_lib", "@com_google_absl//absl/status:statusor", ], ) diff --git a/source/common/profiler/profiler.cc b/source/common/profiler/profiler.cc index f6244ebcfd..0bff360b3a 100644 --- a/source/common/profiler/profiler.cc +++ b/source/common/profiler/profiler.cc @@ -2,6 +2,8 @@ #include +#include "source/common/common/thread.h" + #ifdef PROFILER_AVAILABLE #include "gperftools/heap-profiler.h" @@ -68,11 +70,37 @@ bool Heap::stopProfiler() { return false; } namespace Envoy { namespace Profiler { +static tcmalloc::MallocExtension::AllocationProfilingToken* alloc_profiler = nullptr; + absl::StatusOr TcmallocProfiler::tcmallocHeapProfile() { auto profile = tcmalloc::MallocExtension::SnapshotCurrent(tcmalloc::ProfileType::kHeap); return tcmalloc::Marshal(profile); } +absl::Status TcmallocProfiler::startAllocationProfile() { + ASSERT_IS_MAIN_OR_TEST_THREAD(); + if (alloc_profiler != nullptr) { + return absl::Status(absl::StatusCode::kFailedPrecondition, + "Allocation profiler has already started"); + } + alloc_profiler = new tcmalloc::MallocExtension::AllocationProfilingToken( + tcmalloc::MallocExtension::StartAllocationProfiling()); + return absl::OkStatus(); +} + +absl::StatusOr TcmallocProfiler::stopAllocationProfile() { + ASSERT_IS_MAIN_OR_TEST_THREAD(); + if (!alloc_profiler) { + return absl::Status(absl::StatusCode::kFailedPrecondition, + "Allocation profiler is not started"); + } + const auto profile = std::move(*alloc_profiler).Stop(); + const auto result = tcmalloc::Marshal(profile); + delete alloc_profiler; + alloc_profiler = nullptr; + return result; +} + } // namespace Profiler } // namespace Envoy @@ -86,6 +114,16 @@ absl::StatusOr TcmallocProfiler::tcmallocHeapProfile() { "Heap profile is not implemented in current build"); } +absl::Status TcmallocProfiler::startAllocationProfile() { + return absl::Status(absl::StatusCode::kUnimplemented, + "Allocation profile is not implemented in current build"); +} + +absl::StatusOr TcmallocProfiler::stopAllocationProfile() { + return absl::Status(absl::StatusCode::kUnimplemented, + "Allocation profile is not implemented in current build"); +} + } // namespace Profiler } // namespace Envoy diff --git a/source/common/profiler/profiler.h b/source/common/profiler/profiler.h index 560cfd33e2..11363789f0 100644 --- a/source/common/profiler/profiler.h +++ b/source/common/profiler/profiler.h @@ -66,12 +66,15 @@ class Heap { /** * Default profiler which will be enabled when tcmalloc (not `gperftools`) is used. + * This class is not thread-safe. */ class TcmallocProfiler { public: TcmallocProfiler() = default; static absl::StatusOr tcmallocHeapProfile(); + static absl::Status startAllocationProfile(); + static absl::StatusOr stopAllocationProfile(); }; } // namespace Profiler diff --git a/source/server/admin/admin.cc b/source/server/admin/admin.cc index bfe1322cec..2e470411ab 100644 --- a/source/server/admin/admin.cc +++ b/source/server/admin/admin.cc @@ -166,6 +166,13 @@ AdminImpl::AdminImpl(const std::string& profile_path, Server::Instance& server, makeHandler("/heap_dump", "dump current Envoy heap (if supported)", MAKE_ADMIN_HANDLER(tcmalloc_profiling_handler_.handlerHeapDump), false, false), + makeHandler("/allocprofiler", "enable/disable the allocation profiler (if supported)", + MAKE_ADMIN_HANDLER(tcmalloc_profiling_handler_.handlerAllocationProfiler), + false, true, + {{Admin::ParamDescriptor::Type::Enum, + "enable", + "enable/disable the allocation profiler", + {"y", "n"}}}), makeHandler("/healthcheck/fail", "cause the server to fail health checks", MAKE_ADMIN_HANDLER(server_cmd_handler_.handlerHealthcheckFail), false, true), makeHandler("/healthcheck/ok", "cause the server to pass health checks", diff --git a/source/server/admin/profiling_handler.cc b/source/server/admin/profiling_handler.cc index 0aedcfc477..82a5ef87bf 100644 --- a/source/server/admin/profiling_handler.cc +++ b/source/server/admin/profiling_handler.cc @@ -93,5 +93,34 @@ Http::Code TcmallocProfilingHandler::handlerHeapDump(Http::ResponseHeaderMap&, return Http::Code::NotImplemented; } +Http::Code TcmallocProfilingHandler::handlerAllocationProfiler(Http::ResponseHeaderMap&, + Buffer::Instance& response, + AdminStream& admin_stream) { + Http::Utility::QueryParamsMulti query_params = admin_stream.queryParams(); + const auto enableVal = query_params.getFirstValue("enable"); + if (query_params.data().size() != 1 || !enableVal.has_value() || + (enableVal.value() != "y" && enableVal.value() != "n")) { + response.add("?enable=\n"); + return Http::Code::BadRequest; + } + const bool enable = enableVal.value() == "y"; + if (enable) { + const auto started = Profiler::TcmallocProfiler::startAllocationProfile(); + if (!started.ok()) { + response.add(started.message()); + return Http::Code::BadRequest; + } + response.add("OK\n"); + return Http::Code::OK; + } + const auto profile = Profiler::TcmallocProfiler::stopAllocationProfile(); + if (!profile.ok()) { + response.add(profile.status().message()); + return Http::Code::BadRequest; + } + response.add(profile.value()); + return Http::Code::OK; +} + } // namespace Server } // namespace Envoy diff --git a/source/server/admin/profiling_handler.h b/source/server/admin/profiling_handler.h index ffc64f588b..73f50b14fd 100644 --- a/source/server/admin/profiling_handler.h +++ b/source/server/admin/profiling_handler.h @@ -31,6 +31,9 @@ class TcmallocProfilingHandler { Http::Code handlerHeapDump(Http::ResponseHeaderMap& response_headers, Buffer::Instance& response, AdminStream&); + + Http::Code handlerAllocationProfiler(Http::ResponseHeaderMap& response_headers, + Buffer::Instance& response, AdminStream&); }; } // namespace Server diff --git a/test/server/admin/admin_test.cc b/test/server/admin/admin_test.cc index 4071881f78..fb6f64ff6d 100644 --- a/test/server/admin/admin_test.cc +++ b/test/server/admin/admin_test.cc @@ -142,6 +142,8 @@ TEST_P(AdminInstanceTest, Help) { EXPECT_EQ(Http::Code::OK, getCallback("/help", header_map, response)); const std::string expected = R"EOF(admin commands are: /: Admin home page + /allocprofiler (POST): enable/disable the allocation profiler (if supported) + enable: enable/disable the allocation profiler; One of (y, n) /certs: print certs on machine /clusters: upstream cluster status /config_dump: dump current Envoy configs (experimental) diff --git a/test/server/admin/profiling_handler_test.cc b/test/server/admin/profiling_handler_test.cc index 315764a207..c40e9e9255 100644 --- a/test/server/admin/profiling_handler_test.cc +++ b/test/server/admin/profiling_handler_test.cc @@ -88,5 +88,25 @@ TEST_P(AdminInstanceTest, AdminHeapDump) { #endif } +TEST_P(AdminInstanceTest, AdminAllocationDump) { + Buffer::OwnedImpl data; + Http::TestResponseHeaderMapImpl header_map; + EXPECT_EQ(Http::Code::BadRequest, postCallback("/allocprofiler", header_map, data)); + +#ifdef TCMALLOC + EXPECT_EQ(Http::Code::OK, postCallback("/allocprofiler?enable=y", header_map, data)); + EXPECT_EQ(Http::Code::OK, postCallback("/allocprofiler?enable=n", header_map, data)); + + // Out-of-order calls + EXPECT_EQ(Http::Code::BadRequest, postCallback("/allocprofiler?enable=n", header_map, data)); + EXPECT_EQ(Http::Code::OK, postCallback("/allocprofiler?enable=y", header_map, data)); + EXPECT_EQ(Http::Code::BadRequest, postCallback("/allocprofiler?enable=y", header_map, data)); + EXPECT_EQ(Http::Code::OK, postCallback("/allocprofiler?enable=n", header_map, data)); +#else + EXPECT_EQ(Http::Code::BadRequest, postCallback("/allocprofiler?enable=y", header_map, data)); + EXPECT_EQ(Http::Code::BadRequest, postCallback("/allocprofiler?enable=n", header_map, data)); +#endif +} + } // namespace Server } // namespace Envoy From 94a3b438e6b4d58a4f83960635593540444c4647 Mon Sep 17 00:00:00 2001 From: Fredy Wijaya Date: Mon, 23 Sep 2024 12:20:16 -0500 Subject: [PATCH 57/65] mobile: Revert accidental test changes (#36291) Some `CronetHttp3Test` tests got accidentally commented out. This PR revert these accidental changes. Risk Level: low Testing: `blaze test //test/java/org/chromium/net:cronet_http3_test` Docs Changes: n/a Release Notes: n/a Platform Specific Features: n/a --------- Signed-off-by: Fredy Wijaya --- .../org/chromium/net/CronetHttp3Test.java | 178 +++++++++--------- 1 file changed, 89 insertions(+), 89 deletions(-) diff --git a/mobile/test/java/org/chromium/net/CronetHttp3Test.java b/mobile/test/java/org/chromium/net/CronetHttp3Test.java index 709b634602..f70dcde88e 100644 --- a/mobile/test/java/org/chromium/net/CronetHttp3Test.java +++ b/mobile/test/java/org/chromium/net/CronetHttp3Test.java @@ -40,7 +40,7 @@ public class CronetHttp3Test { // If true, dump envoy logs on test completion. // Ideally we could override this from the command line but that's TBD. - private boolean printEnvoyLogs = true; + private boolean printEnvoyLogs = false; // The HTTP/2 server, set up to alt-svc to the HTTP/3 server private HttpTestServerFactory.HttpTestServer http2TestServer; // The HTTP/3 server @@ -144,86 +144,86 @@ private void doInitialHttp2Request() { assertEquals("h2", callback.mResponseInfo.getNegotiatedProtocol()); } - // @Test - // @SmallTest - // @Feature({"Cronet"}) - // public void basicHttp3Get() throws Exception { - // // Ideally we could override this from the command line but that's TBD. - // setUp(printEnvoyLogs); - // - // // Do the initial HTTP/2 request to get the alt-svc response. - // doInitialHttp2Request(); - // - // // Set up a second request, which will hopefully go out over HTTP/3 due to alt-svc - // // advertisement. - // TestUrlRequestCallback callback = doBasicGetRequest(); - // - // // Verify the second request used HTTP/3 - // assertEquals(200, callback.mResponseInfo.getHttpStatusCode()); - // assertEquals("h3", callback.mResponseInfo.getNegotiatedProtocol()); - // } - - // @Test - // @SmallTest - // @Feature({"Cronet"}) - // public void failToHttp2() throws Exception { - // // Ideally we could override this from the command line but that's TBD. - // setUp(printEnvoyLogs); - // - // // Do the initial HTTP/2 request to get the alt-svc response. - // doInitialHttp2Request(); - // - // // Set up a second request, which will hopefully go out over HTTP/3 due to alt-svc - // // advertisement. - // TestUrlRequestCallback getCallback = doBasicGetRequest(); - // - // // Verify the second request used HTTP/3 - // assertEquals(200, getCallback.mResponseInfo.getHttpStatusCode()); - // assertEquals("h3", getCallback.mResponseInfo.getNegotiatedProtocol()); - // - // // Now stop the HTTP/3 server. - // http3TestServer.shutdown(); - // http3TestServer = null; - // - // // The next request will fail on HTTP2 but should succeed on HTTP/2 despite having a body. - // TestUrlRequestCallback postCallback = doBasicPostRequest(); - // assertEquals(200, postCallback.mResponseInfo.getHttpStatusCode()); - // assertEquals("h2", postCallback.mResponseInfo.getNegotiatedProtocol()); - // } - - // @Test - // @SmallTest - // @Feature({"Cronet"}) - // public void testNoRetryPostAfterHandshake() throws Exception { - // setUp(printEnvoyLogs); - // - // // Do the initial HTTP/2 request to get the alt-svc response. - // doInitialHttp2Request(); - // - // // Set up a second request, which will hopefully go out over HTTP/3 due to alt-svc - // // advertisement. - // TestUrlRequestCallback callback = new TestUrlRequestCallback(); - // UrlRequest.Builder urlRequestBuilder = - // cronvoyEngine.newUrlRequestBuilder(testServerUrl, callback, callback.getExecutor()); - // // Set the upstream to reset after the request. - // urlRequestBuilder.addHeader("reset_after_request", "yes"); - // urlRequestBuilder.addHeader("content-type", "text"); - // urlRequestBuilder.setHttpMethod("POST"); - // TestUploadDataProvider dataProvider = new TestUploadDataProvider( - // TestUploadDataProvider.SuccessCallbackMode.SYNC, callback.getExecutor()); - // dataProvider.addRead("test".getBytes()); - // urlRequestBuilder.setUploadDataProvider(dataProvider, callback.getExecutor()); - // - // urlRequestBuilder.build().start(); - // callback.blockForDone(); - // - // // Both HTTP/3 and HTTP/2 servers will reset after the request. - // assertTrue(callback.mOnErrorCalled); - // // There are 2 requests - the initial HTTP/2 alt-svc request and the HTTP/3 request. - // // By default, POST requests will not retry. - // String stats = cronvoyEngine.getEnvoyEngine().dumpStats(); - // assertTrue(stats.contains("cluster.base.upstream_rq_total: 2")); - // } + @Test + @SmallTest + @Feature({"Cronet"}) + public void basicHttp3Get() throws Exception { + // Ideally we could override this from the command line but that's TBD. + setUp(printEnvoyLogs); + + // Do the initial HTTP/2 request to get the alt-svc response. + doInitialHttp2Request(); + + // Set up a second request, which will hopefully go out over HTTP/3 due to alt-svc + // advertisement. + TestUrlRequestCallback callback = doBasicGetRequest(); + + // Verify the second request used HTTP/3 + assertEquals(200, callback.mResponseInfo.getHttpStatusCode()); + assertEquals("h3", callback.mResponseInfo.getNegotiatedProtocol()); + } + + @Test + @SmallTest + @Feature({"Cronet"}) + public void failToHttp2() throws Exception { + // Ideally we could override this from the command line but that's TBD. + setUp(printEnvoyLogs); + + // Do the initial HTTP/2 request to get the alt-svc response. + doInitialHttp2Request(); + + // Set up a second request, which will hopefully go out over HTTP/3 due to alt-svc + // advertisement. + TestUrlRequestCallback getCallback = doBasicGetRequest(); + + // Verify the second request used HTTP/3 + assertEquals(200, getCallback.mResponseInfo.getHttpStatusCode()); + assertEquals("h3", getCallback.mResponseInfo.getNegotiatedProtocol()); + + // Now stop the HTTP/3 server. + http3TestServer.shutdown(); + http3TestServer = null; + + // The next request will fail on HTTP2 but should succeed on HTTP/2 despite having a body. + TestUrlRequestCallback postCallback = doBasicPostRequest(); + assertEquals(200, postCallback.mResponseInfo.getHttpStatusCode()); + assertEquals("h2", postCallback.mResponseInfo.getNegotiatedProtocol()); + } + + @Test + @SmallTest + @Feature({"Cronet"}) + public void testNoRetryPostAfterHandshake() throws Exception { + setUp(printEnvoyLogs); + + // Do the initial HTTP/2 request to get the alt-svc response. + doInitialHttp2Request(); + + // Set up a second request, which will hopefully go out over HTTP/3 due to alt-svc + // advertisement. + TestUrlRequestCallback callback = new TestUrlRequestCallback(); + UrlRequest.Builder urlRequestBuilder = + cronvoyEngine.newUrlRequestBuilder(testServerUrl, callback, callback.getExecutor()); + // Set the upstream to reset after the request. + urlRequestBuilder.addHeader("reset_after_request", "yes"); + urlRequestBuilder.addHeader("content-type", "text"); + urlRequestBuilder.setHttpMethod("POST"); + TestUploadDataProvider dataProvider = new TestUploadDataProvider( + TestUploadDataProvider.SuccessCallbackMode.SYNC, callback.getExecutor()); + dataProvider.addRead("test".getBytes()); + urlRequestBuilder.setUploadDataProvider(dataProvider, callback.getExecutor()); + + urlRequestBuilder.build().start(); + callback.blockForDone(); + + // Both HTTP/3 and HTTP/2 servers will reset after the request. + assertTrue(callback.mOnErrorCalled); + // There are 2 requests - the initial HTTP/2 alt-svc request and the HTTP/3 request. + // By default, POST requests will not retry. + String stats = cronvoyEngine.getEnvoyEngine().dumpStats(); + assertTrue(stats.contains("cluster.base.upstream_rq_total: 2")); + } // Set up to use HTTP/3, then force HTTP/3 to fail post-handshake. The request should // be retried on HTTP/2 and HTTP/3 will be marked broken. @@ -261,14 +261,14 @@ private void retryPostHandshake() throws Exception { assertTrue(stats.contains("cluster.base.upstream_http3_broken: 1")); } - // @Test - // @SmallTest - // @Feature({"Cronet"}) - // public void testRetryPostHandshake() throws Exception { - // setUp(printEnvoyLogs); - // - // retryPostHandshake(); - // } + @Test + @SmallTest + @Feature({"Cronet"}) + public void testRetryPostHandshake() throws Exception { + setUp(printEnvoyLogs); + + retryPostHandshake(); + } @Test @SmallTest From 98fe1930c63d12c2b4491e2cf25dec3463e2369f Mon Sep 17 00:00:00 2001 From: Kateryna Nezdolii Date: Mon, 23 Sep 2024 21:26:20 +0200 Subject: [PATCH 58/65] Fix asan failure (#36286) Fix for: ``` ==12==ERROR: AddressSanitizer: heap-use-after-free on address 0x60300019d860 at pc 0xb7d3f059f8cc bp 0xe6dc6a8fde80 sp 0xe6dc6a8fd670 WRITE of size 24 at 0x60300019d860 thread T1 #0 0xb7d3f059f8c8 in __asan_memset (/home/nezdolik.linux/.cache/bazel/_bazel_nezdolik/9a5f062d7ba021dba530b9f40b2998a7/execroot/envoy/bazel-out/aarch64-fastbuild/bin/test/extensions/geoip_providers/maxmind/geoip_provider_test+0x48ef8c8) #1 0xb7d3f065bb9c in std::function& std::vector, std::allocator>>::emplace_back>(std::function&&) (/home/nezdolik.linux/.cache/bazel/_bazel_nezdolik/9a5f062d7ba021dba530b9f40b2998a7/execroot/envoy/bazel-out/aarch64-fastbuild/bin/test/extensions/geoip_providers/maxmind/geoip_provider_test+0x49abb9c) #2 0xb7d3f065b6a0 in Envoy::Extensions::GeoipProviders::Maxmind::GeoipProviderTestBase::initializeProvider(std::__cxx11::basic_string, std::allocator> const&, std::optional&)::'lambda'()::operator()() const::'lambda'(std::basic_string_view>, unsigned int, std::function)::operator()(std::basic_string_view>, unsigned int, std::function) const (/home/nezdolik.linux/.cache/bazel/_bazel_nezdolik/9a5f062d7ba021dba530b9f40b2998a7/execroot/envoy/bazel-out/aarch64-fastbuild/bin/test/extensions/geoip_providers/maxmind/geoip_provider_test+0x49ab6a0) #3 0xb7d3f065b2c0 in std::_Function_handler>, unsigned int, std::function), Envoy::Extensions::GeoipProviders::Maxmind::GeoipProviderTestBase::initializeProvider(std::__cxx11::basic_string, std::allocator> const&, std::optional&)::'lambda'()::operator()() const::'lambda'(std::basic_string_view>, unsigned int, std::function)>::_M_invoke(std::_Any_data const&, std::basic_string_view>&&, unsigned int&&, std::function&&) (/home/nezdolik.linux/.cache/bazel/_bazel_nezdolik/9a5f062d7ba021dba530b9f40b2998a7/execroot/envoy/bazel-out/aarch64-fastbuild/bin/test/extensions/geoip_providers/maxmind/geoip_provider_test+0x49ab2c0) #4 0xb7d3f3080050 in decltype(std::forward>, unsigned int, std::function)> const&>(fp)(std::get<0ul>(std::forward>, unsigned int, std::function>>(fp0)), std::get<1ul>(std::forward>, unsigned int, std::function>>(fp0)), std::get<2ul>(std::forward>, unsigned int, std::function>>(fp0)))) testing::internal::ApplyImpl>, unsigned int, std::function)> const&, std::tuple>, unsigned int, std::function>, 0ul, 1ul, 2ul>(std::function>, unsigned int, std::function)> const&, std::tuple>, unsigned int, std::function>&&, testing::internal::IndexSequence<0ul, 1ul, 2ul>) (/home/nezdolik.linux/.cache/bazel/_bazel_nezdolik/9a5f062d7ba021dba530b9f40b2998a7/execroot/envoy/bazel-out/aarch64-fastbuild/bin/test/extensions/geoip_providers/maxmind/geoip_provider_test+0x73d0050) #5 0xb7d3f3080438 in testing::internal::ActionResultHolder* testing::internal::ActionResultHolder::PerformAction>, unsigned int, std::function)>(testing::Action>, unsigned int, std::function)> const&, testing::internal::Function>, unsigned int, std::function)>::ArgumentTuple&&) (/home/nezdolik.linux/.cache/bazel/_bazel_nezdolik/9a5f062d7ba021dba530b9f40b2998a7/execroot/envoy/bazel-out/aarch64-fastbuild/bin/test/extensions/geoip_providers/maxmind/geoip_provider_test+0x73d0438) #6 0xb7d3f307e148 in testing::internal::FunctionMocker>, unsigned int, std::function)>::UntypedPerformAction(void const*, void*) const (/home/nezdolik.linux/.cache/bazel/_bazel_nezdolik/9a5f062d7ba021dba530b9f40b2998a7/execroot/envoy/bazel-out/aarch64-fastbuild/bin/test/extensions/geoip_providers/maxmind/geoip_provider_test+0x73ce148) #7 0xb7d3f531993c in testing::internal::UntypedFunctionMockerBase::UntypedInvokeWith(void*) (/home/nezdolik.linux/.cache/bazel/_bazel_nezdolik/9a5f062d7ba021dba530b9f40b2998a7/execroot/envoy/bazel-out/aarch64-fastbuild/bin/test/extensions/geoip_providers/maxmind/geoip_provider_test+0x966993c) #8 0xb7d3f0657fa0 in testing::internal::FunctionMocker>, unsigned int, std::function)>::Invoke(std::basic_string_view>, unsigned int, std::function) (/home/nezdolik.linux/.cache/bazel/_bazel_nezdolik/9a5f062d7ba021dba530b9f40b2998a7/execroot/envoy/bazel-out/aarch64-fastbuild/bin/test/extensions/geoip_providers/maxmind/geoip_provider_test+0x49a7fa0) #9 0xb7d3f0657c2c in Envoy::Filesystem::MockWatcher::addWatch(std::basic_string_view>, unsigned int, std::function) (/home/nezdolik.linux/.cache/bazel/_bazel_nezdolik/9a5f062d7ba021dba530b9f40b2998a7/execroot/envoy/bazel-out/aarch64-fastbuild/bin/test/extensions/geoip_providers/maxmind/geoip_provider_test+0x49a7c2c) #10 0xb7d3f06b63b4 in std::_Function_handler, std::shared_ptr)::$_0>::_M_invoke(std::_Any_data const&) geoip_provider.cc #11 0xb7d3f45c9fc8 in Envoy::Thread::PosixThreadFactory::createPthread(Envoy::Thread::ThreadHandle*)::$_0::__invoke(void*) thread_impl.cc #12 0xe6dc6ea637cc (/lib/aarch64-linux-gnu/libc.so.6+0x837cc) (BuildId: 5b12268cafe96b30a4b950adece623b540b747be) #13 0xe6dc6eacf5c8 (/lib/aarch64-linux-gnu/libc.so.6+0xef5c8) (BuildId: 5b12268cafe96b30a4b950adece623b540b747be) 0x60300019d860 is located 0 bytes inside of 32-byte region [0x60300019d860,0x60300019d880) freed by thread T0 here: #0 0xb7d3f05a0138 in free (/home/nezdolik.linux/.cache/bazel/_bazel_nezdolik/9a5f062d7ba021dba530b9f40b2998a7/execroot/envoy/bazel-out/aarch64-fastbuild/bin/test/extensions/geoip_providers/maxmind/geoip_provider_test+0x48f0138) #1 0xb7d3f05edd2c in std::vector, std::allocator>>::~vector() (/home/nezdolik.linux/.cache/bazel/_bazel_nezdolik/9a5f062d7ba021dba530b9f40b2998a7/execroot/envoy/bazel-out/aarch64-fastbuild/bin/test/extensions/geoip_providers/maxmind/geoip_provider_test+0x493dd2c) #2 0xb7d3f0648504 in Envoy::Extensions::GeoipProviders::Maxmind::GeoipProviderTestBase::~GeoipProviderTestBase() (/home/nezdolik.linux/.cache/bazel/_bazel_nezdolik/9a5f062d7ba021dba530b9f40b2998a7/execroot/envoy/bazel-out/aarch64-fastbuild/bin/test/extensions/geoip_providers/maxmind/geoip_provider_test+0x4998504) #3 0xb7d3f05eba10 in Envoy::Extensions::GeoipProviders::Maxmind::GeoipProviderTest_ValidConfigCityAndIspDbsSuccessfulLookup_Test::~GeoipProviderTest_ValidConfigCityAndIspDbsSuccessfulLookup_Test() (/home/nezdolik.linux/.cache/bazel/_bazel_nezdolik/9a5f062d7ba021dba530b9f40b2998a7/execroot/envoy/bazel-out/aarch64-fastbuild/bin/test/extensions/geoip_providers/maxmind/geoip_provider_test+0x493ba10) #4 0xb7d3f53a68b0 in testing::Test::DeleteSelf_() (/home/nezdolik.linux/.cache/bazel/_bazel_nezdolik/9a5f062d7ba021dba530b9f40b2998a7/execroot/envoy/bazel-out/aarch64-fastbuild/bin/test/extensions/geoip_providers/maxmind/geoip_provider_test+0x96f68b0) #5 0xb7d3f53a5ccc in void testing::internal::HandleExceptionsInMethodIfSupported(testing::Test*, void (testing::Test::*)(), char const*) (/home/nezdolik.linux/.cache/bazel/_bazel_nezdolik/9a5f062d7ba021dba530b9f40b2998a7/execroot/envoy/bazel-out/aarch64-fastbuild/bin/test/extensions/geoip_providers/maxmind/geoip_provider_test+0x96f5ccc) #6 0xb7d3f53702fc in testing::TestInfo::Run() (/home/nezdolik.linux/.cache/bazel/_bazel_nezdolik/9a5f062d7ba021dba530b9f40b2998a7/execroot/envoy/bazel-out/aarch64-fastbuild/bin/test/extensions/geoip_providers/maxmind/geoip_provider_test+0x96c02fc) #7 0xb7d3f5371dc8 in testing::TestSuite::Run() (/home/nezdolik.linux/.cache/bazel/_bazel_nezdolik/9a5f062d7ba021dba530b9f40b2998a7/execroot/envoy/bazel-out/aarch64-fastbuild/bin/test/extensions/geoip_providers/maxmind/geoip_provider_test+0x96c1dc8) #8 0xb7d3f5394e84 in testing::internal::UnitTestImpl::RunAllTests() (/home/nezdolik.linux/.cache/bazel/_bazel_nezdolik/9a5f062d7ba021dba530b9f40b2998a7/execroot/envoy/bazel-out/aarch64-fastbuild/bin/test/extensions/geoip_providers/maxmind/geoip_provider_test+0x96e4e84) #9 0xb7d3f53a82a4 in bool testing::internal::HandleExceptionsInMethodIfSupported(testing::internal::UnitTestImpl*, bool (testing::internal::UnitTestImpl::*)(), char const*) (/home/nezdolik.linux/.cache/bazel/_bazel_nezdolik/9a5f062d7ba021dba530b9f40b2998a7/execroot/envoy/bazel-out/aarch64-fastbuild/bin/test/extensions/geoip_providers/maxmind/geoip_provider_test+0x96f82a4) #10 0xb7d3f53945d0 in testing::UnitTest::Run() (/home/nezdolik.linux/.cache/bazel/_bazel_nezdolik/9a5f062d7ba021dba530b9f40b2998a7/execroot/envoy/bazel-out/aarch64-fastbuild/bin/test/extensions/geoip_providers/maxmind/geoip_provider_test+0x96e45d0) #11 0xb7d3f2f2ea10 in Envoy::TestRunner::runTests(int, char**) (/home/nezdolik.linux/.cache/bazel/_bazel_nezdolik/9a5f062d7ba021dba530b9f40b2998a7/execroot/envoy/bazel-out/aarch64-fastbuild/bin/test/extensions/geoip_providers/maxmind/geoip_provider_test+0x727ea10) #12 0xb7d3f2f2b2c0 in main (/home/nezdolik.linux/.cache/bazel/_bazel_nezdolik/9a5f062d7ba021dba530b9f40b2998a7/execroot/envoy/bazel-out/aarch64-fastbuild/bin/test/extensions/geoip_providers/maxmind/geoip_provider_test+0x727b2c0) #13 0xe6dc6ea07580 (/lib/aarch64-linux-gnu/libc.so.6+0x27580) (BuildId: 5b12268cafe96b30a4b950adece623b540b747be) #14 0xe6dc6ea07654 in __libc_start_main (/lib/aarch64-linux-gnu/libc.so.6+0x27654) (BuildId: 5b12268cafe96b30a4b950adece623b540b747be) #15 0xb7d3f0502eec in _start (/home/nezdolik.linux/.cache/bazel/_bazel_nezdolik/9a5f062d7ba021dba530b9f40b2998a7/execroot/envoy/bazel-out/aarch64-fastbuild/bin/test/extensions/geoip_providers/maxmind/geoip_provider_test+0x4852eec) previously allocated by thread T1 here: #0 0xb7d3f05a03cc in malloc (/home/nezdolik.linux/.cache/bazel/_bazel_nezdolik/9a5f062d7ba021dba530b9f40b2998a7/execroot/envoy/bazel-out/aarch64-fastbuild/bin/test/extensions/geoip_providers/maxmind/geoip_provider_test+0x48f03cc) #1 0xb7d3f5428378 in operator new(unsigned long) (/home/nezdolik.linux/.cache/bazel/_bazel_nezdolik/9a5f062d7ba021dba530b9f40b2998a7/execroot/envoy/bazel-out/aarch64-fastbuild/bin/test/extensions/geoip_providers/maxmind/geoip_provider_test+0x9778378) #2 0xb7d3f065b994 in std::vector, std::allocator>>::reserve(unsigned long) (/home/nezdolik.linux/.cache/bazel/_bazel_nezdolik/9a5f062d7ba021dba530b9f40b2998a7/execroot/envoy/bazel-out/aarch64-fastbuild/bin/test/extensions/geoip_providers/maxmind/geoip_provider_test+0x49ab994) #3 0xb7d3f065b684 in Envoy::Extensions::GeoipProviders::Maxmind::GeoipProviderTestBase::initializeProvider(std::__cxx11::basic_string, std::allocator> const&, std::optional&)::'lambda'()::operator()() const::'lambda'(std::basic_string_view>, unsigned int, std::function)::operator()(std::basic_string_view>, unsigned int, std::function) const (/home/nezdolik.linux/.cache/bazel/_bazel_nezdolik/9a5f062d7ba021dba530b9f40b2998a7/execroot/envoy/bazel-out/aarch64-fastbuild/bin/test/extensions/geoip_providers/maxmind/geoip_provider_test+0x49ab684) #4 0xb7d3f065b2c0 in std::_Function_handler>, unsigned int, std::function), Envoy::Extensions::GeoipProviders::Maxmind::GeoipProviderTestBase::initializeProvider(std::__cxx11::basic_string, std::allocator> const&, std::optional&)::'lambda'()::operator()() const::'lambda'(std::basic_string_view>, unsigned int, std::function)>::_M_invoke(std::_Any_data const&, std::basic_string_view>&&, unsigned int&&, std::function&&) (/home/nezdolik.linux/.cache/bazel/_bazel_nezdolik/9a5f062d7ba021dba530b9f40b2998a7/execroot/envoy/bazel-out/aarch64-fastbuild/bin/test/extensions/geoip_providers/maxmind/geoip_provider_test+0x49ab2c0) #5 0xb7d3f3080050 in decltype(std::forward>, unsigned int, std::function)> const&>(fp)(std::get<0ul>(std::forward>, unsigned int, std::function>>(fp0)), std::get<1ul>(std::forward>, unsigned int, std::function>>(fp0)), std::get<2ul>(std::forward>, unsigned int, std::function>>(fp0)))) testing::internal::ApplyImpl>, unsigned int, std::function)> const&, std::tuple>, unsigned int, std::function>, 0ul, 1ul, 2ul>(std::function>, unsigned int, std::function)> const&, std::tuple>, unsigned int, std::function>&&, testing::internal::IndexSequence<0ul, 1ul, 2ul>) (/home/nezdolik.linux/.cache/bazel/_bazel_nezdolik/9a5f062d7ba021dba530b9f40b2998a7/execroot/envoy/bazel-out/aarch64-fastbuild/bin/test/extensions/geoip_providers/maxmind/geoip_provider_test+0x73d0050) #6 0xb7d3f3080438 in testing::internal::ActionResultHolder* testing::internal::ActionResultHolder::PerformAction>, unsigned int, std::function)>(testing::Action>, unsigned int, std::function)> const&, testing::internal::Function>, unsigned int, std::function)>::ArgumentTuple&&) (/home/nezdolik.linux/.cache/bazel/_bazel_nezdolik/9a5f062d7ba021dba530b9f40b2998a7/execroot/envoy/bazel-out/aarch64-fastbuild/bin/test/extensions/geoip_providers/maxmind/geoip_provider_test+0x73d0438) #7 0xb7d3f307e148 in testing::internal::FunctionMocker>, unsigned int, std::function)>::UntypedPerformAction(void const*, void*) const (/home/nezdolik.linux/.cache/bazel/_bazel_nezdolik/9a5f062d7ba021dba530b9f40b2998a7/execroot/envoy/bazel-out/aarch64-fastbuild/bin/test/extensions/geoip_providers/maxmind/geoip_provider_test+0x73ce148) #8 0xb7d3f531993c in testing::internal::UntypedFunctionMockerBase::UntypedInvokeWith(void*) (/home/nezdolik.linux/.cache/bazel/_bazel_nezdolik/9a5f062d7ba021dba530b9f40b2998a7/execroot/envoy/bazel-out/aarch64-fastbuild/bin/test/extensions/geoip_providers/maxmind/geoip_provider_test+0x966993c) #9 0xb7d3f0657fa0 in testing::internal::FunctionMocker>, unsigned int, std::function)>::Invoke(std::basic_string_view>, unsigned int, std::function) (/home/nezdolik.linux/.cache/bazel/_bazel_nezdolik/9a5f062d7ba021dba530b9f40b2998a7/execroot/envoy/bazel-out/aarch64-fastbuild/bin/test/extensions/geoip_providers/maxmind/geoip_provider_test+0x49a7fa0) #10 0xb7d3f0657c2c in Envoy::Filesystem::MockWatcher::addWatch(std::basic_string_view>, unsigned int, std::function) (/home/nezdolik.linux/.cache/bazel/_bazel_nezdolik/9a5f062d7ba021dba530b9f40b2998a7/execroot/envoy/bazel-out/aarch64-fastbuild/bin/test/extensions/geoip_providers/maxmind/geoip_provider_test+0x49a7c2c) #11 0xb7d3f06b61d4 in std::_Function_handler, std::shared_ptr)::$_0>::_M_invoke(std::_Any_data const&) geoip_provider.cc #12 0xb7d3f45c9fc8 in Envoy::Thread::PosixThreadFactory::createPthread(Envoy::Thread::ThreadHandle*)::$_0::__invoke(void*) thread_impl.cc #13 0xe6dc6ea637cc (/lib/aarch64-linux-gnu/libc.so.6+0x837cc) (BuildId: 5b12268cafe96b30a4b950adece623b540b747be) #14 0xe6dc6eacf5c8 (/lib/aarch64-linux-gnu/libc.so.6+0xef5c8) (BuildId: 5b12268cafe96b30a4b950adece623b540b747be) ``` Commit Message: Additional Description: Risk Level: Testing: Docs Changes: Release Notes: Platform Specific Features: [Optional Runtime guard:] [Optional Fixes #Issue] [Optional Fixes commit #PR or SHA] [Optional Deprecated:] [Optional [API Considerations](https://github.com/envoyproxy/envoy/blob/main/api/review_checklist.md):] Signed-off-by: Kateryna Nezdolii --- test/extensions/geoip_providers/maxmind/geoip_provider_test.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/extensions/geoip_providers/maxmind/geoip_provider_test.cc b/test/extensions/geoip_providers/maxmind/geoip_provider_test.cc index 14bb461843..29ad29f045 100644 --- a/test/extensions/geoip_providers/maxmind/geoip_provider_test.cc +++ b/test/extensions/geoip_providers/maxmind/geoip_provider_test.cc @@ -157,13 +157,13 @@ class GeoipProviderTestBase { Api::ApiPtr api_; NiceMock server_factory_context_; NiceMock context_; - DriverSharedPtr provider_; MaxmindProviderFactory* provider_factory_; Event::SimulatedTimeSystem time_system_; absl::flat_hash_map captured_lookup_response_; absl::Mutex mutex_; std::vector on_changed_cbs_ ABSL_GUARDED_BY(mutex_); absl::optional cb_added_nullopt = absl::nullopt; + DriverSharedPtr provider_; }; class GeoipProviderTest : public testing::Test, public GeoipProviderTestBase {}; From d741737f825af43f7f80c49d14cea674785f7f0b Mon Sep 17 00:00:00 2001 From: Tianyu <72890320+tyxia@users.noreply.github.com> Date: Mon, 23 Sep 2024 20:53:24 -0400 Subject: [PATCH 59/65] ext_proc: Add allow list for mode override (#36279) Added allow list `allowed_override_modes` for mode_override. Risk Level: LOW Testing: Integration test Docs Changes: N/A Release Notes: Yes Platform Specific Features: N/A --------- Signed-off-by: tyxia --- .../filters/http/ext_proc/v3/ext_proc.proto | 11 ++- changelogs/current.yaml | 5 ++ source/extensions/filters/http/ext_proc/BUILD | 1 + .../filters/http/ext_proc/ext_proc.cc | 26 ++++++- .../filters/http/ext_proc/ext_proc.h | 7 ++ .../ext_proc/ext_proc_integration_test.cc | 67 +++++++++++++++++++ 6 files changed, 113 insertions(+), 4 deletions(-) diff --git a/api/envoy/extensions/filters/http/ext_proc/v3/ext_proc.proto b/api/envoy/extensions/filters/http/ext_proc/v3/ext_proc.proto index c497637b5d..d1a27657f1 100644 --- a/api/envoy/extensions/filters/http/ext_proc/v3/ext_proc.proto +++ b/api/envoy/extensions/filters/http/ext_proc/v3/ext_proc.proto @@ -94,7 +94,7 @@ option (udpa.annotations.file_status).package_version_status = ACTIVE; // ` object in a namespace matching the filter // name. // -// [#next-free-field: 22] +// [#next-free-field: 23] message ExternalProcessor { // Describes the route cache action to be taken when an external processor response // is received in response to request headers. @@ -284,6 +284,15 @@ message ExternalProcessor { // in a single body response message, followed by the remaining body responses. // In all scenarios, the header-body ordering must always be maintained. bool send_body_without_waiting_for_header_response = 21; + + // When :ref:`allow_mode_override + // ` is enabled and + // ``allowed_override_modes`` is configured, the filter config :ref:`processing_mode + // ` + // can only be overridden by the response message from the external processing server iff the + // :ref:`mode_override ` is allowed by + // the ``allowed_override_modes`` allow-list below. + repeated ProcessingMode allowed_override_modes = 22; } // ExtProcHttpService is used for HTTP communication between the filter and the external processing service. diff --git a/changelogs/current.yaml b/changelogs/current.yaml index 34bfdd97fd..3c2c61e60b 100644 --- a/changelogs/current.yaml +++ b/changelogs/current.yaml @@ -404,5 +404,10 @@ new_features: change: | Added ``max_packet_length`` to the QUIC protocol options to allow users to change the largest size of a QUIC packet that can be transmitted over the QUIC connection. +- area: ext_proc + change: | + Added allow list + :ref:`allowed_override_modes ` + for :ref:`mode_override `. deprecated: diff --git a/source/extensions/filters/http/ext_proc/BUILD b/source/extensions/filters/http/ext_proc/BUILD index c0458497d5..c6cb55ffb2 100644 --- a/source/extensions/filters/http/ext_proc/BUILD +++ b/source/extensions/filters/http/ext_proc/BUILD @@ -30,6 +30,7 @@ envoy_cc_library( "//envoy/stats:stats_macros", "//source/common/buffer:buffer_lib", "//source/common/protobuf", + "//source/common/protobuf:utility_lib", "//source/common/runtime:runtime_features_lib", "//source/extensions/filters/common/mutation_rules:mutation_rules_lib", "//source/extensions/filters/http/common:pass_through_filter_lib", diff --git a/source/extensions/filters/http/ext_proc/ext_proc.cc b/source/extensions/filters/http/ext_proc/ext_proc.cc index 3013ea1d82..83dde06362 100644 --- a/source/extensions/filters/http/ext_proc/ext_proc.cc +++ b/source/extensions/filters/http/ext_proc/ext_proc.cc @@ -7,6 +7,7 @@ #include "envoy/extensions/filters/http/ext_proc/v3/processing_mode.pb.h" #include "source/common/http/utility.h" +#include "source/common/protobuf/utility.h" #include "source/common/runtime/runtime_features.h" #include "source/extensions/filters/http/ext_proc/mutation_utils.h" @@ -206,6 +207,8 @@ FilterConfig::FilterConfig( untyped_receiving_namespaces_( config.metadata_options().receiving_namespaces().untyped().begin(), config.metadata_options().receiving_namespaces().untyped().end()), + allowed_override_modes_(config.allowed_override_modes().begin(), + config.allowed_override_modes().end()), expression_manager_(builder, context.localInfo(), config.request_attributes(), config.response_attributes()), immediate_mutation_checker_(context.regexEngine()), @@ -1068,9 +1071,26 @@ void Filter::onReceiveMessage(std::unique_ptr&& r) { // set to true and filter is waiting for header processing response. // Otherwise, the response mode_override proto field is ignored. if (config_->allowModeOverride() && inHeaderProcessState() && response->has_mode_override()) { - ENVOY_LOG(debug, "Processing mode overridden by server for this request"); - decoding_state_.setProcessingMode(response->mode_override()); - encoding_state_.setProcessingMode(response->mode_override()); + bool mode_override_allowed = true; + const auto& mode_overide = response->mode_override(); + // First, check if mode override allow-list is configured + if (!config_->allowedOverrideModes().empty()) { + // Second, check if mode override from response is allowed. + mode_override_allowed = absl::c_any_of( + config_->allowedOverrideModes(), + [&mode_overide]( + const envoy::extensions::filters::http::ext_proc::v3::ProcessingMode& other) { + return Protobuf::util::MessageDifferencer::Equals(mode_overide, other); + }); + } + + if (mode_override_allowed) { + ENVOY_LOG(debug, "Processing mode overridden by server for this request"); + decoding_state_.setProcessingMode(mode_overide); + encoding_state_.setProcessingMode(mode_overide); + } else { + ENVOY_LOG(debug, "Processing mode overridden by server is disallowed"); + } } ENVOY_LOG(debug, "Received {} response", responseCaseToString(response->response_case())); diff --git a/source/extensions/filters/http/ext_proc/ext_proc.h b/source/extensions/filters/http/ext_proc/ext_proc.h index 070b60b58d..a908a1f6f7 100644 --- a/source/extensions/filters/http/ext_proc/ext_proc.h +++ b/source/extensions/filters/http/ext_proc/ext_proc.h @@ -261,6 +261,11 @@ class FilterConfig { return immediate_mutation_checker_; } + const std::vector& + allowedOverrideModes() const { + return allowed_override_modes_; + } + ThreadLocalStreamManager& threadLocalStreamManager() { return thread_local_stream_manager_slot_->getTyped(); } @@ -297,6 +302,8 @@ class FilterConfig { const std::vector untyped_forwarding_namespaces_; const std::vector typed_forwarding_namespaces_; const std::vector untyped_receiving_namespaces_; + const std::vector + allowed_override_modes_; const ExpressionManager expression_manager_; const ImmediateMutationChecker immediate_mutation_checker_; diff --git a/test/extensions/filters/http/ext_proc/ext_proc_integration_test.cc b/test/extensions/filters/http/ext_proc/ext_proc_integration_test.cc index 921850ac73..697a773a1e 100644 --- a/test/extensions/filters/http/ext_proc/ext_proc_integration_test.cc +++ b/test/extensions/filters/http/ext_proc/ext_proc_integration_test.cc @@ -4665,4 +4665,71 @@ TEST_P(ExtProcIntegrationTest, SendHeaderBodyNotSendTrailerTest) { verifyDownstreamResponse(*response, 200); } +TEST_P(ExtProcIntegrationTest, ModeOverrideAllowed) { + proto_config_.mutable_processing_mode()->set_response_header_mode(ProcessingMode::SKIP); + proto_config_.set_allow_mode_override(true); + // Configure mode override allow list. + auto* added_mode = proto_config_.add_allowed_override_modes(); + added_mode->set_request_body_mode(ProcessingMode::NONE); + added_mode = proto_config_.add_allowed_override_modes(); + added_mode->set_request_body_mode(ProcessingMode::STREAMED); + added_mode->set_response_header_mode(ProcessingMode::SKIP); + initializeConfig(); + HttpIntegrationTest::initialize(); + + std::string body_str = std::string(10, 'a'); + auto response = sendDownstreamRequestWithBody(body_str, absl::nullopt); + + // Process request header message. + processGenericMessage( + *grpc_upstreams_[0], true, [](const ProcessingRequest&, ProcessingResponse& resp) { + resp.mutable_request_headers(); + resp.mutable_mode_override()->set_response_header_mode(ProcessingMode::SKIP); + resp.mutable_mode_override()->set_request_body_mode(ProcessingMode::STREAMED); + return true; + }); + + // ext_proc server will receive the body message since the processing body mode has been + // overridden from `ProcessingMode::NONE` to `ProcessingMode::STREAMED` + processRequestBodyMessage(*grpc_upstreams_[0], false, [](const HttpBody& body, BodyResponse&) { + EXPECT_TRUE(body.end_of_stream()); + return true; + }); + handleUpstreamRequest(); + verifyDownstreamResponse(*response, 200); +} + +TEST_P(ExtProcIntegrationTest, ModeOverrideDisallowed) { + proto_config_.mutable_processing_mode()->set_request_body_mode(ProcessingMode::STREAMED); + proto_config_.mutable_processing_mode()->set_response_header_mode(ProcessingMode::SKIP); + proto_config_.set_allow_mode_override(true); + // Configure mode override allow list. + auto* added_mode = proto_config_.add_allowed_override_modes(); + added_mode->set_request_body_mode(ProcessingMode::BUFFERED); + added_mode->set_response_header_mode(ProcessingMode::SKIP); + initializeConfig(); + HttpIntegrationTest::initialize(); + + std::string body_str = std::string(10, 'a'); + auto response = sendDownstreamRequestWithBody(body_str, absl::nullopt); + + // Process request header message. + processGenericMessage( + *grpc_upstreams_[0], true, [](const ProcessingRequest&, ProcessingResponse& resp) { + resp.mutable_request_headers(); + resp.mutable_mode_override()->set_response_header_mode(ProcessingMode::SKIP); + resp.mutable_mode_override()->set_request_body_mode(ProcessingMode::NONE); + return true; + }); + + // ext_proc server still receive the body message even though body mode override was set to + // ProcessingMode::NONE. It is because that ProcessingMode::NONE was not in allow list. + processRequestBodyMessage(*grpc_upstreams_[0], false, [](const HttpBody& body, BodyResponse&) { + EXPECT_TRUE(body.end_of_stream()); + return true; + }); + handleUpstreamRequest(); + verifyDownstreamResponse(*response, 200); +} + } // namespace Envoy From 38530270d6cb3a3a71a9b70b3de55854750b75a9 Mon Sep 17 00:00:00 2001 From: alyssawilk Date: Mon, 23 Sep 2024 20:53:47 -0400 Subject: [PATCH 60/65] runtime: deprecating dfp_mixed_scheme (#36199) Risk Level: low Testing: n/a Docs Changes: n/a Release Notes: inline Fixes https://github.com/envoyproxy/envoy/issues/31973 Signed-off-by: Alyssa Wilk --- changelogs/current.yaml | 3 +++ mobile/library/common/internal_engine.cc | 5 ----- source/common/runtime/runtime_features.cc | 1 - .../extensions/common/dynamic_forward_proxy/dns_cache.h | 3 --- .../network/sni_dynamic_forward_proxy/proxy_filter.cc | 9 +++------ .../common/dynamic_forward_proxy/dns_cache_impl_test.cc | 2 -- 6 files changed, 6 insertions(+), 17 deletions(-) diff --git a/changelogs/current.yaml b/changelogs/current.yaml index 3c2c61e60b..243f058e27 100644 --- a/changelogs/current.yaml +++ b/changelogs/current.yaml @@ -208,6 +208,9 @@ removed_config_or_runtime: - area: tls change: | Removed runtime flag ``envoy.reloadable_features.ssl_transport_failure_reason_format``. +- area: dynamic_foward_proxy + change: | + Removed runtime flag ``envoy.reloadable_features.dfp_mixed_scheme`` and legacy code path. - area: http change: | Removed runtime flag ``envoy.reloadable_features.abort_filter_chain_on_stream_reset`` and legacy diff --git a/mobile/library/common/internal_engine.cc b/mobile/library/common/internal_engine.cc index 4ca9a9075e..ea6c36f4ad 100644 --- a/mobile/library/common/internal_engine.cc +++ b/mobile/library/common/internal_engine.cc @@ -34,11 +34,6 @@ InternalEngine::InternalEngine(std::unique_ptr callbacks, ExtensionRegistry::registerFactories(); Api::External::registerApi(std::string(ENVOY_EVENT_TRACKER_API_NAME), &event_tracker_); - // Envoy Mobile always requires dfp_mixed_scheme for the TLS and cleartext DFP clusters. - // While dfp_mixed_scheme defaults to true, some environments force it to false (e.g. within - // Google), so we force it back to true in Envoy Mobile. - // TODO(abeyad): Remove once this is no longer needed. - Runtime::maybeSetRuntimeGuard("envoy.reloadable_features.dfp_mixed_scheme", true); } InternalEngine::InternalEngine(std::unique_ptr callbacks, diff --git a/source/common/runtime/runtime_features.cc b/source/common/runtime/runtime_features.cc index 7b28eebbb2..0d09985c93 100644 --- a/source/common/runtime/runtime_features.cc +++ b/source/common/runtime/runtime_features.cc @@ -35,7 +35,6 @@ RUNTIME_GUARD(envoy_reloadable_features_check_switch_protocol_websocket_handshak RUNTIME_GUARD(envoy_reloadable_features_conn_pool_delete_when_idle); RUNTIME_GUARD(envoy_reloadable_features_consistent_header_validation); RUNTIME_GUARD(envoy_reloadable_features_defer_processing_backedup_streams); -RUNTIME_GUARD(envoy_reloadable_features_dfp_mixed_scheme); RUNTIME_GUARD(envoy_reloadable_features_disallow_quic_client_udp_mmsg); RUNTIME_GUARD(envoy_reloadable_features_dns_details); RUNTIME_GUARD(envoy_reloadable_features_dns_nodata_noname_is_success); diff --git a/source/extensions/common/dynamic_forward_proxy/dns_cache.h b/source/extensions/common/dynamic_forward_proxy/dns_cache.h index d656efce9c..7afeb0fc41 100644 --- a/source/extensions/common/dynamic_forward_proxy/dns_cache.h +++ b/source/extensions/common/dynamic_forward_proxy/dns_cache.h @@ -28,9 +28,6 @@ class DnsHostInfo { // This normalizes hostnames, respecting the port if it exists, and adding the default port // if there is no port. static std::string normalizeHostForDfp(absl::string_view host, uint16_t default_port) { - if (!Runtime::runtimeFeatureEnabled("envoy.reloadable_features.dfp_mixed_scheme")) { - return std::string(host); - } if (Envoy::Http::HeaderUtility::hostHasPort(host)) { return std::string(host); } diff --git a/source/extensions/filters/network/sni_dynamic_forward_proxy/proxy_filter.cc b/source/extensions/filters/network/sni_dynamic_forward_proxy/proxy_filter.cc index fd6f87d7d2..3a45c764be 100644 --- a/source/extensions/filters/network/sni_dynamic_forward_proxy/proxy_filter.cc +++ b/source/extensions/filters/network/sni_dynamic_forward_proxy/proxy_filter.cc @@ -71,12 +71,9 @@ Network::FilterStatus ProxyFilter::onNewConnection() { port = dynamic_port_filter_state->value(); } else { port = config_->port(); - if (Runtime::runtimeFeatureEnabled("envoy.reloadable_features.dfp_mixed_scheme")) { - read_callbacks_->connection().streamInfo().filterState()->setData( - "envoy.upstream.dynamic_port", std::make_shared(port), - StreamInfo::FilterState::StateType::Mutable, - StreamInfo::FilterState::LifeSpan::Connection); - } + read_callbacks_->connection().streamInfo().filterState()->setData( + "envoy.upstream.dynamic_port", std::make_shared(port), + StreamInfo::FilterState::StateType::Mutable, StreamInfo::FilterState::LifeSpan::Connection); } auto result = config_->cache().loadDnsCacheEntry(host, port, false, *this); diff --git a/test/extensions/common/dynamic_forward_proxy/dns_cache_impl_test.cc b/test/extensions/common/dynamic_forward_proxy/dns_cache_impl_test.cc index 2cba229e1f..2d3dfce1d9 100644 --- a/test/extensions/common/dynamic_forward_proxy/dns_cache_impl_test.cc +++ b/test/extensions/common/dynamic_forward_proxy/dns_cache_impl_test.cc @@ -42,7 +42,6 @@ class DnsCacheImplTest : public testing::Test, public Event::TestUsingSimulatedT void initialize( std::vector> preresolve_hostnames = {}, uint32_t max_hosts = 1024) { - scoped_runtime_.mergeValues({{"envoy.reloadable_features.dfp_mixed_scheme", "true"}}); config_.set_name("foo"); config_.set_dns_lookup_family(envoy::config::cluster::v3::Cluster::V4_ONLY); config_.mutable_max_hosts()->set_value(max_hosts); @@ -1915,7 +1914,6 @@ TEST(DnsCacheManagerImplTest, TestLifetime) { TEST(NoramlizeHost, NormalizeHost) { TestScopedRuntime scoped_runtime; - scoped_runtime.mergeValues({{"envoy.reloadable_features.dfp_mixed_scheme", "true"}}); EXPECT_EQ("localhost:80", DnsHostInfo::normalizeHostForDfp("localhost:80", 80)); EXPECT_EQ("localhost:80", DnsHostInfo::normalizeHostForDfp("localhost:80", 443)); EXPECT_EQ("localhost:443", DnsHostInfo::normalizeHostForDfp("localhost:443", 80)); From 46e8da9d1b01ecf120d503bd0449a3041cb63399 Mon Sep 17 00:00:00 2001 From: Dennis Kniep Date: Tue, 24 Sep 2024 11:49:53 +0200 Subject: [PATCH 61/65] oauth filter: set token cookies regardless of forward_bearer_token option and ability to disable bearertoken and refreshtoken cookie (#35839) **Commit Message:** oauth filter: set token cookies regardless of forward_bearer_token option + ability to disable refreshtoken and bearertoken cookie **Additional Description:** Unconditionally set the BearerToken, IdToken, and RefreshToken cookies in the response. The documentation of forward_bearer_token states "Forward the OAuth token as a XXX to upstream web service." It's confusing for this behavior to affect response cookies as well. This change alone would set the raw bearer token in the client browser which is undesirable by some. Therefore introduced further properties to disable single cookies, if necessary: * `disable_access_token_set_cookie` * `disable_refresh_token_set_cookie` Like it was done here: https://github.com/envoyproxy/envoy/issues/33825 Risk Level: Low Testing: Included Docs Changes: N/A Release Notes: Included Platform Specific Features: N/A Fixes: https://github.com/envoyproxy/envoy/issues/32566 --------- Signed-off-by: Dennis Kniep --- .../filters/http/oauth2/v3/oauth.proto | 18 ++- changelogs/current.yaml | 14 ++ .../extensions/filters/http/oauth2/filter.cc | 74 +++++---- .../extensions/filters/http/oauth2/filter.h | 4 + .../filters/http/oauth2/filter_test.cc | 151 +++++++++++++++++- .../http/oauth2/oauth_integration_test.cc | 8 +- 6 files changed, 226 insertions(+), 43 deletions(-) diff --git a/api/envoy/extensions/filters/http/oauth2/v3/oauth.proto b/api/envoy/extensions/filters/http/oauth2/v3/oauth.proto index df377fd6ad..968ec13608 100644 --- a/api/envoy/extensions/filters/http/oauth2/v3/oauth.proto +++ b/api/envoy/extensions/filters/http/oauth2/v3/oauth.proto @@ -84,7 +84,7 @@ message OAuth2Credentials { // OAuth config // -// [#next-free-field: 19] +// [#next-free-field: 21] message OAuth2Config { enum AuthType { // The ``client_id`` and ``client_secret`` will be sent in the URL encoded request body. @@ -125,7 +125,7 @@ message OAuth2Config { bool forward_bearer_token = 7; // If set to true, preserve the existing authorization header. - // By default Envoy strips the existing authorization header before forwarding upstream. + // By default the client strips the existing authorization header before forwarding upstream. // Can not be set to true if forward_bearer_token is already set to true. // Default value is false. bool preserve_authorization_header = 16; @@ -169,11 +169,23 @@ message OAuth2Config { // This setting is only considered if ``use_refresh_token`` is set to true, otherwise the authorization server expiration or ``default_expires_in`` is used. google.protobuf.Duration default_refresh_token_expires_in = 15; - // If set to true, Envoy will not set a cookie for ID Token even if one is received from the Identity Provider. This may be useful in cases where the ID + // If set to true, the client will not set a cookie for ID Token even if one is received from the Identity Provider. This may be useful in cases where the ID // Token is too large for HTTP cookies (longer than 4096 characters). Enabling this option will only disable setting the cookie response header, the filter // will still process incoming ID Tokens as part of the HMAC if they are there. This is to ensure compatibility while switching this setting on. Future // sessions would not set the IdToken cookie header. bool disable_id_token_set_cookie = 17; + + // If set to true, the client will not set a cookie for Access Token even if one is received from the Identity Provider. + // Enabling this option will only disable setting the cookie response header, the filter + // will still process incoming Access Tokens as part of the HMAC if they are there. This is to ensure compatibility while switching this setting on. Future + // sessions would not set the Access Token cookie header. + bool disable_access_token_set_cookie = 19; + + // If set to true, the client will not set a cookie for Refresh Token even if one is received from the Identity Provider. + // Enabling this option will only disable setting the cookie response header, the filter + // will still process incoming Refresh Tokens as part of the HMAC if they are there. This is to ensure compatibility while switching this setting on. Future + // sessions would not set the Refresh Token cookie header. + bool disable_refresh_token_set_cookie = 20; } // Filter config. diff --git a/changelogs/current.yaml b/changelogs/current.yaml index 243f058e27..4ae0bc88ca 100644 --- a/changelogs/current.yaml +++ b/changelogs/current.yaml @@ -185,6 +185,10 @@ bug_fixes: Fixed a bug in the CONNECT-UDP forwarding mode where Envoy reset the upstream stream when it received HTTP/3 datagrams before receiving the SETTINGS frame from the upstream peer. Envoy now drops the datagrams in this case instead of resetting the stream. +- area: oauth + change: | + Set token cookies in response regardless of :ref:`forward_bearer_token + ` config option. removed_config_or_runtime: # *Normally occurs at the end of the* :ref:`deprecation period ` @@ -407,6 +411,16 @@ new_features: change: | Added ``max_packet_length`` to the QUIC protocol options to allow users to change the largest size of a QUIC packet that can be transmitted over the QUIC connection. +- area: oauth + change: | + Added :ref:`disable_access_token_set_cookie + ` + to disable setting the Access Token cookie. +- area: oauth + change: | + Added :ref:`disable_refresh_token_set_cookie + ` + to disable setting the Refresh Token cookie. - area: ext_proc change: | Added allow list diff --git a/source/extensions/filters/http/oauth2/filter.cc b/source/extensions/filters/http/oauth2/filter.cc index e35d664b0e..12657167f4 100644 --- a/source/extensions/filters/http/oauth2/filter.cc +++ b/source/extensions/filters/http/oauth2/filter.cc @@ -215,7 +215,9 @@ FilterConfig::FilterConfig( forward_bearer_token_(proto_config.forward_bearer_token()), preserve_authorization_header_(proto_config.preserve_authorization_header()), use_refresh_token_(proto_config.use_refresh_token().value()), - disable_id_token_set_cookie_(proto_config.disable_id_token_set_cookie()) { + disable_id_token_set_cookie_(proto_config.disable_id_token_set_cookie()), + disable_access_token_set_cookie_(proto_config.disable_access_token_set_cookie()), + disable_refresh_token_set_cookie_(proto_config.disable_refresh_token_set_cookie()) { if (!context.clusterManager().clusters().hasCluster(oauth_token_endpoint_.cluster())) { throw EnvoyException(fmt::format("OAuth2 filter: unknown cluster '{}' in config. Please " "specify which cluster to direct OAuth requests to.", @@ -579,14 +581,25 @@ Http::FilterHeadersStatus OAuth2Filter::signOutUser(const Http::RequestHeaderMap // Called after fetching access/refresh tokens. void OAuth2Filter::updateTokens(const std::string& access_token, const std::string& id_token, const std::string& refresh_token, std::chrono::seconds expires_in) { - access_token_ = access_token; + if (!config_->disableAccessTokenSetCookie()) { + // Preventing this here excludes all other Access Token functionality + // * setting the cookie + // * omitting from HMAC computation (for setting, not for validating) + access_token_ = access_token; + } if (!config_->disableIdTokenSetCookie()) { // Preventing this here excludes all other ID Token functionality // * setting the cookie // * omitting from HMAC computation (for setting, not for validating) id_token_ = id_token; } - refresh_token_ = refresh_token; + if (!config_->disableRefreshTokenSetCookie()) { + // Preventing this here excludes all other Refresh Token functionality + // * setting the cookie + // * omitting from HMAC computation (for setting, not for validating) + refresh_token_ = refresh_token; + } + expires_in_ = std::to_string(expires_in.count()); expires_refresh_token_in_ = getExpiresTimeForRefreshToken(refresh_token, expires_in); expires_id_token_in_ = getExpiresTimeForIdToken(id_token, expires_in); @@ -606,12 +619,9 @@ std::string OAuth2Filter::getEncodedToken() const { domain = config_->cookieDomain(); } - if (config_->forwardBearerToken()) { - encoded_token = encodeHmac(token_secret_vec, domain, new_expires_, access_token_, id_token_, - refresh_token_); - } else { - encoded_token = encodeHmac(token_secret_vec, domain, new_expires_); - } + encoded_token = + encodeHmac(token_secret_vec, domain, new_expires_, access_token_, id_token_, refresh_token_); + return encoded_token; } @@ -714,14 +724,14 @@ void OAuth2Filter::finishRefreshAccessTokenFlow() { cookies.insert_or_assign(cookie_names.oauth_hmac_, getEncodedToken()); cookies.insert_or_assign(cookie_names.oauth_expires_, new_expires_); - if (config_->forwardBearerToken()) { + if (!access_token_.empty()) { cookies.insert_or_assign(cookie_names.bearer_token_, access_token_); - if (!id_token_.empty()) { - cookies.insert_or_assign(cookie_names.id_token_, id_token_); - } - if (!refresh_token_.empty()) { - cookies.insert_or_assign(cookie_names.refresh_token_, refresh_token_); - } + } + if (!id_token_.empty()) { + cookies.insert_or_assign(cookie_names.id_token_, id_token_); + } + if (!refresh_token_.empty()) { + cookies.insert_or_assign(cookie_names.refresh_token_, refresh_token_); } std::string new_cookies(absl::StrJoin(cookies, "; ", absl::PairFormatter("="))); @@ -765,28 +775,26 @@ void OAuth2Filter::addResponseCookies(Http::ResponseHeaderMap& headers, Http::Headers::get().SetCookie, absl::StrCat(cookie_names.oauth_expires_, "=", new_expires_, cookie_tail_http_only)); - // If opted-in, we also create a new Bearer cookie for the authorization token provided by the - // auth server. - if (config_->forwardBearerToken()) { + if (!access_token_.empty()) { headers.addReferenceKey( Http::Headers::get().SetCookie, absl::StrCat(cookie_names.bearer_token_, "=", access_token_, cookie_tail_http_only)); + } - if (!id_token_.empty()) { - const std::string id_token_cookie_tail_http_only = - fmt::format(CookieTailHttpOnlyFormatString, expires_id_token_in_); - headers.addReferenceKey( - Http::Headers::get().SetCookie, - absl::StrCat(cookie_names.id_token_, "=", id_token_, id_token_cookie_tail_http_only)); - } + if (!id_token_.empty()) { + const std::string id_token_cookie_tail_http_only = + fmt::format(CookieTailHttpOnlyFormatString, expires_id_token_in_); + headers.addReferenceKey( + Http::Headers::get().SetCookie, + absl::StrCat(cookie_names.id_token_, "=", id_token_, id_token_cookie_tail_http_only)); + } - if (!refresh_token_.empty()) { - const std::string refresh_token_cookie_tail_http_only = - fmt::format(CookieTailHttpOnlyFormatString, expires_refresh_token_in_); - headers.addReferenceKey(Http::Headers::get().SetCookie, - absl::StrCat(cookie_names.refresh_token_, "=", refresh_token_, - refresh_token_cookie_tail_http_only)); - } + if (!refresh_token_.empty()) { + const std::string refresh_token_cookie_tail_http_only = + fmt::format(CookieTailHttpOnlyFormatString, expires_refresh_token_in_); + headers.addReferenceKey(Http::Headers::get().SetCookie, + absl::StrCat(cookie_names.refresh_token_, "=", refresh_token_, + refresh_token_cookie_tail_http_only)); } } diff --git a/source/extensions/filters/http/oauth2/filter.h b/source/extensions/filters/http/oauth2/filter.h index c4f6680ea7..0fcad488f9 100644 --- a/source/extensions/filters/http/oauth2/filter.h +++ b/source/extensions/filters/http/oauth2/filter.h @@ -152,6 +152,8 @@ class FilterConfig { return default_refresh_token_expires_in_; } bool disableIdTokenSetCookie() const { return disable_id_token_set_cookie_; } + bool disableAccessTokenSetCookie() const { return disable_access_token_set_cookie_; } + bool disableRefreshTokenSetCookie() const { return disable_refresh_token_set_cookie_; } const OptRef retryPolicy() const { if (!retry_policy_.has_value()) { return absl::nullopt; @@ -186,6 +188,8 @@ class FilterConfig { const bool preserve_authorization_header_ : 1; const bool use_refresh_token_ : 1; const bool disable_id_token_set_cookie_ : 1; + const bool disable_access_token_set_cookie_ : 1; + const bool disable_refresh_token_set_cookie_ : 1; absl::optional retry_policy_; }; diff --git a/test/extensions/filters/http/oauth2/filter_test.cc b/test/extensions/filters/http/oauth2/filter_test.cc index e5110a4762..58c638e3a5 100644 --- a/test/extensions/filters/http/oauth2/filter_test.cc +++ b/test/extensions/filters/http/oauth2/filter_test.cc @@ -115,7 +115,9 @@ class OAuth2Test : public testing::TestWithParam { ::envoy::extensions::filters::http::oauth2::v3::OAuth2Config_AuthType:: OAuth2Config_AuthType_URL_ENCODED_BODY, int default_refresh_token_expires_in = 0, bool preserve_authorization_header = false, - bool disable_id_token_set_cookie = false, bool set_cookie_domain = false) { + bool disable_id_token_set_cookie = false, bool set_cookie_domain = false, + bool disable_access_token_set_cookie = false, + bool disable_refresh_token_set_cookie = false) { envoy::extensions::filters::http::oauth2::v3::OAuth2Config p; auto* endpoint = p.mutable_token_endpoint(); endpoint->set_cluster("auth.example.com"); @@ -128,6 +130,8 @@ class OAuth2Test : public testing::TestWithParam { p.set_forward_bearer_token(forward_bearer_token); p.set_preserve_authorization_header(preserve_authorization_header); p.set_disable_id_token_set_cookie(disable_id_token_set_cookie); + p.set_disable_access_token_set_cookie(disable_access_token_set_cookie); + p.set_disable_refresh_token_set_cookie(disable_refresh_token_set_cookie); auto* useRefreshToken = p.mutable_use_refresh_token(); useRefreshToken->set_value(use_refresh_token); @@ -680,6 +684,63 @@ TEST_F(OAuth2Test, OAuthOkPreserveForeignAuthHeader) { EXPECT_EQ(scope_.counterFromString("test.oauth_success").value(), 1); } +TEST_F(OAuth2Test, SetBearerToken) { + init(getConfig(false /* forward_bearer_token */)); + + // Set SystemTime to a fixed point so we get consistent HMAC encodings between test runs. + test_time_.setSystemTime(SystemTime(std::chrono::seconds(1000))); + + Http::TestRequestHeaderMapImpl request_headers{ + {Http::Headers::get().Path.get(), + "/_oauth?code=123&state=url%3Dhttps%253A%252F%252Fasdf%26nonce%3D1234567890000000"}, + {Http::Headers::get().Cookie.get(), + "OauthNonce=1234567890000000;path=/;Max-Age=600;secure;HttpOnly"}, + {Http::Headers::get().Host.get(), "traffic.example.com"}, + {Http::Headers::get().Scheme.get(), "https"}, + {Http::Headers::get().Method.get(), Http::Headers::get().MethodValues.Get}, + }; + + EXPECT_CALL(*validator_, setParams(_, _)); + EXPECT_CALL(*validator_, isValid()).WillOnce(Return(false)); + + // Sanitized return reference mocking + // std::string legit_token{"legit_token"}; + // EXPECT_CALL(*validator_, token()).WillRepeatedly(ReturnRef(legit_token)); + + EXPECT_CALL(*oauth_client_, asyncGetAccessToken("123", TEST_CLIENT_ID, "asdf_client_secret_fdsa", + "https://traffic.example.com" + TEST_CALLBACK, + AuthType::UrlEncodedBody)); + + EXPECT_EQ(Http::FilterHeadersStatus::StopAllIterationAndBuffer, + filter_->decodeHeaders(request_headers, false)); + + // Expected response after the callback & validation is complete - verifying we kept the + // state and method of the original request, including the query string parameters. + Http::TestRequestHeaderMapImpl response_headers{ + {Http::Headers::get().Status.get(), "302"}, + {Http::Headers::get().SetCookie.get(), "OauthHMAC=" + "4TKyxPV/F7yyvr0XgJ2bkWFOc8t4IOFen1k29b84MAQ=;" + "path=/;Max-Age=600;secure;HttpOnly"}, + {Http::Headers::get().SetCookie.get(), + "OauthExpires=1600;path=/;Max-Age=600;secure;HttpOnly"}, + {Http::Headers::get().SetCookie.get(), + "BearerToken=access_code;path=/;Max-Age=600;secure;HttpOnly"}, + {Http::Headers::get().SetCookie.get(), + "IdToken=some-id-token;path=/;Max-Age=600;secure;HttpOnly"}, + {Http::Headers::get().SetCookie.get(), + "RefreshToken=some-refresh-token;path=/;Max-Age=600;secure;HttpOnly"}, + {Http::Headers::get().Location.get(), "https://asdf"}, + }; + + EXPECT_CALL(decoder_callbacks_, encodeHeaders_(HeaderMapEqualRef(&response_headers), true)); + + filter_->onGetAccessTokenSuccess("access_code", "some-id-token", "some-refresh-token", + std::chrono::seconds(600)); + + EXPECT_EQ(scope_.counterFromString("test.oauth_failure").value(), 0); + EXPECT_EQ(scope_.counterFromString("test.oauth_success").value(), 1); +} + /** * Scenario: The OAuth filter receives a request without valid OAuth cookies to a non-callback URL * (indicating that the user needs to re-validate cookies or get 401'd). @@ -771,7 +832,6 @@ TEST_F(OAuth2Test, OAuthErrorNonOAuthHttpCallback) { "fV62OgLipChTQQC3UFgDp+l5sCiSb3zt7nCoJiVivWw=;" "path=/;Max-Age=;secure;HttpOnly"}, {Http::Headers::get().SetCookie.get(), "OauthExpires=;path=/;Max-Age=;secure;HttpOnly"}, - {Http::Headers::get().SetCookie.get(), "BearerToken=;path=/;Max-Age=;secure;HttpOnly"}, {Http::Headers::get().Location.get(), "https://traffic.example.com/test?name=admin&level=trace"}, }; @@ -1380,7 +1440,6 @@ TEST_F(OAuth2Test, OAuthTestFullFlowPostWithParameters) { "fV62OgLipChTQQC3UFgDp+l5sCiSb3zt7nCoJiVivWw=;" "path=/;Max-Age=;secure;HttpOnly"}, {Http::Headers::get().SetCookie.get(), "OauthExpires=;path=/;Max-Age=;secure;HttpOnly"}, - {Http::Headers::get().SetCookie.get(), "BearerToken=;path=/;Max-Age=;secure;HttpOnly"}, {Http::Headers::get().Location.get(), "https://traffic.example.com/test?name=admin&level=trace"}, }; @@ -1581,8 +1640,6 @@ TEST_F(OAuth2Test, OAuthTestFullFlowPostWithCookieDomain) { "domain=example.com;path=/;Max-Age=;secure;HttpOnly"}, {Http::Headers::get().SetCookie.get(), "OauthExpires=;domain=example.com;path=/;Max-Age=;secure;HttpOnly"}, - {Http::Headers::get().SetCookie.get(), - "BearerToken=;domain=example.com;path=/;Max-Age=;secure;HttpOnly"}, {Http::Headers::get().Location.get(), "https://traffic.example.com/test?name=admin&level=trace"}, }; @@ -1679,6 +1736,89 @@ TEST_F(DisabledIdTokenTests, SetCookieIgnoresIdTokenWhenDisabledRefreshToken) { EXPECT_THAT(response_headers, HeaderMapEqualRef(&expected_headers_)); } +class DisabledTokenTests : public OAuth2Test { +public: + DisabledTokenTests() : OAuth2Test(false) { + // Set SystemTime to a fixed point so we get consistent HMAC encodings between test runs. + test_time_.setSystemTime(SystemTime(std::chrono::seconds(1000))); + + request_headers_ = { + {Http::Headers::get().Host.get(), "traffic.example.com"}, + {Http::Headers::get().Path.get(), "/_oauth"}, + {Http::Headers::get().Method.get(), Http::Headers::get().MethodValues.Get}, + }; + + // Note no Token cookies below. + expected_headers_ = { + {Http::Headers::get().Status.get(), "302"}, + {Http::Headers::get().SetCookie.get(), + "OauthHMAC=" + hmac_without_tokens_ + ";path=/;Max-Age=600;secure;HttpOnly"}, + {Http::Headers::get().SetCookie.get(), + "OauthExpires=1600;path=/;Max-Age=600;secure;HttpOnly"}, + }; + + init(getConfig( + true /* forward_bearer_token */, true /* use_refresh_token */, + ::envoy::extensions::filters::http::oauth2::v3::OAuth2Config_AuthType:: + OAuth2Config_AuthType_URL_ENCODED_BODY /* encoded_body_type */, + 600 /* default_refresh_token_expires_in */, false /* preserve_authorization_header */, + true /* disable_id_token_set_cookie */, false /* set_cookie_domain */, + true /* disable_access_token_set_cookie */, true /* disable_refresh_token_set_cookie */)); + + EXPECT_CALL(*validator_, token()).WillRepeatedly(ReturnRef(hmac_without_tokens_)); + EXPECT_CALL(*validator_, setParams(_, _)); + EXPECT_CALL(*validator_, isValid()).WillOnce(Return(false)); + } + + std::string hmac_without_tokens_{"Crs4S83olTGsGL7jbxBWw37gvuv0P2WbOvGTr/F6Z0o="}; + const std::string access_code_{"access_code"}; + const std::string id_token_{"some-id-token"}; + const std::string refresh_token_{"some-refresh-token"}; + const std::chrono::seconds expires_in_{600}; + Http::TestRequestHeaderMapImpl request_headers_; + Http::TestResponseHeaderMapImpl expected_headers_; +}; + +// When disable_id_token_set_cookie is `true`, then during the access token flow the filter should +// *not* set the IdToken cookie in the 302 response and should produce an HMAC that does not +// consider the id-token. +TEST_F(DisabledTokenTests, SetCookieIgnoresTokensWhenAllTokensAreDisabled1) { + EXPECT_EQ(Http::FilterHeadersStatus::StopIteration, + filter_->decodeHeaders(request_headers_, false)); + + expected_headers_.addCopy(Http::Headers::get().Location.get(), ""); + EXPECT_CALL(decoder_callbacks_, encodeHeaders_(HeaderMapEqualRef(&expected_headers_), true)); + + // All Tokens are still received from the IdP, but not set in the response headers above. + filter_->onGetAccessTokenSuccess(access_code_, id_token_, refresh_token_, expires_in_); +} + +// When disable_id_token_set_cookie is `true`, then during the refresh token flow the filter should +// *not* set the IdToken request header that's forwarded, the response headers that are returned, +// and should produce an HMAC that does not consider the id-token. +TEST_F(DisabledTokenTests, SetCookieIgnoresTokensWhenAllTokensAreDisabled2) { + EXPECT_EQ(Http::FilterHeadersStatus::StopIteration, + filter_->decodeHeaders(request_headers_, false)); + + // All tokens are still received from the IdP, but not set in the request headers that are + // forwarded. + EXPECT_CALL(decoder_callbacks_, continueDecoding()); + filter_->onRefreshAccessTokenSuccess(access_code_, id_token_, refresh_token_, expires_in_); + auto cookies = Http::Utility::parseCookies(request_headers_); + const auto cookie_names = config_->cookieNames(); + EXPECT_EQ(cookies[cookie_names.oauth_hmac_], hmac_without_tokens_); + EXPECT_EQ(cookies[cookie_names.oauth_expires_], + "1600"); // Uses default_refresh_token_expires_in since not a legitimate JWT. + EXPECT_EQ(cookies.contains(cookie_names.bearer_token_), false); + EXPECT_EQ(cookies.contains(cookie_names.refresh_token_), false); + EXPECT_EQ(cookies.contains(cookie_names.id_token_), false); + + // And ensure when the response comes back, it has the same cookies in the `expected_headers_`. + Http::TestResponseHeaderMapImpl response_headers = {{Http::Headers::get().Status.get(), "302"}}; + filter_->encodeHeaders(response_headers, false); + EXPECT_THAT(response_headers, HeaderMapEqualRef(&expected_headers_)); +} + /** * Testing oauth response after tokens are set. * @@ -2280,7 +2420,6 @@ TEST_F(OAuth2Test, OAuthTestFullFlowWithUseRefreshToken) { "fV62OgLipChTQQC3UFgDp+l5sCiSb3zt7nCoJiVivWw=;" "path=/;Max-Age=;secure;HttpOnly"}, {Http::Headers::get().SetCookie.get(), "OauthExpires=;path=/;Max-Age=;secure;HttpOnly"}, - {Http::Headers::get().SetCookie.get(), "BearerToken=;path=/;Max-Age=;secure;HttpOnly"}, {Http::Headers::get().Location.get(), "https://traffic.example.com/test?name=admin&level=trace"}, }; diff --git a/test/extensions/filters/http/oauth2/oauth_integration_test.cc b/test/extensions/filters/http/oauth2/oauth_integration_test.cc index 0ee7b5e6eb..7cb83bc119 100644 --- a/test/extensions/filters/http/oauth2/oauth_integration_test.cc +++ b/test/extensions/filters/http/oauth2/oauth_integration_test.cc @@ -300,7 +300,7 @@ name: oauth checkClientSecretInRequest(token_secret); oauth2_request_->encodeHeaders( - Http::TestRequestHeaderMapImpl{{":status", "200"}, {"content-type", "application/json"}}, + Http::TestResponseHeaderMapImpl{{":status", "200"}, {"content-type", "application/json"}}, false); envoy::extensions::http_filters::oauth2::OAuthResponse oauth_response; @@ -342,6 +342,10 @@ name: oauth Http::Utility::parseSetCookieValue(response->headers(), default_cookie_names_.oauth_hmac_); std::string oauth_expires = Http::Utility::parseSetCookieValue( response->headers(), default_cookie_names_.oauth_expires_); + std::string bearer_token = Http::Utility::parseSetCookieValue( + response->headers(), default_cookie_names_.bearer_token_); + std::string refresh_token = Http::Utility::parseSetCookieValue( + response->headers(), default_cookie_names_.refresh_token_); RELEASE_ASSERT(response->waitForEndStream(), "unexpected timeout"); cleanup(); @@ -359,6 +363,8 @@ name: oauth {"cookie", absl::StrCat(default_cookie_names_.oauth_hmac_, "=", hmac)}, {"cookie", absl::StrCat(default_cookie_names_.oauth_expires_, "=", oauth_expires)}, {"cookie", absl::StrCat(default_cookie_names_.oauth_nonce_, "=1234567890000000")}, + {"cookie", absl::StrCat(default_cookie_names_.bearer_token_, "=", bearer_token)}, + {"cookie", absl::StrCat(default_cookie_names_.refresh_token_, "=", refresh_token)}, }; auto encoder_decoder2 = codec_client_->startRequest(headersWithCookie, true); response = std::move(encoder_decoder2.second); From 8b4eeee9755f4fd36e33af52952ab302c6cbe421 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 24 Sep 2024 10:52:53 +0100 Subject: [PATCH 62/65] build(deps): bump aiodocker from 0.22.2 to 0.23.0 in /tools/base (#36281) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- tools/base/requirements.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/base/requirements.txt b/tools/base/requirements.txt index a5e34dba82..431280bd70 100644 --- a/tools/base/requirements.txt +++ b/tools/base/requirements.txt @@ -76,9 +76,9 @@ aio-run-runner==0.3.3 \ # envoy-github-abstract # envoy-github-release # envoy-gpg-sign -aiodocker==0.22.2 \ - --hash=sha256:8730795a817836d22df36efb04dc0f07c09f5f66b61dac539a7e436d6f4e1af0 \ - --hash=sha256:ac16c9e13c01446a57b32481edca3557cdb8678fe19bb1d2debfe0cb7dc2ab29 +aiodocker==0.23.0 \ + --hash=sha256:45ede291063c7d1c24e78a766013c25e85b354a3bdcca68fe2bca64348e4dee2 \ + --hash=sha256:8c7ff2fc9e557898ae77bc9c1af8916f269285f230aedf1abbb81436054baed4 # via # -r requirements.in # envoy-distribution-distrotest From e3c90c5acda6e7ebc1cac39e437bbb6b5865bcc9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 24 Sep 2024 09:53:01 +0000 Subject: [PATCH 63/65] build(deps): bump thrift from 0.20.0 to 0.21.0 in /tools/base (#36280) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- tools/base/requirements.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/base/requirements.txt b/tools/base/requirements.txt index 431280bd70..64a866aaac 100644 --- a/tools/base/requirements.txt +++ b/tools/base/requirements.txt @@ -1363,8 +1363,8 @@ sphinxext-rediraffe==0.2.7 \ --hash=sha256:651dcbfae5ffda9ffd534dfb8025f36120e5efb6ea1a33f5420023862b9f725d \ --hash=sha256:9e430a52d4403847f4ffb3a8dd6dfc34a9fe43525305131f52ed899743a5fd8c # via envoy-docs-sphinx-runner -thrift==0.20.0 \ - --hash=sha256:4dd662eadf6b8aebe8a41729527bd69adf6ceaa2a8681cbef64d1273b3e8feba +thrift==0.21.0 \ + --hash=sha256:5e6f7c50f936ebfa23e924229afc95eb219f8c8e5a83202dd4a391244803e402 # via -r requirements.in tomli==2.0.1 \ --hash=sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc \ From 865aa1081a0a66d13b2564382abc89129c1ba090 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 24 Sep 2024 10:53:14 +0100 Subject: [PATCH 64/65] build(deps): bump yarl from 1.11.1 to 1.12.1 in /tools/base (#36297) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- tools/base/requirements.txt | 186 ++++++++++++++++++------------------ 1 file changed, 93 insertions(+), 93 deletions(-) diff --git a/tools/base/requirements.txt b/tools/base/requirements.txt index 64a866aaac..2dd1c2abd7 100644 --- a/tools/base/requirements.txt +++ b/tools/base/requirements.txt @@ -1515,99 +1515,99 @@ yapf==0.40.2 \ # via # -r requirements.in # envoy-code-check -yarl==1.11.1 \ - --hash=sha256:01a8697ec24f17c349c4f655763c4db70eebc56a5f82995e5e26e837c6eb0e49 \ - --hash=sha256:02da8759b47d964f9173c8675710720b468aa1c1693be0c9c64abb9d8d9a4867 \ - --hash=sha256:04293941646647b3bfb1719d1d11ff1028e9c30199509a844da3c0f5919dc520 \ - --hash=sha256:067b961853c8e62725ff2893226fef3d0da060656a9827f3f520fb1d19b2b68a \ - --hash=sha256:077da604852be488c9a05a524068cdae1e972b7dc02438161c32420fb4ec5e14 \ - --hash=sha256:09696438cb43ea6f9492ef237761b043f9179f455f405279e609f2bc9100212a \ - --hash=sha256:0b8486f322d8f6a38539136a22c55f94d269addb24db5cb6f61adc61eabc9d93 \ - --hash=sha256:0ea9682124fc062e3d931c6911934a678cb28453f957ddccf51f568c2f2b5e05 \ - --hash=sha256:0f351fa31234699d6084ff98283cb1e852270fe9e250a3b3bf7804eb493bd937 \ - --hash=sha256:14438dfc5015661f75f85bc5adad0743678eefee266ff0c9a8e32969d5d69f74 \ - --hash=sha256:15061ce6584ece023457fb8b7a7a69ec40bf7114d781a8c4f5dcd68e28b5c53b \ - --hash=sha256:15439f3c5c72686b6c3ff235279630d08936ace67d0fe5c8d5bbc3ef06f5a420 \ - --hash=sha256:17b5a386d0d36fb828e2fb3ef08c8829c1ebf977eef88e5367d1c8c94b454639 \ - --hash=sha256:18ac56c9dd70941ecad42b5a906820824ca72ff84ad6fa18db33c2537ae2e089 \ - --hash=sha256:1bb2d9e212fb7449b8fb73bc461b51eaa17cc8430b4a87d87be7b25052d92f53 \ - --hash=sha256:1e969fa4c1e0b1a391f3fcbcb9ec31e84440253325b534519be0d28f4b6b533e \ - --hash=sha256:1fa2e7a406fbd45b61b4433e3aa254a2c3e14c4b3186f6e952d08a730807fa0c \ - --hash=sha256:2164cd9725092761fed26f299e3f276bb4b537ca58e6ff6b252eae9631b5c96e \ - --hash=sha256:21a7c12321436b066c11ec19c7e3cb9aec18884fe0d5b25d03d756a9e654edfe \ - --hash=sha256:238a21849dd7554cb4d25a14ffbfa0ef380bb7ba201f45b144a14454a72ffa5a \ - --hash=sha256:250e888fa62d73e721f3041e3a9abf427788a1934b426b45e1b92f62c1f68366 \ - --hash=sha256:25861303e0be76b60fddc1250ec5986c42f0a5c0c50ff57cc30b1be199c00e63 \ - --hash=sha256:267b24f891e74eccbdff42241c5fb4f974de2d6271dcc7d7e0c9ae1079a560d9 \ - --hash=sha256:27fcb271a41b746bd0e2a92182df507e1c204759f460ff784ca614e12dd85145 \ - --hash=sha256:2909fa3a7d249ef64eeb2faa04b7957e34fefb6ec9966506312349ed8a7e77bf \ - --hash=sha256:3257978c870728a52dcce8c2902bf01f6c53b65094b457bf87b2644ee6238ddc \ - --hash=sha256:327c724b01b8641a1bf1ab3b232fb638706e50f76c0b5bf16051ab65c868fac5 \ - --hash=sha256:3de5292f9f0ee285e6bd168b2a77b2a00d74cbcfa420ed078456d3023d2f6dff \ - --hash=sha256:3fce4da3703ee6048ad4138fe74619c50874afe98b1ad87b2698ef95bf92c96d \ - --hash=sha256:3ff6b1617aa39279fe18a76c8d165469c48b159931d9b48239065767ee455b2b \ - --hash=sha256:400cd42185f92de559d29eeb529e71d80dfbd2f45c36844914a4a34297ca6f00 \ - --hash=sha256:4179522dc0305c3fc9782549175c8e8849252fefeb077c92a73889ccbcd508ad \ - --hash=sha256:4307d9a3417eea87715c9736d050c83e8c1904e9b7aada6ce61b46361b733d92 \ - --hash=sha256:476e20c433b356e16e9a141449f25161e6b69984fb4cdbd7cd4bd54c17844998 \ - --hash=sha256:489fa8bde4f1244ad6c5f6d11bb33e09cf0d1d0367edb197619c3e3fc06f3d91 \ - --hash=sha256:48a28bed68ab8fb7e380775f0029a079f08a17799cb3387a65d14ace16c12e2b \ - --hash=sha256:48dfd117ab93f0129084577a07287376cc69c08138694396f305636e229caa1a \ - --hash=sha256:4973eac1e2ff63cf187073cd4e1f1148dcd119314ab79b88e1b3fad74a18c9d5 \ - --hash=sha256:498442e3af2a860a663baa14fbf23fb04b0dd758039c0e7c8f91cb9279799bff \ - --hash=sha256:501c503eed2bb306638ccb60c174f856cc3246c861829ff40eaa80e2f0330367 \ - --hash=sha256:504cf0d4c5e4579a51261d6091267f9fd997ef58558c4ffa7a3e1460bd2336fa \ - --hash=sha256:61a5f2c14d0a1adfdd82258f756b23a550c13ba4c86c84106be4c111a3a4e413 \ - --hash=sha256:637c7ddb585a62d4469f843dac221f23eec3cbad31693b23abbc2c366ad41ff4 \ - --hash=sha256:66b63c504d2ca43bf7221a1f72fbe981ff56ecb39004c70a94485d13e37ebf45 \ - --hash=sha256:67459cf8cf31da0e2cbdb4b040507e535d25cfbb1604ca76396a3a66b8ba37a6 \ - --hash=sha256:688654f8507464745ab563b041d1fb7dab5d9912ca6b06e61d1c4708366832f5 \ - --hash=sha256:6907daa4b9d7a688063ed098c472f96e8181733c525e03e866fb5db480a424df \ - --hash=sha256:69721b8effdb588cb055cc22f7c5105ca6fdaa5aeb3ea09021d517882c4a904c \ - --hash=sha256:6d23754b9939cbab02c63434776df1170e43b09c6a517585c7ce2b3d449b7318 \ - --hash=sha256:7175a87ab8f7fbde37160a15e58e138ba3b2b0e05492d7351314a250d61b1591 \ - --hash=sha256:72bf26f66456baa0584eff63e44545c9f0eaed9b73cb6601b647c91f14c11f38 \ - --hash=sha256:74db2ef03b442276d25951749a803ddb6e270d02dda1d1c556f6ae595a0d76a8 \ - --hash=sha256:750f656832d7d3cb0c76be137ee79405cc17e792f31e0a01eee390e383b2936e \ - --hash=sha256:75e0ae31fb5ccab6eda09ba1494e87eb226dcbd2372dae96b87800e1dcc98804 \ - --hash=sha256:768ecc550096b028754ea28bf90fde071c379c62c43afa574edc6f33ee5daaec \ - --hash=sha256:7d51324a04fc4b0e097ff8a153e9276c2593106a811704025bbc1d6916f45ca6 \ - --hash=sha256:7e975a2211952a8a083d1b9d9ba26472981ae338e720b419eb50535de3c02870 \ - --hash=sha256:8215f6f21394d1f46e222abeb06316e77ef328d628f593502d8fc2a9117bde83 \ - --hash=sha256:8258c86f47e080a258993eed877d579c71da7bda26af86ce6c2d2d072c11320d \ - --hash=sha256:8418c053aeb236b20b0ab8fa6bacfc2feaaf7d4683dd96528610989c99723d5f \ - --hash=sha256:87f020d010ba80a247c4abc335fc13421037800ca20b42af5ae40e5fd75e7909 \ - --hash=sha256:884eab2ce97cbaf89f264372eae58388862c33c4f551c15680dd80f53c89a269 \ - --hash=sha256:8a336eaa7ee7e87cdece3cedb395c9657d227bfceb6781295cf56abcd3386a26 \ - --hash=sha256:8aef1b64da41d18026632d99a06b3fefe1d08e85dd81d849fa7c96301ed22f1b \ - --hash=sha256:8aef97ba1dd2138112890ef848e17d8526fe80b21f743b4ee65947ea184f07a2 \ - --hash=sha256:8ed653638ef669e0efc6fe2acb792275cb419bf9cb5c5049399f3556995f23c7 \ - --hash=sha256:9361628f28f48dcf8b2f528420d4d68102f593f9c2e592bfc842f5fb337e44fd \ - --hash=sha256:946eedc12895873891aaceb39bceb484b4977f70373e0122da483f6c38faaa68 \ - --hash=sha256:94d0caaa912bfcdc702a4204cd5e2bb01eb917fc4f5ea2315aa23962549561b0 \ - --hash=sha256:964a428132227edff96d6f3cf261573cb0f1a60c9a764ce28cda9525f18f7786 \ - --hash=sha256:999bfee0a5b7385a0af5ffb606393509cfde70ecca4f01c36985be6d33e336da \ - --hash=sha256:a08ea567c16f140af8ddc7cb58e27e9138a1386e3e6e53982abaa6f2377b38cc \ - --hash=sha256:a28b70c9e2213de425d9cba5ab2e7f7a1c8ca23a99c4b5159bf77b9c31251447 \ - --hash=sha256:a34e1e30f1774fa35d37202bbeae62423e9a79d78d0874e5556a593479fdf239 \ - --hash=sha256:a4264515f9117be204935cd230fb2a052dd3792789cc94c101c535d349b3dab0 \ - --hash=sha256:a7915ea49b0c113641dc4d9338efa9bd66b6a9a485ffe75b9907e8573ca94b84 \ - --hash=sha256:aac44097d838dda26526cffb63bdd8737a2dbdf5f2c68efb72ad83aec6673c7e \ - --hash=sha256:b91044952da03b6f95fdba398d7993dd983b64d3c31c358a4c89e3c19b6f7aef \ - --hash=sha256:ba444bdd4caa2a94456ef67a2f383710928820dd0117aae6650a4d17029fa25e \ - --hash=sha256:c2dc4250fe94d8cd864d66018f8344d4af50e3758e9d725e94fecfa27588ff82 \ - --hash=sha256:c35f493b867912f6fda721a59cc7c4766d382040bdf1ddaeeaa7fa4d072f4675 \ - --hash=sha256:c92261eb2ad367629dc437536463dc934030c9e7caca861cc51990fe6c565f26 \ - --hash=sha256:ce928c9c6409c79e10f39604a7e214b3cb69552952fbda8d836c052832e6a979 \ - --hash=sha256:d95b52fbef190ca87d8c42f49e314eace4fc52070f3dfa5f87a6594b0c1c6e46 \ - --hash=sha256:dae7bd0daeb33aa3e79e72877d3d51052e8b19c9025ecf0374f542ea8ec120e4 \ - --hash=sha256:e286580b6511aac7c3268a78cdb861ec739d3e5a2a53b4809faef6b49778eaff \ - --hash=sha256:e4b53f73077e839b3f89c992223f15b1d2ab314bdbdf502afdc7bb18e95eae27 \ - --hash=sha256:e8f63904df26d1a66aabc141bfd258bf738b9bc7bc6bdef22713b4f5ef789a4c \ - --hash=sha256:f3a6d90cab0bdf07df8f176eae3a07127daafcf7457b997b2bf46776da2c7eb7 \ - --hash=sha256:f41fa79114a1d2eddb5eea7b912d6160508f57440bd302ce96eaa384914cd265 \ - --hash=sha256:f46f81501160c28d0c0b7333b4f7be8983dbbc161983b6fb814024d1b4952f79 \ - --hash=sha256:f61db3b7e870914dbd9434b560075e0366771eecbe6d2b5561f5bc7485f39efd +yarl==1.12.1 \ + --hash=sha256:0103c52f8dfe5d573c856322149ddcd6d28f51b4d4a3ee5c4b3c1b0a05c3d034 \ + --hash=sha256:01549468858b87d36f967c97d02e6e54106f444aeb947ed76f8f71f85ed07cec \ + --hash=sha256:0274b1b7a9c9c32b7bf250583e673ff99fb9fccb389215841e2652d9982de740 \ + --hash=sha256:0ac33d22b2604b020569a82d5f8a03ba637ba42cc1adf31f616af70baf81710b \ + --hash=sha256:0d0a5e87bc48d76dfcfc16295201e9812d5f33d55b4a0b7cad1025b92bf8b91b \ + --hash=sha256:10b690cd78cbaca2f96a7462f303fdd2b596d3978b49892e4b05a7567c591572 \ + --hash=sha256:126309c0f52a2219b3d1048aca00766429a1346596b186d51d9fa5d2070b7b13 \ + --hash=sha256:15871130439ad10abb25a4631120d60391aa762b85fcab971411e556247210a0 \ + --hash=sha256:17d4dc4ff47893a06737b8788ed2ba2f5ac4e8bb40281c8603920f7d011d5bdd \ + --hash=sha256:18c2a7757561f05439c243f517dbbb174cadfae3a72dee4ae7c693f5b336570f \ + --hash=sha256:1d4017e78fb22bc797c089b746230ad78ecd3cdb215bc0bd61cb72b5867da57e \ + --hash=sha256:1f50a37aeeb5179d293465e522fd686080928c4d89e0ff215e1f963405ec4def \ + --hash=sha256:20d817c0893191b2ab0ba30b45b77761e8dfec30a029b7c7063055ca71157f84 \ + --hash=sha256:22839d1d1eab9e4b427828a88a22beb86f67c14d8ff81175505f1cc8493f3500 \ + --hash=sha256:22dda2799c8d39041d731e02bf7690f0ef34f1691d9ac9dfcb98dd1e94c8b058 \ + --hash=sha256:2376d8cf506dffd0e5f2391025ae8675b09711016656590cb03b55894161fcfa \ + --hash=sha256:24197ba3114cc85ddd4091e19b2ddc62650f2e4a899e51b074dfd52d56cf8c72 \ + --hash=sha256:24416bb5e221e29ddf8aac5b97e94e635ca2c5be44a1617ad6fe32556df44294 \ + --hash=sha256:2631c9d7386bd2d4ce24ecc6ebf9ae90b3efd713d588d90504eaa77fec4dba01 \ + --hash=sha256:28389a68981676bf74e2e199fe42f35d1aa27a9c98e3a03e6f58d2d3d054afe1 \ + --hash=sha256:2aee7594d2c2221c717a8e394bbed4740029df4c0211ceb0f04815686e99c795 \ + --hash=sha256:2e430ac432f969ef21770645743611c1618362309e3ad7cab45acd1ad1a540ff \ + --hash=sha256:2e912b282466444023610e4498e3795c10e7cfd641744524876239fcf01d538d \ + --hash=sha256:30ffc046ebddccb3c4cac72c1a3e1bc343492336f3ca86d24672e90ccc5e788a \ + --hash=sha256:319c206e83e46ec2421b25b300c8482b6fe8a018baca246be308c736d9dab267 \ + --hash=sha256:326b8a079a9afcac0575971e56dabdf7abb2ea89a893e6949b77adfeb058b50e \ + --hash=sha256:36ee0115b9edca904153a66bb74a9ff1ce38caff015de94eadfb9ba8e6ecd317 \ + --hash=sha256:3e26e64f42bce5ddf9002092b2c37b13071c2e6413d5c05f9fa9de58ed2f7749 \ + --hash=sha256:4ea99e64b2ad2635e0f0597b63f5ea6c374791ff2fa81cdd4bad8ed9f047f56f \ + --hash=sha256:501a1576716032cc6d48c7c47bcdc42d682273415a8f2908e7e72cb4625801f3 \ + --hash=sha256:54c8cee662b5f8c30ad7eedfc26123f845f007798e4ff1001d9528fe959fd23c \ + --hash=sha256:595bbcdbfc4a9c6989d7489dca8510cba053ff46b16c84ffd95ac8e90711d419 \ + --hash=sha256:5b860055199aec8d6fe4dcee3c5196ce506ca198a50aab0059ffd26e8e815828 \ + --hash=sha256:5c667b383529520b8dd6bd496fc318678320cb2a6062fdfe6d3618da6b8790f6 \ + --hash=sha256:5fb475a4cdde582c9528bb412b98f899680492daaba318231e96f1a0a1bb0d53 \ + --hash=sha256:607d12f0901f6419a8adceb139847c42c83864b85371f58270e42753f9780fa6 \ + --hash=sha256:64c5b0f2b937fe40d0967516eee5504b23cb247b8b7ffeba7213a467d9646fdc \ + --hash=sha256:664380c7ed524a280b6a2d5d9126389c3e96cd6e88986cdb42ca72baa27421d6 \ + --hash=sha256:6af871f70cfd5b528bd322c65793b5fd5659858cdfaa35fbe563fb99b667ed1f \ + --hash=sha256:6c89894cc6f6ddd993813e79244b36b215c14f65f9e4f1660b1f2ba9e5594b95 \ + --hash=sha256:6dee0496d5f1a8f57f0f28a16f81a2033fc057a2cf9cd710742d11828f8c80e2 \ + --hash=sha256:6e9a9f50892153bad5046c2a6df153224aa6f0573a5a8ab44fc54a1e886f6e21 \ + --hash=sha256:712ba8722c0699daf186de089ddc4677651eb9875ed7447b2ad50697522cbdd9 \ + --hash=sha256:717f185086bb9d817d4537dd18d5df5d657598cd00e6fc22e4d54d84de266c1d \ + --hash=sha256:71978ba778948760cff528235c951ea0ef7a4f9c84ac5a49975f8540f76c3f73 \ + --hash=sha256:71af3766bb46738d12cc288d9b8de7ef6f79c31fd62757e2b8a505fe3680b27f \ + --hash=sha256:73a183042ae0918c82ce2df38c3db2409b0eeae88e3afdfc80fb67471a95b33b \ + --hash=sha256:7564525a4673fde53dee7d4c307a961c0951918f0b8c7f09b2c9e02067cf6504 \ + --hash=sha256:76a59d1b63de859398bc7764c860a769499511463c1232155061fe0147f13e01 \ + --hash=sha256:7e9905fc2dc1319e4c39837b906a024cf71b1261cc66b0cd89678f779c0c61f5 \ + --hash=sha256:8112f640a4f7e7bf59f7cabf0d47a29b8977528c521d73a64d5cc9e99e48a174 \ + --hash=sha256:835010cc17d0020e7931d39e487d72c8e01c98e669b6896a8b8c9aa8ca69a949 \ + --hash=sha256:838dde2cb570cfbb4cab8a876a0974e8b90973ea40b3ac27a79b8a74c8a2db15 \ + --hash=sha256:8d31dd0245d88cf7239e96e8f2a99f815b06e458a5854150f8e6f0e61618d41b \ + --hash=sha256:96b34830bd6825ca0220bf005ea99ac83eb9ce51301ddb882dcf613ae6cd95fb \ + --hash=sha256:96c8ff1e1dd680e38af0887927cab407a4e51d84a5f02ae3d6eb87233036c763 \ + --hash=sha256:9a7ee79183f0b17dcede8b6723e7da2ded529cf159a878214be9a5d3098f5b1e \ + --hash=sha256:a3e2aff8b822ab0e0bdbed9f50494b3a35629c4b9488ae391659973a37a9f53f \ + --hash=sha256:a4f3ab9eb8ab2d585ece959c48d234f7b39ac0ca1954a34d8b8e58a52064bdb3 \ + --hash=sha256:a8b54949267bd5704324397efe9fbb6aa306466dee067550964e994d309db5f1 \ + --hash=sha256:a96198d5d26f40557d986c1253bfe0e02d18c9d9b93cf389daf1a3c9f7c755fa \ + --hash=sha256:aebbd47df77190ada603157f0b3670d578c110c31746ecc5875c394fdcc59a99 \ + --hash=sha256:af1107299cef049ad00a93df4809517be432283a0847bcae48343ebe5ea340dc \ + --hash=sha256:b63465b53baeaf2122a337d4ab57d6bbdd09fcadceb17a974cfa8a0300ad9c67 \ + --hash=sha256:ba1c779b45a399cc25f511c681016626f69e51e45b9d350d7581998722825af9 \ + --hash=sha256:bce00f3b1f7f644faae89677ca68645ed5365f1c7f874fdd5ebf730a69640d38 \ + --hash=sha256:bfdf419bf5d3644f94cd7052954fc233522f5a1b371fc0b00219ebd9c14d5798 \ + --hash=sha256:c1caa5763d1770216596e0a71b5567f27aac28c95992110212c108ec74589a48 \ + --hash=sha256:c3e4e1f7b08d1ec6b685ccd3e2d762219c550164fbf524498532e39f9413436e \ + --hash=sha256:c85ab016e96a975afbdb9d49ca90f3bca9920ef27c64300843fe91c3d59d8d20 \ + --hash=sha256:c924deab8105f86980983eced740433fb7554a7f66db73991affa4eda99d5402 \ + --hash=sha256:d4f818f6371970d6a5d1e42878389bbfb69dcde631e4bbac5ec1cb11158565ca \ + --hash=sha256:d920401941cb898ef089422e889759dd403309eb370d0e54f1bdf6ca07fef603 \ + --hash=sha256:da045bd1147d12bd43fb032296640a7cc17a7f2eaba67495988362e99db24fd2 \ + --hash=sha256:dc3192a81ecd5ff954cecd690327badd5a84d00b877e1573f7c9097ce13e5bfb \ + --hash=sha256:ddae504cfb556fe220efae65e35be63cd11e3c314b202723fc2119ce19f0ca2e \ + --hash=sha256:de4544b1fb29cf14870c4e2b8a897c0242449f5dcebd3e0366aa0aa3cf58a23a \ + --hash=sha256:dea360778e0668a7ad25d7727d03364de8a45bfd5d808f81253516b9f2217765 \ + --hash=sha256:e2254fe137c4a360b0a13173a56444f756252c9283ba4d267ca8e9081cd140ea \ + --hash=sha256:e64f0421892a207d3780903085c1b04efeb53b16803b23d947de5a7261b71355 \ + --hash=sha256:e97a29b37830ba1262d8dfd48ddb5b28ad4d3ebecc5d93a9c7591d98641ec737 \ + --hash=sha256:eacbcf30efaca7dc5cb264228ffecdb95fdb1e715b1ec937c0ce6b734161e0c8 \ + --hash=sha256:eee5ff934b0c9f4537ff9596169d56cab1890918004791a7a06b879b3ba2a7ef \ + --hash=sha256:eff6bac402719c14e17efe845d6b98593c56c843aca6def72080fbede755fd1f \ + --hash=sha256:f10954b233d4df5cc3137ffa5ced97f8894152df817e5d149bf05a0ef2ab8134 \ + --hash=sha256:f23bb1a7a6e8e8b612a164fdd08e683bcc16c76f928d6dbb7bdbee2374fbfee6 \ + --hash=sha256:f494c01b28645c431239863cb17af8b8d15b93b0d697a0320d5dd34cd9d7c2fa \ + --hash=sha256:f6a071d2c3d39b4104f94fc08ab349e9b19b951ad4b8e3b6d7ea92d6ef7ccaf8 \ + --hash=sha256:f736f54565f8dd7e3ab664fef2bc461d7593a389a7f28d4904af8d55a91bd55f \ + --hash=sha256:f8981a94a27ac520a398302afb74ae2c0be1c3d2d215c75c582186a006c9e7b0 \ + --hash=sha256:fd24996e12e1ba7c397c44be75ca299da14cde34d74bc5508cce233676cc68d0 \ + --hash=sha256:ff54340fc1129e8e181827e2234af3ff659b4f17d9bbe77f43bc19e6577fadec # via # -r requirements.in # aiohttp From 0d39eef892c859483773c4c9a601fd2d0cba4f57 Mon Sep 17 00:00:00 2001 From: phlax Date: Tue, 24 Sep 2024 10:59:42 +0100 Subject: [PATCH 65/65] bazel/ci: Prepare repo for using Engflow RBE (#36293) Signed-off-by: Ryan Northey --- .bazelrc | 19 +++++++++++++------ .github/workflows/_precheck_deps.yml | 2 +- .github/workflows/_publish_build.yml | 2 +- .github/workflows/_publish_verify.yml | 4 ++-- .github/workflows/envoy-macos.yml | 1 + bazel/BUILD | 5 +++++ bazel/envoy_binary.bzl | 7 +++++++ bazel/envoy_library.bzl | 7 +++++++ bazel/envoy_test.bzl | 27 ++++++++++++++++++++++++++- ci/mac_ci_steps.sh | 2 ++ 10 files changed, 65 insertions(+), 11 deletions(-) diff --git a/.bazelrc b/.bazelrc index 9bfd858fe7..014610e8c7 100644 --- a/.bazelrc +++ b/.bazelrc @@ -46,7 +46,6 @@ build --action_env=BAZEL_VOLATILE_DIRTY --host_action_env=BAZEL_VOLATILE_DIRTY # Prevent stamped caches from busting (eg in PRs) # Requires setting `BAZEL_FAKE_SCM_REVISION` in the env. build --action_env=BAZEL_FAKE_SCM_REVISION --host_action_env=BAZEL_FAKE_SCM_REVISION - build --test_summary=terse build:docs-ci --action_env=DOCS_RST_CHECK=1 --host_action_env=DOCS_RST_CHECK=1 @@ -515,19 +514,27 @@ build:rbe-engflow --bes_timeout=3600s build:rbe-engflow --bes_upload_mode=fully_async build:rbe-engflow --nolegacy_important_outputs -build:cache-envoy-engflow --google_default_credentials=false +# RBE (Engflow Envoy) +build:common-envoy-engflow --google_default_credentials=false +build:common-envoy-engflow --credential_helper=*.engflow.com=%workspace%/bazel/engflow-bazel-credential-helper.sh +build:common-envoy-engflow --grpc_keepalive_time=30s + build:cache-envoy-engflow --remote_cache=grpcs://morganite.cluster.engflow.com build:cache-envoy-engflow --remote_timeout=3600s -build:cache-envoy-engflow --credential_helper=*.engflow.com=%workspace%/bazel/engflow-bazel-credential-helper.sh -build:cache-envoy-engflow --grpc_keepalive_time=30s build:bes-envoy-engflow --bes_backend=grpcs://morganite.cluster.engflow.com/ build:bes-envoy-engflow --bes_results_url=https://morganite.cluster.engflow.com/invocation/ build:bes-envoy-engflow --bes_timeout=3600s build:bes-envoy-engflow --bes_upload_mode=fully_async -build:rbe-envoy-engflow --config=cache-envoy-engflow -build:rbe-envoy-engflow --config=bes-envoy-engflow +build:bes-envoy-engflow --nolegacy_important_outputs build:rbe-envoy-engflow --remote_executor=grpcs://morganite.cluster.engflow.com build:rbe-envoy-engflow --remote_default_exec_properties=container-image=docker://gcr.io/envoy-ci/envoy-build@sha256:7adc40c09508f957624c4d2e0f5aeecb73a59207ee6ded53b107eac828c091b2 +build:rbe-envoy-engflow --jobs=200 +build:rbe-envoy-engflow --define=engflow_rbe=true + +build:remote-envoy-engflow --config=common-envoy-engflow +build:remote-envoy-engflow --config=cache-envoy-engflow +build:remote-envoy-engflow --config=bes-envoy-engflow +build:remote-envoy-engflow --config=rbe-envoy-engflow ############################################################################# # debug: Various Bazel debugging flags diff --git a/.github/workflows/_precheck_deps.yml b/.github/workflows/_precheck_deps.yml index 37c513e40e..6479772d3d 100644 --- a/.github/workflows/_precheck_deps.yml +++ b/.github/workflows/_precheck_deps.yml @@ -29,7 +29,7 @@ jobs: uses: ./.github/workflows/_run.yml name: ${{ matrix.target }} with: - bazel-extra: '--config=rbe-envoy-engflow' + bazel-extra: '--config=remote-envoy-engflow' cache-build-image: ${{ fromJSON(inputs.request).request.build-image.default }} request: ${{ inputs.request }} error-match: | diff --git a/.github/workflows/_publish_build.yml b/.github/workflows/_publish_build.yml index efc08f2902..3ce77d4dc6 100644 --- a/.github/workflows/_publish_build.yml +++ b/.github/workflows/_publish_build.yml @@ -59,7 +59,7 @@ jobs: name: Release (x64) arch: x64 bazel-extra: >- - --config=rbe-envoy-engflow + --config=remote-envoy-engflow rbe: true runs-on: ubuntu-24.04 - target: release.server_only diff --git a/.github/workflows/_publish_verify.yml b/.github/workflows/_publish_verify.yml index 09344b1da4..80e93d0a2b 100644 --- a/.github/workflows/_publish_verify.yml +++ b/.github/workflows/_publish_verify.yml @@ -30,7 +30,7 @@ jobs: name: ${{ matrix.name || matrix.target }} uses: ./.github/workflows/_run.yml with: - bazel-extra: ${{ matrix.bazel-extra || '--config=rbe-envoy-engflow' }} + bazel-extra: ${{ matrix.bazel-extra || '--config=remote-envoy-engflow' }} cache-build-image: ${{ matrix.cache-build-image }} cache-build-image-key-suffix: ${{ matrix.arch == 'arm64' && format('-{0}', matrix.arch) || '' }} container-command: ${{ matrix.container-command }} @@ -85,7 +85,7 @@ jobs: name: ${{ matrix.name || matrix.target }} uses: ./.github/workflows/_run.yml with: - bazel-extra: ${{ matrix.bazel-extra || '--config=rbe-envoy-engflow' }} + bazel-extra: ${{ matrix.bazel-extra || '--config=remote-envoy-engflow' }} cache-build-image: ${{ fromJSON(inputs.request).request.build-image.default }} cache-build-image-key-suffix: ${{ matrix.arch == 'arm64' && format('-{0}', matrix.arch) || '' }} container-command: ./ci/run_envoy_docker.sh diff --git a/.github/workflows/envoy-macos.yml b/.github/workflows/envoy-macos.yml index f3d41dad82..4c5da31f4e 100644 --- a/.github/workflows/envoy-macos.yml +++ b/.github/workflows/envoy-macos.yml @@ -66,6 +66,7 @@ jobs: --flaky_test_attempts=2 --config=bes-envoy-engflow --config=cache-envoy-engflow + --config=common-envoy-engflow --config=ci) export BAZEL_BUILD_EXTRA_OPTIONS=${_BAZEL_BUILD_EXTRA_OPTIONS[*]} diff --git a/bazel/BUILD b/bazel/BUILD index adb3fe7905..77da1e1fce 100644 --- a/bazel/BUILD +++ b/bazel/BUILD @@ -744,6 +744,11 @@ alias( }), ) +config_setting( + name = "engflow_rbe", + define_values = {"engflow_rbe": "true"}, +) + selects.config_setting_group( name = "apple", match_any = [ diff --git a/bazel/envoy_binary.bzl b/bazel/envoy_binary.bzl index e9038a522f..c1df1d1b6f 100644 --- a/bazel/envoy_binary.bzl +++ b/bazel/envoy_binary.bzl @@ -18,6 +18,8 @@ def envoy_cc_binary( data = [], testonly = 0, visibility = None, + engflow_pool = None, + exec_properties = {}, external_deps = [], repository = "", stamp = 1, @@ -27,6 +29,10 @@ def envoy_cc_binary( tags = [], features = [], linkstatic = True): + exec_properties = exec_properties | select({ + repository + "//bazel:engflow_rbe": {"Pool": engflow_pool} if engflow_pool else {}, + "//conditions:default": {}, + }) linker_inputs = envoy_exported_symbols_input() if not linkopts: @@ -42,6 +48,7 @@ def envoy_cc_binary( data = data, additional_linker_inputs = linker_inputs, copts = envoy_copts(repository), + exec_properties = exec_properties, linkopts = linkopts, testonly = testonly, linkstatic = linkstatic, diff --git a/bazel/envoy_library.bzl b/bazel/envoy_library.bzl index d5ed602b2f..9e20ac47ef 100644 --- a/bazel/envoy_library.bzl +++ b/bazel/envoy_library.bzl @@ -98,6 +98,8 @@ def envoy_cc_library( hdrs = [], copts = [], visibility = None, + engflow_pool = None, + exec_properties = {}, external_deps = [], tcmalloc_dep = None, repository = "", @@ -112,6 +114,10 @@ def envoy_cc_library( linkopts = []): if tcmalloc_dep: deps += tcmalloc_external_deps(repository) + exec_properties = exec_properties | select({ + repository + "//bazel:engflow_rbe": {"Pool": engflow_pool} if engflow_pool else {}, + "//conditions:default": {}, + }) # If alwayslink is not specified, allow turning it off via --define=library_autolink=disabled # alwayslink is defaulted on for envoy_cc_extensions to ensure the REGISTRY macros work. @@ -132,6 +138,7 @@ def envoy_cc_library( textual_hdrs = textual_hdrs, deps = deps + [envoy_external_dep_path(dep) for dep in external_deps] + envoy_pch_deps(repository, "//source/common/common:common_pch"), + exec_properties = exec_properties, alwayslink = alwayslink, linkstatic = envoy_linkstatic(), strip_include_prefix = strip_include_prefix, diff --git a/bazel/envoy_test.bzl b/bazel/envoy_test.bzl index c9a4266603..b9fd4841ef 100644 --- a/bazel/envoy_test.bzl +++ b/bazel/envoy_test.bzl @@ -80,11 +80,17 @@ def envoy_cc_fuzz_test( name, corpus, dictionaries = [], + engflow_pool = None, + exec_properties = {}, repository = "", size = "medium", deps = [], tags = [], **kwargs): + exec_properties = exec_properties | select({ + repository + "//bazel:engflow_rbe": {"Pool": engflow_pool} if engflow_pool else {}, + "//conditions:default": {}, + }) if not (corpus.startswith("//") or corpus.startswith(":") or corpus.startswith("@")): corpus_name = name + "_corpus_files" native.filegroup( @@ -97,6 +103,7 @@ def envoy_cc_fuzz_test( test_lib_name = name + "_lib" envoy_cc_test_library( name = test_lib_name, + exec_properties = exec_properties, deps = deps + envoy_stdlib_deps() + [ repository + "//test/fuzz:fuzz_runner_lib", repository + "//test/test_common:test_version_linkstamp", @@ -121,6 +128,7 @@ def envoy_cc_fuzz_test( "//conditions:default": ["$(locations %s)" % corpus_name], }), data = [corpus_name], + exec_properties = exec_properties, # No fuzzing on macOS or Windows deps = select({ "@envoy//bazel:apple": [repository + "//test:dummy_main"], @@ -163,9 +171,13 @@ def envoy_cc_test( size = "medium", flaky = False, env = {}, + engflow_pool = None, exec_properties = {}): coverage_tags = tags + ([] if coverage else ["nocoverage"]) - + exec_properties = exec_properties | select({ + repository + "//bazel:engflow_rbe": {"Pool": engflow_pool} if engflow_pool else {}, + "//conditions:default": {}, + }) native.cc_test( name = name, srcs = srcs, @@ -199,6 +211,8 @@ def envoy_cc_test_library( srcs = [], hdrs = [], data = [], + engflow_pool = None, + exec_properties = {}, external_deps = [], deps = [], repository = "", @@ -207,6 +221,10 @@ def envoy_cc_test_library( copts = [], alwayslink = 1, **kargs): + exec_properties = exec_properties | select({ + repository + "//bazel:engflow_rbe": {"Pool": engflow_pool} if engflow_pool else {}, + "//conditions:default": {}, + }) disable_pch = kargs.pop("disable_pch", True) _envoy_cc_test_infrastructure_library( name, @@ -267,13 +285,20 @@ def envoy_benchmark_test( name, benchmark_binary, data = [], + engflow_pool = None, + exec_properties = {}, tags = [], repository = "", **kargs): + exec_properties = exec_properties | select({ + repository + "//bazel:engflow_rbe": {"Pool": engflow_pool} if engflow_pool else {}, + "//conditions:default": {}, + }) native.sh_test( name = name, srcs = [repository + "//bazel:test_for_benchmark_wrapper.sh"], data = [":" + benchmark_binary] + data, + exec_properties = exec_properties, args = ["%s/%s" % (native.package_name(), benchmark_binary)], tags = tags + ["nocoverage"], **kargs diff --git a/ci/mac_ci_steps.sh b/ci/mac_ci_steps.sh index 2f2cc584f3..a09175c1c0 100755 --- a/ci/mac_ci_steps.sh +++ b/ci/mac_ci_steps.sh @@ -17,6 +17,8 @@ BAZEL_BUILD_OPTIONS=( "${BAZEL_BUILD_EXTRA_OPTIONS[@]}" "${BAZEL_EXTRA_TEST_OPTIONS[@]}") +echo "RUN MAC: ${BAZEL_BUILD_OPTIONS[*]}" + NCPU=$(sysctl -n hw.ncpu) if [[ $NCPU -gt 0 ]]; then echo "limiting build to $NCPU jobs, based on CPU count"