From c50c9a4edb8fc2d2bbfd0649b1cf7d104fd4d172 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=BE=84=E6=BD=AD?= Date: Thu, 9 May 2024 22:14:56 +0800 Subject: [PATCH 01/20] Fix typo of comment (#34025) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 澄潭 --- source/common/protobuf/utility.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/common/protobuf/utility.h b/source/common/protobuf/utility.h index 1fa3111bae68..7e613772fe4a 100644 --- a/source/common/protobuf/utility.h +++ b/source/common/protobuf/utility.h @@ -61,7 +61,7 @@ return DurationUtil::durationToMilliseconds(msg.field_name()); \ }((message))) -// Obtain the milliseconds value of a google.protobuf.Duration field if set. Otherwise, return the +// Obtain the seconds value of a google.protobuf.Duration field if set. Otherwise, return the // default value. #define PROTOBUF_GET_SECONDS_OR_DEFAULT(message, field_name, default_value) \ ((message).has_##field_name() ? DurationUtil::durationToSeconds((message).field_name()) \ From ec4a3b77b44f7a9f4c9796b6eef90c6cda27980f Mon Sep 17 00:00:00 2001 From: code Date: Thu, 9 May 2024 22:18:56 +0800 Subject: [PATCH 02/20] upstream lb: move all lb implementations to extensions/ (#34027) * upstream lb: move all lb implementations to extensions/ Signed-off-by: wbpcode Co-authored-by: wbpcode --- .../filters/network/source/router/BUILD | 2 +- .../filters/network/source/router/router.h | 2 +- contrib/golang/filters/network/source/BUILD | 4 +- .../golang/filters/network/source/golang.h | 2 +- .../golang/filters/network/source/upstream.h | 2 +- .../filters/network/source/BUILD | 2 +- .../filters/network/source/router/BUILD | 2 +- .../filters/network/source/router/router.h | 2 +- .../network/source/router/router_impl.h | 2 +- .../filters/network/source/router/BUILD | 2 +- .../network/source/router/router_impl.h | 2 +- source/common/router/BUILD | 2 +- source/common/router/router.h | 2 +- source/common/tcp_proxy/BUILD | 2 +- source/common/tcp_proxy/tcp_proxy.h | 2 +- source/common/upstream/BUILD | 27 +- source/common/upstream/cluster_factory_impl.h | 2 +- .../common/upstream/cluster_manager_impl.cc | 2 +- .../upstream/load_balancer_context_base.h | 40 +++ source/common/upstream/upstream_impl.h | 6 +- source/extensions/clusters/aggregate/BUILD | 1 + .../clusters/aggregate/lb_context.h | 2 +- .../extensions/clusters/redis/redis_cluster.h | 2 +- .../clusters/redis/redis_cluster_lb.h | 2 +- .../filters/http/adaptive_concurrency/BUILD | 1 + .../extensions/filters/http/ext_authz/BUILD | 1 + .../filters/http/stateful_session/BUILD | 2 +- .../http/stateful_session/stateful_session.cc | 2 +- .../filters/network/common/redis/BUILD | 2 +- .../network/common/redis/client_impl.h | 2 +- .../filters/network/dubbo_proxy/router/BUILD | 2 +- .../network/dubbo_proxy/router/router_impl.h | 2 +- .../filters/network/redis_proxy/BUILD | 2 +- .../network/redis_proxy/conn_pool_impl.h | 2 +- .../filters/network/thrift_proxy/router/BUILD | 4 +- .../network/thrift_proxy/router/router_impl.h | 2 +- .../thrift_proxy/router/shadow_writer_impl.h | 2 +- source/extensions/filters/udp/udp_proxy/BUILD | 2 +- .../filters/udp/udp_proxy/udp_proxy_filter.h | 4 +- .../load_balancing_policies/common/BUILD | 27 +- .../common}/load_balancer_impl.cc | 171 +----------- .../common}/load_balancer_impl.h | 254 +----------------- .../common/thread_aware_lb_impl.h | 2 +- .../least_request/BUILD | 11 +- .../least_request/config.cc | 2 +- .../least_request/config.h | 1 - .../least_request/least_request_lb.cc | 144 ++++++++++ .../least_request/least_request_lb.h | 114 ++++++++ .../load_balancing_policies/maglev/BUILD | 2 +- .../load_balancing_policies/random/BUILD | 11 +- .../load_balancing_policies/random/config.cc | 2 +- .../load_balancing_policies/random/config.h | 1 - .../random/random_lb.cc | 33 +++ .../random/random_lb.h | 40 +++ .../load_balancing_policies/ring_hash/BUILD | 2 +- .../ring_hash/ring_hash_lb.cc | 1 - .../load_balancing_policies/round_robin/BUILD | 11 +- .../round_robin/config.cc | 2 +- .../round_robin/config.h | 1 - .../round_robin/round_robin_lb.cc | 5 + .../round_robin/round_robin_lb.h | 88 ++++++ .../load_balancing_policies/subset/BUILD | 4 +- .../subset/subset_lb.cc | 1 - .../subset/subset_lb.h | 2 +- .../retry/priority/previous_priorities/BUILD | 2 +- .../previous_priorities/previous_priorities.h | 2 +- source/extensions/upstreams/http/http/BUILD | 2 +- source/extensions/upstreams/http/tcp/BUILD | 2 +- source/extensions/upstreams/http/udp/BUILD | 2 +- test/common/upstream/BUILD | 19 +- .../least_request_load_balancer_fuzz_test.cc | 2 + .../upstream/load_balancer_benchmark.cc | 3 + .../common/upstream/load_balancer_fuzz_base.h | 2 +- .../upstream/load_balancer_impl_test.cc | 17 +- .../upstream/load_balancer_simulation_test.cc | 4 +- .../random_load_balancer_fuzz_test.cc | 2 + .../round_robin_load_balancer_fuzz_test.cc | 2 + .../load_balancing_policies/subset/BUILD | 1 - test/integration/BUILD | 4 +- .../custom_cluster_integration_test.cc | 2 +- test/integration/eds_integration_test.cc | 2 +- test/integration/upstreams/BUILD | 2 +- test/mocks/upstream/mocks.h | 2 +- 83 files changed, 644 insertions(+), 510 deletions(-) create mode 100644 source/common/upstream/load_balancer_context_base.h rename source/{common/upstream => extensions/load_balancing_policies/common}/load_balancer_impl.cc (90%) rename source/{common/upstream => extensions/load_balancing_policies/common}/load_balancer_impl.h (65%) create mode 100644 source/extensions/load_balancing_policies/least_request/least_request_lb.cc create mode 100644 source/extensions/load_balancing_policies/least_request/least_request_lb.h create mode 100644 source/extensions/load_balancing_policies/random/random_lb.cc create mode 100644 source/extensions/load_balancing_policies/random/random_lb.h create mode 100644 source/extensions/load_balancing_policies/round_robin/round_robin_lb.cc create mode 100644 source/extensions/load_balancing_policies/round_robin/round_robin_lb.h diff --git a/contrib/generic_proxy/filters/network/source/router/BUILD b/contrib/generic_proxy/filters/network/source/router/BUILD index 2f38b1cddde5..9297d5886821 100644 --- a/contrib/generic_proxy/filters/network/source/router/BUILD +++ b/contrib/generic_proxy/filters/network/source/router/BUILD @@ -29,7 +29,7 @@ envoy_cc_library( "//source/common/router:metadatamatchcriteria_lib", "//source/common/stream_info:stream_info_lib", "//source/common/tracing:tracer_lib", - "//source/common/upstream:load_balancer_lib", + "//source/common/upstream:load_balancer_context_base_lib", "@envoy_api//contrib/envoy/extensions/filters/network/generic_proxy/router/v3:pkg_cc_proto", ], ) diff --git a/contrib/generic_proxy/filters/network/source/router/router.h b/contrib/generic_proxy/filters/network/source/router/router.h index 2ec9954b468b..2c8e7642954c 100644 --- a/contrib/generic_proxy/filters/network/source/router/router.h +++ b/contrib/generic_proxy/filters/network/source/router/router.h @@ -8,7 +8,7 @@ #include "source/common/buffer/buffer_impl.h" #include "source/common/common/linked_object.h" #include "source/common/stream_info/stream_info_impl.h" -#include "source/common/upstream/load_balancer_impl.h" +#include "source/common/upstream/load_balancer_context_base.h" #include "contrib/envoy/extensions/filters/network/generic_proxy/router/v3/router.pb.h" #include "contrib/envoy/extensions/filters/network/generic_proxy/router/v3/router.pb.validate.h" diff --git a/contrib/golang/filters/network/source/BUILD b/contrib/golang/filters/network/source/BUILD index fec216df0a6d..43c1013b81ae 100644 --- a/contrib/golang/filters/network/source/BUILD +++ b/contrib/golang/filters/network/source/BUILD @@ -49,7 +49,7 @@ envoy_cc_library( "//source/common/network:utility_lib", "//source/common/stream_info:stream_info_lib", "//source/common/tcp:conn_pool_lib", - "//source/common/upstream:load_balancer_lib", + "//source/common/upstream:load_balancer_context_base_lib", "//source/extensions/filters/network/common:factory_base_lib", "@envoy_api//contrib/envoy/extensions/filters/network/golang/v3alpha:pkg_cc_proto", ], @@ -97,7 +97,7 @@ envoy_cc_contrib_extension( "//source/common/common:minimal_logger_lib", "//source/common/memory:utils_lib", "//source/common/network:connection_lib", - "//source/common/upstream:load_balancer_lib", + "//source/common/upstream:load_balancer_context_base_lib", "//source/extensions/filters/network:well_known_names", "//source/extensions/filters/network/common:factory_base_lib", "@envoy_api//contrib/envoy/extensions/filters/network/golang/v3alpha:pkg_cc_proto", diff --git a/contrib/golang/filters/network/source/golang.h b/contrib/golang/filters/network/source/golang.h index 1b181efbff01..5096793baeea 100644 --- a/contrib/golang/filters/network/source/golang.h +++ b/contrib/golang/filters/network/source/golang.h @@ -11,7 +11,7 @@ #include "source/common/buffer/buffer_impl.h" #include "source/common/common/logger.h" #include "source/common/network/connection_impl.h" -#include "source/common/upstream/load_balancer_impl.h" +#include "source/common/upstream/load_balancer_context_base.h" #include "source/extensions/filters/network/common/factory_base.h" #include "contrib/envoy/extensions/filters/network/golang/v3alpha/golang.pb.h" diff --git a/contrib/golang/filters/network/source/upstream.h b/contrib/golang/filters/network/source/upstream.h index 8ee09d3f89c2..b63804c5358c 100644 --- a/contrib/golang/filters/network/source/upstream.h +++ b/contrib/golang/filters/network/source/upstream.h @@ -16,7 +16,7 @@ #include "source/common/memory/utils.h" #include "source/common/network/connection_impl.h" #include "source/common/stream_info/stream_info_impl.h" -#include "source/common/upstream/load_balancer_impl.h" +#include "source/common/upstream/load_balancer_context_base.h" #include "source/extensions/filters/network/common/factory_base.h" #include "contrib/envoy/extensions/filters/network/golang/v3alpha/golang.pb.h" diff --git a/contrib/rocketmq_proxy/filters/network/source/BUILD b/contrib/rocketmq_proxy/filters/network/source/BUILD index d274adf6c6d0..e421666b9f09 100644 --- a/contrib/rocketmq_proxy/filters/network/source/BUILD +++ b/contrib/rocketmq_proxy/filters/network/source/BUILD @@ -108,7 +108,7 @@ envoy_cc_library( "//source/common/common:linked_object", "//source/common/protobuf:utility_lib", "//source/common/stats:timespan_lib", - "//source/common/upstream:load_balancer_lib", + "//source/common/upstream:load_balancer_context_base_lib", "//source/extensions/filters/network:well_known_names", "@envoy_api//contrib/envoy/extensions/filters/network/rocketmq_proxy/v3:pkg_cc_proto", ], diff --git a/contrib/rocketmq_proxy/filters/network/source/router/BUILD b/contrib/rocketmq_proxy/filters/network/source/router/BUILD index 03eb3b741abf..a73dd0442cfc 100644 --- a/contrib/rocketmq_proxy/filters/network/source/router/BUILD +++ b/contrib/rocketmq_proxy/filters/network/source/router/BUILD @@ -14,7 +14,7 @@ envoy_cc_library( deps = [ "//envoy/tcp:conn_pool_interface", "//envoy/upstream:load_balancer_interface", - "//source/common/upstream:load_balancer_lib", + "//source/common/upstream:load_balancer_context_base_lib", ], ) diff --git a/contrib/rocketmq_proxy/filters/network/source/router/router.h b/contrib/rocketmq_proxy/filters/network/source/router/router.h index 7a4f9c60db9f..97938b5ab2b5 100644 --- a/contrib/rocketmq_proxy/filters/network/source/router/router.h +++ b/contrib/rocketmq_proxy/filters/network/source/router/router.h @@ -2,7 +2,7 @@ #include "envoy/tcp/conn_pool.h" -#include "source/common/upstream/load_balancer_impl.h" +#include "source/common/upstream/load_balancer_context_base.h" namespace Envoy { namespace Extensions { diff --git a/contrib/rocketmq_proxy/filters/network/source/router/router_impl.h b/contrib/rocketmq_proxy/filters/network/source/router/router_impl.h index 14ff5e5d54c3..29fe30601ed7 100644 --- a/contrib/rocketmq_proxy/filters/network/source/router/router_impl.h +++ b/contrib/rocketmq_proxy/filters/network/source/router/router_impl.h @@ -5,7 +5,7 @@ #include "envoy/upstream/thread_local_cluster.h" #include "source/common/common/logger.h" -#include "source/common/upstream/load_balancer_impl.h" +#include "source/common/upstream/load_balancer_context_base.h" #include "contrib/rocketmq_proxy/filters/network/source/router/router.h" diff --git a/contrib/sip_proxy/filters/network/source/router/BUILD b/contrib/sip_proxy/filters/network/source/router/BUILD index 5275cd138714..4f9b933eb8ba 100644 --- a/contrib/sip_proxy/filters/network/source/router/BUILD +++ b/contrib/sip_proxy/filters/network/source/router/BUILD @@ -57,7 +57,7 @@ envoy_cc_library( "//source/common/common:logger_lib", "//source/common/http:header_utility_lib", "//source/common/router:metadatamatchcriteria_lib", - "//source/common/upstream:load_balancer_lib", + "//source/common/upstream:load_balancer_context_base_lib", "@envoy_api//contrib/envoy/extensions/filters/network/sip_proxy/tra/v3alpha:pkg_cc_proto", "@envoy_api//contrib/envoy/extensions/filters/network/sip_proxy/v3alpha:pkg_cc_proto", ], diff --git a/contrib/sip_proxy/filters/network/source/router/router_impl.h b/contrib/sip_proxy/filters/network/source/router/router_impl.h index baa33bf4e1ef..eed22812d89c 100644 --- a/contrib/sip_proxy/filters/network/source/router/router_impl.h +++ b/contrib/sip_proxy/filters/network/source/router/router_impl.h @@ -12,7 +12,7 @@ #include "source/common/common/macros.h" #include "source/common/http/header_utility.h" #include "source/common/tracing/http_tracer_impl.h" -#include "source/common/upstream/load_balancer_impl.h" +#include "source/common/upstream/load_balancer_context_base.h" #include "contrib/envoy/extensions/filters/network/sip_proxy/tra/v3alpha/tra.pb.h" #include "contrib/envoy/extensions/filters/network/sip_proxy/v3alpha/route.pb.h" diff --git a/source/common/router/BUILD b/source/common/router/BUILD index d1e479b885d2..32bd4c6b39ea 100644 --- a/source/common/router/BUILD +++ b/source/common/router/BUILD @@ -336,7 +336,7 @@ envoy_cc_library( "//source/common/stream_info:stream_info_lib", "//source/common/stream_info:uint32_accessor_lib", "//source/common/tracing:http_tracer_lib", - "//source/common/upstream:load_balancer_lib", + "//source/common/upstream:load_balancer_context_base_lib", "//source/common/upstream:upstream_factory_context_lib", "//source/extensions/common/proxy_protocol:proxy_protocol_header_lib", "//source/extensions/filters/http/common:factory_base_lib", diff --git a/source/common/router/router.h b/source/common/router/router.h index d9e733cfa898..227a8f4a5a11 100644 --- a/source/common/router/router.h +++ b/source/common/router/router.h @@ -42,7 +42,7 @@ #include "source/common/router/upstream_request.h" #include "source/common/stats/symbol_table.h" #include "source/common/stream_info/stream_info_impl.h" -#include "source/common/upstream/load_balancer_impl.h" +#include "source/common/upstream/load_balancer_context_base.h" #include "source/common/upstream/upstream_factory_context_impl.h" namespace Envoy { diff --git a/source/common/tcp_proxy/BUILD b/source/common/tcp_proxy/BUILD index c6883b43aec3..cf6d9e8bd3e0 100644 --- a/source/common/tcp_proxy/BUILD +++ b/source/common/tcp_proxy/BUILD @@ -87,7 +87,7 @@ envoy_cc_library( "//source/common/stream_info:stream_id_provider_lib", "//source/common/stream_info:stream_info_lib", "//source/common/stream_info:uint64_accessor_lib", - "//source/common/upstream:load_balancer_lib", + "//source/common/upstream:load_balancer_context_base_lib", "//source/extensions/upstreams/tcp/generic:config", "@envoy_api//envoy/config/accesslog/v3:pkg_cc_proto", "@envoy_api//envoy/extensions/filters/network/tcp_proxy/v3:pkg_cc_proto", diff --git a/source/common/tcp_proxy/tcp_proxy.h b/source/common/tcp_proxy/tcp_proxy.h index a01bf7e1fc95..aee119325257 100644 --- a/source/common/tcp_proxy/tcp_proxy.h +++ b/source/common/tcp_proxy/tcp_proxy.h @@ -33,7 +33,7 @@ #include "source/common/network/utility.h" #include "source/common/stream_info/stream_info_impl.h" #include "source/common/tcp_proxy/upstream.h" -#include "source/common/upstream/load_balancer_impl.h" +#include "source/common/upstream/load_balancer_context_base.h" #include "absl/container/node_hash_map.h" diff --git a/source/common/upstream/BUILD b/source/common/upstream/BUILD index 9bf7be3c011b..1def579c48c7 100644 --- a/source/common/upstream/BUILD +++ b/source/common/upstream/BUILD @@ -82,7 +82,7 @@ envoy_cc_library( ":cds_api_lib", ":cluster_discovery_manager_lib", ":host_utility_lib", - ":load_balancer_lib", + ":load_balancer_context_base_lib", ":load_stats_reporter_lib", ":od_cds_api_lib", "//envoy/api:api_interface", @@ -258,24 +258,10 @@ envoy_cc_library( ) envoy_cc_library( - name = "load_balancer_lib", - srcs = ["load_balancer_impl.cc"], - hdrs = ["load_balancer_impl.h"], + name = "load_balancer_context_base_lib", + hdrs = ["load_balancer_context_base.h"], deps = [ - ":scheduler_lib", - "//envoy/common:random_generator_interface", - "//envoy/runtime:runtime_interface", - "//envoy/stats:stats_interface", "//envoy/upstream:load_balancer_interface", - "//envoy/upstream:upstream_interface", - "//source/common/common:assert_lib", - "//source/common/protobuf:utility_lib", - "//source/common/runtime:runtime_protos_lib", - "@envoy_api//envoy/config/cluster/v3:pkg_cc_proto", - "@envoy_api//envoy/config/core/v3:pkg_cc_proto", - "@envoy_api//envoy/extensions/load_balancing_policies/least_request/v3:pkg_cc_proto", - "@envoy_api//envoy/extensions/load_balancing_policies/random/v3:pkg_cc_proto", - "@envoy_api//envoy/extensions/load_balancing_policies/round_robin/v3:pkg_cc_proto", ], ) @@ -283,7 +269,7 @@ envoy_cc_library( name = "load_balancer_factory_base_lib", hdrs = ["load_balancer_factory_base.h"], deps = [ - ":load_balancer_lib", + "//envoy/upstream:load_balancer_interface", ], ) @@ -442,8 +428,9 @@ envoy_cc_library( ], external_deps = ["abseil_synchronization"], deps = [ - ":load_balancer_lib", + ":load_balancer_context_base_lib", ":resource_manager_lib", + ":scheduler_lib", ":upstream_factory_context_lib", "//envoy/event:timer_interface", "//envoy/local_info:local_info_interface", @@ -516,7 +503,7 @@ envoy_cc_library( name = "cluster_factory_includes", hdrs = ["cluster_factory_impl.h"], deps = [ - ":load_balancer_lib", + ":load_balancer_context_base_lib", ":outlier_detection_lib", ":resource_manager_lib", ":upstream_includes", diff --git a/source/common/upstream/cluster_factory_impl.h b/source/common/upstream/cluster_factory_impl.h index de4291ed270b..c6eb4aba43be 100644 --- a/source/common/upstream/cluster_factory_impl.h +++ b/source/common/upstream/cluster_factory_impl.h @@ -39,7 +39,7 @@ #include "source/common/network/utility.h" #include "source/common/protobuf/utility.h" #include "source/common/stats/isolated_store_impl.h" -#include "source/common/upstream/load_balancer_impl.h" +#include "source/common/upstream/load_balancer_context_base.h" #include "source/common/upstream/outlier_detection_impl.h" #include "source/common/upstream/resource_manager_impl.h" #include "source/common/upstream/upstream_impl.h" diff --git a/source/common/upstream/cluster_manager_impl.cc b/source/common/upstream/cluster_manager_impl.cc index 294d4aedfd69..1679e15f24c3 100644 --- a/source/common/upstream/cluster_manager_impl.cc +++ b/source/common/upstream/cluster_manager_impl.cc @@ -42,7 +42,7 @@ #include "source/common/tcp/conn_pool.h" #include "source/common/upstream/cds_api_impl.h" #include "source/common/upstream/cluster_factory_impl.h" -#include "source/common/upstream/load_balancer_impl.h" +#include "source/common/upstream/load_balancer_context_base.h" #include "source/common/upstream/priority_conn_pool_map_impl.h" #ifdef ENVOY_ENABLE_QUIC diff --git a/source/common/upstream/load_balancer_context_base.h b/source/common/upstream/load_balancer_context_base.h new file mode 100644 index 000000000000..ded22edbdb01 --- /dev/null +++ b/source/common/upstream/load_balancer_context_base.h @@ -0,0 +1,40 @@ +#pragma once + +#include "envoy/upstream/load_balancer.h" + +namespace Envoy { +namespace Upstream { + +class LoadBalancerContextBase : public LoadBalancerContext { +public: + absl::optional computeHashKey() override { return {}; } + + const Network::Connection* downstreamConnection() const override { return nullptr; } + + const Router::MetadataMatchCriteria* metadataMatchCriteria() override { return nullptr; } + + const StreamInfo::StreamInfo* requestStreamInfo() const override { return nullptr; } + + const Http::RequestHeaderMap* downstreamHeaders() const override { return nullptr; } + + const HealthyAndDegradedLoad& + determinePriorityLoad(const PrioritySet&, const HealthyAndDegradedLoad& original_priority_load, + const Upstream::RetryPriority::PriorityMappingFunc&) override { + return original_priority_load; + } + + bool shouldSelectAnotherHost(const Host&) override { return false; } + + uint32_t hostSelectionRetryCount() const override { return 1; } + + Network::Socket::OptionsSharedPtr upstreamSocketOptions() const override { return nullptr; } + + Network::TransportSocketOptionsConstSharedPtr upstreamTransportSocketOptions() const override { + return nullptr; + } + + absl::optional overrideHostToSelect() const override { return {}; } +}; + +} // namespace Upstream +} // namespace Envoy diff --git a/source/common/upstream/upstream_impl.h b/source/common/upstream/upstream_impl.h index 5b34cd2c9d2b..f40ce0c35617 100644 --- a/source/common/upstream/upstream_impl.h +++ b/source/common/upstream/upstream_impl.h @@ -57,7 +57,8 @@ #include "source/common/network/utility.h" #include "source/common/shared_pool/shared_pool.h" #include "source/common/stats/isolated_store_impl.h" -#include "source/common/upstream/load_balancer_impl.h" +#include "source/common/upstream/edf_scheduler.h" +#include "source/common/upstream/load_balancer_context_base.h" #include "source/common/upstream/resource_manager_impl.h" #include "source/common/upstream/transport_socket_match_impl.h" #include "source/common/upstream/upstream_factory_context_impl.h" @@ -71,6 +72,9 @@ namespace Envoy { namespace Upstream { +// Priority levels and localities are considered overprovisioned with this factor. +static constexpr uint32_t kDefaultOverProvisioningFactor = 140; + using ClusterProto = envoy::config::cluster::v3::Cluster; using UpstreamNetworkFilterConfigProviderManager = diff --git a/source/extensions/clusters/aggregate/BUILD b/source/extensions/clusters/aggregate/BUILD index 8a640940b7c7..8637c8db0f39 100644 --- a/source/extensions/clusters/aggregate/BUILD +++ b/source/extensions/clusters/aggregate/BUILD @@ -18,6 +18,7 @@ envoy_cc_extension( deps = [ "//source/common/upstream:cluster_factory_lib", "//source/common/upstream:upstream_includes", + "//source/extensions/load_balancing_policies/common:load_balancer_lib", "@envoy_api//envoy/config/cluster/v3:pkg_cc_proto", "@envoy_api//envoy/extensions/clusters/aggregate/v3:pkg_cc_proto", ], diff --git a/source/extensions/clusters/aggregate/lb_context.h b/source/extensions/clusters/aggregate/lb_context.h index e388cde7dbeb..871370076d61 100644 --- a/source/extensions/clusters/aggregate/lb_context.h +++ b/source/extensions/clusters/aggregate/lb_context.h @@ -1,7 +1,7 @@ #pragma once -#include "source/common/upstream/load_balancer_impl.h" #include "source/common/upstream/upstream_impl.h" +#include "source/extensions/load_balancing_policies/common/load_balancer_impl.h" namespace Envoy { namespace Extensions { diff --git a/source/extensions/clusters/redis/redis_cluster.h b/source/extensions/clusters/redis/redis_cluster.h index bc32be51d88c..edf9b412448d 100644 --- a/source/extensions/clusters/redis/redis_cluster.h +++ b/source/extensions/clusters/redis/redis_cluster.h @@ -50,7 +50,7 @@ #include "source/common/network/utility.h" #include "source/common/stats/isolated_store_impl.h" #include "source/common/upstream/cluster_factory_impl.h" -#include "source/common/upstream/load_balancer_impl.h" +#include "source/common/upstream/load_balancer_context_base.h" #include "source/common/upstream/outlier_detection_impl.h" #include "source/common/upstream/resource_manager_impl.h" #include "source/common/upstream/upstream_impl.h" diff --git a/source/extensions/clusters/redis/redis_cluster_lb.h b/source/extensions/clusters/redis/redis_cluster_lb.h index 222a8bae8dce..b3b9725e0d91 100644 --- a/source/extensions/clusters/redis/redis_cluster_lb.h +++ b/source/extensions/clusters/redis/redis_cluster_lb.h @@ -8,7 +8,7 @@ #include "envoy/upstream/upstream.h" #include "source/common/network/address_impl.h" -#include "source/common/upstream/load_balancer_impl.h" +#include "source/common/upstream/load_balancer_context_base.h" #include "source/common/upstream/upstream_impl.h" #include "source/extensions/clusters/redis/crc16.h" #include "source/extensions/filters/network/common/redis/client.h" diff --git a/source/extensions/filters/http/adaptive_concurrency/BUILD b/source/extensions/filters/http/adaptive_concurrency/BUILD index 64434ebeae59..993e71213efc 100644 --- a/source/extensions/filters/http/adaptive_concurrency/BUILD +++ b/source/extensions/filters/http/adaptive_concurrency/BUILD @@ -19,6 +19,7 @@ envoy_cc_library( hdrs = ["adaptive_concurrency_filter.h"], deps = [ "//envoy/http:filter_interface", + "//source/common/runtime:runtime_protos_lib", "//source/extensions/filters/http/adaptive_concurrency/controller:controller_lib", "//source/extensions/filters/http/common:pass_through_filter_lib", "@envoy_api//envoy/extensions/filters/http/adaptive_concurrency/v3:pkg_cc_proto", diff --git a/source/extensions/filters/http/ext_authz/BUILD b/source/extensions/filters/http/ext_authz/BUILD index 77f6f3655d32..6fbb0b871ed1 100644 --- a/source/extensions/filters/http/ext_authz/BUILD +++ b/source/extensions/filters/http/ext_authz/BUILD @@ -28,6 +28,7 @@ envoy_cc_library( "//source/common/http:codes_lib", "//source/common/http:utility_lib", "//source/common/router:config_lib", + "//source/common/runtime:runtime_protos_lib", "//source/extensions/filters/common/ext_authz:ext_authz_grpc_lib", "//source/extensions/filters/common/ext_authz:ext_authz_http_lib", "@envoy_api//envoy/config/core/v3:pkg_cc_proto", diff --git a/source/extensions/filters/http/stateful_session/BUILD b/source/extensions/filters/http/stateful_session/BUILD index 4c158154d75c..6fb123b92f23 100644 --- a/source/extensions/filters/http/stateful_session/BUILD +++ b/source/extensions/filters/http/stateful_session/BUILD @@ -20,7 +20,7 @@ envoy_cc_library( "//source/common/config:utility_lib", "//source/common/http:utility_lib", "//source/common/protobuf:utility_lib", - "//source/common/upstream:load_balancer_lib", + "//source/common/upstream:load_balancer_context_base_lib", "//source/extensions/filters/http:well_known_names", "//source/extensions/filters/http/common:pass_through_filter_lib", "@envoy_api//envoy/extensions/filters/http/stateful_session/v3:pkg_cc_proto", diff --git a/source/extensions/filters/http/stateful_session/stateful_session.cc b/source/extensions/filters/http/stateful_session/stateful_session.cc index ff6bc670d27b..fd9928bebd4f 100644 --- a/source/extensions/filters/http/stateful_session/stateful_session.cc +++ b/source/extensions/filters/http/stateful_session/stateful_session.cc @@ -5,7 +5,7 @@ #include "source/common/config/utility.h" #include "source/common/http/utility.h" -#include "source/common/upstream/load_balancer_impl.h" +#include "source/common/upstream/load_balancer_context_base.h" namespace Envoy { namespace Extensions { diff --git a/source/extensions/filters/network/common/redis/BUILD b/source/extensions/filters/network/common/redis/BUILD index 4561a35a52e5..6fe082a13407 100644 --- a/source/extensions/filters/network/common/redis/BUILD +++ b/source/extensions/filters/network/common/redis/BUILD @@ -69,7 +69,7 @@ envoy_cc_library( "//source/common/common:assert_lib", "//source/common/network:filter_lib", "//source/common/protobuf:utility_lib", - "//source/common/upstream:load_balancer_lib", + "//source/common/upstream:load_balancer_context_base_lib", "//source/common/upstream:upstream_lib", "@envoy_api//envoy/extensions/filters/network/redis_proxy/v3:pkg_cc_proto", ], diff --git a/source/extensions/filters/network/common/redis/client_impl.h b/source/extensions/filters/network/common/redis/client_impl.h index 7c65856d3f44..ccf8c86e018b 100644 --- a/source/extensions/filters/network/common/redis/client_impl.h +++ b/source/extensions/filters/network/common/redis/client_impl.h @@ -12,7 +12,7 @@ #include "source/common/network/filter_impl.h" #include "source/common/protobuf/utility.h" #include "source/common/singleton/const_singleton.h" -#include "source/common/upstream/load_balancer_impl.h" +#include "source/common/upstream/load_balancer_context_base.h" #include "source/common/upstream/upstream_impl.h" #include "source/extensions/filters/network/common/redis/client.h" #include "source/extensions/filters/network/common/redis/utility.h" diff --git a/source/extensions/filters/network/dubbo_proxy/router/BUILD b/source/extensions/filters/network/dubbo_proxy/router/BUILD index 0901f4a09516..583aedef9ff8 100644 --- a/source/extensions/filters/network/dubbo_proxy/router/BUILD +++ b/source/extensions/filters/network/dubbo_proxy/router/BUILD @@ -67,7 +67,7 @@ envoy_cc_library( "//source/common/config:well_known_names", "//source/common/http:header_utility_lib", "//source/common/router:metadatamatchcriteria_lib", - "//source/common/upstream:load_balancer_lib", + "//source/common/upstream:load_balancer_context_base_lib", "//source/extensions/filters/network/dubbo_proxy:app_exception_lib", "//source/extensions/filters/network/dubbo_proxy:protocol_interface", "//source/extensions/filters/network/dubbo_proxy:serializer_interface", diff --git a/source/extensions/filters/network/dubbo_proxy/router/router_impl.h b/source/extensions/filters/network/dubbo_proxy/router/router_impl.h index 24ebfe88d7d0..ac2b3980370c 100644 --- a/source/extensions/filters/network/dubbo_proxy/router/router_impl.h +++ b/source/extensions/filters/network/dubbo_proxy/router/router_impl.h @@ -9,7 +9,7 @@ #include "source/common/common/logger.h" #include "source/common/config/well_known_names.h" #include "source/common/router/metadatamatchcriteria_impl.h" -#include "source/common/upstream/load_balancer_impl.h" +#include "source/common/upstream/load_balancer_context_base.h" #include "source/extensions/filters/network/dubbo_proxy/filters/filter.h" #include "source/extensions/filters/network/dubbo_proxy/router/router.h" diff --git a/source/extensions/filters/network/redis_proxy/BUILD b/source/extensions/filters/network/redis_proxy/BUILD index 506ec5d2b484..6c015aa3fd81 100644 --- a/source/extensions/filters/network/redis_proxy/BUILD +++ b/source/extensions/filters/network/redis_proxy/BUILD @@ -92,7 +92,7 @@ envoy_cc_library( "//source/common/network:address_lib", "//source/common/network:filter_lib", "//source/common/protobuf:utility_lib", - "//source/common/upstream:load_balancer_lib", + "//source/common/upstream:load_balancer_context_base_lib", "//source/common/upstream:upstream_lib", "//source/extensions/clusters/redis:redis_cluster_lb", "//source/extensions/common/dynamic_forward_proxy:dns_cache_interface", diff --git a/source/extensions/filters/network/redis_proxy/conn_pool_impl.h b/source/extensions/filters/network/redis_proxy/conn_pool_impl.h index 7068744e520c..82c152793911 100644 --- a/source/extensions/filters/network/redis_proxy/conn_pool_impl.h +++ b/source/extensions/filters/network/redis_proxy/conn_pool_impl.h @@ -18,7 +18,7 @@ #include "source/common/network/filter_impl.h" #include "source/common/protobuf/utility.h" #include "source/common/singleton/const_singleton.h" -#include "source/common/upstream/load_balancer_impl.h" +#include "source/common/upstream/load_balancer_context_base.h" #include "source/common/upstream/upstream_impl.h" #include "source/extensions/clusters/redis/redis_cluster_lb.h" #include "source/extensions/common/dynamic_forward_proxy/dns_cache.h" diff --git a/source/extensions/filters/network/thrift_proxy/router/BUILD b/source/extensions/filters/network/thrift_proxy/router/BUILD index 3930475e2b19..6910d7abaf60 100644 --- a/source/extensions/filters/network/thrift_proxy/router/BUILD +++ b/source/extensions/filters/network/thrift_proxy/router/BUILD @@ -78,7 +78,7 @@ envoy_cc_library( "//envoy/upstream:load_balancer_interface", "//envoy/upstream:thread_local_cluster_interface", "//source/common/common:linked_object", - "//source/common/upstream:load_balancer_lib", + "//source/common/upstream:load_balancer_context_base_lib", "//source/extensions/filters/network:well_known_names", "//source/extensions/filters/network/thrift_proxy:app_exception_lib", "//source/extensions/filters/network/thrift_proxy:conn_manager_lib", @@ -104,7 +104,7 @@ envoy_cc_library( "//envoy/upstream:thread_local_cluster_interface", "//source/common/http:header_utility_lib", "//source/common/router:metadatamatchcriteria_lib", - "//source/common/upstream:load_balancer_lib", + "//source/common/upstream:load_balancer_context_base_lib", "//source/extensions/filters/network/thrift_proxy:app_exception_lib", "//source/extensions/filters/network/thrift_proxy:conn_manager_lib", "//source/extensions/filters/network/thrift_proxy:protocol_converter_lib", diff --git a/source/extensions/filters/network/thrift_proxy/router/router_impl.h b/source/extensions/filters/network/thrift_proxy/router/router_impl.h index f8fb0e7df2b8..e2aeecce17e8 100644 --- a/source/extensions/filters/network/thrift_proxy/router/router_impl.h +++ b/source/extensions/filters/network/thrift_proxy/router/router_impl.h @@ -11,7 +11,7 @@ #include "source/common/http/header_utility.h" #include "source/common/router/metadatamatchcriteria_impl.h" -#include "source/common/upstream/load_balancer_impl.h" +#include "source/common/upstream/load_balancer_context_base.h" #include "source/extensions/filters/network/thrift_proxy/conn_manager.h" #include "source/extensions/filters/network/thrift_proxy/filters/filter.h" #include "source/extensions/filters/network/thrift_proxy/router/router.h" diff --git a/source/extensions/filters/network/thrift_proxy/router/shadow_writer_impl.h b/source/extensions/filters/network/thrift_proxy/router/shadow_writer_impl.h index 75f873d95297..0131db3cf408 100644 --- a/source/extensions/filters/network/thrift_proxy/router/shadow_writer_impl.h +++ b/source/extensions/filters/network/thrift_proxy/router/shadow_writer_impl.h @@ -9,7 +9,7 @@ #include "source/common/common/linked_object.h" #include "source/common/common/logger.h" -#include "source/common/upstream/load_balancer_impl.h" +#include "source/common/upstream/load_balancer_context_base.h" #include "source/extensions/filters/network/thrift_proxy/app_exception_impl.h" #include "source/extensions/filters/network/thrift_proxy/conn_manager.h" #include "source/extensions/filters/network/thrift_proxy/router/router.h" diff --git a/source/extensions/filters/udp/udp_proxy/BUILD b/source/extensions/filters/udp/udp_proxy/BUILD index 7e0c5561690c..ba70f7ca39fe 100644 --- a/source/extensions/filters/udp/udp_proxy/BUILD +++ b/source/extensions/filters/udp/udp_proxy/BUILD @@ -46,7 +46,7 @@ envoy_cc_library( "//source/common/network:utility_lib", "//source/common/router:header_parser_lib", "//source/common/stream_info:stream_info_lib", - "//source/common/upstream:load_balancer_lib", + "//source/common/upstream:load_balancer_context_base_lib", "//source/extensions/filters/udp/udp_proxy/router:router_lib", "//source/extensions/filters/udp/udp_proxy/session_filters:filter_config_interface", "//source/extensions/filters/udp/udp_proxy/session_filters:filter_interface", diff --git a/source/extensions/filters/udp/udp_proxy/udp_proxy_filter.h b/source/extensions/filters/udp/udp_proxy/udp_proxy_filter.h index e85cbc412ef8..c47b85510783 100644 --- a/source/extensions/filters/udp/udp_proxy/udp_proxy_filter.h +++ b/source/extensions/filters/udp/udp_proxy/udp_proxy_filter.h @@ -1,5 +1,7 @@ #pragma once +#include + #include "envoy/access_log/access_log.h" #include "envoy/config/accesslog/v3/accesslog.pb.h" #include "envoy/event/file_event.h" @@ -26,7 +28,7 @@ #include "source/common/protobuf/utility.h" #include "source/common/router/header_parser.h" #include "source/common/stream_info/stream_info_impl.h" -#include "source/common/upstream/load_balancer_impl.h" +#include "source/common/upstream/load_balancer_context_base.h" #include "source/extensions/filters/udp/udp_proxy/hash_policy_impl.h" #include "source/extensions/filters/udp/udp_proxy/router/router_impl.h" #include "source/extensions/filters/udp/udp_proxy/session_filters/filter.h" diff --git a/source/extensions/load_balancing_policies/common/BUILD b/source/extensions/load_balancing_policies/common/BUILD index cf39c30e80a7..cd4ea6a5cc7a 100644 --- a/source/extensions/load_balancing_policies/common/BUILD +++ b/source/extensions/load_balancing_policies/common/BUILD @@ -23,10 +23,35 @@ envoy_cc_library( hdrs = ["thread_aware_lb_impl.h"], external_deps = ["abseil_synchronization"], deps = [ + ":load_balancer_lib", "//source/common/common:minimal_logger_lib", "//source/common/config:metadata_lib", "//source/common/config:well_known_names", - "//source/common/upstream:load_balancer_lib", "@envoy_api//envoy/config/cluster/v3:pkg_cc_proto", ], ) + +envoy_cc_library( + name = "load_balancer_lib", + srcs = ["load_balancer_impl.cc"], + hdrs = ["load_balancer_impl.h"], + # previously considered core code and used by mobile. + visibility = ["//visibility:public"], + deps = [ + "//envoy/common:random_generator_interface", + "//envoy/runtime:runtime_interface", + "//envoy/stats:stats_interface", + "//envoy/upstream:load_balancer_interface", + "//envoy/upstream:upstream_interface", + "//source/common/common:assert_lib", + "//source/common/protobuf:utility_lib", + "//source/common/runtime:runtime_protos_lib", + "//source/common/upstream:load_balancer_context_base_lib", + "//source/common/upstream:scheduler_lib", + "@envoy_api//envoy/config/cluster/v3:pkg_cc_proto", + "@envoy_api//envoy/config/core/v3:pkg_cc_proto", + "@envoy_api//envoy/extensions/load_balancing_policies/least_request/v3:pkg_cc_proto", + "@envoy_api//envoy/extensions/load_balancing_policies/random/v3:pkg_cc_proto", + "@envoy_api//envoy/extensions/load_balancing_policies/round_robin/v3:pkg_cc_proto", + ], +) diff --git a/source/common/upstream/load_balancer_impl.cc b/source/extensions/load_balancing_policies/common/load_balancer_impl.cc similarity index 90% rename from source/common/upstream/load_balancer_impl.cc rename to source/extensions/load_balancing_policies/common/load_balancer_impl.cc index c058082eb52d..ec79f321bafa 100644 --- a/source/common/upstream/load_balancer_impl.cc +++ b/source/extensions/load_balancing_policies/common/load_balancer_impl.cc @@ -1,4 +1,4 @@ -#include "source/common/upstream/load_balancer_impl.h" +#include "source/extensions/load_balancing_policies/common/load_balancer_impl.h" #include #include @@ -28,12 +28,6 @@ static const std::string RuntimeZoneEnabled = "upstream.zone_routing.enabled"; static const std::string RuntimeMinClusterSize = "upstream.zone_routing.min_cluster_size"; static const std::string RuntimePanicThreshold = "upstream.healthy_panic_threshold"; -bool tooManyPreconnects(size_t num_preconnect_picks, uint32_t healthy_hosts) { - // Currently we only allow the number of preconnected connections to equal the - // number of healthy hosts. - return num_preconnect_picks >= healthy_hosts; -} - // Distributes load between priorities based on the per priority availability and the normalized // total availability. Load is assigned to each priority according to how available each priority is // adjusted for the normalized total availability. @@ -1274,168 +1268,5 @@ double EdfLoadBalancerBase::applySlowStartFactor(double host_weight, const Host& } } -double LeastRequestLoadBalancer::hostWeight(const Host& host) const { - // This method is called to calculate the dynamic weight as following when all load balancing - // weights are not equal: - // - // `weight = load_balancing_weight / (active_requests + 1)^active_request_bias` - // - // `active_request_bias` can be configured via runtime and its value is cached in - // `active_request_bias_` to avoid having to do a runtime lookup each time a host weight is - // calculated. - // - // When `active_request_bias == 0.0` we behave like `RoundRobinLoadBalancer` and return the - // host weight without considering the number of active requests at the time we do the pick. - // - // When `active_request_bias > 0.0` we scale the host weight by the number of active - // requests at the time we do the pick. We always add 1 to avoid division by 0. - // - // It might be possible to do better by picking two hosts off of the schedule, and selecting the - // one with fewer active requests at the time of selection. - - double host_weight = static_cast(host.weight()); - - // If the value of active requests is the max value, adding +1 will overflow - // it and cause a divide by zero. This won't happen in normal cases but stops - // failing fuzz tests - const uint64_t active_request_value = - host.stats().rq_active_.value() != std::numeric_limits::max() - ? host.stats().rq_active_.value() + 1 - : host.stats().rq_active_.value(); - - if (active_request_bias_ == 1.0) { - host_weight = static_cast(host.weight()) / active_request_value; - } else if (active_request_bias_ != 0.0) { - host_weight = - static_cast(host.weight()) / std::pow(active_request_value, active_request_bias_); - } - - if (!noHostsAreInSlowStart()) { - return applySlowStartFactor(host_weight, host); - } else { - return host_weight; - } -} - -HostConstSharedPtr LeastRequestLoadBalancer::unweightedHostPeek(const HostVector&, - const HostsSource&) { - // LeastRequestLoadBalancer can not do deterministic preconnecting, because - // any other thread might select the least-requested-host between preconnect and - // host-pick, and change the rq_active checks. - return nullptr; -} - -HostConstSharedPtr LeastRequestLoadBalancer::unweightedHostPick(const HostVector& hosts_to_use, - const HostsSource&) { - HostSharedPtr candidate_host = nullptr; - - switch (selection_method_) { - case envoy::extensions::load_balancing_policies::least_request::v3::LeastRequest::FULL_SCAN: - candidate_host = unweightedHostPickFullScan(hosts_to_use); - break; - case envoy::extensions::load_balancing_policies::least_request::v3::LeastRequest::N_CHOICES: - candidate_host = unweightedHostPickNChoices(hosts_to_use); - break; - default: - IS_ENVOY_BUG("unknown selection method specified for least request load balancer"); - } - - return candidate_host; -} - -HostSharedPtr LeastRequestLoadBalancer::unweightedHostPickFullScan(const HostVector& hosts_to_use) { - HostSharedPtr candidate_host = nullptr; - - size_t num_hosts_known_tied_for_least = 0; - - const size_t num_hosts = hosts_to_use.size(); - - for (size_t i = 0; i < num_hosts; ++i) { - const HostSharedPtr& sampled_host = hosts_to_use[i]; - - if (candidate_host == nullptr) { - // Make a first choice to start the comparisons. - num_hosts_known_tied_for_least = 1; - candidate_host = sampled_host; - continue; - } - - const auto candidate_active_rq = candidate_host->stats().rq_active_.value(); - const auto sampled_active_rq = sampled_host->stats().rq_active_.value(); - - if (sampled_active_rq < candidate_active_rq) { - // Reset the count of known tied hosts. - num_hosts_known_tied_for_least = 1; - candidate_host = sampled_host; - } else if (sampled_active_rq == candidate_active_rq) { - ++num_hosts_known_tied_for_least; - - // Use reservoir sampling to select 1 unique sample from the total number of hosts N - // that will tie for least requests after processing the full hosts array. - // - // Upon each new tie encountered, replace candidate_host with sampled_host - // with probability (1 / num_hosts_known_tied_for_least percent). - // The end result is that each tied host has an equal 1 / N chance of being the - // candidate_host returned by this function. - const size_t random_tied_host_index = random_.random() % num_hosts_known_tied_for_least; - if (random_tied_host_index == 0) { - candidate_host = sampled_host; - } - } - } - - return candidate_host; -} - -HostSharedPtr LeastRequestLoadBalancer::unweightedHostPickNChoices(const HostVector& hosts_to_use) { - HostSharedPtr candidate_host = nullptr; - - for (uint32_t choice_idx = 0; choice_idx < choice_count_; ++choice_idx) { - const int rand_idx = random_.random() % hosts_to_use.size(); - const HostSharedPtr& sampled_host = hosts_to_use[rand_idx]; - - if (candidate_host == nullptr) { - // Make a first choice to start the comparisons. - candidate_host = sampled_host; - continue; - } - - const auto candidate_active_rq = candidate_host->stats().rq_active_.value(); - const auto sampled_active_rq = sampled_host->stats().rq_active_.value(); - - if (sampled_active_rq < candidate_active_rq) { - candidate_host = sampled_host; - } - } - - return candidate_host; -} - -HostConstSharedPtr RandomLoadBalancer::peekAnotherHost(LoadBalancerContext* context) { - if (tooManyPreconnects(stashed_random_.size(), total_healthy_hosts_)) { - return nullptr; - } - return peekOrChoose(context, true); -} - -HostConstSharedPtr RandomLoadBalancer::chooseHostOnce(LoadBalancerContext* context) { - return peekOrChoose(context, false); -} - -HostConstSharedPtr RandomLoadBalancer::peekOrChoose(LoadBalancerContext* context, bool peek) { - uint64_t random_hash = random(peek); - const absl::optional hosts_source = hostSourceToUse(context, random_hash); - if (!hosts_source) { - return nullptr; - } - - const HostVector& hosts_to_use = hostSourceToHosts(*hosts_source); - if (hosts_to_use.empty()) { - return nullptr; - } - - return hosts_to_use[random_hash % hosts_to_use.size()]; -} - } // namespace Upstream } // namespace Envoy diff --git a/source/common/upstream/load_balancer_impl.h b/source/extensions/load_balancing_policies/common/load_balancer_impl.h similarity index 65% rename from source/common/upstream/load_balancer_impl.h rename to source/extensions/load_balancing_policies/common/load_balancer_impl.h index a7c31f5d12c0..3fa42d3a535d 100644 --- a/source/common/upstream/load_balancer_impl.h +++ b/source/extensions/load_balancing_policies/common/load_balancer_impl.h @@ -22,12 +22,16 @@ #include "source/common/protobuf/utility.h" #include "source/common/runtime/runtime_protos.h" #include "source/common/upstream/edf_scheduler.h" +#include "source/common/upstream/load_balancer_context_base.h" namespace Envoy { namespace Upstream { -// Priority levels and localities are considered overprovisioned with this factor. -static constexpr uint32_t kDefaultOverProvisioningFactor = 140; +inline bool tooManyPreconnects(size_t num_preconnect_picks, uint32_t healthy_hosts) { + // Currently we only allow the number of preconnected connections to equal the + // number of healthy hosts. + return num_preconnect_picks >= healthy_hosts; +} class LoadBalancerConfigHelper { public: @@ -210,37 +214,6 @@ class LoadBalancerBase : public LoadBalancer, protected Logger::Loggable computeHashKey() override { return {}; } - - const Network::Connection* downstreamConnection() const override { return nullptr; } - - const Router::MetadataMatchCriteria* metadataMatchCriteria() override { return nullptr; } - - const StreamInfo::StreamInfo* requestStreamInfo() const override { return nullptr; } - - const Http::RequestHeaderMap* downstreamHeaders() const override { return nullptr; } - - const HealthyAndDegradedLoad& - determinePriorityLoad(const PrioritySet&, const HealthyAndDegradedLoad& original_priority_load, - const Upstream::RetryPriority::PriorityMappingFunc&) override { - return original_priority_load; - } - - bool shouldSelectAnotherHost(const Host&) override { return false; } - - uint32_t hostSelectionRetryCount() const override { return 1; } - - Network::Socket::OptionsSharedPtr upstreamSocketOptions() const override { return nullptr; } - - Network::TransportSocketOptionsConstSharedPtr upstreamTransportSocketOptions() const override { - return nullptr; - } - - absl::optional overrideHostToSelect() const override { return {}; } -}; - /** * Base class for zone aware load balancers */ @@ -568,220 +541,5 @@ class EdfLoadBalancerBase : public ZoneAwareLoadBalancerBase { const double slow_start_min_weight_percent_; }; -/** - * A round robin load balancer. When in weighted mode, EDF scheduling is used. When in not - * weighted mode, simple RR index selection is used. - */ -class RoundRobinLoadBalancer : public EdfLoadBalancerBase { -public: - RoundRobinLoadBalancer( - const PrioritySet& priority_set, const PrioritySet* local_priority_set, ClusterLbStats& stats, - Runtime::Loader& runtime, Random::RandomGenerator& random, - const envoy::config::cluster::v3::Cluster::CommonLbConfig& common_config, - OptRef round_robin_config, - TimeSource& time_source) - : EdfLoadBalancerBase( - priority_set, local_priority_set, stats, runtime, random, - PROTOBUF_PERCENT_TO_ROUNDED_INTEGER_OR_DEFAULT(common_config, healthy_panic_threshold, - 100, 50), - LoadBalancerConfigHelper::localityLbConfigFromCommonLbConfig(common_config), - round_robin_config.has_value() - ? LoadBalancerConfigHelper::slowStartConfigFromLegacyProto(round_robin_config.ref()) - : absl::nullopt, - time_source) { - initialize(); - } - - RoundRobinLoadBalancer( - const PrioritySet& priority_set, const PrioritySet* local_priority_set, ClusterLbStats& stats, - Runtime::Loader& runtime, Random::RandomGenerator& random, uint32_t healthy_panic_threshold, - const envoy::extensions::load_balancing_policies::round_robin::v3::RoundRobin& - round_robin_config, - TimeSource& time_source) - : EdfLoadBalancerBase( - priority_set, local_priority_set, stats, runtime, random, healthy_panic_threshold, - LoadBalancerConfigHelper::localityLbConfigFromProto(round_robin_config), - LoadBalancerConfigHelper::slowStartConfigFromProto(round_robin_config), time_source) { - initialize(); - } - -private: - void refreshHostSource(const HostsSource& source) override { - // insert() is used here on purpose so that we don't overwrite the index if the host source - // already exists. Note that host sources will never be removed, but given how uncommon this - // is it probably doesn't matter. - rr_indexes_.insert({source, seed_}); - // If the list of hosts changes, the order of picks change. Discard the - // index. - peekahead_index_ = 0; - } - double hostWeight(const Host& host) const override { - if (!noHostsAreInSlowStart()) { - return applySlowStartFactor(host.weight(), host); - } - return host.weight(); - } - - HostConstSharedPtr unweightedHostPeek(const HostVector& hosts_to_use, - const HostsSource& source) override { - auto i = rr_indexes_.find(source); - if (i == rr_indexes_.end()) { - return nullptr; - } - return hosts_to_use[(i->second + (peekahead_index_)++) % hosts_to_use.size()]; - } - - HostConstSharedPtr unweightedHostPick(const HostVector& hosts_to_use, - const HostsSource& source) override { - if (peekahead_index_ > 0) { - --peekahead_index_; - } - // To avoid storing the RR index in the base class, we end up using a second map here with - // host source as the key. This means that each LB decision will require two map lookups in - // the unweighted case. We might consider trying to optimize this in the future. - ASSERT(rr_indexes_.find(source) != rr_indexes_.end()); - return hosts_to_use[rr_indexes_[source]++ % hosts_to_use.size()]; - } - - uint64_t peekahead_index_{}; - absl::flat_hash_map rr_indexes_; -}; - -/** - * Weighted Least Request load balancer. - * - * In a normal setup when all hosts have the same weight it randomly picks up N healthy hosts - * (where N is specified in the LB configuration) and compares number of active requests. Technique - * is based on http://www.eecs.harvard.edu/~michaelm/postscripts/mythesis.pdf and is known as P2C - * (power of two choices). - * - * When hosts have different weights, an RR EDF schedule is used. Host weight is scaled - * by the number of active requests at pick/insert time. Thus, hosts will never fully drain as - * they would in normal P2C, though they will get picked less and less often. In the future, we - * can consider two alternate algorithms: - * 1) Expand out all hosts by weight (using more memory) and do standard P2C. - * 2) Use a weighted Maglev table, and perform P2C on two random hosts selected from the table. - * The benefit of the Maglev table is at the expense of resolution, memory usage is capped. - * Additionally, the Maglev table can be shared amongst all threads. - */ -class LeastRequestLoadBalancer : public EdfLoadBalancerBase { -public: - LeastRequestLoadBalancer( - const PrioritySet& priority_set, const PrioritySet* local_priority_set, ClusterLbStats& stats, - Runtime::Loader& runtime, Random::RandomGenerator& random, - const envoy::config::cluster::v3::Cluster::CommonLbConfig& common_config, - OptRef least_request_config, - TimeSource& time_source) - : EdfLoadBalancerBase( - priority_set, local_priority_set, stats, runtime, random, - PROTOBUF_PERCENT_TO_ROUNDED_INTEGER_OR_DEFAULT(common_config, healthy_panic_threshold, - 100, 50), - LoadBalancerConfigHelper::localityLbConfigFromCommonLbConfig(common_config), - least_request_config.has_value() - ? LoadBalancerConfigHelper::slowStartConfigFromLegacyProto( - least_request_config.ref()) - : absl::nullopt, - time_source), - choice_count_( - least_request_config.has_value() - ? PROTOBUF_GET_WRAPPED_OR_DEFAULT(least_request_config.ref(), choice_count, 2) - : 2), - active_request_bias_runtime_( - least_request_config.has_value() && least_request_config->has_active_request_bias() - ? absl::optional( - {least_request_config->active_request_bias(), runtime}) - : absl::nullopt) { - initialize(); - } - - LeastRequestLoadBalancer( - const PrioritySet& priority_set, const PrioritySet* local_priority_set, ClusterLbStats& stats, - Runtime::Loader& runtime, Random::RandomGenerator& random, uint32_t healthy_panic_threshold, - const envoy::extensions::load_balancing_policies::least_request::v3::LeastRequest& - least_request_config, - TimeSource& time_source) - : EdfLoadBalancerBase( - priority_set, local_priority_set, stats, runtime, random, healthy_panic_threshold, - LoadBalancerConfigHelper::localityLbConfigFromProto(least_request_config), - LoadBalancerConfigHelper::slowStartConfigFromProto(least_request_config), time_source), - choice_count_(PROTOBUF_GET_WRAPPED_OR_DEFAULT(least_request_config, choice_count, 2)), - active_request_bias_runtime_( - least_request_config.has_active_request_bias() - ? absl::optional( - {least_request_config.active_request_bias(), runtime}) - : absl::nullopt), - selection_method_(least_request_config.selection_method()) { - initialize(); - } - -protected: - void refresh(uint32_t priority) override { - active_request_bias_ = active_request_bias_runtime_ != absl::nullopt - ? active_request_bias_runtime_.value().value() - : 1.0; - - if (active_request_bias_ < 0.0 || std::isnan(active_request_bias_)) { - ENVOY_LOG_MISC(warn, - "upstream: invalid active request bias supplied (runtime key {}), using 1.0", - active_request_bias_runtime_->runtimeKey()); - active_request_bias_ = 1.0; - } - - EdfLoadBalancerBase::refresh(priority); - } - -private: - void refreshHostSource(const HostsSource&) override {} - double hostWeight(const Host& host) const override; - HostConstSharedPtr unweightedHostPeek(const HostVector& hosts_to_use, - const HostsSource& source) override; - HostConstSharedPtr unweightedHostPick(const HostVector& hosts_to_use, - const HostsSource& source) override; - HostSharedPtr unweightedHostPickFullScan(const HostVector& hosts_to_use); - HostSharedPtr unweightedHostPickNChoices(const HostVector& hosts_to_use); - - const uint32_t choice_count_; - - // The exponent used to calculate host weights can be configured via runtime. We cache it for - // performance reasons and refresh it in `LeastRequestLoadBalancer::refresh(uint32_t priority)` - // whenever a `HostSet` is updated. - double active_request_bias_{}; - - const absl::optional active_request_bias_runtime_; - const envoy::extensions::load_balancing_policies::least_request::v3::LeastRequest::SelectionMethod - selection_method_{}; -}; - -/** - * Random load balancer that picks a random host out of all hosts. - */ -class RandomLoadBalancer : public ZoneAwareLoadBalancerBase { -public: - RandomLoadBalancer(const PrioritySet& priority_set, const PrioritySet* local_priority_set, - ClusterLbStats& stats, Runtime::Loader& runtime, - Random::RandomGenerator& random, - const envoy::config::cluster::v3::Cluster::CommonLbConfig& common_config) - : ZoneAwareLoadBalancerBase( - priority_set, local_priority_set, stats, runtime, random, - PROTOBUF_PERCENT_TO_ROUNDED_INTEGER_OR_DEFAULT(common_config, healthy_panic_threshold, - 100, 50), - LoadBalancerConfigHelper::localityLbConfigFromCommonLbConfig(common_config)) {} - - RandomLoadBalancer( - const PrioritySet& priority_set, const PrioritySet* local_priority_set, ClusterLbStats& stats, - Runtime::Loader& runtime, Random::RandomGenerator& random, uint32_t healthy_panic_threshold, - const envoy::extensions::load_balancing_policies::random::v3::Random& random_config) - : ZoneAwareLoadBalancerBase( - priority_set, local_priority_set, stats, runtime, random, healthy_panic_threshold, - LoadBalancerConfigHelper::localityLbConfigFromProto(random_config)) {} - - // Upstream::ZoneAwareLoadBalancerBase - HostConstSharedPtr chooseHostOnce(LoadBalancerContext* context) override; - HostConstSharedPtr peekAnotherHost(LoadBalancerContext* context) override; - -protected: - HostConstSharedPtr peekOrChoose(LoadBalancerContext* context, bool peek); -}; - } // namespace Upstream } // namespace Envoy diff --git a/source/extensions/load_balancing_policies/common/thread_aware_lb_impl.h b/source/extensions/load_balancing_policies/common/thread_aware_lb_impl.h index 31ad4dfd3946..f8217218fcc8 100644 --- a/source/extensions/load_balancing_policies/common/thread_aware_lb_impl.h +++ b/source/extensions/load_balancing_policies/common/thread_aware_lb_impl.h @@ -8,7 +8,7 @@ #include "source/common/common/logger.h" #include "source/common/config/metadata.h" #include "source/common/config/well_known_names.h" -#include "source/common/upstream/load_balancer_impl.h" +#include "source/extensions/load_balancing_policies/common/load_balancer_impl.h" #include "absl/strings/string_view.h" #include "absl/synchronization/mutex.h" diff --git a/source/extensions/load_balancing_policies/least_request/BUILD b/source/extensions/load_balancing_policies/least_request/BUILD index e813160593b1..00568c486b1c 100644 --- a/source/extensions/load_balancing_policies/least_request/BUILD +++ b/source/extensions/load_balancing_policies/least_request/BUILD @@ -1,6 +1,7 @@ load( "//bazel:envoy_build_system.bzl", "envoy_cc_extension", + "envoy_cc_library", "envoy_extension_package", ) @@ -17,9 +18,17 @@ envoy_cc_extension( "//test:__subpackages__", ], deps = [ + ":least_request_lb_lib", "//source/common/common:minimal_logger_lib", - "//source/common/upstream:load_balancer_lib", + "//source/common/upstream:load_balancer_context_base_lib", "//source/extensions/load_balancing_policies/common:factory_base", "@envoy_api//envoy/extensions/load_balancing_policies/least_request/v3:pkg_cc_proto", ], ) + +envoy_cc_library( + name = "least_request_lb_lib", + srcs = ["least_request_lb.cc"], + hdrs = ["least_request_lb.h"], + deps = ["//source/extensions/load_balancing_policies/common:load_balancer_lib"], +) diff --git a/source/extensions/load_balancing_policies/least_request/config.cc b/source/extensions/load_balancing_policies/least_request/config.cc index 26e0890ca244..973154ed8724 100644 --- a/source/extensions/load_balancing_policies/least_request/config.cc +++ b/source/extensions/load_balancing_policies/least_request/config.cc @@ -2,7 +2,7 @@ #include "envoy/extensions/load_balancing_policies/least_request/v3/least_request.pb.h" -#include "source/common/upstream/load_balancer_impl.h" +#include "source/extensions/load_balancing_policies/least_request/least_request_lb.h" namespace Envoy { namespace Extensions { diff --git a/source/extensions/load_balancing_policies/least_request/config.h b/source/extensions/load_balancing_policies/least_request/config.h index cdd2e9e93353..3d3f92372de9 100644 --- a/source/extensions/load_balancing_policies/least_request/config.h +++ b/source/extensions/load_balancing_policies/least_request/config.h @@ -5,7 +5,6 @@ #include "envoy/upstream/load_balancer.h" #include "source/common/common/logger.h" -#include "source/common/upstream/load_balancer_impl.h" #include "source/extensions/load_balancing_policies/common/factory_base.h" namespace Envoy { diff --git a/source/extensions/load_balancing_policies/least_request/least_request_lb.cc b/source/extensions/load_balancing_policies/least_request/least_request_lb.cc new file mode 100644 index 000000000000..40ac47724e24 --- /dev/null +++ b/source/extensions/load_balancing_policies/least_request/least_request_lb.cc @@ -0,0 +1,144 @@ +#include "source/extensions/load_balancing_policies/least_request/least_request_lb.h" + +namespace Envoy { +namespace Upstream { + +double LeastRequestLoadBalancer::hostWeight(const Host& host) const { + // This method is called to calculate the dynamic weight as following when all load balancing + // weights are not equal: + // + // `weight = load_balancing_weight / (active_requests + 1)^active_request_bias` + // + // `active_request_bias` can be configured via runtime and its value is cached in + // `active_request_bias_` to avoid having to do a runtime lookup each time a host weight is + // calculated. + // + // When `active_request_bias == 0.0` we behave like `RoundRobinLoadBalancer` and return the + // host weight without considering the number of active requests at the time we do the pick. + // + // When `active_request_bias > 0.0` we scale the host weight by the number of active + // requests at the time we do the pick. We always add 1 to avoid division by 0. + // + // It might be possible to do better by picking two hosts off of the schedule, and selecting the + // one with fewer active requests at the time of selection. + + double host_weight = static_cast(host.weight()); + + // If the value of active requests is the max value, adding +1 will overflow + // it and cause a divide by zero. This won't happen in normal cases but stops + // failing fuzz tests + const uint64_t active_request_value = + host.stats().rq_active_.value() != std::numeric_limits::max() + ? host.stats().rq_active_.value() + 1 + : host.stats().rq_active_.value(); + + if (active_request_bias_ == 1.0) { + host_weight = static_cast(host.weight()) / active_request_value; + } else if (active_request_bias_ != 0.0) { + host_weight = + static_cast(host.weight()) / std::pow(active_request_value, active_request_bias_); + } + + if (!noHostsAreInSlowStart()) { + return applySlowStartFactor(host_weight, host); + } else { + return host_weight; + } +} + +HostConstSharedPtr LeastRequestLoadBalancer::unweightedHostPeek(const HostVector&, + const HostsSource&) { + // LeastRequestLoadBalancer can not do deterministic preconnecting, because + // any other thread might select the least-requested-host between preconnect and + // host-pick, and change the rq_active checks. + return nullptr; +} + +HostConstSharedPtr LeastRequestLoadBalancer::unweightedHostPick(const HostVector& hosts_to_use, + const HostsSource&) { + HostSharedPtr candidate_host = nullptr; + + switch (selection_method_) { + case envoy::extensions::load_balancing_policies::least_request::v3::LeastRequest::FULL_SCAN: + candidate_host = unweightedHostPickFullScan(hosts_to_use); + break; + case envoy::extensions::load_balancing_policies::least_request::v3::LeastRequest::N_CHOICES: + candidate_host = unweightedHostPickNChoices(hosts_to_use); + break; + default: + IS_ENVOY_BUG("unknown selection method specified for least request load balancer"); + } + + return candidate_host; +} + +HostSharedPtr LeastRequestLoadBalancer::unweightedHostPickFullScan(const HostVector& hosts_to_use) { + HostSharedPtr candidate_host = nullptr; + + size_t num_hosts_known_tied_for_least = 0; + + const size_t num_hosts = hosts_to_use.size(); + + for (size_t i = 0; i < num_hosts; ++i) { + const HostSharedPtr& sampled_host = hosts_to_use[i]; + + if (candidate_host == nullptr) { + // Make a first choice to start the comparisons. + num_hosts_known_tied_for_least = 1; + candidate_host = sampled_host; + continue; + } + + const auto candidate_active_rq = candidate_host->stats().rq_active_.value(); + const auto sampled_active_rq = sampled_host->stats().rq_active_.value(); + + if (sampled_active_rq < candidate_active_rq) { + // Reset the count of known tied hosts. + num_hosts_known_tied_for_least = 1; + candidate_host = sampled_host; + } else if (sampled_active_rq == candidate_active_rq) { + ++num_hosts_known_tied_for_least; + + // Use reservoir sampling to select 1 unique sample from the total number of hosts N + // that will tie for least requests after processing the full hosts array. + // + // Upon each new tie encountered, replace candidate_host with sampled_host + // with probability (1 / num_hosts_known_tied_for_least percent). + // The end result is that each tied host has an equal 1 / N chance of being the + // candidate_host returned by this function. + const size_t random_tied_host_index = random_.random() % num_hosts_known_tied_for_least; + if (random_tied_host_index == 0) { + candidate_host = sampled_host; + } + } + } + + return candidate_host; +} + +HostSharedPtr LeastRequestLoadBalancer::unweightedHostPickNChoices(const HostVector& hosts_to_use) { + HostSharedPtr candidate_host = nullptr; + + for (uint32_t choice_idx = 0; choice_idx < choice_count_; ++choice_idx) { + const int rand_idx = random_.random() % hosts_to_use.size(); + const HostSharedPtr& sampled_host = hosts_to_use[rand_idx]; + + if (candidate_host == nullptr) { + // Make a first choice to start the comparisons. + candidate_host = sampled_host; + continue; + } + + const auto candidate_active_rq = candidate_host->stats().rq_active_.value(); + const auto sampled_active_rq = sampled_host->stats().rq_active_.value(); + + if (sampled_active_rq < candidate_active_rq) { + candidate_host = sampled_host; + } + } + + return candidate_host; +} + +} // namespace Upstream +} // namespace Envoy diff --git a/source/extensions/load_balancing_policies/least_request/least_request_lb.h b/source/extensions/load_balancing_policies/least_request/least_request_lb.h new file mode 100644 index 000000000000..2c4dadbb0477 --- /dev/null +++ b/source/extensions/load_balancing_policies/least_request/least_request_lb.h @@ -0,0 +1,114 @@ +#pragma once + +#include "source/extensions/load_balancing_policies/common/load_balancer_impl.h" + +namespace Envoy { +namespace Upstream { + +/** + * Weighted Least Request load balancer. + * + * In a normal setup when all hosts have the same weight it randomly picks up N healthy hosts + * (where N is specified in the LB configuration) and compares number of active requests. Technique + * is based on http://www.eecs.harvard.edu/~michaelm/postscripts/mythesis.pdf and is known as P2C + * (power of two choices). + * + * When hosts have different weights, an RR EDF schedule is used. Host weight is scaled + * by the number of active requests at pick/insert time. Thus, hosts will never fully drain as + * they would in normal P2C, though they will get picked less and less often. In the future, we + * can consider two alternate algorithms: + * 1) Expand out all hosts by weight (using more memory) and do standard P2C. + * 2) Use a weighted Maglev table, and perform P2C on two random hosts selected from the table. + * The benefit of the Maglev table is at the expense of resolution, memory usage is capped. + * Additionally, the Maglev table can be shared amongst all threads. + */ +class LeastRequestLoadBalancer : public EdfLoadBalancerBase { +public: + LeastRequestLoadBalancer( + const PrioritySet& priority_set, const PrioritySet* local_priority_set, ClusterLbStats& stats, + Runtime::Loader& runtime, Random::RandomGenerator& random, + const envoy::config::cluster::v3::Cluster::CommonLbConfig& common_config, + OptRef least_request_config, + TimeSource& time_source) + : EdfLoadBalancerBase( + priority_set, local_priority_set, stats, runtime, random, + PROTOBUF_PERCENT_TO_ROUNDED_INTEGER_OR_DEFAULT(common_config, healthy_panic_threshold, + 100, 50), + LoadBalancerConfigHelper::localityLbConfigFromCommonLbConfig(common_config), + least_request_config.has_value() + ? LoadBalancerConfigHelper::slowStartConfigFromLegacyProto( + least_request_config.ref()) + : absl::nullopt, + time_source), + choice_count_( + least_request_config.has_value() + ? PROTOBUF_GET_WRAPPED_OR_DEFAULT(least_request_config.ref(), choice_count, 2) + : 2), + active_request_bias_runtime_( + least_request_config.has_value() && least_request_config->has_active_request_bias() + ? absl::optional( + {least_request_config->active_request_bias(), runtime}) + : absl::nullopt) { + initialize(); + } + + LeastRequestLoadBalancer( + const PrioritySet& priority_set, const PrioritySet* local_priority_set, ClusterLbStats& stats, + Runtime::Loader& runtime, Random::RandomGenerator& random, uint32_t healthy_panic_threshold, + const envoy::extensions::load_balancing_policies::least_request::v3::LeastRequest& + least_request_config, + TimeSource& time_source) + : EdfLoadBalancerBase( + priority_set, local_priority_set, stats, runtime, random, healthy_panic_threshold, + LoadBalancerConfigHelper::localityLbConfigFromProto(least_request_config), + LoadBalancerConfigHelper::slowStartConfigFromProto(least_request_config), time_source), + choice_count_(PROTOBUF_GET_WRAPPED_OR_DEFAULT(least_request_config, choice_count, 2)), + active_request_bias_runtime_( + least_request_config.has_active_request_bias() + ? absl::optional( + {least_request_config.active_request_bias(), runtime}) + : absl::nullopt), + selection_method_(least_request_config.selection_method()) { + initialize(); + } + +protected: + void refresh(uint32_t priority) override { + active_request_bias_ = active_request_bias_runtime_ != absl::nullopt + ? active_request_bias_runtime_.value().value() + : 1.0; + + if (active_request_bias_ < 0.0 || std::isnan(active_request_bias_)) { + ENVOY_LOG_MISC(warn, + "upstream: invalid active request bias supplied (runtime key {}), using 1.0", + active_request_bias_runtime_->runtimeKey()); + active_request_bias_ = 1.0; + } + + EdfLoadBalancerBase::refresh(priority); + } + +private: + void refreshHostSource(const HostsSource&) override {} + double hostWeight(const Host& host) const override; + HostConstSharedPtr unweightedHostPeek(const HostVector& hosts_to_use, + const HostsSource& source) override; + HostConstSharedPtr unweightedHostPick(const HostVector& hosts_to_use, + const HostsSource& source) override; + HostSharedPtr unweightedHostPickFullScan(const HostVector& hosts_to_use); + HostSharedPtr unweightedHostPickNChoices(const HostVector& hosts_to_use); + + const uint32_t choice_count_; + + // The exponent used to calculate host weights can be configured via runtime. We cache it for + // performance reasons and refresh it in `LeastRequestLoadBalancer::refresh(uint32_t priority)` + // whenever a `HostSet` is updated. + double active_request_bias_{}; + + const absl::optional active_request_bias_runtime_; + const envoy::extensions::load_balancing_policies::least_request::v3::LeastRequest::SelectionMethod + selection_method_{}; +}; + +} // namespace Upstream +} // namespace Envoy diff --git a/source/extensions/load_balancing_policies/maglev/BUILD b/source/extensions/load_balancing_policies/maglev/BUILD index e3bc489bd04f..4d4de511b083 100644 --- a/source/extensions/load_balancing_policies/maglev/BUILD +++ b/source/extensions/load_balancing_policies/maglev/BUILD @@ -52,8 +52,8 @@ envoy_cc_extension( deps = [ ":maglev_lb_lib", "//source/common/common:minimal_logger_lib", + "//source/common/upstream:load_balancer_context_base_lib", "//source/common/upstream:load_balancer_factory_base_lib", - "//source/common/upstream:load_balancer_lib", "//source/extensions/load_balancing_policies/common:factory_base", "@envoy_api//envoy/extensions/load_balancing_policies/maglev/v3:pkg_cc_proto", ], diff --git a/source/extensions/load_balancing_policies/random/BUILD b/source/extensions/load_balancing_policies/random/BUILD index d73731664f21..6f1a3f49d81a 100644 --- a/source/extensions/load_balancing_policies/random/BUILD +++ b/source/extensions/load_balancing_policies/random/BUILD @@ -1,6 +1,7 @@ load( "//bazel:envoy_build_system.bzl", "envoy_cc_extension", + "envoy_cc_library", "envoy_extension_package", ) @@ -17,9 +18,17 @@ envoy_cc_extension( "//test:__subpackages__", ], deps = [ + ":random_lb_lib", "//source/common/common:minimal_logger_lib", - "//source/common/upstream:load_balancer_lib", + "//source/common/upstream:load_balancer_context_base_lib", "//source/extensions/load_balancing_policies/common:factory_base", "@envoy_api//envoy/extensions/load_balancing_policies/random/v3:pkg_cc_proto", ], ) + +envoy_cc_library( + name = "random_lb_lib", + srcs = ["random_lb.cc"], + hdrs = ["random_lb.h"], + deps = ["//source/extensions/load_balancing_policies/common:load_balancer_lib"], +) diff --git a/source/extensions/load_balancing_policies/random/config.cc b/source/extensions/load_balancing_policies/random/config.cc index cd045886785f..de95ba855ca9 100644 --- a/source/extensions/load_balancing_policies/random/config.cc +++ b/source/extensions/load_balancing_policies/random/config.cc @@ -2,7 +2,7 @@ #include "envoy/extensions/load_balancing_policies/random/v3/random.pb.h" -#include "source/common/upstream/load_balancer_impl.h" +#include "source/extensions/load_balancing_policies/random/random_lb.h" namespace Envoy { namespace Extensions { diff --git a/source/extensions/load_balancing_policies/random/config.h b/source/extensions/load_balancing_policies/random/config.h index 3af1348d0f9d..25a3991f65e0 100644 --- a/source/extensions/load_balancing_policies/random/config.h +++ b/source/extensions/load_balancing_policies/random/config.h @@ -5,7 +5,6 @@ #include "envoy/upstream/load_balancer.h" #include "source/common/common/logger.h" -#include "source/common/upstream/load_balancer_impl.h" #include "source/extensions/load_balancing_policies/common/factory_base.h" namespace Envoy { diff --git a/source/extensions/load_balancing_policies/random/random_lb.cc b/source/extensions/load_balancing_policies/random/random_lb.cc new file mode 100644 index 000000000000..fb96091befbb --- /dev/null +++ b/source/extensions/load_balancing_policies/random/random_lb.cc @@ -0,0 +1,33 @@ +#include "source/extensions/load_balancing_policies/random/random_lb.h" + +namespace Envoy { +namespace Upstream { + +HostConstSharedPtr RandomLoadBalancer::peekAnotherHost(LoadBalancerContext* context) { + if (tooManyPreconnects(stashed_random_.size(), total_healthy_hosts_)) { + return nullptr; + } + return peekOrChoose(context, true); +} + +HostConstSharedPtr RandomLoadBalancer::chooseHostOnce(LoadBalancerContext* context) { + return peekOrChoose(context, false); +} + +HostConstSharedPtr RandomLoadBalancer::peekOrChoose(LoadBalancerContext* context, bool peek) { + uint64_t random_hash = random(peek); + const absl::optional hosts_source = hostSourceToUse(context, random_hash); + if (!hosts_source) { + return nullptr; + } + + const HostVector& hosts_to_use = hostSourceToHosts(*hosts_source); + if (hosts_to_use.empty()) { + return nullptr; + } + + return hosts_to_use[random_hash % hosts_to_use.size()]; +} + +} // namespace Upstream +} // namespace Envoy diff --git a/source/extensions/load_balancing_policies/random/random_lb.h b/source/extensions/load_balancing_policies/random/random_lb.h new file mode 100644 index 000000000000..786f3ec7fc08 --- /dev/null +++ b/source/extensions/load_balancing_policies/random/random_lb.h @@ -0,0 +1,40 @@ +#pragma once + +#include "source/extensions/load_balancing_policies/common/load_balancer_impl.h" + +namespace Envoy { +namespace Upstream { + +/** + * Random load balancer that picks a random host out of all hosts. + */ +class RandomLoadBalancer : public ZoneAwareLoadBalancerBase { +public: + RandomLoadBalancer(const PrioritySet& priority_set, const PrioritySet* local_priority_set, + ClusterLbStats& stats, Runtime::Loader& runtime, + Random::RandomGenerator& random, + const envoy::config::cluster::v3::Cluster::CommonLbConfig& common_config) + : ZoneAwareLoadBalancerBase( + priority_set, local_priority_set, stats, runtime, random, + PROTOBUF_PERCENT_TO_ROUNDED_INTEGER_OR_DEFAULT(common_config, healthy_panic_threshold, + 100, 50), + LoadBalancerConfigHelper::localityLbConfigFromCommonLbConfig(common_config)) {} + + RandomLoadBalancer( + const PrioritySet& priority_set, const PrioritySet* local_priority_set, ClusterLbStats& stats, + Runtime::Loader& runtime, Random::RandomGenerator& random, uint32_t healthy_panic_threshold, + const envoy::extensions::load_balancing_policies::random::v3::Random& random_config) + : ZoneAwareLoadBalancerBase( + priority_set, local_priority_set, stats, runtime, random, healthy_panic_threshold, + LoadBalancerConfigHelper::localityLbConfigFromProto(random_config)) {} + + // Upstream::ZoneAwareLoadBalancerBase + HostConstSharedPtr chooseHostOnce(LoadBalancerContext* context) override; + HostConstSharedPtr peekAnotherHost(LoadBalancerContext* context) override; + +protected: + HostConstSharedPtr peekOrChoose(LoadBalancerContext* context, bool peek); +}; + +} // namespace Upstream +} // namespace Envoy diff --git a/source/extensions/load_balancing_policies/ring_hash/BUILD b/source/extensions/load_balancing_policies/ring_hash/BUILD index 652f8e20a6e0..435b97c0eaf7 100644 --- a/source/extensions/load_balancing_policies/ring_hash/BUILD +++ b/source/extensions/load_balancing_policies/ring_hash/BUILD @@ -36,8 +36,8 @@ envoy_cc_extension( deps = [ ":ring_hash_lb_lib", "//source/common/common:minimal_logger_lib", + "//source/common/upstream:load_balancer_context_base_lib", "//source/common/upstream:load_balancer_factory_base_lib", - "//source/common/upstream:load_balancer_lib", "//source/extensions/load_balancing_policies/common:factory_base", "@envoy_api//envoy/extensions/load_balancing_policies/ring_hash/v3:pkg_cc_proto", ], diff --git a/source/extensions/load_balancing_policies/ring_hash/ring_hash_lb.cc b/source/extensions/load_balancing_policies/ring_hash/ring_hash_lb.cc index cd1fa0543a9c..ad2d2f6af790 100644 --- a/source/extensions/load_balancing_policies/ring_hash/ring_hash_lb.cc +++ b/source/extensions/load_balancing_policies/ring_hash/ring_hash_lb.cc @@ -8,7 +8,6 @@ #include "envoy/config/cluster/v3/cluster.pb.h" #include "source/common/common/assert.h" -#include "source/common/upstream/load_balancer_impl.h" #include "absl/container/inlined_vector.h" #include "absl/strings/string_view.h" diff --git a/source/extensions/load_balancing_policies/round_robin/BUILD b/source/extensions/load_balancing_policies/round_robin/BUILD index d945d54f94a1..719addf5ecb6 100644 --- a/source/extensions/load_balancing_policies/round_robin/BUILD +++ b/source/extensions/load_balancing_policies/round_robin/BUILD @@ -1,6 +1,7 @@ load( "//bazel:envoy_build_system.bzl", "envoy_cc_extension", + "envoy_cc_library", "envoy_extension_package", ) @@ -15,9 +16,17 @@ envoy_cc_extension( # previously considered core code and used by mobile. visibility = ["//visibility:public"], deps = [ + ":round_robin_lb_lib", "//source/common/common:minimal_logger_lib", - "//source/common/upstream:load_balancer_lib", + "//source/common/upstream:load_balancer_context_base_lib", "//source/extensions/load_balancing_policies/common:factory_base", "@envoy_api//envoy/extensions/load_balancing_policies/round_robin/v3:pkg_cc_proto", ], ) + +envoy_cc_library( + name = "round_robin_lb_lib", + srcs = ["round_robin_lb.cc"], + hdrs = ["round_robin_lb.h"], + deps = ["//source/extensions/load_balancing_policies/common:load_balancer_lib"], +) diff --git a/source/extensions/load_balancing_policies/round_robin/config.cc b/source/extensions/load_balancing_policies/round_robin/config.cc index 761a2fe86cf4..415ee567d3ff 100644 --- a/source/extensions/load_balancing_policies/round_robin/config.cc +++ b/source/extensions/load_balancing_policies/round_robin/config.cc @@ -2,7 +2,7 @@ #include "envoy/extensions/load_balancing_policies/round_robin/v3/round_robin.pb.h" -#include "source/common/upstream/load_balancer_impl.h" +#include "source/extensions/load_balancing_policies/round_robin/round_robin_lb.h" namespace Envoy { namespace Extensions { diff --git a/source/extensions/load_balancing_policies/round_robin/config.h b/source/extensions/load_balancing_policies/round_robin/config.h index bcd63339d9e1..c2ad4dca934b 100644 --- a/source/extensions/load_balancing_policies/round_robin/config.h +++ b/source/extensions/load_balancing_policies/round_robin/config.h @@ -5,7 +5,6 @@ #include "envoy/upstream/load_balancer.h" #include "source/common/common/logger.h" -#include "source/common/upstream/load_balancer_impl.h" #include "source/extensions/load_balancing_policies/common/factory_base.h" namespace Envoy { diff --git a/source/extensions/load_balancing_policies/round_robin/round_robin_lb.cc b/source/extensions/load_balancing_policies/round_robin/round_robin_lb.cc new file mode 100644 index 000000000000..37b37db7099c --- /dev/null +++ b/source/extensions/load_balancing_policies/round_robin/round_robin_lb.cc @@ -0,0 +1,5 @@ +#include "source/extensions/load_balancing_policies/round_robin/round_robin_lb.h" + +namespace Envoy { +namespace Upstream {} +} // namespace Envoy diff --git a/source/extensions/load_balancing_policies/round_robin/round_robin_lb.h b/source/extensions/load_balancing_policies/round_robin/round_robin_lb.h new file mode 100644 index 000000000000..2b1626d4a5ee --- /dev/null +++ b/source/extensions/load_balancing_policies/round_robin/round_robin_lb.h @@ -0,0 +1,88 @@ +#pragma once + +#include "source/extensions/load_balancing_policies/common/load_balancer_impl.h" + +namespace Envoy { +namespace Upstream { + +/** + * A round robin load balancer. When in weighted mode, EDF scheduling is used. When in not + * weighted mode, simple RR index selection is used. + */ +class RoundRobinLoadBalancer : public EdfLoadBalancerBase { +public: + RoundRobinLoadBalancer( + const PrioritySet& priority_set, const PrioritySet* local_priority_set, ClusterLbStats& stats, + Runtime::Loader& runtime, Random::RandomGenerator& random, + const envoy::config::cluster::v3::Cluster::CommonLbConfig& common_config, + OptRef round_robin_config, + TimeSource& time_source) + : EdfLoadBalancerBase( + priority_set, local_priority_set, stats, runtime, random, + PROTOBUF_PERCENT_TO_ROUNDED_INTEGER_OR_DEFAULT(common_config, healthy_panic_threshold, + 100, 50), + LoadBalancerConfigHelper::localityLbConfigFromCommonLbConfig(common_config), + round_robin_config.has_value() + ? LoadBalancerConfigHelper::slowStartConfigFromLegacyProto(round_robin_config.ref()) + : absl::nullopt, + time_source) { + initialize(); + } + + RoundRobinLoadBalancer( + const PrioritySet& priority_set, const PrioritySet* local_priority_set, ClusterLbStats& stats, + Runtime::Loader& runtime, Random::RandomGenerator& random, uint32_t healthy_panic_threshold, + const envoy::extensions::load_balancing_policies::round_robin::v3::RoundRobin& + round_robin_config, + TimeSource& time_source) + : EdfLoadBalancerBase( + priority_set, local_priority_set, stats, runtime, random, healthy_panic_threshold, + LoadBalancerConfigHelper::localityLbConfigFromProto(round_robin_config), + LoadBalancerConfigHelper::slowStartConfigFromProto(round_robin_config), time_source) { + initialize(); + } + +private: + void refreshHostSource(const HostsSource& source) override { + // insert() is used here on purpose so that we don't overwrite the index if the host source + // already exists. Note that host sources will never be removed, but given how uncommon this + // is it probably doesn't matter. + rr_indexes_.insert({source, seed_}); + // If the list of hosts changes, the order of picks change. Discard the + // index. + peekahead_index_ = 0; + } + double hostWeight(const Host& host) const override { + if (!noHostsAreInSlowStart()) { + return applySlowStartFactor(host.weight(), host); + } + return host.weight(); + } + + HostConstSharedPtr unweightedHostPeek(const HostVector& hosts_to_use, + const HostsSource& source) override { + auto i = rr_indexes_.find(source); + if (i == rr_indexes_.end()) { + return nullptr; + } + return hosts_to_use[(i->second + (peekahead_index_)++) % hosts_to_use.size()]; + } + + HostConstSharedPtr unweightedHostPick(const HostVector& hosts_to_use, + const HostsSource& source) override { + if (peekahead_index_ > 0) { + --peekahead_index_; + } + // To avoid storing the RR index in the base class, we end up using a second map here with + // host source as the key. This means that each LB decision will require two map lookups in + // the unweighted case. We might consider trying to optimize this in the future. + ASSERT(rr_indexes_.find(source) != rr_indexes_.end()); + return hosts_to_use[rr_indexes_[source]++ % hosts_to_use.size()]; + } + + uint64_t peekahead_index_{}; + absl::flat_hash_map rr_indexes_; +}; + +} // namespace Upstream +} // namespace Envoy diff --git a/source/extensions/load_balancing_policies/subset/BUILD b/source/extensions/load_balancing_policies/subset/BUILD index f119886fc3a6..b3c62934a4d6 100644 --- a/source/extensions/load_balancing_policies/subset/BUILD +++ b/source/extensions/load_balancing_policies/subset/BUILD @@ -41,8 +41,8 @@ envoy_cc_extension( deps = [ ":subset_lb_lib", "//source/common/common:minimal_logger_lib", + "//source/common/upstream:load_balancer_context_base_lib", "//source/common/upstream:load_balancer_factory_base_lib", - "//source/common/upstream:load_balancer_lib", ], ) @@ -54,7 +54,7 @@ envoy_cc_extension( "//envoy/upstream:load_balancer_interface", "//envoy/upstream:upstream_interface", "//source/common/config:utility_lib", - "//source/common/upstream:load_balancer_lib", + "//source/common/upstream:load_balancer_context_base_lib", "//source/common/upstream:upstream_lib", "@envoy_api//envoy/config/cluster/v3:pkg_cc_proto", "@envoy_api//envoy/extensions/load_balancing_policies/common/v3:pkg_cc_proto", diff --git a/source/extensions/load_balancing_policies/subset/subset_lb.cc b/source/extensions/load_balancing_policies/subset/subset_lb.cc index dd61200404d6..5d0cd7fd7e44 100644 --- a/source/extensions/load_balancing_policies/subset/subset_lb.cc +++ b/source/extensions/load_balancing_policies/subset/subset_lb.cc @@ -11,7 +11,6 @@ #include "source/common/config/metadata.h" #include "source/common/config/well_known_names.h" #include "source/common/protobuf/utility.h" -#include "source/common/upstream/load_balancer_impl.h" #include "absl/container/node_hash_set.h" diff --git a/source/extensions/load_balancing_policies/subset/subset_lb.h b/source/extensions/load_balancing_policies/subset/subset_lb.h index e2b432d46795..78854be3eb9b 100644 --- a/source/extensions/load_balancing_policies/subset/subset_lb.h +++ b/source/extensions/load_balancing_policies/subset/subset_lb.h @@ -20,7 +20,7 @@ #include "source/common/common/macros.h" #include "source/common/protobuf/protobuf.h" #include "source/common/protobuf/utility.h" -#include "source/common/upstream/load_balancer_impl.h" +#include "source/common/upstream/load_balancer_context_base.h" #include "source/common/upstream/upstream_impl.h" #include "source/extensions/load_balancing_policies/subset/subset_lb_config.h" diff --git a/source/extensions/retry/priority/previous_priorities/BUILD b/source/extensions/retry/priority/previous_priorities/BUILD index 0df95fe8f405..7bcd1e3542a4 100644 --- a/source/extensions/retry/priority/previous_priorities/BUILD +++ b/source/extensions/retry/priority/previous_priorities/BUILD @@ -15,7 +15,7 @@ envoy_cc_library( hdrs = ["previous_priorities.h"], deps = [ "//envoy/upstream:retry_interface", - "//source/common/upstream:load_balancer_lib", + "//source/extensions/load_balancing_policies/common:load_balancer_lib", ], ) diff --git a/source/extensions/retry/priority/previous_priorities/previous_priorities.h b/source/extensions/retry/priority/previous_priorities/previous_priorities.h index 5cceb5f8fbae..1bfcd7ae0d1c 100644 --- a/source/extensions/retry/priority/previous_priorities/previous_priorities.h +++ b/source/extensions/retry/priority/previous_priorities/previous_priorities.h @@ -2,7 +2,7 @@ #include "envoy/upstream/retry.h" -#include "source/common/upstream/load_balancer_impl.h" +#include "source/extensions/load_balancing_policies/common/load_balancer_impl.h" namespace Envoy { namespace Extensions { diff --git a/source/extensions/upstreams/http/http/BUILD b/source/extensions/upstreams/http/http/BUILD index d53b9a92a9dd..a189df85a1cd 100644 --- a/source/extensions/upstreams/http/http/BUILD +++ b/source/extensions/upstreams/http/http/BUILD @@ -48,7 +48,7 @@ envoy_cc_library( "//source/common/network:application_protocol_lib", "//source/common/network:transport_socket_options_lib", "//source/common/router:router_lib", - "//source/common/upstream:load_balancer_lib", + "//source/common/upstream:load_balancer_context_base_lib", "//source/extensions/common/proxy_protocol:proxy_protocol_header_lib", ], ) diff --git a/source/extensions/upstreams/http/tcp/BUILD b/source/extensions/upstreams/http/tcp/BUILD index 869c0ee5ec6a..696d3578941b 100644 --- a/source/extensions/upstreams/http/tcp/BUILD +++ b/source/extensions/upstreams/http/tcp/BUILD @@ -47,7 +47,7 @@ envoy_cc_library( "//source/common/network:application_protocol_lib", "//source/common/network:transport_socket_options_lib", "//source/common/router:router_lib", - "//source/common/upstream:load_balancer_lib", + "//source/common/upstream:load_balancer_context_base_lib", "//source/extensions/common/proxy_protocol:proxy_protocol_header_lib", ], ) diff --git a/source/extensions/upstreams/http/udp/BUILD b/source/extensions/upstreams/http/udp/BUILD index 6cd59424ef05..f8dd3a223e7d 100644 --- a/source/extensions/upstreams/http/udp/BUILD +++ b/source/extensions/upstreams/http/udp/BUILD @@ -47,7 +47,7 @@ envoy_cc_library( "//source/common/network:application_protocol_lib", "//source/common/network:transport_socket_options_lib", "//source/common/router:router_lib", - "//source/common/upstream:load_balancer_lib", + "//source/common/upstream:load_balancer_context_base_lib", "//source/extensions/common/proxy_protocol:proxy_protocol_header_lib", "@com_github_google_quiche//:quiche_common_capsule_lib", "@com_github_google_quiche//:quiche_common_connect_udp_datagram_payload_lib", diff --git a/test/common/upstream/BUILD b/test/common/upstream/BUILD index c6da09098024..3b333be88502 100644 --- a/test/common/upstream/BUILD +++ b/test/common/upstream/BUILD @@ -272,9 +272,12 @@ envoy_cc_test( ":utility_lib", "//source/common/common:random_generator_lib", "//source/common/network:utility_lib", - "//source/common/upstream:load_balancer_lib", + "//source/common/upstream:load_balancer_context_base_lib", "//source/common/upstream:upstream_includes", "//source/common/upstream:upstream_lib", + "//source/extensions/load_balancing_policies/least_request:config", + "//source/extensions/load_balancing_policies/random:config", + "//source/extensions/load_balancing_policies/round_robin:config", "//test/mocks:common_lib", "//test/mocks/runtime:runtime_mocks", "//test/mocks/upstream:cluster_info_mocks", @@ -297,7 +300,7 @@ envoy_cc_test_library( deps = [ ":load_balancer_fuzz_proto_cc_proto", ":utility_lib", - "//source/common/upstream:load_balancer_lib", + "//source/common/upstream:load_balancer_context_base_lib", "//test/fuzz:random_lib", "//test/mocks:common_lib", "//test/mocks/runtime:runtime_mocks", @@ -336,6 +339,7 @@ envoy_cc_fuzz_test( ":load_balancer_fuzz_proto_cc_proto", ":random_load_balancer_fuzz_proto_cc_proto", ":utility_lib", + "//source/extensions/load_balancing_policies/random:config", ], ) @@ -347,9 +351,12 @@ envoy_cc_test( "//source/common/common:random_generator_lib", "//source/common/network:utility_lib", "//source/common/runtime:runtime_lib", - "//source/common/upstream:load_balancer_lib", + "//source/common/upstream:load_balancer_context_base_lib", "//source/common/upstream:upstream_includes", "//source/common/upstream:upstream_lib", + "//source/extensions/load_balancing_policies/least_request:config", + "//source/extensions/load_balancing_policies/random:config", + "//source/extensions/load_balancing_policies/round_robin:config", "//test/mocks/runtime:runtime_mocks", "//test/mocks/upstream:cluster_info_mocks", "//test/mocks/upstream:host_set_mocks", @@ -473,8 +480,11 @@ envoy_cc_benchmark_binary( "//source/common/common:random_generator_lib", "//source/common/memory:stats_lib", "//source/common/upstream:upstream_lib", + "//source/extensions/load_balancing_policies/least_request:config", "//source/extensions/load_balancing_policies/maglev:config", + "//source/extensions/load_balancing_policies/random:config", "//source/extensions/load_balancing_policies/ring_hash:config", + "//source/extensions/load_balancing_policies/round_robin:config", "//test/common/upstream:utility_lib", "//test/mocks/upstream:cluster_info_mocks", "//test/test_common:printers_lib", @@ -707,6 +717,7 @@ envoy_cc_test_library( deps = [ ":load_balancer_fuzz_lib", ":zone_aware_load_balancer_fuzz_proto_cc_proto", + "//source/extensions/load_balancing_policies/common:load_balancer_lib", "//test/mocks/upstream:host_set_mocks", "//test/mocks/upstream:priority_set_mocks", "@envoy_api//envoy/config/cluster/v3:pkg_cc_proto", @@ -730,6 +741,7 @@ envoy_cc_fuzz_test( ":round_robin_load_balancer_fuzz_proto_cc_proto", ":utility_lib", ":zone_aware_load_balancer_fuzz_lib", + "//source/extensions/load_balancing_policies/round_robin:config", "//test/fuzz:utility_lib", ], ) @@ -751,6 +763,7 @@ envoy_cc_fuzz_test( ":least_request_load_balancer_fuzz_proto_cc_proto", ":utility_lib", ":zone_aware_load_balancer_fuzz_lib", + "//source/extensions/load_balancing_policies/least_request:config", ], ) diff --git a/test/common/upstream/least_request_load_balancer_fuzz_test.cc b/test/common/upstream/least_request_load_balancer_fuzz_test.cc index 195409b52406..a1e022e89dbd 100644 --- a/test/common/upstream/least_request_load_balancer_fuzz_test.cc +++ b/test/common/upstream/least_request_load_balancer_fuzz_test.cc @@ -1,5 +1,7 @@ #include +#include "source/extensions/load_balancing_policies/least_request/least_request_lb.h" + #include "test/common/upstream/least_request_load_balancer_fuzz.pb.validate.h" #include "test/common/upstream/zone_aware_load_balancer_fuzz_base.h" #include "test/fuzz/fuzz_runner.h" diff --git a/test/common/upstream/load_balancer_benchmark.cc b/test/common/upstream/load_balancer_benchmark.cc index 9c12760cc17b..d4b51fe18e0a 100644 --- a/test/common/upstream/load_balancer_benchmark.cc +++ b/test/common/upstream/load_balancer_benchmark.cc @@ -7,8 +7,11 @@ #include "source/common/common/random_generator.h" #include "source/common/memory/stats.h" #include "source/common/upstream/upstream_impl.h" +#include "source/extensions/load_balancing_policies/least_request/least_request_lb.h" #include "source/extensions/load_balancing_policies/maglev/maglev_lb.h" +#include "source/extensions/load_balancing_policies/random/random_lb.h" #include "source/extensions/load_balancing_policies/ring_hash/ring_hash_lb.h" +#include "source/extensions/load_balancing_policies/round_robin/round_robin_lb.h" #include "test/benchmark/main.h" #include "test/common/upstream/utility.h" diff --git a/test/common/upstream/load_balancer_fuzz_base.h b/test/common/upstream/load_balancer_fuzz_base.h index 689b11fa59d1..d0d8d2595df3 100644 --- a/test/common/upstream/load_balancer_fuzz_base.h +++ b/test/common/upstream/load_balancer_fuzz_base.h @@ -2,7 +2,7 @@ #include "envoy/config/cluster/v3/cluster.pb.h" -#include "source/common/upstream/load_balancer_impl.h" +#include "source/common/upstream/load_balancer_context_base.h" #include "test/common/upstream/load_balancer_fuzz.pb.validate.h" #include "test/fuzz/random.h" diff --git a/test/common/upstream/load_balancer_impl_test.cc b/test/common/upstream/load_balancer_impl_test.cc index 61523f537c4d..316e53811411 100644 --- a/test/common/upstream/load_balancer_impl_test.cc +++ b/test/common/upstream/load_balancer_impl_test.cc @@ -13,8 +13,11 @@ #include "source/common/common/random_generator.h" #include "source/common/network/utility.h" -#include "source/common/upstream/load_balancer_impl.h" +#include "source/common/upstream/load_balancer_context_base.h" #include "source/common/upstream/upstream_impl.h" +#include "source/extensions/load_balancing_policies/least_request/least_request_lb.h" +#include "source/extensions/load_balancing_policies/random/random_lb.h" +#include "source/extensions/load_balancing_policies/round_robin/round_robin_lb.h" #include "test/common/upstream/utility.h" #include "test/mocks/common.h" @@ -2843,6 +2846,18 @@ class LeastRequestLoadBalancerTest : public LoadBalancerTestBase { TEST_P(LeastRequestLoadBalancerTest, NoHosts) { EXPECT_EQ(nullptr, lb_.chooseHost(nullptr)); } +TEST_P(LeastRequestLoadBalancerTest, SingleHostAndPeek) { + hostSet().healthy_hosts_ = {makeTestHost(info_, "tcp://127.0.0.1:80", simTime())}; + hostSet().hosts_ = hostSet().healthy_hosts_; + hostSet().runCallbacks({}, {}); // Trigger callbacks. The added/removed lists are not relevant. + + // Host weight is 1 and peek. + { + EXPECT_CALL(random_, random()).WillOnce(Return(0)); + EXPECT_EQ(nullptr, lb_.peekAnotherHost(nullptr)); + } +} + TEST_P(LeastRequestLoadBalancerTest, SingleHost) { hostSet().healthy_hosts_ = {makeTestHost(info_, "tcp://127.0.0.1:80", simTime())}; hostSet().hosts_ = hostSet().healthy_hosts_; diff --git a/test/common/upstream/load_balancer_simulation_test.cc b/test/common/upstream/load_balancer_simulation_test.cc index d223b5c48ea6..767b0e4919c3 100644 --- a/test/common/upstream/load_balancer_simulation_test.cc +++ b/test/common/upstream/load_balancer_simulation_test.cc @@ -11,8 +11,10 @@ #include "source/common/common/fmt.h" #include "source/common/common/random_generator.h" #include "source/common/network/utility.h" -#include "source/common/upstream/load_balancer_impl.h" +#include "source/common/upstream/load_balancer_context_base.h" #include "source/common/upstream/upstream_impl.h" +#include "source/extensions/load_balancing_policies/least_request/least_request_lb.h" +#include "source/extensions/load_balancing_policies/random/random_lb.h" #include "test/common/upstream/utility.h" #include "test/mocks/common.h" diff --git a/test/common/upstream/random_load_balancer_fuzz_test.cc b/test/common/upstream/random_load_balancer_fuzz_test.cc index 6d5700654989..a2b49e234741 100644 --- a/test/common/upstream/random_load_balancer_fuzz_test.cc +++ b/test/common/upstream/random_load_balancer_fuzz_test.cc @@ -1,5 +1,7 @@ #include +#include "source/extensions/load_balancing_policies/random/random_lb.h" + #include "test/common/upstream/load_balancer_fuzz_base.h" #include "test/common/upstream/random_load_balancer_fuzz.pb.validate.h" #include "test/fuzz/fuzz_runner.h" diff --git a/test/common/upstream/round_robin_load_balancer_fuzz_test.cc b/test/common/upstream/round_robin_load_balancer_fuzz_test.cc index 8d65f75e8ff7..19540c30c279 100644 --- a/test/common/upstream/round_robin_load_balancer_fuzz_test.cc +++ b/test/common/upstream/round_robin_load_balancer_fuzz_test.cc @@ -2,6 +2,8 @@ #include "envoy/common/optref.h" +#include "source/extensions/load_balancing_policies/round_robin/round_robin_lb.h" + #include "test/common/upstream/round_robin_load_balancer_fuzz.pb.validate.h" #include "test/common/upstream/zone_aware_load_balancer_fuzz_base.h" #include "test/fuzz/fuzz_runner.h" diff --git a/test/extensions/load_balancing_policies/subset/BUILD b/test/extensions/load_balancing_policies/subset/BUILD index 50a924fdc7c3..a56bdcdbf460 100644 --- a/test/extensions/load_balancing_policies/subset/BUILD +++ b/test/extensions/load_balancing_policies/subset/BUILD @@ -51,7 +51,6 @@ envoy_extension_cc_test( deps = [ "//source/common/common:minimal_logger_lib", "//source/common/network:utility_lib", - "//source/common/upstream:load_balancer_lib", "//source/common/upstream:upstream_includes", "//source/common/upstream:upstream_lib", "//source/extensions/load_balancing_policies/least_request:config", diff --git a/test/integration/BUILD b/test/integration/BUILD index ad8fe57efba0..555d93c0121d 100644 --- a/test/integration/BUILD +++ b/test/integration/BUILD @@ -160,7 +160,7 @@ envoy_cc_test( ], deps = [ ":http_integration_lib", - "//source/common/upstream:load_balancer_lib", + "//source/common/upstream:load_balancer_context_base_lib", "//test/config:utility_lib", "//test/integration/filters:eds_ready_filter_config_lib", "//test/test_common:network_utility_lib", @@ -281,7 +281,7 @@ envoy_cc_test( ], deps = [ ":http_integration_lib", - "//source/common/upstream:load_balancer_lib", + "//source/common/upstream:load_balancer_context_base_lib", "//test/config:utility_lib", "//test/integration/clusters:custom_static_cluster", "//test/test_common:network_utility_lib", diff --git a/test/integration/custom_cluster_integration_test.cc b/test/integration/custom_cluster_integration_test.cc index 74e4b9d7eed8..0ba7910e1a2c 100644 --- a/test/integration/custom_cluster_integration_test.cc +++ b/test/integration/custom_cluster_integration_test.cc @@ -2,7 +2,7 @@ #include "envoy/config/cluster/v3/cluster.pb.h" #include "source/common/network/address_impl.h" -#include "source/common/upstream/load_balancer_impl.h" +#include "source/common/upstream/load_balancer_context_base.h" #include "test/config/utility.h" #include "test/integration/clusters/cluster_factory_config.pb.h" diff --git a/test/integration/eds_integration_test.cc b/test/integration/eds_integration_test.cc index 54f0f916ed0d..79f09522311f 100644 --- a/test/integration/eds_integration_test.cc +++ b/test/integration/eds_integration_test.cc @@ -5,7 +5,7 @@ #include "envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.pb.h" #include "envoy/type/v3/http.pb.h" -#include "source/common/upstream/load_balancer_impl.h" +#include "source/common/upstream/load_balancer_context_base.h" #include "test/config/utility.h" #include "test/integration/http_integration.h" diff --git a/test/integration/upstreams/BUILD b/test/integration/upstreams/BUILD index 15246549e521..8a961bccc031 100644 --- a/test/integration/upstreams/BUILD +++ b/test/integration/upstreams/BUILD @@ -23,7 +23,7 @@ envoy_cc_library( "//source/common/http:header_map_lib", "//source/common/http:headers_lib", "//source/common/router:router_lib", - "//source/common/upstream:load_balancer_lib", + "//source/common/upstream:load_balancer_context_base_lib", "//source/extensions/upstreams/http/http:upstream_request_lib", "//source/extensions/upstreams/http/tcp:upstream_request_lib", ], diff --git a/test/mocks/upstream/mocks.h b/test/mocks/upstream/mocks.h index f256737945d0..040c252d929e 100644 --- a/test/mocks/upstream/mocks.h +++ b/test/mocks/upstream/mocks.h @@ -14,7 +14,7 @@ #include "source/common/common/callback_impl.h" #include "source/common/upstream/health_discovery_service.h" -#include "source/common/upstream/load_balancer_impl.h" +#include "source/common/upstream/load_balancer_context_base.h" #include "source/common/upstream/upstream_impl.h" #include "test/mocks/config/mocks.h" From ca04c12befdf6e79b055649f4c38c73fbc9d3f3d Mon Sep 17 00:00:00 2001 From: alyssawilk Date: Thu, 9 May 2024 10:22:32 -0400 Subject: [PATCH 03/20] mobile: testing drain on reresolve (#34029) Signed-off-by: Alyssa Wilk --- mobile/library/cc/engine_builder.cc | 1 + .../base_client_integration_test.cc | 64 ++++++++------ .../base_client_integration_test.h | 3 + .../integration/client_integration_test.cc | 85 +++++++++++++++++-- mobile/test/common/internal_engine_test.cc | 2 +- .../dynamic_forward_proxy/test_resolver.h | 5 ++ 6 files changed, 126 insertions(+), 34 deletions(-) diff --git a/mobile/library/cc/engine_builder.cc b/mobile/library/cc/engine_builder.cc index 614416c2ff86..515d0000cf59 100644 --- a/mobile/library/cc/engine_builder.cc +++ b/mobile/library/cc/engine_builder.cc @@ -843,6 +843,7 @@ std::unique_ptr EngineBuilder::generate list->add_patterns()->set_prefix("http.hcm.decompressor."); list->add_patterns()->set_prefix("pulse."); list->add_patterns()->set_prefix("runtime.load_success"); + list->add_patterns()->set_prefix("dns_cache"); list->add_patterns()->mutable_safe_regex()->set_regex( "^vhost\\.[\\w]+\\.vcluster\\.[\\w]+?\\.upstream_rq_(?:[12345]xx|[3-5][0-9][0-9]|retry|" "total)"); diff --git a/mobile/test/common/integration/base_client_integration_test.cc b/mobile/test/common/integration/base_client_integration_test.cc index 21f7564beb6b..cc0b3bceb285 100644 --- a/mobile/test/common/integration/base_client_integration_test.cc +++ b/mobile/test/common/integration/base_client_integration_test.cc @@ -80,45 +80,53 @@ BaseClientIntegrationTest::BaseClientIntegrationTest(Network::Address::IpVersion void BaseClientIntegrationTest::initialize() { BaseIntegrationTest::initialize(); + + HttpTestUtility::addDefaultHeaders(default_request_headers_); + default_request_headers_.setHost(fake_upstreams_[0]->localAddress()->asStringView()); + + createNewStream(stream_prototype_, cc_, stream_); +} + +void BaseClientIntegrationTest::createNewStream( + Platform::StreamPrototypeSharedPtr& stream_prototype, callbacks_called& cc, + Platform::StreamSharedPtr& stream) { + { absl::MutexLock l(&engine_lock_); - stream_prototype_ = engine_->streamClient()->newStreamPrototype(); + stream_prototype = engine_->streamClient()->newStreamPrototype(); } - stream_prototype_->setOnHeaders( - [this](Platform::ResponseHeadersSharedPtr headers, bool, envoy_stream_intel intel) { - cc_.on_headers_calls++; - cc_.status = absl::StrCat(headers->httpStatus()); - cc_.on_header_consumed_bytes_from_response = intel.consumed_bytes_from_response; + stream_prototype->setOnHeaders( + [&](Platform::ResponseHeadersSharedPtr headers, bool, envoy_stream_intel intel) { + cc.on_headers_calls++; + cc.status = absl::StrCat(headers->httpStatus()); + cc.on_header_consumed_bytes_from_response = intel.consumed_bytes_from_response; }); - stream_prototype_->setOnData([this](envoy_data c_data, bool) { - cc_.on_data_calls++; + stream_prototype->setOnData([&](envoy_data c_data, bool) { + cc.on_data_calls++; release_envoy_data(c_data); }); - stream_prototype_->setOnComplete( - [this](envoy_stream_intel, envoy_final_stream_intel final_intel) { - memcpy(&last_stream_final_intel_, &final_intel, sizeof(envoy_final_stream_intel)); - if (expect_data_streams_) { - validateStreamIntel(final_intel, expect_dns_, upstream_tls_, cc_.on_complete_calls == 0); - } - cc_.on_complete_received_byte_count = final_intel.received_byte_count; - cc_.on_complete_calls++; - cc_.terminal_callback->setReady(); - }); - stream_prototype_->setOnError( - [this](Platform::EnvoyErrorSharedPtr, envoy_stream_intel, envoy_final_stream_intel) { - cc_.on_error_calls++; - cc_.terminal_callback->setReady(); + stream_prototype->setOnComplete([&](envoy_stream_intel, envoy_final_stream_intel final_intel) { + memcpy(&last_stream_final_intel_, &final_intel, sizeof(envoy_final_stream_intel)); + if (expect_data_streams_) { + validateStreamIntel(final_intel, expect_dns_, upstream_tls_, cc.on_complete_calls == 0); + } + cc.on_complete_received_byte_count = final_intel.received_byte_count; + cc.on_complete_calls++; + cc.terminal_callback->setReady(); + }); + stream_prototype->setOnError( + [&](Platform::EnvoyErrorSharedPtr, envoy_stream_intel, envoy_final_stream_intel) { + cc.on_error_calls++; + cc.terminal_callback->setReady(); }); - stream_prototype_->setOnCancel([this](envoy_stream_intel, envoy_final_stream_intel final_intel) { + stream_prototype->setOnCancel([&](envoy_stream_intel, envoy_final_stream_intel final_intel) { EXPECT_NE(-1, final_intel.stream_start_ms); - cc_.on_cancel_calls++; - cc_.terminal_callback->setReady(); + cc.on_cancel_calls++; + cc.terminal_callback->setReady(); }); - stream_ = (*stream_prototype_).start(explicit_flow_control_); - HttpTestUtility::addDefaultHeaders(default_request_headers_); - default_request_headers_.setHost(fake_upstreams_[0]->localAddress()->asStringView()); + stream = (*stream_prototype).start(explicit_flow_control_); } void BaseClientIntegrationTest::threadRoutine(absl::Notification& engine_running) { diff --git a/mobile/test/common/integration/base_client_integration_test.h b/mobile/test/common/integration/base_client_integration_test.h index b9941051706b..91a9d872b38d 100644 --- a/mobile/test/common/integration/base_client_integration_test.h +++ b/mobile/test/common/integration/base_client_integration_test.h @@ -51,6 +51,9 @@ class BaseClientIntegrationTest : public BaseIntegrationTest { return reinterpret_cast(engine_->engine_); } virtual void initialize() override; + void createNewStream(Platform::StreamPrototypeSharedPtr& stream_prototype, callbacks_called& cc, + Platform::StreamSharedPtr& stream_); + void createEnvoy() override; void threadRoutine(absl::Notification& engine_running); diff --git a/mobile/test/common/integration/client_integration_test.cc b/mobile/test/common/integration/client_integration_test.cc index 8895b50356c7..35c9fe66dc33 100644 --- a/mobile/test/common/integration/client_integration_test.cc +++ b/mobile/test/common/integration/client_integration_test.cc @@ -79,8 +79,7 @@ class ClientIntegrationTest builder_.enablePlatformCertificatesValidation(true); // Create a k-v store for DNS lookup which createEnvoy() will use to point // www.lyft.com -> fake H3 backend. - builder_.addKeyValueStore("reserved.platform_store", test_key_value_store_); - builder_.enableDnsCache(true, /* save_interval_seconds */ 1); + add_fake_dns_ = true; upstream_tls_ = true; add_quic_hints_ = true; } else if (getCodecType() == Http::CodecType::HTTP2) { @@ -89,6 +88,11 @@ class ClientIntegrationTest upstream_tls_ = true; } + if (add_fake_dns_) { + builder_.addKeyValueStore("reserved.platform_store", test_key_value_store_); + builder_.enableDnsCache(true, /* save_interval_seconds */ 1); + } + BaseClientIntegrationTest::initialize(); if (getCodecType() == Http::CodecType::HTTP3) { @@ -114,14 +118,14 @@ class ClientIntegrationTest void createEnvoy() override { // Allow last minute addition of QUIC hints. This is done lazily as it must be done after // upstreams are created. + auto upstream_port = fake_upstreams_[0]->localAddress()->ip()->port(); if (add_quic_hints_) { - auto address = fake_upstreams_[0]->localAddress(); - auto upstream_port = fake_upstreams_[0]->localAddress()->ip()->port(); // With canonical suffix, having a quic hint of foo.lyft.com will make // www.lyft.com being recognized as QUIC ready. builder_.addQuicCanonicalSuffix(".lyft.com"); builder_.addQuicHint("foo.lyft.com", upstream_port); - + } + if (add_fake_dns_) { // Force www.lyft.com to resolve to the fake upstream. It's the only domain // name the certs work for so we want that in the request, but we need to // fake resolution to not result in a request to the real www.lyft.com @@ -172,6 +176,7 @@ class ClientIntegrationTest protected: std::unique_ptr helper_handle_; bool add_quic_hints_ = false; + bool add_fake_dns_ = false; static std::shared_ptr test_key_value_store_; FakeHttpConnectionPtr upstream_connection_; FakeStreamPtr upstream_request_; @@ -582,6 +587,76 @@ TEST_P(ClientIntegrationTest, InvalidDomainFakeResolver) { ASSERT_EQ(cc_.status, "200"); } +TEST_P(ClientIntegrationTest, ReresolveAndDrain) { + builder_.enableDrainPostDnsRefresh(true); + add_fake_dns_ = true; + Network::OverrideAddrInfoDnsResolverFactory factory; + Registry::InjectFactory inject_factory(factory); + Registry::InjectFactory::forceAllowDuplicates(); + + initialize(); + if (version_ != Network::Address::IpVersion::v4) { + return; // This test relies on ipv4 loopback. + } + + auto next_address = Network::Utility::parseInternetAddress( + "127.0.0.3", fake_upstreams_[0]->localAddress()->ip()->port()); + // This will hopefully be miniminally flaky because of low use of 127.0.0.3 + // but may need to be disabled. + createUpstream(next_address, upstreamConfig()); + ASSERT_EQ(fake_upstreams_.size(), 3); + + // Make the "original" upstream and reresolve upstream return different errors. + auto* au = reinterpret_cast(fake_upstreams_[0].get()); + au->setResponseHeaders(std::make_unique( + Http::TestResponseHeaderMapImpl({{":status", "201"}}))); + au = reinterpret_cast(fake_upstreams_[2].get()); + au->setResponseHeaders(std::make_unique( + Http::TestResponseHeaderMapImpl({{":status", "202"}}))); + + // Send a request. The original upstream should be used because of DNS block. + default_request_headers_.setHost( + absl::StrCat("www.lyft.com:", fake_upstreams_[0]->localAddress()->ip()->port())); + stream_->sendHeaders(std::make_unique(default_request_headers_), + true); + terminal_callback_.waitReady(); + ASSERT_EQ(cc_.status, "201"); + // No DNS queries, because of the initial cache load. + EXPECT_EQ(0, getCounterValue("dns_cache.base_dns_cache.dns_query_attempt")); + EXPECT_EQ(1, getCounterValue("dns_cache.base_dns_cache.cache_load")); + + // Reset connectivity state. This should force a resolve but we will not + // unblock it. + { + absl::MutexLock l(&engine_lock_); + engine_->engine()->resetConnectivityState(); + } + + // Make sure the attempt happened. + ASSERT_TRUE(waitForCounterGe("dns_cache.base_dns_cache.dns_query_attempt", 1)); + EXPECT_EQ(0, getCounterValue("dns_cache.base_dns_cache.dns_query_success")); + // The next request should go to the original upstream as there's been no drain. + createNewStream(stream_prototype_, cc_, stream_); + stream_->sendHeaders(std::make_unique(default_request_headers_), + true); + terminal_callback_.waitReady(); + ASSERT_EQ(cc_.status, "201"); + // No DNS query should have finished. + EXPECT_EQ(0, getCounterValue("dns_cache.base_dns_cache.dns_query_success")); + + // Force the lookup to resolve to localhost. + // Unblock the resolution and wait for it to succeed. + Network::TestResolver::unblockResolve("127.0.0.3"); + ASSERT_TRUE(waitForCounterGe("dns_cache.base_dns_cache.dns_query_success", 1)); + + // Do one final request. It should go to the second upstream and return 202 + createNewStream(stream_prototype_, cc_, stream_); + stream_->sendHeaders(std::make_unique(default_request_headers_), + true); + terminal_callback_.waitReady(); + ASSERT_EQ(cc_.status, "202"); +} + TEST_P(ClientIntegrationTest, BasicBeforeResponseHeaders) { initialize(); diff --git a/mobile/test/common/internal_engine_test.cc b/mobile/test/common/internal_engine_test.cc index 198c312ba326..9497a1bcaf08 100644 --- a/mobile/test/common/internal_engine_test.cc +++ b/mobile/test/common/internal_engine_test.cc @@ -148,7 +148,7 @@ TEST_F(InternalEngineTest, AccessEngineAfterInitialization) { absl::Notification getClusterManagerInvoked; // Running engine functions should work because the engine is running - EXPECT_EQ("runtime.load_success: 1\n", engine_->engine_->dumpStats()); + EXPECT_THAT(engine_->engine_->dumpStats(), testing::HasSubstr("runtime.load_success: 1\n")); engine_->terminate(); ASSERT_TRUE(engine_->isTerminated()); diff --git a/test/extensions/filters/http/dynamic_forward_proxy/test_resolver.h b/test/extensions/filters/http/dynamic_forward_proxy/test_resolver.h index 8bde24c404b6..6f34021272c3 100644 --- a/test/extensions/filters/http/dynamic_forward_proxy/test_resolver.h +++ b/test/extensions/filters/http/dynamic_forward_proxy/test_resolver.h @@ -14,6 +14,11 @@ namespace Network { // A test resolver which blocks resolution until unblockResolve is called. class TestResolver : public GetAddrInfoDnsResolver { public: + ~TestResolver() { + absl::MutexLock guard(&mutex_); + blocked_resolutions_.clear(); + } + using GetAddrInfoDnsResolver::GetAddrInfoDnsResolver; static void unblockResolve(absl::optional dns_override = {}) { From 9c9c29670f256d52e62e02a476e9f772cb2221ef Mon Sep 17 00:00:00 2001 From: alyssawilk Date: Thu, 9 May 2024 10:25:28 -0400 Subject: [PATCH 04/20] filesystem: removing an exception (#33968) Risk Level: low Testing: updated tests Docs Changes: n/a Release Notes: n/a envoyproxy/envoy-mobile#176 Signed-off-by: Alyssa Wilk --- .../common/filesystem/kqueue/watcher_impl.cc | 21 ++++++++++++------- .../common/filesystem/kqueue/watcher_impl.h | 4 ++-- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/source/common/filesystem/kqueue/watcher_impl.cc b/source/common/filesystem/kqueue/watcher_impl.cc index 16b7ee59dd41..4b6d43ed8d09 100644 --- a/source/common/filesystem/kqueue/watcher_impl.cc +++ b/source/common/filesystem/kqueue/watcher_impl.cc @@ -34,15 +34,18 @@ WatcherImpl::~WatcherImpl() { absl::Status WatcherImpl::addWatch(absl::string_view path, uint32_t events, Watcher::OnChangedCb cb) { - FileWatchPtr watch = addWatch(path, events, cb, false); - if (watch == nullptr) { + absl::StatusOr watch_or_error = addWatch(path, events, cb, false); + RETURN_IF_STATUS_NOT_OK(watch_or_error); + if (watch_or_error.value() == nullptr) { return absl::InvalidArgumentError(absl::StrCat("invalid watch path ", path)); } return absl::OkStatus(); } -WatcherImpl::FileWatchPtr WatcherImpl::addWatch(absl::string_view path, uint32_t events, - Watcher::OnChangedCb cb, bool path_must_exist) { +absl::StatusOr WatcherImpl::addWatch(absl::string_view path, + uint32_t events, + Watcher::OnChangedCb cb, + bool path_must_exist) { bool watching_dir = false; std::string pathname(path); int watch_fd = open(pathname.c_str(), O_SYMLINK); @@ -52,7 +55,7 @@ WatcherImpl::FileWatchPtr WatcherImpl::addWatch(absl::string_view path, uint32_t } const auto result_or_error = file_system_.splitPathFromFilename(path); - THROW_IF_STATUS_NOT_OK(result_or_error, throw); + RETURN_IF_STATUS_NOT_OK(result_or_error); watch_fd = open(std::string(result_or_error.value().directory_).c_str(), 0); if (watch_fd == -1) { return nullptr; @@ -124,7 +127,9 @@ void WatcherImpl::onKqueueEvent() { if (event.fflags & NOTE_WRITE) { // directory was written -- check if the file we're actually watching appeared - FileWatchPtr new_file = addWatch(file->file_, file->events_, file->callback_, true); + auto file_or_error = addWatch(file->file_, file->events_, file->callback_, true); + THROW_IF_STATUS_NOT_OK(file_or_error, throw); + FileWatchPtr new_file = file_or_error.value(); if (new_file != nullptr) { removeWatch(file); file = new_file; @@ -143,7 +148,9 @@ void WatcherImpl::onKqueueEvent() { if (event.fflags & NOTE_DELETE) { removeWatch(file); - FileWatchPtr new_file = addWatch(file->file_, file->events_, file->callback_, true); + auto file_or_error = addWatch(file->file_, file->events_, file->callback_, true); + THROW_IF_STATUS_NOT_OK(file_or_error, throw); + FileWatchPtr new_file = file_or_error.value(); if (new_file == nullptr) { return; } diff --git a/source/common/filesystem/kqueue/watcher_impl.h b/source/common/filesystem/kqueue/watcher_impl.h index 22e7f9f06dbc..100bfe58035b 100644 --- a/source/common/filesystem/kqueue/watcher_impl.h +++ b/source/common/filesystem/kqueue/watcher_impl.h @@ -43,8 +43,8 @@ class WatcherImpl : public Watcher, Logger::Loggable { using FileWatchPtr = std::shared_ptr; void onKqueueEvent(); - FileWatchPtr addWatch(absl::string_view path, uint32_t events, Watcher::OnChangedCb cb, - bool pathMustExist); + absl::StatusOr addWatch(absl::string_view path, uint32_t events, + Watcher::OnChangedCb cb, bool pathMustExist); void removeWatch(FileWatchPtr& watch); Filesystem::Instance& file_system_; From 4252036d0a6f7223e010da8723d08494ff03eff7 Mon Sep 17 00:00:00 2001 From: Fredy Wijaya Date: Thu, 9 May 2024 09:34:05 -0500 Subject: [PATCH 05/20] mobile: Refactor the stream callback implementation (#34014) This PR refactors the stream callback implementation by removing the envoy_http_callbacks C wrapper and Envoy::Platform::StreamCallbacks. The new implementation uses the built-in C++ Envoy Core data types as much as possible instead of going through the wrapper types. By removing the C wrapper types, we get the benefit of not having to deal with manual memory management. Prior to this PR, the Envoy::Platform::StreamCallbacks was a shared_ptr. By changing the StreamPrototype::start to take a move-only EnvoyStreamCallbacks, we no longer need to use a shared_ptr, which IMO is a better design. The Android and iOS implementations still use some C wrapper types because to getting rid of the C wrapper types completely requires a lot of changes on both Android and iOS implementation, which is best done in a follow up PR. Risk Level: medium Testing: unit & integration tests Docs Changes: n/a Release Notes: n/a Platform Specific Features: mobile Signed-off-by: Fredy Wijaya --- .../examples/cc/fetch_client/fetch_client.cc | 73 ++- .../examples/cc/fetch_client/fetch_client.h | 24 +- mobile/library/cc/BUILD | 4 +- mobile/library/cc/envoy_error.h | 24 - mobile/library/cc/stream_callbacks.cc | 127 ----- mobile/library/cc/stream_callbacks.h | 49 -- mobile/library/cc/stream_prototype.cc | 45 +- mobile/library/cc/stream_prototype.h | 21 +- mobile/library/common/BUILD | 2 + mobile/library/common/bridge/BUILD | 1 + mobile/library/common/bridge/utility.cc | 10 + mobile/library/common/bridge/utility.h | 4 + mobile/library/common/data/utility.cc | 6 + mobile/library/common/data/utility.h | 10 + mobile/library/common/engine_types.h | 103 ++++ mobile/library/common/http/BUILD | 1 + mobile/library/common/http/client.cc | 54 +-- mobile/library/common/http/client.h | 11 +- mobile/library/common/internal_engine.cc | 9 +- mobile/library/common/internal_engine.h | 2 +- mobile/library/common/types/c_types.h | 132 ------ mobile/library/jni/BUILD | 2 + mobile/library/jni/jni_impl.cc | 67 ++- mobile/library/objective-c/BUILD | 2 + .../objective-c/EnvoyHTTPStreamImpl.mm | 58 ++- mobile/test/cc/BUILD | 1 + mobile/test/cc/engine_test.cc | 83 ++-- mobile/test/cc/integration/BUILD | 4 + mobile/test/cc/integration/lifetimes_test.cc | 42 +- mobile/test/cc/integration/send_data_test.cc | 43 +- .../test/cc/integration/send_headers_test.cc | 42 +- .../test/cc/integration/send_trailers_test.cc | 42 +- mobile/test/common/http/client_test.cc | 439 +++++++++--------- .../base_client_integration_test.cc | 34 +- .../base_client_integration_test.h | 3 +- .../integration/client_integration_test.cc | 280 ++++++----- mobile/test/common/internal_engine_test.cc | 79 +--- 37 files changed, 898 insertions(+), 1035 deletions(-) delete mode 100644 mobile/library/cc/envoy_error.h delete mode 100644 mobile/library/cc/stream_callbacks.cc delete mode 100644 mobile/library/cc/stream_callbacks.h diff --git a/mobile/examples/cc/fetch_client/fetch_client.cc b/mobile/examples/cc/fetch_client/fetch_client.cc index 0ecc807e5a88..034c40056704 100644 --- a/mobile/examples/cc/fetch_client/fetch_client.cc +++ b/mobile/examples/cc/fetch_client/fetch_client.cc @@ -9,8 +9,11 @@ #include "source/common/stats/thread_local_store.h" #include "source/exe/platform_impl.h" +#include "library/cc/engine_builder.h" +#include "library/cc/stream.h" #include "library/common/data/utility.h" #include "library/common/http/header_utility.h" +#include "library/common/types/c_types.h" namespace Envoy { @@ -41,8 +44,8 @@ void Fetch::fetch(const std::vector& urls) { } } -void Fetch::sendRequest(const absl::string_view url_string) { - Envoy::Http::Utility::Url url; +void Fetch::sendRequest(absl::string_view url_string) { + Http::Utility::Url url; if (!url.initialize(url_string, /*is_connect_request=*/false)) { std::cerr << "Unable to parse url: '" << url_string << "'\n"; return; @@ -55,45 +58,41 @@ void Fetch::sendRequest(const absl::string_view url_string) { absl::MutexLock lock(&engine_mutex_); stream_prototype = engine_->streamClient()->newStreamPrototype(); } - stream_prototype->setOnHeaders( - [](Platform::ResponseHeadersSharedPtr headers, bool, envoy_stream_intel intel) { - std::cerr << "Received headers on connection: " << intel.connection_id << "\n"; - - const Platform::RawHeaderMap raw_headers = headers->allHeaders(); - for (const auto& [key, header] : raw_headers) { - for (const auto& val : header) { - std::cout << key << ": " << val << "\n"; - } - } - }); - stream_prototype->setOnData([](envoy_data c_data, bool fin) { - std::cout << Data::Utility::copyToString(c_data); - if (fin) { - std::cout << "Received final data\n"; + EnvoyStreamCallbacks stream_callbacks; + stream_callbacks.on_headers_ = [](const Http::ResponseHeaderMap& headers, bool /* end_stream */, + envoy_stream_intel intel) { + std::cerr << "Received headers on connection: " << intel.connection_id << "with headers:\n" + << headers << "\n"; + }; + stream_callbacks.on_data_ = [](const Buffer::Instance& buffer, uint64_t length, bool end_stream, + envoy_stream_intel) { + std::string response_body(length, ' '); + buffer.copyOut(0, length, response_body.data()); + std::cerr << response_body << "\n"; + if (end_stream) { + std::cerr << "Received final data\n"; } - release_envoy_data(c_data); - }); - stream_prototype->setOnComplete( - [&request_finished](envoy_stream_intel, envoy_final_stream_intel final_intel) { - std::cerr << "Request finished after " - << final_intel.stream_end_ms - final_intel.stream_start_ms << "ms\n"; - request_finished.Notify(); - }); - stream_prototype->setOnError([&request_finished](Platform::EnvoyErrorSharedPtr, - envoy_stream_intel, + }; + stream_callbacks.on_complete_ = [&request_finished](envoy_stream_intel, + envoy_final_stream_intel final_intel) { + std::cerr << "Request finished after " + << final_intel.stream_end_ms - final_intel.stream_start_ms << "ms\n"; + request_finished.Notify(); + }; + stream_callbacks.on_error_ = [&request_finished](EnvoyError error, envoy_stream_intel, envoy_final_stream_intel final_intel) { std::cerr << "Request failed after " << final_intel.stream_end_ms - final_intel.stream_start_ms - << "ms\n"; + << "ms with error message: " << error.message << "\n"; request_finished.Notify(); - }); - stream_prototype->setOnCancel( - [&request_finished](envoy_stream_intel, envoy_final_stream_intel final_intel) { - std::cerr << "Request cancelled after " - << final_intel.stream_end_ms - final_intel.stream_start_ms << "ms\n"; - request_finished.Notify(); - }); - - Platform::StreamSharedPtr stream = stream_prototype->start(/*explicit_flow_control=*/false); + }; + stream_callbacks.on_cancel_ = [&request_finished](envoy_stream_intel, + envoy_final_stream_intel final_intel) { + std::cerr << "Request cancelled after " + << final_intel.stream_end_ms - final_intel.stream_start_ms << "ms\n"; + request_finished.Notify(); + }; + Platform::StreamSharedPtr stream = + stream_prototype->start(std::move(stream_callbacks), /*explicit_flow_control=*/false); auto headers = Http::Utility::createRequestHeaderMapPtr(); headers->addCopy(Http::LowerCaseString(":method"), "GET"); diff --git a/mobile/examples/cc/fetch_client/fetch_client.h b/mobile/examples/cc/fetch_client/fetch_client.h index 7e28ace30b2c..46aa9de920d1 100644 --- a/mobile/examples/cc/fetch_client/fetch_client.h +++ b/mobile/examples/cc/fetch_client/fetch_client.h @@ -13,16 +13,12 @@ #include "source/common/stats/allocator_impl.h" #include "source/common/stats/thread_local_store.h" #include "source/exe/platform_impl.h" -#include "source/exe/process_wide.h" #include "absl/base/thread_annotations.h" #include "absl/synchronization/mutex.h" #include "absl/synchronization/notification.h" -#include "library/cc/engine_builder.h" -#include "library/cc/stream.h" #include "library/cc/stream_prototype.h" #include "library/common/http/client.h" -#include "library/common/types/c_types.h" namespace Envoy { @@ -34,16 +30,16 @@ class Fetch { private: void runEngine(absl::Notification& engine_running); - void sendRequest(const absl::string_view url); - - Envoy::Thread::MutexBasicLockable lock_; - Envoy::Logger::Context logging_context_; - Envoy::PlatformImpl platform_impl_; - Envoy::Stats::SymbolTableImpl symbol_table_; - Envoy::Event::RealTimeSystem time_system_; // NO_CHECK_FORMAT(real_time) - Envoy::Stats::AllocatorImpl stats_allocator_; - Envoy::Stats::ThreadLocalStoreImpl store_root_; - Envoy::Random::RandomGeneratorImpl random_generator_; + void sendRequest(absl::string_view url); + + Thread::MutexBasicLockable lock_; + Logger::Context logging_context_; + PlatformImpl platform_impl_; + Stats::SymbolTableImpl symbol_table_; + Event::RealTimeSystem time_system_; // NO_CHECK_FORMAT(real_time) + Stats::AllocatorImpl stats_allocator_; + Stats::ThreadLocalStoreImpl store_root_; + Random::RandomGeneratorImpl random_generator_; envoy::config::bootstrap::v3::Bootstrap bootstrap_; Api::ApiPtr api_; diff --git a/mobile/library/cc/BUILD b/mobile/library/cc/BUILD index 929e80af84c8..163646756e8e 100644 --- a/mobile/library/cc/BUILD +++ b/mobile/library/cc/BUILD @@ -75,7 +75,6 @@ envoy_cc_library( "response_trailers_builder.cc", "retry_policy.cc", "stream.cc", - "stream_callbacks.cc", "stream_client.cc", "stream_prototype.cc", "string_accessor.cc", @@ -84,7 +83,6 @@ envoy_cc_library( "bridge_utility.h", "direct_response_testing.h", "engine.h", - "envoy_error.h", "headers.h", "headers_builder.h", "key_value_store.h", @@ -99,7 +97,6 @@ envoy_cc_library( "response_trailers_builder.h", "retry_policy.h", "stream.h", - "stream_callbacks.h", "stream_client.h", "stream_prototype.h", "string_accessor.h", @@ -109,6 +106,7 @@ envoy_cc_library( repository = "@envoy", visibility = ["//visibility:public"], deps = [ + "//library/common:engine_types_lib", "//library/common:internal_engine_lib_no_stamp", "//library/common/api:c_types", "//library/common/data:utility_lib", diff --git a/mobile/library/cc/envoy_error.h b/mobile/library/cc/envoy_error.h deleted file mode 100644 index c4f109d4251e..000000000000 --- a/mobile/library/cc/envoy_error.h +++ /dev/null @@ -1,24 +0,0 @@ -#pragma once - -#include -#include -#include -#include - -#include "absl/types/optional.h" -#include "library/common/types/c_types.h" - -namespace Envoy { -namespace Platform { - -struct EnvoyError { - envoy_error_code_t error_code; - std::string message; - absl::optional attempt_count; - absl::optional cause; -}; - -using EnvoyErrorSharedPtr = std::shared_ptr; - -} // namespace Platform -} // namespace Envoy diff --git a/mobile/library/cc/stream_callbacks.cc b/mobile/library/cc/stream_callbacks.cc deleted file mode 100644 index 1de7f20a39c9..000000000000 --- a/mobile/library/cc/stream_callbacks.cc +++ /dev/null @@ -1,127 +0,0 @@ -#include "stream_callbacks.h" - -#include "library/cc/bridge_utility.h" -#include "library/cc/response_headers_builder.h" -#include "library/cc/response_trailers_builder.h" -#include "library/common/data/utility.h" - -namespace Envoy { -namespace Platform { - -namespace { - -void c_on_headers(envoy_headers headers, bool end_stream, envoy_stream_intel intel, void* context) { - auto stream_callbacks = *static_cast(context); - if (stream_callbacks->on_headers.has_value()) { - auto raw_headers = envoyHeadersAsRawHeaderMap(headers); - ResponseHeadersBuilder builder; - for (const auto& pair : raw_headers) { - if (pair.first == ":status") { - builder.addHttpStatus(std::stoi(pair.second[0])); - } - builder.set(pair.first, pair.second); - } - auto on_headers = stream_callbacks->on_headers.value(); - on_headers(builder.build(), end_stream, intel); - } else { - release_envoy_headers(headers); - } -} - -void c_on_data(envoy_data data, bool end_stream, envoy_stream_intel, void* context) { - auto stream_callbacks = *static_cast(context); - if (stream_callbacks->on_data.has_value()) { - auto on_data = stream_callbacks->on_data.value(); - on_data(data, end_stream); - } else { - release_envoy_data(data); - } -} - -void c_on_trailers(envoy_headers metadata, envoy_stream_intel intel, void* context) { - auto stream_callbacks = *static_cast(context); - if (stream_callbacks->on_trailers.has_value()) { - auto raw_headers = envoyHeadersAsRawHeaderMap(metadata); - ResponseTrailersBuilder builder; - for (const auto& pair : raw_headers) { - builder.set(pair.first, pair.second); - } - auto on_trailers = stream_callbacks->on_trailers.value(); - on_trailers(builder.build(), intel); - } else { - release_envoy_headers(metadata); - } -} - -void c_on_error(envoy_error raw_error, envoy_stream_intel intel, - envoy_final_stream_intel final_intel, void* context) { - auto stream_callbacks_ptr = static_cast(context); - auto stream_callbacks = *stream_callbacks_ptr; - if (stream_callbacks->on_error.has_value()) { - EnvoyErrorSharedPtr error = std::make_shared(); - error->error_code = raw_error.error_code; - error->message = Data::Utility::copyToString(raw_error.message); - error->attempt_count = absl::optional(raw_error.attempt_count); - auto on_error = stream_callbacks->on_error.value(); - on_error(error, intel, final_intel); - } - release_envoy_error(raw_error); - delete stream_callbacks_ptr; -} - -void c_on_complete(envoy_stream_intel intel, envoy_final_stream_intel final_intel, void* context) { - auto stream_callbacks_ptr = static_cast(context); - auto stream_callbacks = *stream_callbacks_ptr; - if (stream_callbacks->on_complete.has_value()) { - auto on_complete = stream_callbacks->on_complete.value(); - on_complete(intel, final_intel); - } - delete stream_callbacks_ptr; -} - -void c_on_cancel(envoy_stream_intel intel, envoy_final_stream_intel final_intel, void* context) { - auto stream_callbacks_ptr = static_cast(context); - auto stream_callbacks = *stream_callbacks_ptr; - if (stream_callbacks->on_cancel.has_value()) { - auto on_cancel = stream_callbacks->on_cancel.value(); - on_cancel(intel, final_intel); - } - delete stream_callbacks_ptr; -} - -void c_on_send_window_available(envoy_stream_intel intel, void* context) { - auto stream_callbacks_ptr = static_cast(context); - auto stream_callbacks = *stream_callbacks_ptr; - if (stream_callbacks->on_send_window_available.has_value()) { - auto on_send_window_available = stream_callbacks->on_send_window_available.value(); - on_send_window_available(intel); - } -} - -} // namespace - -envoy_http_callbacks StreamCallbacks::asEnvoyHttpCallbacks() { - return envoy_http_callbacks{ - &c_on_headers, - &c_on_data, - nullptr, - &c_on_trailers, - &c_on_error, - &c_on_complete, - &c_on_cancel, - &c_on_send_window_available, - // Each of the function pointers in the returned `envoy_http_callbacks` struct have a - // `void* context` parameter. The value of the `context` field of this struct is passed in as - // the value of that parameter. Because this context passes through JNI, the context field - // can not be a smart pointer and must instead be a standard C-pointer. However, the - // `StreamCallbacks` object is reference counted and so will be destroyed when the final - // shared_ptr is destroyed. So in order to make sure that it lives long enough, the `context` - // field here stores a pointer to a newly created `shared_ptr` which will not go out of scope - // when this method returns. When the `StreamCallbacks` is no longer need (c_on_complete, - // c_on_cancel, c_on_error), this new `shared_ptr` will need to be deleted. - new StreamCallbacksSharedPtr(shared_from_this()), - }; -} - -} // namespace Platform -} // namespace Envoy diff --git a/mobile/library/cc/stream_callbacks.h b/mobile/library/cc/stream_callbacks.h deleted file mode 100644 index 29c0b32f890d..000000000000 --- a/mobile/library/cc/stream_callbacks.h +++ /dev/null @@ -1,49 +0,0 @@ -#pragma once - -#include -#include -#include - -#include "absl/types/optional.h" -#include "library/cc/envoy_error.h" -#include "library/cc/response_headers.h" -#include "library/cc/response_trailers.h" -#include "library/cc/stream.h" -#include "library/common/types/c_types.h" - -namespace Envoy { -namespace Platform { - -class Stream; -using StreamSharedPtr = std::shared_ptr; - -using OnHeadersCallback = std::function; -using OnDataCallback = std::function; -using OnTrailersCallback = - std::function; -using OnErrorCallback = std::function; -using OnCompleteCallback = - std::function; -using OnCancelCallback = - std::function; -using OnSendWindowAvailableCallback = std::function; - -// See library/common/types/c_types.h for what these callbacks should do. -struct StreamCallbacks : public std::enable_shared_from_this { - absl::optional on_headers; - absl::optional on_data; - absl::optional on_trailers; - absl::optional on_error; - absl::optional on_complete; - absl::optional on_cancel; - absl::optional on_send_window_available; - - envoy_http_callbacks asEnvoyHttpCallbacks(); -}; - -using StreamCallbacksSharedPtr = std::shared_ptr; - -} // namespace Platform -} // namespace Envoy diff --git a/mobile/library/cc/stream_prototype.cc b/mobile/library/cc/stream_prototype.cc index 7f7aa5f3d951..4ac6e8357ef6 100644 --- a/mobile/library/cc/stream_prototype.cc +++ b/mobile/library/cc/stream_prototype.cc @@ -5,51 +5,14 @@ namespace Envoy { namespace Platform { -StreamPrototype::StreamPrototype(EngineSharedPtr engine) : engine_(engine) { - callbacks_ = std::make_shared(); -} +StreamPrototype::StreamPrototype(EngineSharedPtr engine) : engine_(engine) {} -StreamSharedPtr StreamPrototype::start(bool explicit_flow_control) { +StreamSharedPtr StreamPrototype::start(EnvoyStreamCallbacks&& stream_callbacks, + bool explicit_flow_control) { auto envoy_stream = engine_->engine_->initStream(); - engine_->engine_->startStream(envoy_stream, callbacks_->asEnvoyHttpCallbacks(), - explicit_flow_control); + engine_->engine_->startStream(envoy_stream, std::move(stream_callbacks), explicit_flow_control); return std::make_shared(engine_->engine_, envoy_stream); } -StreamPrototype& StreamPrototype::setOnHeaders(OnHeadersCallback closure) { - callbacks_->on_headers = closure; - return *this; -} - -StreamPrototype& StreamPrototype::setOnData(OnDataCallback closure) { - callbacks_->on_data = closure; - return *this; -} - -StreamPrototype& StreamPrototype::setOnTrailers(OnTrailersCallback closure) { - callbacks_->on_trailers = closure; - return *this; -} - -StreamPrototype& StreamPrototype::setOnError(OnErrorCallback closure) { - callbacks_->on_error = closure; - return *this; -} - -StreamPrototype& StreamPrototype::setOnComplete(OnCompleteCallback closure) { - callbacks_->on_complete = closure; - return *this; -} - -StreamPrototype& StreamPrototype::setOnCancel(OnCancelCallback closure) { - callbacks_->on_cancel = closure; - return *this; -} - -StreamPrototype& StreamPrototype::setOnSendWindowAvailable(OnSendWindowAvailableCallback closure) { - callbacks_->on_send_window_available = closure; - return *this; -} - } // namespace Platform } // namespace Envoy diff --git a/mobile/library/cc/stream_prototype.h b/mobile/library/cc/stream_prototype.h index f6b551c4fb3a..fca1eb8d91e2 100644 --- a/mobile/library/cc/stream_prototype.h +++ b/mobile/library/cc/stream_prototype.h @@ -3,12 +3,8 @@ #include #include "library/cc/engine.h" -#include "library/cc/envoy_error.h" -#include "library/cc/response_headers.h" -#include "library/cc/response_trailers.h" #include "library/cc/stream.h" -#include "library/cc/stream_callbacks.h" -#include "library/common/types/c_types.h" +#include "library/common/engine_types.h" namespace Envoy { namespace Platform { @@ -18,21 +14,14 @@ using EngineSharedPtr = std::shared_ptr; class StreamPrototype { public: - StreamPrototype(EngineSharedPtr engine); + explicit StreamPrototype(EngineSharedPtr engine); - StreamSharedPtr start(bool explicit_flow_control = false); - - StreamPrototype& setOnHeaders(OnHeadersCallback closure); - StreamPrototype& setOnData(OnDataCallback closure); - StreamPrototype& setOnTrailers(OnTrailersCallback closure); - StreamPrototype& setOnError(OnErrorCallback closure); - StreamPrototype& setOnComplete(OnCompleteCallback closure); - StreamPrototype& setOnCancel(OnCancelCallback closure); - StreamPrototype& setOnSendWindowAvailable(OnSendWindowAvailableCallback closure); + /** Starts the stream. */ + StreamSharedPtr start(EnvoyStreamCallbacks&& stream_callbacks, + bool explicit_flow_control = false); private: EngineSharedPtr engine_; - StreamCallbacksSharedPtr callbacks_; }; using StreamPrototypeSharedPtr = std::shared_ptr; diff --git a/mobile/library/common/BUILD b/mobile/library/common/BUILD index 482272b0490f..5327ebda5765 100644 --- a/mobile/library/common/BUILD +++ b/mobile/library/common/BUILD @@ -86,6 +86,8 @@ envoy_cc_library( "@com_google_absl//absl/container:flat_hash_map", "@com_google_absl//absl/functional:any_invocable", "@com_google_absl//absl/strings", + "@envoy//source/common/buffer:buffer_lib", "@envoy//source/common/common:base_logger_lib", + "@envoy//source/common/http:header_map_lib", ], ) diff --git a/mobile/library/common/bridge/BUILD b/mobile/library/common/bridge/BUILD index 41cdaf96b2df..90c46b6a2e19 100644 --- a/mobile/library/common/bridge/BUILD +++ b/mobile/library/common/bridge/BUILD @@ -11,6 +11,7 @@ envoy_cc_library( repository = "@envoy", visibility = ["//visibility:public"], deps = [ + "//library/common:engine_types_lib", "//library/common/data:utility_lib", "//library/common/types:c_types_lib", "@envoy//envoy/http:codes_interface", diff --git a/mobile/library/common/bridge/utility.cc b/mobile/library/common/bridge/utility.cc index 813342ebd2e6..6769e85dbba3 100644 --- a/mobile/library/common/bridge/utility.cc +++ b/mobile/library/common/bridge/utility.cc @@ -23,6 +23,16 @@ envoy_map makeEnvoyMap(std::initializer_list return makeEnvoyMap>>(map); } +envoy_error toBridgeError(const EnvoyError& error) { + envoy_error error_bridge{}; + error_bridge.message = Data::Utility::copyToBridgeData(error.message); + error_bridge.error_code = error.error_code; + if (error.attempt_count.has_value()) { + error_bridge.attempt_count = *error.attempt_count; + } + return error_bridge; +} + } // namespace Utility } // namespace Bridge } // namespace Envoy diff --git a/mobile/library/common/bridge/utility.h b/mobile/library/common/bridge/utility.h index 7e5f8b350288..dd765904eaef 100644 --- a/mobile/library/common/bridge/utility.h +++ b/mobile/library/common/bridge/utility.h @@ -5,6 +5,7 @@ #include "source/common/http/codes.h" #include "library/common/data/utility.h" +#include "library/common/engine_types.h" #include "library/common/types/c_types.h" namespace Envoy { @@ -34,6 +35,9 @@ template envoy_map makeEnvoyMap(const T& map) { // Function overload that helps resolve makeEnvoyMap({{"key", "value"}}). envoy_map makeEnvoyMap(std::initializer_list> map); +// Converts from `EnvoyError` to `envoy_error`. +envoy_error toBridgeError(const EnvoyError& envoy_error); + } // namespace Utility } // namespace Bridge } // namespace Envoy diff --git a/mobile/library/common/data/utility.cc b/mobile/library/common/data/utility.cc index 6d97dc3d356e..fca6415a34d7 100644 --- a/mobile/library/common/data/utility.cc +++ b/mobile/library/common/data/utility.cc @@ -35,6 +35,12 @@ envoy_data toBridgeData(Buffer::Instance& data, uint32_t max_bytes) { return bridge_data; } +envoy_data toBridgeDataNoDrain(const Buffer::Instance& data, uint32_t max_bytes) { + updateMaxBytes(max_bytes, data); + envoy_data bridge_data = copyToBridgeData(data, max_bytes); + return bridge_data; +} + envoy_data copyToBridgeData(absl::string_view str) { uint8_t* buffer = static_cast(safe_malloc(sizeof(uint8_t) * str.length())); memcpy(buffer, str.data(), str.length()); // NOLINT(safe-memcpy) diff --git a/mobile/library/common/data/utility.h b/mobile/library/common/data/utility.h index 913116be4a42..c65bb58b6cb7 100644 --- a/mobile/library/common/data/utility.h +++ b/mobile/library/common/data/utility.h @@ -23,6 +23,16 @@ Buffer::InstancePtr toInternalData(envoy_data data); */ envoy_data toBridgeData(Buffer::Instance& data, uint32_t max_bytes = 0); +/** + * Transform from Buffer::Instance to envoy_data. The `Buffer::Instance` is not drained after + * converting it to `envoy_data`. + * + * @param data, the Buffer::Instance to transform. + * @param max_bytes, the maximum bytes to transform or 0 to copy all available data. + * @return envoy_data, the bridge transformation of the Buffer::Instance param. + */ +envoy_data toBridgeDataNoDrain(const Buffer::Instance& data, uint32_t max_bytes = 0); + /** * Copy from string to envoy_data. * @param str, the string to copy. diff --git a/mobile/library/common/engine_types.h b/mobile/library/common/engine_types.h index e5e2ee8eaf4a..34c32675af4c 100644 --- a/mobile/library/common/engine_types.h +++ b/mobile/library/common/engine_types.h @@ -2,11 +2,15 @@ #include +#include "envoy/buffer/buffer.h" +#include "envoy/http/header_map.h" + #include "source/common/common/base_logger.h" #include "absl/container/flat_hash_map.h" #include "absl/functional/any_invocable.h" #include "absl/strings/string_view.h" +#include "library/common/types/c_types.h" namespace Envoy { @@ -32,6 +36,105 @@ struct EnvoyEventTracker { absl::AnyInvocable on_exit_ = [] {}; }; +/** The Envoy error passed into `EnvoyStreamCallbacks::on_error_` callback. */ +struct EnvoyError { + envoy_error_code_t error_code; + std::string message; + absl::optional attempt_count = absl::nullopt; +}; + +/** The callbacks for the stream. */ +struct EnvoyStreamCallbacks { + /** + * The callback for headers on a stream. + * + * The callback function passes the following parameters. + * - headers: the headers received. + * - end_stream: to indicate whether the response is headers-only. + * - stream_intel: contains internal stream metrics. + */ + absl::AnyInvocable + on_headers_ = [](const Http::ResponseHeaderMap&, bool, envoy_stream_intel) {}; + + /** + * The callback for data on a stream. + * + * This callback can be invoked multiple times when data is streamed. + * + * The callback function pases the following parameters. + * - buffer: the data received. + * - end_stream: whether the data is the last data frame. + * - stream_intel: contains internal stream metrics. + */ + absl::AnyInvocable + on_data_ = [](const Buffer::Instance&, uint64_t, bool, envoy_stream_intel) {}; + + /** + * The callback for trailers on a stream. + * + * Note that end stream is implied when on_trailers is called. + * + * The callback function pases the following parameters. + * - trailers: the trailers received. + * - stream_intel: contains internal stream metrics. + */ + absl::AnyInvocable on_trailers_ = + [](const Http::ResponseTrailerMap&, envoy_stream_intel) {}; + + /** + * The callback for when a stream bi-directionally completes without error. + * + * This is a TERMINAL callback. Exactly one terminal callback will be called per stream. + * + * The callback function pases the following parameters. + * - stream_intel: contains internal stream metrics. + * - final_stream_intel: contains final internal stream metrics. + */ + absl::AnyInvocable on_complete_ = + [](envoy_stream_intel, envoy_final_stream_intel) {}; + + /** + * The callback for errors with a stream. + * + * This is a TERMINAL callback. Exactly one terminal callback will be called per stream. + * + * The callback function pases the following parameters. + * - error: the error received/caused by the stream. + * - stream_intel: contains internal stream metrics. + * - final_stream_intel: contains final internal stream metrics. + */ + absl::AnyInvocable on_error_ = + [](EnvoyError, envoy_stream_intel, envoy_final_stream_intel) {}; + + /** + * The callback for when the stream is cancelled. + * + * This is a TERMINAL callback. Exactly one terminal callback will be called per stream. + * + * The callback function pases the following parameters. + * - stream_intel: contains internal stream metrics. + * - final_stream_intel: contains final internal stream metrics. + */ + absl::AnyInvocable on_cancel_ = + [](envoy_stream_intel, envoy_final_stream_intel) {}; + + /** + * The callback which notifies when there is buffer available for request body upload. + * + * This is only ever called when the library is in explicit flow control mode. In explicit mode, + * this will be called after the first call to decodeData, when more buffer is available locally + * for request body. It will then be called once per decodeData call to inform the sender when it + * is safe to send more data. + * + * The callback function pases the following parameters. + * - stream_intel: contains internal stream metrics. + */ + absl::AnyInvocable on_send_window_available_ = [](envoy_stream_intel) { + }; +}; + /** Networks classified by the physical link. */ enum class NetworkType : int { // This is the default and includes cases where network characteristics are unknown. diff --git a/mobile/library/common/http/BUILD b/mobile/library/common/http/BUILD index 08eb555bca58..8df8c651b643 100644 --- a/mobile/library/common/http/BUILD +++ b/mobile/library/common/http/BUILD @@ -11,6 +11,7 @@ envoy_cc_library( external_deps = ["abseil_optional"], repository = "@envoy", deps = [ + "//library/common:engine_types_lib", "//library/common/bridge:utility_lib", "//library/common/buffer:bridge_fragment_lib", "//library/common/data:utility_lib", diff --git a/mobile/library/common/http/client.cc b/mobile/library/common/http/client.cc index 1b99cde7a3e2..bc0fc600dcd6 100644 --- a/mobile/library/common/http/client.cc +++ b/mobile/library/common/http/client.cc @@ -31,16 +31,12 @@ constexpr auto SlowCallbackWarningThreshold = std::chrono::seconds(1); } // namespace Client::DirectStreamCallbacks::DirectStreamCallbacks(DirectStream& direct_stream, - envoy_http_callbacks bridge_callbacks, + EnvoyStreamCallbacks&& stream_callbacks, Client& http_client) - : direct_stream_(direct_stream), bridge_callbacks_(bridge_callbacks), http_client_(http_client), - explicit_flow_control_(direct_stream_.explicit_flow_control_) {} + : direct_stream_(direct_stream), stream_callbacks_(std::move(stream_callbacks)), + http_client_(http_client), explicit_flow_control_(direct_stream_.explicit_flow_control_) {} -Client::DirectStreamCallbacks::~DirectStreamCallbacks() { - if (error_.has_value()) { - release_envoy_error(error_.value()); - } -} +Client::DirectStreamCallbacks::~DirectStreamCallbacks() {} void Client::DirectStreamCallbacks::encodeHeaders(const ResponseHeaderMap& headers, bool end_stream) { @@ -80,8 +76,14 @@ void Client::DirectStreamCallbacks::encodeHeaders(const ResponseHeaderMap& heade auto callback_time_ms = std::make_unique( http_client_.stats().on_headers_callback_latency_, http_client_.timeSource()); - bridge_callbacks_.on_headers(Utility::toBridgeHeaders(headers, alpn), end_stream, streamIntel(), - bridge_callbacks_.context); + if (alpn.empty()) { + stream_callbacks_.on_headers_(headers, end_stream, streamIntel()); + } else { + auto new_headers = ResponseHeaderMapImpl::create(); + ResponseHeaderMapImpl::copyFrom(*new_headers, headers); + new_headers->addCopy(LowerCaseString("x-envoy-upstream-alpn"), alpn); + stream_callbacks_.on_headers_(*new_headers, end_stream, streamIntel()); + } callback_time_ms->complete(); auto elapsed = callback_time_ms->elapsed(); @@ -166,8 +168,9 @@ void Client::DirectStreamCallbacks::sendDataToBridge(Buffer::Instance& data, boo // to resumeData. Set before on-data to handle reentrant callbacks. bytes_to_send_ = 0; - bridge_callbacks_.on_data(Data::Utility::toBridgeData(data, bytes_to_send), send_end_stream, - streamIntel(), bridge_callbacks_.context); + stream_callbacks_.on_data_(data, bytes_to_send, send_end_stream, streamIntel()); + // We can drain the data up to bytes_to_send since we are done with it. + data.drain(bytes_to_send); callback_time_ms->complete(); auto elapsed = callback_time_ms->elapsed(); @@ -207,8 +210,7 @@ void Client::DirectStreamCallbacks::sendTrailersToBridge(const ResponseTrailerMa auto callback_time_ms = std::make_unique( http_client_.stats().on_trailers_callback_latency_, http_client_.timeSource()); - bridge_callbacks_.on_trailers(Utility::toBridgeHeaders(trailers), streamIntel(), - bridge_callbacks_.context); + stream_callbacks_.on_trailers_(trailers, streamIntel()); callback_time_ms->complete(); auto elapsed = callback_time_ms->elapsed(); @@ -283,7 +285,7 @@ void Client::DirectStreamCallbacks::onComplete() { auto callback_time_ms = std::make_unique( http_client_.stats().on_complete_callback_latency_, http_client_.timeSource()); - bridge_callbacks_.on_complete(streamIntel(), finalStreamIntel(), bridge_callbacks_.context); + stream_callbacks_.on_complete_(streamIntel(), finalStreamIntel()); callback_time_ms->complete(); auto elapsed = callback_time_ms->elapsed(); @@ -338,8 +340,7 @@ void Client::DirectStreamCallbacks::sendErrorToBridge() { auto callback_time_ms = std::make_unique( http_client_.stats().on_error_callback_latency_, http_client_.timeSource()); - bridge_callbacks_.on_error(error_.value(), streamIntel(), finalStreamIntel(), - bridge_callbacks_.context); + stream_callbacks_.on_error_(error_.value(), streamIntel(), finalStreamIntel()); error_.reset(); callback_time_ms->complete(); @@ -351,7 +352,7 @@ void Client::DirectStreamCallbacks::sendErrorToBridge() { void Client::DirectStreamCallbacks::onSendWindowAvailable() { ENVOY_LOG(debug, "[S{}] remote send window available", direct_stream_.stream_handle_); - bridge_callbacks_.on_send_window_available(streamIntel(), bridge_callbacks_.context); + stream_callbacks_.on_send_window_available_(streamIntel()); } void Client::DirectStreamCallbacks::onCancel() { @@ -367,7 +368,7 @@ void Client::DirectStreamCallbacks::onCancel() { auto callback_time_ms = std::make_unique( http_client_.stats().on_cancel_callback_latency_, http_client_.timeSource()); - bridge_callbacks_.on_cancel(streamIntel(), finalStreamIntel(), bridge_callbacks_.context); + stream_callbacks_.on_cancel_(streamIntel(), finalStreamIntel()); callback_time_ms->complete(); auto elapsed = callback_time_ms->elapsed(); @@ -427,11 +428,11 @@ void Client::DirectStreamCallbacks::latchError() { if (error_.has_value()) { return; // Only latch error once. } - error_ = envoy_error(); + error_ = EnvoyError{}; OptRef request_decoder = direct_stream_.requestDecoder(); if (!request_decoder) { - error_->message = envoy_nodata; + error_->message = ""; return; } const auto& info = request_decoder->streamInfo(); @@ -445,12 +446,7 @@ void Client::DirectStreamCallbacks::latchError() { error_->error_code = ENVOY_STREAM_RESET; } - if (info.responseCodeDetails().has_value()) { - error_->message = Data::Utility::copyToBridgeData(info.responseCodeDetails().value()); - } else { - error_->message = envoy_nodata; - } - + error_->message = info.responseCodeDetails().value_or(""); error_->attempt_count = info.attemptCount().value_or(0); } @@ -515,13 +511,13 @@ void Client::DirectStream::dumpState(std::ostream&, int indent_level) const { ENVOY_LOG(error, "\n{}", ss.str()); } -void Client::startStream(envoy_stream_t new_stream_handle, envoy_http_callbacks bridge_callbacks, +void Client::startStream(envoy_stream_t new_stream_handle, EnvoyStreamCallbacks&& stream_callbacks, bool explicit_flow_control) { ASSERT(dispatcher_.isThreadSafe()); Client::DirectStreamSharedPtr direct_stream{new DirectStream(new_stream_handle, *this)}; direct_stream->explicit_flow_control_ = explicit_flow_control; direct_stream->callbacks_ = - std::make_unique(*direct_stream, bridge_callbacks, *this); + std::make_unique(*direct_stream, std::move(stream_callbacks), *this); // Note: streams created by Envoy Mobile are tagged as is_internally_created. This means that // the Http::ConnectionManager _will not_ sanitize headers when creating a stream. diff --git a/mobile/library/common/http/client.h b/mobile/library/common/http/client.h index ed9d00f57857..ac21de62c700 100644 --- a/mobile/library/common/http/client.h +++ b/mobile/library/common/http/client.h @@ -18,6 +18,7 @@ #include "absl/container/flat_hash_map.h" #include "absl/types/optional.h" +#include "library/common/engine_types.h" #include "library/common/event/provisional_dispatcher.h" #include "library/common/network/synthetic_address_impl.h" #include "library/common/types/c_types.h" @@ -65,10 +66,10 @@ class Client : public Logger::Loggable { * opening a stream may fail. The returned handle is immediately valid for use with this API, but * there is no guarantee it will ever functionally represent an open stream. * @param stream, the stream to start. - * @param bridge_callbacks, wrapper for callbacks for events on this stream. + * @param stream_callbacks, the callbacks for events on this stream. * @param explicit_flow_control, whether the stream will require explicit flow control. */ - void startStream(envoy_stream_t stream, envoy_http_callbacks bridge_callbacks, + void startStream(envoy_stream_t stream, EnvoyStreamCallbacks&& stream_callbacks, bool explicit_flow_control); /** @@ -143,7 +144,7 @@ class Client : public Logger::Loggable { */ class DirectStreamCallbacks : public ResponseEncoder, public Logger::Loggable { public: - DirectStreamCallbacks(DirectStream& direct_stream, envoy_http_callbacks bridge_callbacks, + DirectStreamCallbacks(DirectStream& direct_stream, EnvoyStreamCallbacks&& stream_callbacks, Client& http_client); virtual ~DirectStreamCallbacks(); @@ -198,9 +199,9 @@ class Client : public Logger::Loggable { envoy_final_stream_intel& finalStreamIntel(); DirectStream& direct_stream_; - const envoy_http_callbacks bridge_callbacks_; + EnvoyStreamCallbacks stream_callbacks_; Client& http_client_; - absl::optional error_; + absl::optional error_; bool success_{}; // Buffered response data when in explicit flow control mode. diff --git a/mobile/library/common/internal_engine.cc b/mobile/library/common/internal_engine.cc index 521433d81884..b3a0d668657e 100644 --- a/mobile/library/common/internal_engine.cc +++ b/mobile/library/common/internal_engine.cc @@ -43,11 +43,12 @@ InternalEngine::InternalEngine(std::unique_ptr callbacks, envoy_stream_t InternalEngine::initStream() { return current_stream_handle_++; } envoy_status_t InternalEngine::startStream(envoy_stream_t stream, - envoy_http_callbacks bridge_callbacks, + EnvoyStreamCallbacks&& stream_callbacks, bool explicit_flow_control) { - return dispatcher_->post([&, stream, bridge_callbacks, explicit_flow_control]() { - http_client_->startStream(stream, bridge_callbacks, explicit_flow_control); - }); + return dispatcher_->post( + [&, stream, stream_callbacks = std::move(stream_callbacks), explicit_flow_control]() mutable { + http_client_->startStream(stream, std::move(stream_callbacks), explicit_flow_control); + }); } envoy_status_t InternalEngine::sendHeaders(envoy_stream_t stream, Http::RequestHeaderMapPtr headers, diff --git a/mobile/library/common/internal_engine.h b/mobile/library/common/internal_engine.h index a4885877ec84..6e911ef92816 100644 --- a/mobile/library/common/internal_engine.h +++ b/mobile/library/common/internal_engine.h @@ -62,7 +62,7 @@ class InternalEngine : public Logger::Loggable { // These functions are wrappers around http client functions, which hand off // to http client functions of the same name after doing a dispatcher post // (thread context switch) - envoy_status_t startStream(envoy_stream_t stream, envoy_http_callbacks bridge_callbacks, + envoy_status_t startStream(envoy_stream_t stream, EnvoyStreamCallbacks&& stream_callbacks, bool explicit_flow_control); /** diff --git a/mobile/library/common/types/c_types.h b/mobile/library/common/types/c_types.h index c60ddc6e3496..df1ce2052ba0 100644 --- a/mobile/library/common/types/c_types.h +++ b/mobile/library/common/types/c_types.h @@ -283,135 +283,3 @@ extern const envoy_headers envoy_noheaders; // Convenience constant to pass to function calls with no tags. extern const envoy_stats_tags envoy_stats_notags; - -#ifdef __cplusplus -extern "C" { // function pointers -#endif - -/** - * Callback signature for headers on an HTTP stream. - * - * @param headers, the headers received. - * @param end_stream, whether the response is headers-only. - * @param stream_intel, contains internal stream metrics, context, and other details. - * @param context, contains the necessary state to carry out platform-specific dispatch and - * execution. - */ -typedef void (*envoy_on_headers_f)(envoy_headers headers, bool end_stream, - envoy_stream_intel stream_intel, void* context); - -/** - * Callback signature for data on an HTTP stream. - * - * This callback can be invoked multiple times when data is streamed. - * - * @param data, the data received. - * @param end_stream, whether the data is the last data frame. - * @param stream_intel, contains internal stream metrics, context, and other details. - * @param context, contains the necessary state to carry out platform-specific dispatch and - * execution. - */ -typedef void (*envoy_on_data_f)(envoy_data data, bool end_stream, envoy_stream_intel stream_intel, - void* context); - -/** - * Callback signature for metadata on an HTTP stream. - * - * Note that metadata frames are prohibited from ending a stream. - * - * @param metadata, the metadata received. - * @param stream_intel, contains internal stream metrics, context, and other details. - * @param context, contains the necessary state to carry out platform-specific dispatch and - * execution. - * @return void*, return context (may be unused). - */ -typedef void (*envoy_on_metadata_f)(envoy_headers metadata, envoy_stream_intel stream_intel, - void* context); - -/** - * Callback signature for trailers on an HTTP stream. - * - * Note that end stream is implied when on_trailers is called. - * - * @param trailers, the trailers received. - * @param stream_intel, contains internal stream metrics, context, and other details. - * @param context, contains the necessary state to carry out platform-specific dispatch and - * execution. - */ -typedef void (*envoy_on_trailers_f)(envoy_headers trailers, envoy_stream_intel stream_intel, - void* context); - -/** - * Callback signature for errors with an HTTP stream. - * - * This is a TERMINAL callback. Exactly one terminal callback will be called per stream. - * - * @param envoy_error, the error received/caused by the async HTTP stream. - * @param stream_intel, contains internal stream metrics, context, and other details. - * @param final_stream_intel, contains final internal stream metrics, context, and other details. - * @param context, contains the necessary state to carry out platform-specific dispatch and - * execution. - */ -typedef void (*envoy_on_error_f)(envoy_error error, envoy_stream_intel stream_intel, - envoy_final_stream_intel final_stream_intel, void* context); - -/** - * Callback signature for when an HTTP stream bi-directionally completes without error. - * - * This is a TERMINAL callback. Exactly one terminal callback will be called per stream. - * - * @param stream_intel, contains internal stream metrics, context, and other details. - * @param final_stream_intel, contains final internal stream metrics, context, and other details. - * @param context, contains the necessary state to carry out platform-specific dispatch and - * execution. - */ -typedef void (*envoy_on_complete_f)(envoy_stream_intel stream_intel, - envoy_final_stream_intel final_stream_intel, void* context); - -/** - * Callback signature for when an HTTP stream is cancelled. - * - * This is a TERMINAL callback. Exactly one terminal callback will be called per stream. - * - * @param stream_intel, contains internal stream metrics, context, and other details. - * @param final_stream_intel, contains final internal stream metrics, context, and other details. - * @param context, contains the necessary state to carry out platform-specific dispatch and - * execution. - */ -typedef void (*envoy_on_cancel_f)(envoy_stream_intel stream_intel, - envoy_final_stream_intel final_stream_intel, void* context); - -/** - * Callback signature which notify when there is buffer available for request - * body upload. - * - * This is only ever called when the library is in explicit flow control mode. - * In explicit mode, this will be called after the first call to decodeData, when - * more buffer is available locally for request body. It will then be called once per - * decodeData call to inform the sender when it is safe to send more data. - * - * @param stream_intel, contains internal stream metrics, context, and other details. - * @param context, contains the necessary state to carry out platform-specific dispatch and - * execution. - */ -typedef void (*envoy_on_send_window_available_f)(envoy_stream_intel stream_intel, void* context); - -#ifdef __cplusplus -} // function pointers -#endif - -/** - * Interface to handle HTTP callbacks. - */ -typedef struct { - envoy_on_headers_f on_headers; - envoy_on_data_f on_data; - envoy_on_metadata_f on_metadata; - envoy_on_trailers_f on_trailers; - envoy_on_error_f on_error; - envoy_on_complete_f on_complete; - envoy_on_cancel_f on_cancel; - envoy_on_send_window_available_f on_send_window_available; - // Context passed through to callbacks to provide dispatch and execution state. - void* context; -} envoy_http_callbacks; diff --git a/mobile/library/jni/BUILD b/mobile/library/jni/BUILD index d38f9c43bb2f..353a136d1ef3 100644 --- a/mobile/library/jni/BUILD +++ b/mobile/library/jni/BUILD @@ -80,6 +80,8 @@ envoy_cc_library( "//library/cc:engine_builder_lib", "//library/common:internal_engine_lib", "//library/common/api:c_types", + "//library/common/bridge:utility_lib", + "//library/common/data:utility_lib", "//library/common/extensions/cert_validator/platform_bridge:c_types_lib", "//library/common/extensions/key_value/platform:config", "//library/common/types:managed_types_lib", diff --git a/mobile/library/jni/jni_impl.cc b/mobile/library/jni/jni_impl.cc index ca7c6fd0a4b5..fcc6060afb3f 100644 --- a/mobile/library/jni/jni_impl.cc +++ b/mobile/library/jni/jni_impl.cc @@ -1,11 +1,11 @@ #include #include -#include #include "source/common/protobuf/protobuf.h" #include "library/cc/engine_builder.h" #include "library/common/api/c_types.h" +#include "library/common/bridge/utility.h" #include "library/common/data/utility.h" #include "library/common/extensions/filters/http/platform_bridge/c_types.h" #include "library/common/extensions/key_value/platform/c_types.h" @@ -403,9 +403,6 @@ static envoy_filter_data_status jvm_http_filter_on_response_data(envoy_data data /*pending_headers*/ pending_headers}; } -static void jvm_on_metadata(envoy_headers /* metadata */, envoy_stream_intel /*stream_intel*/, - void* /*context*/) {} - static Envoy::JNI::LocalRefUniquePtr jvm_on_trailers(const char* method, envoy_headers trailers, envoy_stream_intel stream_intel, @@ -827,24 +824,58 @@ extern "C" JNIEXPORT jlong JNICALL Java_io_envoyproxy_envoymobile_engine_JniLibr } extern "C" JNIEXPORT jint JNICALL Java_io_envoyproxy_envoymobile_engine_JniLibrary_startStream( - JNIEnv* env, jclass, jlong engine_handle, jlong stream_handle, jobject j_context, + JNIEnv* env, jclass, jlong engine_handle, jlong stream_handle, jobject java_stream_callbacks, jboolean explicit_flow_control) { - // TODO: To be truly safe we may need stronger guarantees of operation ordering on this ref. - jobject retained_context = env->NewGlobalRef(j_context); - envoy_http_callbacks native_callbacks = {jvm_on_response_headers, - jvm_on_response_data, - jvm_on_metadata, - jvm_on_response_trailers, - jvm_on_error, - jvm_on_complete, - jvm_on_cancel, - jvm_on_send_window_available, - retained_context}; + Envoy::JNI::JniHelper jni_helper(env); + auto java_stream_callbacks_global_ref = jni_helper.newGlobalRef(java_stream_callbacks).release(); auto engine = reinterpret_cast(engine_handle); + Envoy::EnvoyStreamCallbacks stream_callbacks; + // TODO(fredyw): Rewrite the whole implementation to not use the bridge data structures. + stream_callbacks.on_headers_ = + [java_stream_callbacks_global_ref](const Envoy::Http::ResponseHeaderMap& headers, + bool end_stream, envoy_stream_intel stream_intel) { + envoy_headers bridge_headers = Envoy::Http::Utility::toBridgeHeaders(headers); + jvm_on_response_headers(bridge_headers, end_stream, stream_intel, + java_stream_callbacks_global_ref); + }; + stream_callbacks.on_data_ = [java_stream_callbacks_global_ref]( + const Envoy::Buffer::Instance& buffer, uint64_t length, + bool end_stream, envoy_stream_intel stream_intel) { + envoy_data bridge_data = Envoy::Data::Utility::toBridgeDataNoDrain(buffer, length); + jvm_on_response_data(bridge_data, end_stream, stream_intel, java_stream_callbacks_global_ref); + }; + stream_callbacks.on_trailers_ = + [java_stream_callbacks_global_ref](const Envoy::Http::ResponseTrailerMap& trailers, + envoy_stream_intel stream_intel) { + envoy_headers bridge_trailers = Envoy::Http::Utility::toBridgeHeaders(trailers); + jvm_on_response_trailers(bridge_trailers, stream_intel, java_stream_callbacks_global_ref); + }; + stream_callbacks.on_complete_ = + [java_stream_callbacks_global_ref](envoy_stream_intel stream_intel, + envoy_final_stream_intel final_stream_intel) { + jvm_on_complete(stream_intel, final_stream_intel, java_stream_callbacks_global_ref); + }; + stream_callbacks.on_error_ = [java_stream_callbacks_global_ref]( + Envoy::EnvoyError error, envoy_stream_intel stream_intel, + envoy_final_stream_intel final_stream_intel) { + envoy_error bridge_error = Envoy::Bridge::Utility::toBridgeError(error); + jvm_on_error(bridge_error, stream_intel, final_stream_intel, java_stream_callbacks_global_ref); + }; + stream_callbacks.on_cancel_ = + [java_stream_callbacks_global_ref](envoy_stream_intel stream_intel, + envoy_final_stream_intel final_stream_intel) { + jvm_on_cancel(stream_intel, final_stream_intel, java_stream_callbacks_global_ref); + }; + stream_callbacks.on_send_window_available_ = + [java_stream_callbacks_global_ref](envoy_stream_intel stream_intel) { + jvm_on_send_window_available(stream_intel, java_stream_callbacks_global_ref); + }; + envoy_status_t result = engine->startStream(static_cast(stream_handle), - native_callbacks, explicit_flow_control); + std::move(stream_callbacks), explicit_flow_control); if (result != ENVOY_SUCCESS) { - env->DeleteGlobalRef(retained_context); // No callbacks are fired and we need to release + env->DeleteGlobalRef( + java_stream_callbacks_global_ref); // No callbacks are fired and we need to release } return result; } diff --git a/mobile/library/objective-c/BUILD b/mobile/library/objective-c/BUILD index 33afcc52f244..28d35394514e 100644 --- a/mobile/library/objective-c/BUILD +++ b/mobile/library/objective-c/BUILD @@ -59,6 +59,8 @@ envoy_objc_library( "//library/cc:engine_builder_lib", "//library/common:internal_engine_lib", "//library/common/api:c_types", + "//library/common/bridge:utility_lib", + "//library/common/data:utility_lib", "//library/common/http:header_utility_lib", "//library/common/network:apple_platform_cert_verifier", "//library/common/network:apple_proxy_resolution_lib", diff --git a/mobile/library/objective-c/EnvoyHTTPStreamImpl.mm b/mobile/library/objective-c/EnvoyHTTPStreamImpl.mm index 4274863a3772..c9146f31b9d7 100644 --- a/mobile/library/objective-c/EnvoyHTTPStreamImpl.mm +++ b/mobile/library/objective-c/EnvoyHTTPStreamImpl.mm @@ -3,6 +3,9 @@ #include "source/common/buffer/buffer_impl.h" +#include "library/common/bridge/utility.h" +#include "library/common/data/utility.h" + #import "library/common/types/c_types.h" #import "library/common/internal_engine.h" #include "library/common/http/header_utility.h" @@ -46,9 +49,6 @@ static void ios_on_data(envoy_data data, bool end_stream, envoy_stream_intel str }); } -static void ios_on_metadata(envoy_headers metadata, envoy_stream_intel stream_intel, - void *context) {} - static void ios_on_trailers(envoy_headers trailers, envoy_stream_intel stream_intel, void *context) { ios_context *c = (ios_context *)context; @@ -130,7 +130,7 @@ static void ios_on_error(envoy_error error, envoy_stream_intel stream_intel, @implementation EnvoyHTTPStreamImpl { EnvoyHTTPStreamImpl *_strongSelf; EnvoyHTTPCallbacks *_platformCallbacks; - envoy_http_callbacks _nativeCallbacks; + ios_context *_context; envoy_stream_t _streamHandle; Envoy::InternalEngine *_engine; } @@ -154,13 +154,7 @@ - (instancetype)initWithHandle:(envoy_stream_t)handle context->stream = self; context->closed = (atomic_bool *)safe_malloc(sizeof(atomic_bool)); atomic_store(context->closed, NO); - - // Create native callbacks - envoy_http_callbacks native_callbacks = { - ios_on_headers, ios_on_data, ios_on_metadata, ios_on_trailers, - ios_on_error, ios_on_complete, ios_on_cancel, ios_on_send_window_available, - context}; - _nativeCallbacks = native_callbacks; + _context = context; _engine = reinterpret_cast(engine); @@ -168,15 +162,49 @@ - (instancetype)initWithHandle:(envoy_stream_t)handle // start_stream could result in a reset that would release the native ref. _strongSelf = self; _streamHandle = _engine->initStream(); - _engine->startStream(_streamHandle, native_callbacks, explicitFlowControl); + + // Create native callbacks + Envoy::EnvoyStreamCallbacks streamCallbacks; + streamCallbacks.on_headers_ = [context](const Envoy::Http::ResponseHeaderMap &headers, + bool end_stream, envoy_stream_intel stream_intel) { + envoy_headers bridge_headers = Envoy::Http::Utility::toBridgeHeaders(headers); + ios_on_headers(bridge_headers, end_stream, stream_intel, context); + }; + streamCallbacks.on_data_ = [context](const Envoy::Buffer::Instance &buffer, uint64_t length, + bool end_stream, envoy_stream_intel stream_intel) { + envoy_data bridge_data = Envoy::Data::Utility::toBridgeDataNoDrain(buffer, length); + ios_on_data(bridge_data, end_stream, stream_intel, context); + }; + streamCallbacks.on_trailers_ = [context](const Envoy::Http::ResponseTrailerMap &trailers, + envoy_stream_intel stream_intel) { + envoy_headers bridge_trailers = Envoy::Http::Utility::toBridgeHeaders(trailers); + ios_on_trailers(bridge_trailers, stream_intel, context); + }; + streamCallbacks.on_complete_ = [context](envoy_stream_intel stream_intel, + envoy_final_stream_intel final_stream_intel) { + ios_on_complete(stream_intel, final_stream_intel, context); + }; + streamCallbacks.on_error_ = [context](Envoy::EnvoyError error, envoy_stream_intel stream_intel, + envoy_final_stream_intel final_stream_intel) { + envoy_error bridge_error = Envoy::Bridge::Utility::toBridgeError(error); + ios_on_error(bridge_error, stream_intel, final_stream_intel, context); + }; + streamCallbacks.on_cancel_ = [context](envoy_stream_intel stream_intel, + envoy_final_stream_intel final_stream_intel) { + ios_on_cancel(stream_intel, final_stream_intel, context); + }; + streamCallbacks.on_send_window_available_ = [context](envoy_stream_intel stream_intel) { + ios_on_send_window_available(stream_intel, context); + }; + + _engine->startStream(_streamHandle, std::move(streamCallbacks), explicitFlowControl); return self; } - (void)dealloc { - ios_context *context = (ios_context *)_nativeCallbacks.context; - free(context->closed); - free(context); + free(_context->closed); + free(_context); } - (void)sendHeaders:(EnvoyHeaders *)headers close:(BOOL)close { diff --git a/mobile/test/cc/BUILD b/mobile/test/cc/BUILD index 09f52739a7c4..b408325f999e 100644 --- a/mobile/test/cc/BUILD +++ b/mobile/test/cc/BUILD @@ -10,6 +10,7 @@ envoy_cc_test( repository = "@envoy", deps = [ "//library/cc:engine_builder_lib", + "//library/common:engine_types_lib", "//test/common/integration:engine_with_test_server", "//test/common/integration:test_server_lib", "@envoy//source/common/common:assert_lib", diff --git a/mobile/test/cc/engine_test.cc b/mobile/test/cc/engine_test.cc index 0a67d11dedff..3bd96e8bc9f1 100644 --- a/mobile/test/cc/engine_test.cc +++ b/mobile/test/cc/engine_test.cc @@ -6,6 +6,7 @@ #include "absl/synchronization/notification.h" #include "gtest/gtest.h" #include "library/cc/engine_builder.h" +#include "library/common/engine_types.h" #include "library/common/http/header_utility.h" namespace Envoy { @@ -26,29 +27,28 @@ TEST(EngineTest, SetLogger) { EngineWithTestServer engine_with_test_server(engine_builder, TestServerType::HTTP2_WITH_TLS); engine_running.WaitForNotification(); - int actual_status_code = 0; + std::string actual_status_code; bool actual_end_stream = false; absl::Notification stream_complete; + EnvoyStreamCallbacks stream_callbacks; + stream_callbacks.on_headers_ = [&](const Http::ResponseHeaderMap& headers, bool end_stream, + envoy_stream_intel) { + actual_status_code = headers.getStatusValue(); + actual_end_stream = end_stream; + }; + stream_callbacks.on_data_ = [&](const Buffer::Instance&, uint64_t /* length */, bool end_stream, + envoy_stream_intel) { actual_end_stream = end_stream; }; + stream_callbacks.on_complete_ = [&](envoy_stream_intel, envoy_final_stream_intel) { + stream_complete.Notify(); + }; + stream_callbacks.on_error_ = [&](EnvoyError, envoy_stream_intel, envoy_final_stream_intel) { + stream_complete.Notify(); + }; + stream_callbacks.on_cancel_ = [&](envoy_stream_intel, envoy_final_stream_intel) { + stream_complete.Notify(); + }; auto stream_prototype = engine_with_test_server.engine()->streamClient()->newStreamPrototype(); - auto stream = (*stream_prototype) - .setOnHeaders([&](Platform::ResponseHeadersSharedPtr headers, bool end_stream, - envoy_stream_intel) { - actual_status_code = headers->httpStatus(); - actual_end_stream = end_stream; - }) - .setOnData([&](envoy_data data, bool end_stream) { - actual_end_stream = end_stream; - release_envoy_data(data); - }) - .setOnComplete([&](envoy_stream_intel, envoy_final_stream_intel) { - stream_complete.Notify(); - }) - .setOnError([&](Platform::EnvoyErrorSharedPtr, envoy_stream_intel, - envoy_final_stream_intel) { stream_complete.Notify(); }) - .setOnCancel([&](envoy_stream_intel, envoy_final_stream_intel) { - stream_complete.Notify(); - }) - .start(); + Platform::StreamSharedPtr stream = stream_prototype->start(std::move(stream_callbacks)); auto headers = Http::Utility::createRequestHeaderMapPtr(); headers->addCopy(Http::LowerCaseString(":method"), "GET"); @@ -59,7 +59,7 @@ TEST(EngineTest, SetLogger) { stream->sendHeaders(std::move(headers), true); stream_complete.WaitForNotification(); - EXPECT_EQ(actual_status_code, 200); + EXPECT_EQ(actual_status_code, "200"); EXPECT_TRUE(actual_end_stream); EXPECT_TRUE(logging_was_called.load()); } @@ -75,29 +75,28 @@ TEST(EngineTest, SetEngineCallbacks) { EngineWithTestServer engine_with_test_server(engine_builder, TestServerType::HTTP2_WITH_TLS); engine_running.WaitForNotification(); - int actual_status_code = 0; + std::string actual_status_code; bool actual_end_stream = false; absl::Notification stream_complete; + EnvoyStreamCallbacks stream_callbacks; + stream_callbacks.on_headers_ = [&](const Http::ResponseHeaderMap& headers, bool end_stream, + envoy_stream_intel) { + actual_status_code = headers.getStatusValue(); + actual_end_stream = end_stream; + }; + stream_callbacks.on_data_ = [&](const Buffer::Instance&, uint64_t /* length */, bool end_stream, + envoy_stream_intel) { actual_end_stream = end_stream; }; + stream_callbacks.on_complete_ = [&](envoy_stream_intel, envoy_final_stream_intel) { + stream_complete.Notify(); + }; + stream_callbacks.on_error_ = [&](EnvoyError, envoy_stream_intel, envoy_final_stream_intel) { + stream_complete.Notify(); + }; + stream_callbacks.on_cancel_ = [&](envoy_stream_intel, envoy_final_stream_intel) { + stream_complete.Notify(); + }; auto stream_prototype = engine_with_test_server.engine()->streamClient()->newStreamPrototype(); - auto stream = (*stream_prototype) - .setOnHeaders([&](Platform::ResponseHeadersSharedPtr headers, bool end_stream, - envoy_stream_intel) { - actual_status_code = headers->httpStatus(); - actual_end_stream = end_stream; - }) - .setOnData([&](envoy_data data, bool end_stream) { - actual_end_stream = end_stream; - release_envoy_data(data); - }) - .setOnComplete([&](envoy_stream_intel, envoy_final_stream_intel) { - stream_complete.Notify(); - }) - .setOnError([&](Platform::EnvoyErrorSharedPtr, envoy_stream_intel, - envoy_final_stream_intel) { stream_complete.Notify(); }) - .setOnCancel([&](envoy_stream_intel, envoy_final_stream_intel) { - stream_complete.Notify(); - }) - .start(); + Platform::StreamSharedPtr stream = stream_prototype->start(std::move(stream_callbacks)); auto headers = Http::Utility::createRequestHeaderMapPtr(); headers->addCopy(Http::LowerCaseString(":method"), "GET"); @@ -108,7 +107,7 @@ TEST(EngineTest, SetEngineCallbacks) { stream->sendHeaders(std::move(headers), true); stream_complete.WaitForNotification(); - EXPECT_EQ(actual_status_code, 200); + EXPECT_EQ(actual_status_code, "200"); EXPECT_TRUE(actual_end_stream); } diff --git a/mobile/test/cc/integration/BUILD b/mobile/test/cc/integration/BUILD index f8a2f25539aa..8c7e2b16c4da 100644 --- a/mobile/test/cc/integration/BUILD +++ b/mobile/test/cc/integration/BUILD @@ -10,6 +10,7 @@ envoy_cc_test( repository = "@envoy", deps = [ "//library/cc:engine_builder_lib", + "//library/common:engine_types_lib", "//library/common/http:header_utility_lib", "//test/common/integration:engine_with_test_server", "//test/common/integration:test_server_lib", @@ -23,6 +24,7 @@ envoy_cc_test( repository = "@envoy", deps = [ "//library/cc:engine_builder_lib", + "//library/common:engine_types_lib", "//library/common/http:header_utility_lib", "//test/common/integration:engine_with_test_server", "//test/common/integration:test_server_lib", @@ -36,6 +38,7 @@ envoy_cc_test( repository = "@envoy", deps = [ "//library/cc:engine_builder_lib", + "//library/common:engine_types_lib", "//library/common/http:header_utility_lib", "//test/common/integration:engine_with_test_server", "//test/common/integration:test_server_lib", @@ -49,6 +52,7 @@ envoy_cc_test( repository = "@envoy", deps = [ "//library/cc:engine_builder_lib", + "//library/common:engine_types_lib", "//library/common/http:header_utility_lib", "//test/common/integration:engine_with_test_server", "//test/common/integration:test_server_lib", diff --git a/mobile/test/cc/integration/lifetimes_test.cc b/mobile/test/cc/integration/lifetimes_test.cc index e2c226ae624f..6e3111aacacc 100644 --- a/mobile/test/cc/integration/lifetimes_test.cc +++ b/mobile/test/cc/integration/lifetimes_test.cc @@ -4,8 +4,8 @@ #include "absl/synchronization/notification.h" #include "gtest/gtest.h" #include "library/cc/engine_builder.h" -#include "library/cc/envoy_error.h" #include "library/cc/request_headers.h" +#include "library/common/engine_types.h" #include "library/common/http/header_utility.h" namespace Envoy { @@ -20,26 +20,28 @@ void sendRequest() { EngineWithTestServer engine_with_test_server(engine_builder, TestServerType::HTTP2_WITH_TLS); engine_running.WaitForNotification(); - absl::Notification stream_complete; - int actual_status_code; + std::string actual_status_code; bool actual_end_stream; + absl::Notification stream_complete; + EnvoyStreamCallbacks stream_callbacks; + stream_callbacks.on_headers_ = [&](const Http::ResponseHeaderMap& headers, bool end_stream, + envoy_stream_intel) { + actual_status_code = headers.getStatusValue(); + actual_end_stream = end_stream; + }; + stream_callbacks.on_data_ = [&](const Buffer::Instance&, uint64_t /* length */, bool end_stream, + envoy_stream_intel) { actual_end_stream = end_stream; }; + stream_callbacks.on_complete_ = [&](envoy_stream_intel, envoy_final_stream_intel) { + stream_complete.Notify(); + }; + stream_callbacks.on_error_ = [&](EnvoyError, envoy_stream_intel, envoy_final_stream_intel) { + stream_complete.Notify(); + }; + stream_callbacks.on_cancel_ = [&](envoy_stream_intel, envoy_final_stream_intel) { + stream_complete.Notify(); + }; auto stream_prototype = engine_with_test_server.engine()->streamClient()->newStreamPrototype(); - auto stream = (*stream_prototype) - .setOnHeaders([&](Platform::ResponseHeadersSharedPtr headers, bool end_stream, - envoy_stream_intel) { - actual_status_code = headers->httpStatus(); - actual_end_stream = end_stream; - }) - .setOnData([&](envoy_data, bool end_stream) { actual_end_stream = end_stream; }) - .setOnComplete([&](envoy_stream_intel, envoy_final_stream_intel) { - stream_complete.Notify(); - }) - .setOnError([&](Platform::EnvoyErrorSharedPtr, envoy_stream_intel, - envoy_final_stream_intel) { stream_complete.Notify(); }) - .setOnCancel([&](envoy_stream_intel, envoy_final_stream_intel) { - stream_complete.Notify(); - }) - .start(); + Platform::StreamSharedPtr stream = stream_prototype->start(std::move(stream_callbacks)); auto headers = Http::Utility::createRequestHeaderMapPtr(); headers->addCopy(Http::LowerCaseString(":method"), "GET"); @@ -50,7 +52,7 @@ void sendRequest() { stream->sendHeaders(std::move(headers), true); stream_complete.WaitForNotification(); - EXPECT_EQ(actual_status_code, 200); + EXPECT_EQ(actual_status_code, "200"); EXPECT_TRUE(actual_end_stream); } diff --git a/mobile/test/cc/integration/send_data_test.cc b/mobile/test/cc/integration/send_data_test.cc index bb86806db1ec..13a013e6138e 100644 --- a/mobile/test/cc/integration/send_data_test.cc +++ b/mobile/test/cc/integration/send_data_test.cc @@ -1,11 +1,10 @@ #include "test/common/integration/engine_with_test_server.h" #include "test/common/integration/test_server.h" -#include "absl/strings/str_format.h" #include "absl/synchronization/notification.h" #include "gtest/gtest.h" #include "library/cc/engine_builder.h" -#include "library/cc/envoy_error.h" +#include "library/common/engine_types.h" #include "library/common/http/header_utility.h" namespace Envoy { @@ -34,28 +33,28 @@ TEST(SendDataTest, Success) { EngineWithTestServer engine_with_test_server(engine_builder, TestServerType::HTTP2_WITH_TLS); engine_running.WaitForNotification(); - int actual_status_code; + std::string actual_status_code; bool actual_end_stream; absl::Notification stream_complete; + EnvoyStreamCallbacks stream_callbacks; + stream_callbacks.on_headers_ = [&](const Http::ResponseHeaderMap& headers, bool end_stream, + envoy_stream_intel) { + actual_status_code = headers.getStatusValue(); + actual_end_stream = end_stream; + }; + stream_callbacks.on_data_ = [&](const Buffer::Instance&, uint64_t /* length */, bool end_stream, + envoy_stream_intel) { actual_end_stream = end_stream; }; + stream_callbacks.on_complete_ = [&](envoy_stream_intel, envoy_final_stream_intel) { + stream_complete.Notify(); + }; + stream_callbacks.on_error_ = [&](EnvoyError, envoy_stream_intel, envoy_final_stream_intel) { + stream_complete.Notify(); + }; + stream_callbacks.on_cancel_ = [&](envoy_stream_intel, envoy_final_stream_intel) { + stream_complete.Notify(); + }; auto stream_prototype = engine_with_test_server.engine()->streamClient()->newStreamPrototype(); - Platform::StreamSharedPtr stream = - (*stream_prototype) - .setOnHeaders( - [&](Platform::ResponseHeadersSharedPtr headers, bool end_stream, envoy_stream_intel) { - actual_status_code = headers->httpStatus(); - actual_end_stream = end_stream; - }) - .setOnData([&](envoy_data data, bool end_stream) { - actual_end_stream = end_stream; - data.release(data.context); - }) - .setOnComplete( - [&](envoy_stream_intel, envoy_final_stream_intel) { stream_complete.Notify(); }) - .setOnError([&](Platform::EnvoyErrorSharedPtr, envoy_stream_intel, - envoy_final_stream_intel) { stream_complete.Notify(); }) - .setOnCancel( - [&](envoy_stream_intel, envoy_final_stream_intel) { stream_complete.Notify(); }) - .start(); + Platform::StreamSharedPtr stream = stream_prototype->start(std::move(stream_callbacks)); auto headers = Http::Utility::createRequestHeaderMapPtr(); headers->addCopy(Http::LowerCaseString(":method"), "GET"); @@ -68,7 +67,7 @@ TEST(SendDataTest, Success) { stream->close(std::make_unique("request body")); stream_complete.WaitForNotification(); - EXPECT_EQ(actual_status_code, 200); + EXPECT_EQ(actual_status_code, "200"); EXPECT_TRUE(actual_end_stream); } diff --git a/mobile/test/cc/integration/send_headers_test.cc b/mobile/test/cc/integration/send_headers_test.cc index 0f2941e29af9..2b6f017c0b8a 100644 --- a/mobile/test/cc/integration/send_headers_test.cc +++ b/mobile/test/cc/integration/send_headers_test.cc @@ -4,7 +4,7 @@ #include "absl/synchronization/notification.h" #include "gtest/gtest.h" #include "library/cc/engine_builder.h" -#include "library/cc/envoy_error.h" +#include "library/common/engine_types.h" #include "library/common/http/header_utility.h" namespace Envoy { @@ -33,28 +33,28 @@ TEST(SendHeadersTest, Success) { EngineWithTestServer engine_with_test_server(engine_builder, TestServerType::HTTP2_WITH_TLS); engine_running.WaitForNotification(); - int actual_status_code; + std::string actual_status_code; bool actual_end_stream; absl::Notification stream_complete; + EnvoyStreamCallbacks stream_callbacks; + stream_callbacks.on_headers_ = [&](const Http::ResponseHeaderMap& headers, bool end_stream, + envoy_stream_intel) { + actual_status_code = headers.getStatusValue(); + actual_end_stream = end_stream; + }; + stream_callbacks.on_data_ = [&](const Buffer::Instance&, uint64_t /* length */, bool end_stream, + envoy_stream_intel) { actual_end_stream = end_stream; }; + stream_callbacks.on_complete_ = [&](envoy_stream_intel, envoy_final_stream_intel) { + stream_complete.Notify(); + }; + stream_callbacks.on_error_ = [&](EnvoyError, envoy_stream_intel, envoy_final_stream_intel) { + stream_complete.Notify(); + }; + stream_callbacks.on_cancel_ = [&](envoy_stream_intel, envoy_final_stream_intel) { + stream_complete.Notify(); + }; auto stream_prototype = engine_with_test_server.engine()->streamClient()->newStreamPrototype(); - Platform::StreamSharedPtr stream = - (*stream_prototype) - .setOnHeaders( - [&](Platform::ResponseHeadersSharedPtr headers, bool end_stream, envoy_stream_intel) { - actual_status_code = headers->httpStatus(); - actual_end_stream = end_stream; - }) - .setOnData([&](envoy_data data, bool end_stream) { - actual_end_stream = end_stream; - data.release(data.context); - }) - .setOnComplete( - [&](envoy_stream_intel, envoy_final_stream_intel) { stream_complete.Notify(); }) - .setOnError([&](Platform::EnvoyErrorSharedPtr, envoy_stream_intel, - envoy_final_stream_intel) { stream_complete.Notify(); }) - .setOnCancel( - [&](envoy_stream_intel, envoy_final_stream_intel) { stream_complete.Notify(); }) - .start(); + Platform::StreamSharedPtr stream = stream_prototype->start(std::move(stream_callbacks)); auto headers = Http::Utility::createRequestHeaderMapPtr(); headers->addCopy(Http::LowerCaseString(":method"), "GET"); @@ -65,7 +65,7 @@ TEST(SendHeadersTest, Success) { stream->sendHeaders(std::move(headers), true); stream_complete.WaitForNotification(); - EXPECT_EQ(actual_status_code, 200); + EXPECT_EQ(actual_status_code, "200"); EXPECT_TRUE(actual_end_stream); } diff --git a/mobile/test/cc/integration/send_trailers_test.cc b/mobile/test/cc/integration/send_trailers_test.cc index c3e7de75c59b..07a3d3a5ccec 100644 --- a/mobile/test/cc/integration/send_trailers_test.cc +++ b/mobile/test/cc/integration/send_trailers_test.cc @@ -4,7 +4,7 @@ #include "absl/synchronization/notification.h" #include "gtest/gtest.h" #include "library/cc/engine_builder.h" -#include "library/cc/envoy_error.h" +#include "library/common/engine_types.h" #include "library/common/http/header_utility.h" namespace Envoy { @@ -33,26 +33,30 @@ TEST(SendTrailersTest, Success) { engine_with_test_server.testServer().setResponse({}, "body", {{"trailer-key", "trailer-value"}}); - int actual_status_code; + std::string actual_status_code; std::string actual_trailer_value; absl::Notification stream_complete; + EnvoyStreamCallbacks stream_callbacks; + stream_callbacks.on_headers_ = [&](const Http::ResponseHeaderMap& headers, bool /* end_stream */, + envoy_stream_intel) { + actual_status_code = headers.getStatusValue(); + }; + stream_callbacks.on_trailers_ = [&](const Http::ResponseTrailerMap& trailers, + envoy_stream_intel) { + actual_trailer_value = + trailers.get(Http::LowerCaseString("trailer-key"))[0]->value().getStringView(); + }; + stream_callbacks.on_complete_ = [&](envoy_stream_intel, envoy_final_stream_intel) { + stream_complete.Notify(); + }; + stream_callbacks.on_error_ = [&](EnvoyError, envoy_stream_intel, envoy_final_stream_intel) { + stream_complete.Notify(); + }; + stream_callbacks.on_cancel_ = [&](envoy_stream_intel, envoy_final_stream_intel) { + stream_complete.Notify(); + }; auto stream_prototype = engine_with_test_server.engine()->streamClient()->newStreamPrototype(); - Platform::StreamSharedPtr stream = - (*stream_prototype) - .setOnHeaders([&](Platform::ResponseHeadersSharedPtr headers, bool, envoy_stream_intel) { - actual_status_code = headers->httpStatus(); - }) - .setOnTrailers([&](Platform::ResponseTrailersSharedPtr trailers, envoy_stream_intel) { - ASSERT_TRUE(trailers->contains("trailer-key")); - actual_trailer_value = (*trailers)["trailer-key"][0]; - }) - .setOnComplete( - [&](envoy_stream_intel, envoy_final_stream_intel) { stream_complete.Notify(); }) - .setOnError([&](Platform::EnvoyErrorSharedPtr, envoy_stream_intel, - envoy_final_stream_intel) { stream_complete.Notify(); }) - .setOnCancel( - [&](envoy_stream_intel, envoy_final_stream_intel) { stream_complete.Notify(); }) - .start(); + Platform::StreamSharedPtr stream = stream_prototype->start(std::move(stream_callbacks)); auto headers = Http::Utility::createRequestHeaderMapPtr(); headers->addCopy(Http::LowerCaseString(":method"), "GET"); @@ -68,7 +72,7 @@ TEST(SendTrailersTest, Success) { stream_complete.WaitForNotification(); - EXPECT_EQ(actual_status_code, 200); + EXPECT_EQ(actual_status_code, "200"); EXPECT_EQ(actual_trailer_value, "trailer-value"); } diff --git a/mobile/test/common/http/client_test.cc b/mobile/test/common/http/client_test.cc index f50cd9dfcc1f..3677fb775f7c 100644 --- a/mobile/test/common/http/client_test.cc +++ b/mobile/test/common/http/client_test.cc @@ -1,7 +1,6 @@ #include #include "source/common/buffer/buffer_impl.h" -#include "source/common/http/context_impl.h" #include "source/common/stats/isolated_store_impl.h" #include "test/common/http/common.h" @@ -11,7 +10,6 @@ #include "test/mocks/event/mocks.h" #include "test/mocks/http/api_listener.h" #include "test/mocks/http/mocks.h" -#include "test/mocks/local_info/mocks.h" #include "test/mocks/upstream/mocks.h" #include "gmock/gmock.h" @@ -59,65 +57,8 @@ class TestHandle : public RequestDecoderHandle { }; class ClientTest : public testing::TestWithParam { -public: - typedef struct { - uint32_t on_headers_calls; - uint32_t on_data_calls; - uint32_t on_trailers_calls; - uint32_t on_complete_calls; - uint32_t on_error_calls; - uint32_t on_cancel_calls; - uint32_t on_send_window_available_calls; - std::string expected_status_; - bool end_stream_with_headers_; - std::string body_data_; - } callbacks_called; - +protected: ClientTest() { - bridge_callbacks_.context = &cc_; - - // Set up default bridge callbacks. Indivividual tests can override. - bridge_callbacks_.on_complete = [](envoy_stream_intel, envoy_final_stream_intel, - void* context) -> void { - callbacks_called* cc = static_cast(context); - cc->on_complete_calls++; - }; - bridge_callbacks_.on_headers = [](envoy_headers c_headers, bool end_stream, envoy_stream_intel, - void* context) -> void { - ResponseHeaderMapPtr response_headers = toResponseHeaders(c_headers); - callbacks_called* cc = static_cast(context); - EXPECT_EQ(end_stream, cc->end_stream_with_headers_); - EXPECT_EQ(response_headers->Status()->value().getStringView(), cc->expected_status_); - cc->on_headers_calls++; - }; - bridge_callbacks_.on_error = [](envoy_error, envoy_stream_intel, envoy_final_stream_intel, - void* context) -> void { - callbacks_called* cc = static_cast(context); - cc->on_error_calls++; - }; - bridge_callbacks_.on_data = [](envoy_data c_data, bool, envoy_stream_intel, - void* context) -> void { - callbacks_called* cc = static_cast(context); - cc->on_data_calls++; - cc->body_data_ += Data::Utility::copyToString(c_data); - release_envoy_data(c_data); - }; - bridge_callbacks_.on_cancel = [](envoy_stream_intel, envoy_final_stream_intel, - void* context) -> void { - callbacks_called* cc = static_cast(context); - cc->on_cancel_calls++; - }; - bridge_callbacks_.on_send_window_available = [](envoy_stream_intel, void* context) -> void { - callbacks_called* cc = static_cast(context); - cc->on_send_window_available_calls++; - }; - bridge_callbacks_.on_trailers = [](envoy_headers c_trailers, envoy_stream_intel, - void* context) -> void { - ResponseHeaderMapPtr response_trailers = toResponseHeaders(c_trailers); - EXPECT_TRUE(response_trailers.get() != nullptr); - callbacks_called* cc = static_cast(context); - cc->on_trailers_calls++; - }; helper_handle_ = test::SystemHelperPeer::replaceSystemHelper(); EXPECT_CALL(helper_handle_->mock_helper(), isCleartextPermitted(_)) .WillRepeatedly(Return(true)); @@ -127,13 +68,62 @@ class ClientTest : public testing::TestWithParam { }); } + struct StreamCallbacksCalled { + uint32_t on_headers_calls_{0}; + uint32_t on_data_calls_{0}; + uint32_t on_trailers_calls_{0}; + uint32_t on_complete_calls_{0}; + uint32_t on_error_calls_{0}; + uint32_t on_cancel_calls_{0}; + uint32_t on_send_window_available_calls_{0}; + std::string expected_status_{"200"}; + bool end_stream_with_headers_{true}; + std::string body_data_{""}; + }; + RequestHeaderMapPtr createDefaultRequestHeaders() { auto headers = Utility::createRequestHeaderMapPtr(); HttpTestUtility::addDefaultHeaders(*headers); return headers; } - void createStream() { + EnvoyStreamCallbacks createDefaultStreamCallbacks(StreamCallbacksCalled& callbacks_called) { + EnvoyStreamCallbacks stream_callbacks; + + stream_callbacks.on_headers_ = [&](const ResponseHeaderMap& headers, bool end_stream, + envoy_stream_intel) -> void { + EXPECT_EQ(end_stream, callbacks_called.end_stream_with_headers_); + EXPECT_EQ(headers.Status()->value().getStringView(), callbacks_called.expected_status_); + callbacks_called.on_headers_calls_++; + }; + stream_callbacks.on_data_ = [&](const Buffer::Instance& buffer, uint64_t length, + bool /* end_stream */, envoy_stream_intel) -> void { + callbacks_called.on_data_calls_++; + std::string response_body(length, ' '); + buffer.copyOut(0, length, response_body.data()); + callbacks_called.body_data_ += response_body; + }; + stream_callbacks.on_trailers_ = [&](const ResponseTrailerMap&, envoy_stream_intel) -> void { + callbacks_called.on_trailers_calls_++; + }; + stream_callbacks.on_complete_ = [&](envoy_stream_intel, envoy_final_stream_intel) -> void { + callbacks_called.on_complete_calls_++; + }; + stream_callbacks.on_error_ = [&](EnvoyError, envoy_stream_intel, + envoy_final_stream_intel) -> void { + callbacks_called.on_error_calls_++; + }; + stream_callbacks.on_cancel_ = [&](envoy_stream_intel, envoy_final_stream_intel) -> void { + callbacks_called.on_cancel_calls_++; + }; + stream_callbacks.on_send_window_available_ = [&](envoy_stream_intel) -> void { + callbacks_called.on_send_window_available_calls_++; + }; + + return stream_callbacks; + } + + void createStream(EnvoyStreamCallbacks&& stream_callbacks) { ON_CALL(dispatcher_, isThreadSafe()).WillByDefault(Return(true)); ON_CALL(*request_decoder_, streamInfo()).WillByDefault(ReturnRef(stream_info_)); @@ -145,7 +135,7 @@ class ClientTest : public testing::TestWithParam { response_encoder_ = &encoder; return std::make_unique(*request_decoder_); })); - http_client_.startStream(stream_, bridge_callbacks_, explicit_flow_control_); + http_client_.startStream(stream_, std::move(stream_callbacks), explicit_flow_control_); } void resumeDataIfExplicitFlowControl(int32_t bytes) { @@ -162,16 +152,12 @@ class ClientTest : public testing::TestWithParam { NiceMock stream_info_; ResponseEncoder* response_encoder_{}; NiceMock dispatcher_; - envoy_http_callbacks bridge_callbacks_; - callbacks_called cc_ = {0, 0, 0, 0, 0, 0, 0, "200", true, ""}; NiceMock random_; Stats::IsolatedStoreImpl stats_store_; bool explicit_flow_control_{GetParam()}; Client http_client_{std::move(owned_api_listener_), dispatcher_, *stats_store_.rootScope(), random_}; envoy_stream_t stream_ = 1; - -protected: std::unique_ptr helper_handle_; }; @@ -179,7 +165,8 @@ INSTANTIATE_TEST_SUITE_P(TestModes, ClientTest, ::testing::Bool()); TEST_P(ClientTest, BasicStreamHeaders) { // Create a stream, and set up request_decoder_ and response_encoder_ - createStream(); + StreamCallbacksCalled callbacks_called; + createStream(createDefaultStreamCallbacks(callbacks_called)); // Send request headers. EXPECT_CALL(dispatcher_, pushTrackedObject(_)); @@ -193,28 +180,30 @@ TEST_P(ClientTest, BasicStreamHeaders) { EXPECT_CALL(dispatcher_, deferredDelete_(_)); TestResponseHeaderMapImpl response_headers{{":status", "200"}}; response_encoder_->encodeHeaders(response_headers, true); - ASSERT_EQ(cc_.on_headers_calls, 1); - // Ensure that the callbacks on the bridge_callbacks_ were called. - ASSERT_EQ(cc_.on_complete_calls, 1); + ASSERT_EQ(callbacks_called.on_headers_calls_, 1); + // Ensure that the callbacks on the EnvoyStreamCallbacks were called. + ASSERT_EQ(callbacks_called.on_complete_calls_, 1); } TEST_P(ClientTest, BasicStreamData) { - cc_.end_stream_with_headers_ = false; + StreamCallbacksCalled callbacks_called; + callbacks_called.end_stream_with_headers_ = false; + auto stream_callbacks = createDefaultStreamCallbacks(callbacks_called); - bridge_callbacks_.on_data = [](envoy_data c_data, bool end_stream, envoy_stream_intel, - void* context) -> void { + stream_callbacks.on_data_ = [&](const Buffer::Instance& buffer, uint64_t length, bool end_stream, + envoy_stream_intel) -> void { EXPECT_TRUE(end_stream); - EXPECT_EQ(Data::Utility::copyToString(c_data), "response body"); - callbacks_called* cc = static_cast(context); - cc->on_data_calls++; - release_envoy_data(c_data); + std::string response_body(length, ' '); + buffer.copyOut(0, length, response_body.data()); + EXPECT_EQ(response_body, "response body"); + callbacks_called.on_data_calls_++; }; // Build body data auto request_data = std::make_unique("request body"); // Create a stream, and set up request_decoder_ and response_encoder_ - createStream(); + createStream(std::move(stream_callbacks)); // Send request data. Although HTTP would need headers before data this unit test only wants to // test data functionality. @@ -230,23 +219,24 @@ TEST_P(ClientTest, BasicStreamData) { EXPECT_CALL(dispatcher_, deferredDelete_(_)); Buffer::OwnedImpl response_data("response body"); response_encoder_->encodeData(response_data, true); - ASSERT_EQ(cc_.on_data_calls, 1); - // Ensure that the callbacks on the bridge_callbacks_ were called. - ASSERT_EQ(cc_.on_complete_calls, 1); + ASSERT_EQ(callbacks_called.on_data_calls_, 1); + // Ensure that the callbacks on the EnvoyStreamCallbacks were called. + ASSERT_EQ(callbacks_called.on_complete_calls_, 1); } TEST_P(ClientTest, BasicStreamTrailers) { - bridge_callbacks_.on_trailers = [](envoy_headers c_trailers, envoy_stream_intel, - void* context) -> void { - ResponseHeaderMapPtr response_trailers = toResponseHeaders(c_trailers); - EXPECT_EQ(response_trailers->get(LowerCaseString("x-test-trailer"))[0]->value().getStringView(), + StreamCallbacksCalled callbacks_called; + auto stream_callbacks = createDefaultStreamCallbacks(callbacks_called); + + stream_callbacks.on_trailers_ = [&](const Http::ResponseTrailerMap& trailers, + envoy_stream_intel) -> void { + EXPECT_EQ(trailers.get(LowerCaseString("x-test-trailer"))[0]->value().getStringView(), "test_trailer"); - callbacks_called* cc = static_cast(context); - cc->on_trailers_calls++; + callbacks_called.on_trailers_calls_++; }; // Create a stream, and set up request_decoder_ and response_encoder_ - createStream(); + createStream(std::move(stream_callbacks)); // Send request trailers. Although HTTP would need headers before trailers this unit test only // wants to test trailers functionality. @@ -262,9 +252,9 @@ TEST_P(ClientTest, BasicStreamTrailers) { EXPECT_CALL(dispatcher_, deferredDelete_(_)); TestResponseTrailerMapImpl response_trailers{{"x-test-trailer", "test_trailer"}}; response_encoder_->encodeTrailers(response_trailers); - ASSERT_EQ(cc_.on_trailers_calls, 1); - // Ensure that the callbacks on the bridge_callbacks_ were called. - ASSERT_EQ(cc_.on_complete_calls, 1); + ASSERT_EQ(callbacks_called.on_trailers_calls_, 1); + // Ensure that the callbacks on the EnvoyStreamCallbacks were called. + ASSERT_EQ(callbacks_called.on_complete_calls_, 1); } TEST_P(ClientTest, MultipleDataStream) { @@ -282,7 +272,8 @@ TEST_P(ClientTest, MultipleDataStream) { }); } - cc_.end_stream_with_headers_ = false; + StreamCallbacksCalled callbacks_called; + callbacks_called.end_stream_with_headers_ = false; // Build first body data auto request_data1 = std::make_unique("request body1"); @@ -290,7 +281,7 @@ TEST_P(ClientTest, MultipleDataStream) { auto request_data2 = std::make_unique("request body2"); // Create a stream, and set up request_decoder_ and response_encoder_ - createStream(); + createStream(createDefaultStreamCallbacks(callbacks_called)); // Send request headers. EXPECT_CALL(dispatcher_, pushTrackedObject(_)); @@ -303,12 +294,12 @@ TEST_P(ClientTest, MultipleDataStream) { EXPECT_CALL(dispatcher_, popTrackedObject(_)); EXPECT_CALL(*request_decoder_, decodeData(BufferStringEqual("request body1"), false)); http_client_.sendData(stream_, std::move(request_data1), false); - EXPECT_EQ(cc_.on_send_window_available_calls, 0); + EXPECT_EQ(callbacks_called.on_send_window_available_calls_, 0); if (explicit_flow_control_) { EXPECT_TRUE(process_buffered_data_callback->enabled_); process_buffered_data_callback->invokeCallback(); // The buffer is not full: expect an on_send_window_available call. - EXPECT_EQ(cc_.on_send_window_available_calls, 1); + EXPECT_EQ(callbacks_called.on_send_window_available_calls_, 1); } // Send second request data. @@ -317,35 +308,36 @@ TEST_P(ClientTest, MultipleDataStream) { EXPECT_CALL(*request_decoder_, decodeData(BufferStringEqual("request body2"), true)); http_client_.sendData(stream_, std::move(request_data2), true); // The stream is done: no further on_send_window_available calls should happen. - EXPECT_EQ(cc_.on_send_window_available_calls, explicit_flow_control_ ? 1 : 0); + EXPECT_EQ(callbacks_called.on_send_window_available_calls_, explicit_flow_control_ ? 1 : 0); // Encode response headers and data. EXPECT_CALL(dispatcher_, pushTrackedObject(_)).Times(3); EXPECT_CALL(dispatcher_, popTrackedObject(_)).Times(3); TestResponseHeaderMapImpl response_headers{{":status", "200"}}; response_encoder_->encodeHeaders(response_headers, false); - ASSERT_EQ(cc_.on_headers_calls, 1); + ASSERT_EQ(callbacks_called.on_headers_calls_, 1); Buffer::OwnedImpl response_data("response body"); response_encoder_->encodeData(response_data, false); resumeDataIfExplicitFlowControl(20); - ASSERT_EQ(cc_.on_data_calls, 1); - EXPECT_EQ("response body", cc_.body_data_); + ASSERT_EQ(callbacks_called.on_data_calls_, 1); + EXPECT_EQ("response body", callbacks_called.body_data_); EXPECT_CALL(dispatcher_, deferredDelete_(_)); Buffer::OwnedImpl response_data2("response body2"); response_encoder_->encodeData(response_data2, true); resumeDataIfExplicitFlowControl(20); - ASSERT_EQ(cc_.on_data_calls, 2); - EXPECT_EQ("response bodyresponse body2", cc_.body_data_); - // Ensure that the callbacks on the bridge_callbacks_ were called. - ASSERT_EQ(cc_.on_complete_calls, 1); + ASSERT_EQ(callbacks_called.on_data_calls_, 2); + EXPECT_EQ("response bodyresponse body2", callbacks_called.body_data_); + // Ensure that the callbacks on the EnvoyStreamCallbacks were called. + ASSERT_EQ(callbacks_called.on_complete_calls_, 1); } TEST_P(ClientTest, EmptyDataWithEndStream) { - cc_.end_stream_with_headers_ = false; + StreamCallbacksCalled callbacks_called; + callbacks_called.end_stream_with_headers_ = false; // Create a stream, and set up request_decoder_ and response_encoder_ - createStream(); + createStream(createDefaultStreamCallbacks(callbacks_called)); // Send request headers. EXPECT_CALL(*request_decoder_, decodeHeaders_(_, true)); http_client_.sendHeaders(stream_, createDefaultRequestHeaders(), true); @@ -353,12 +345,12 @@ TEST_P(ClientTest, EmptyDataWithEndStream) { // Encode response headers and data. TestResponseHeaderMapImpl response_headers{{":status", "200"}}; response_encoder_->encodeHeaders(response_headers, false); - ASSERT_EQ(cc_.on_headers_calls, 1); + ASSERT_EQ(callbacks_called.on_headers_calls_, 1); Buffer::OwnedImpl response_data("response body"); response_encoder_->encodeData(response_data, false); resumeDataIfExplicitFlowControl(20); - ASSERT_EQ(cc_.on_data_calls, 1); - EXPECT_EQ("response body", cc_.body_data_); + ASSERT_EQ(callbacks_called.on_data_calls_, 1); + EXPECT_EQ("response body", callbacks_called.body_data_); // Make sure end of stream as communicated by an empty data with fin is // processed correctly. @@ -368,10 +360,10 @@ TEST_P(ClientTest, EmptyDataWithEndStream) { Buffer::OwnedImpl response_data2(""); response_encoder_->encodeData(response_data2, true); resumeDataIfExplicitFlowControl(20); - ASSERT_EQ(cc_.on_data_calls, 2); - EXPECT_EQ("response body", cc_.body_data_); - // Ensure that the callbacks on the bridge_callbacks_ were called. - ASSERT_EQ(cc_.on_complete_calls, 1); + ASSERT_EQ(callbacks_called.on_data_calls_, 2); + EXPECT_EQ("response body", callbacks_called.body_data_); + // Ensure that the callbacks on the EnvoyStreamCallbacks were called. + ASSERT_EQ(callbacks_called.on_complete_calls_, 1); } TEST_P(ClientTest, MultipleStreams) { @@ -379,7 +371,9 @@ TEST_P(ClientTest, MultipleStreams) { envoy_stream_t stream2 = 2; // Create a stream, and set up request_decoder_ and response_encoder_ - createStream(); + StreamCallbacksCalled callbacks_called1; + auto stream_callbacks1 = createDefaultStreamCallbacks(callbacks_called1); + createStream(std::move(stream_callbacks1)); // Send request headers. EXPECT_CALL(dispatcher_, pushTrackedObject(_)); @@ -388,25 +382,20 @@ TEST_P(ClientTest, MultipleStreams) { http_client_.sendHeaders(stream1, createDefaultRequestHeaders(), true); // Start stream2. - // Setup bridge_callbacks_ to handle the response headers. + // Setup EnvoyStreamCallbacks to handle the response headers. NiceMock request_decoder2; ON_CALL(request_decoder2, streamInfo()).WillByDefault(ReturnRef(stream_info_)); ResponseEncoder* response_encoder2{}; - envoy_http_callbacks bridge_callbacks_2; - callbacks_called cc2 = {0, 0, 0, 0, 0, 0, 0, "200", true, ""}; - bridge_callbacks_2.context = &cc2; - bridge_callbacks_2.on_headers = [](envoy_headers c_headers, bool end_stream, envoy_stream_intel, - void* context) -> void { + StreamCallbacksCalled callbacks_called2; + auto stream_callbacks2 = createDefaultStreamCallbacks(callbacks_called1); + stream_callbacks2.on_headers_ = [&](const ResponseHeaderMap& headers, bool end_stream, + envoy_stream_intel) -> void { EXPECT_TRUE(end_stream); - ResponseHeaderMapPtr response_headers = toResponseHeaders(c_headers); - EXPECT_EQ(response_headers->Status()->value().getStringView(), "200"); - bool* on_headers_called2 = static_cast(context); - *on_headers_called2 = true; + EXPECT_EQ(headers.Status()->value().getStringView(), "200"); + callbacks_called2.on_headers_calls_ = true; }; - bridge_callbacks_2.on_complete = [](envoy_stream_intel, envoy_final_stream_intel, - void* context) -> void { - callbacks_called* cc = static_cast(context); - cc->on_complete_calls++; + stream_callbacks2.on_complete_ = [&](envoy_stream_intel, envoy_final_stream_intel) -> void { + callbacks_called2.on_complete_calls_++; }; // Create a stream. @@ -420,7 +409,7 @@ TEST_P(ClientTest, MultipleStreams) { response_encoder2 = &encoder; return std::make_unique(request_decoder2); })); - http_client_.startStream(stream2, bridge_callbacks_2, explicit_flow_control_); + http_client_.startStream(stream2, std::move(stream_callbacks2), explicit_flow_control_); // Send request headers. EXPECT_CALL(dispatcher_, pushTrackedObject(_)); @@ -434,9 +423,9 @@ TEST_P(ClientTest, MultipleStreams) { EXPECT_CALL(dispatcher_, deferredDelete_(_)); TestResponseHeaderMapImpl response_headers2{{":status", "200"}}; response_encoder2->encodeHeaders(response_headers2, true); - ASSERT_EQ(cc2.on_headers_calls, 1); - // Ensure that the on_headers on the bridge_callbacks_ was called. - ASSERT_EQ(cc2.on_complete_calls, 1); + ASSERT_EQ(callbacks_called2.on_headers_calls_, 1); + // Ensure that the on_headers on the EnvoyStreamCallbacks was called. + ASSERT_EQ(callbacks_called2.on_complete_calls_, 1); // Finish stream 1. EXPECT_CALL(dispatcher_, pushTrackedObject(_)); @@ -444,23 +433,23 @@ TEST_P(ClientTest, MultipleStreams) { EXPECT_CALL(dispatcher_, deferredDelete_(_)); TestResponseHeaderMapImpl response_headers{{":status", "200"}}; response_encoder_->encodeHeaders(response_headers, true); - ASSERT_EQ(cc_.on_headers_calls, 1); - ASSERT_EQ(cc_.on_complete_calls, 1); + ASSERT_EQ(callbacks_called1.on_headers_calls_, 1); + ASSERT_EQ(callbacks_called1.on_complete_calls_, 1); } TEST_P(ClientTest, EnvoyLocalError) { // Override the on_error default with some custom checks. - bridge_callbacks_.on_error = [](envoy_error error, envoy_stream_intel, envoy_final_stream_intel, - void* context) -> void { + StreamCallbacksCalled callbacks_called; + auto stream_callbacks = createDefaultStreamCallbacks(callbacks_called); + stream_callbacks.on_error_ = [&](EnvoyError error, envoy_stream_intel, + envoy_final_stream_intel) -> void { EXPECT_EQ(error.error_code, ENVOY_CONNECTION_FAILURE); EXPECT_EQ(error.attempt_count, 123); - callbacks_called* cc = static_cast(context); - cc->on_error_calls++; - release_envoy_error(error); + callbacks_called.on_error_calls_++; }; // Create a stream, and set up request_decoder_ and response_encoder_ - createStream(); + createStream(std::move(stream_callbacks)); // Send request headers. EXPECT_CALL(dispatcher_, pushTrackedObject(_)); @@ -477,10 +466,10 @@ TEST_P(ClientTest, EnvoyLocalError) { stream_info_.setResponseCodeDetails("nope"); stream_info_.setAttemptCount(123); response_encoder_->getStream().resetStream(Http::StreamResetReason::LocalConnectionFailure); - ASSERT_EQ(cc_.on_headers_calls, 0); - // Ensure that the callbacks on the bridge_callbacks_ were called. - ASSERT_EQ(cc_.on_complete_calls, 0); - ASSERT_EQ(cc_.on_error_calls, 1); + ASSERT_EQ(callbacks_called.on_headers_calls_, 0); + // Ensure that the callbacks on the EnvoyStreamCallbacks were called. + ASSERT_EQ(callbacks_called.on_complete_calls_, 0); + ASSERT_EQ(callbacks_called.on_error_calls_, 1); } TEST_P(ClientTest, ResetStreamLocal) { @@ -488,15 +477,16 @@ TEST_P(ClientTest, ResetStreamLocal) { ON_CALL(dispatcher_, isThreadSafe()).WillByDefault(Return(true)); // Create a stream, and set up request_decoder_ and response_encoder_ - createStream(); + StreamCallbacksCalled callbacks_called; + createStream(createDefaultStreamCallbacks(callbacks_called)); EXPECT_CALL(dispatcher_, pushTrackedObject(_)).Times(2); EXPECT_CALL(dispatcher_, popTrackedObject(_)).Times(2); EXPECT_CALL(dispatcher_, deferredDelete_(_)); http_client_.cancelStream(stream_); - ASSERT_EQ(cc_.on_cancel_calls, 1); - ASSERT_EQ(cc_.on_error_calls, 0); - ASSERT_EQ(cc_.on_complete_calls, 0); + ASSERT_EQ(callbacks_called.on_cancel_calls_, 1); + ASSERT_EQ(callbacks_called.on_error_calls_, 0); + ASSERT_EQ(callbacks_called.on_complete_calls_, 0); } TEST_P(ClientTest, DoubleResetStreamLocal) { @@ -504,7 +494,8 @@ TEST_P(ClientTest, DoubleResetStreamLocal) { ON_CALL(dispatcher_, isThreadSafe()).WillByDefault(Return(true)); // Create a stream, and set up request_decoder_ and response_encoder_ - createStream(); + StreamCallbacksCalled callbacks_called; + createStream(createDefaultStreamCallbacks(callbacks_called)); EXPECT_CALL(dispatcher_, deferredDelete_(_)); EXPECT_CALL(dispatcher_, pushTrackedObject(_)).Times(2); @@ -514,27 +505,26 @@ TEST_P(ClientTest, DoubleResetStreamLocal) { // Second cancel call has no effect because stream is already cancelled. http_client_.cancelStream(stream_); - ASSERT_EQ(cc_.on_cancel_calls, 1); - ASSERT_EQ(cc_.on_error_calls, 0); - ASSERT_EQ(cc_.on_complete_calls, 0); + ASSERT_EQ(callbacks_called.on_cancel_calls_, 1); + ASSERT_EQ(callbacks_called.on_error_calls_, 0); + ASSERT_EQ(callbacks_called.on_complete_calls_, 0); } TEST_P(ClientTest, RemoteResetAfterStreamStart) { - cc_.end_stream_with_headers_ = false; + StreamCallbacksCalled callbacks_called; + callbacks_called.end_stream_with_headers_ = false; - bridge_callbacks_.on_error = [](envoy_error error, envoy_stream_intel, envoy_final_stream_intel, - void* context) -> void { + auto stream_callbacks = createDefaultStreamCallbacks(callbacks_called); + stream_callbacks.on_error_ = [&](EnvoyError error, envoy_stream_intel, + envoy_final_stream_intel) -> void { EXPECT_EQ(error.error_code, ENVOY_STREAM_RESET); - EXPECT_EQ(error.message.length, 0); + EXPECT_EQ(error.message.length(), 0); EXPECT_EQ(error.attempt_count, 0); - // This will use envoy_noop_release. - release_envoy_error(error); - callbacks_called* cc = static_cast(context); - cc->on_error_calls++; + callbacks_called.on_error_calls_++; }; // Create a stream, and set up request_decoder_ and response_encoder_ - createStream(); + createStream(std::move(stream_callbacks)); // Used to verify that when a reset is received, the Http::Client::DirectStream fires // runResetCallbacks. The Http::ConnectionManager depends on the Http::Client::DirectStream @@ -553,7 +543,7 @@ TEST_P(ClientTest, RemoteResetAfterStreamStart) { EXPECT_CALL(dispatcher_, popTrackedObject(_)); TestResponseHeaderMapImpl response_headers{{":status", "200"}}; response_encoder_->encodeHeaders(response_headers, false); - ASSERT_EQ(cc_.on_headers_calls, 1); + ASSERT_EQ(callbacks_called.on_headers_calls_, 1); // Expect that when a reset is received, the Http::Client::DirectStream fires // runResetCallbacks. The Http::ConnectionManager depends on the Http::Client::DirectStream @@ -564,14 +554,15 @@ TEST_P(ClientTest, RemoteResetAfterStreamStart) { EXPECT_CALL(callbacks, onResetStream(StreamResetReason::RemoteReset, _)); EXPECT_CALL(dispatcher_, deferredDelete_(_)); response_encoder_->getStream().resetStream(StreamResetReason::RemoteReset); - // Ensure that the on_error on the bridge_callbacks_ was called. - ASSERT_EQ(cc_.on_error_calls, 1); - ASSERT_EQ(cc_.on_complete_calls, 0); + // Ensure that the on_error on the EnvoyStreamCallbacks was called. + ASSERT_EQ(callbacks_called.on_error_calls_, 1); + ASSERT_EQ(callbacks_called.on_complete_calls_, 0); } TEST_P(ClientTest, StreamResetAfterOnComplete) { // Create a stream, and set up request_decoder_ and response_encoder_ - createStream(); + StreamCallbacksCalled callbacks_called; + createStream(createDefaultStreamCallbacks(callbacks_called)); // Send request headers. EXPECT_CALL(dispatcher_, pushTrackedObject(_)); @@ -585,18 +576,19 @@ TEST_P(ClientTest, StreamResetAfterOnComplete) { EXPECT_CALL(dispatcher_, deferredDelete_(_)); TestResponseHeaderMapImpl response_headers{{":status", "200"}}; response_encoder_->encodeHeaders(response_headers, true); - ASSERT_EQ(cc_.on_headers_calls, 1); - // Ensure that the callbacks on the bridge_callbacks_ were called. - ASSERT_EQ(cc_.on_complete_calls, 1); + ASSERT_EQ(callbacks_called.on_headers_calls_, 1); + // Ensure that the callbacks on the EnvoyStreamCallbacks were called. + ASSERT_EQ(callbacks_called.on_complete_calls_, 1); // Cancellation should have no effect as the stream should have already been cleaned up. http_client_.cancelStream(stream_); - ASSERT_EQ(cc_.on_cancel_calls, 0); + ASSERT_EQ(callbacks_called.on_cancel_calls_, 0); } TEST_P(ClientTest, ResetWhenRemoteClosesBeforeLocal) { // Create a stream, and set up request_decoder_ and response_encoder_ - createStream(); + StreamCallbacksCalled callbacks_called; + createStream(createDefaultStreamCallbacks(callbacks_called)); // Encode response headers. EXPECT_CALL(dispatcher_, pushTrackedObject(_)); @@ -604,17 +596,18 @@ TEST_P(ClientTest, ResetWhenRemoteClosesBeforeLocal) { EXPECT_CALL(dispatcher_, deferredDelete_(_)); TestResponseHeaderMapImpl response_headers{{":status", "200"}}; response_encoder_->encodeHeaders(response_headers, true); - ASSERT_EQ(cc_.on_headers_calls, 1); - ASSERT_EQ(cc_.on_complete_calls, 1); + ASSERT_EQ(callbacks_called.on_headers_calls_, 1); + ASSERT_EQ(callbacks_called.on_complete_calls_, 1); // Fire stream reset because Envoy does not allow half-open streams on the local side. response_encoder_->getStream().resetStream(StreamResetReason::RemoteReset); - ASSERT_EQ(cc_.on_error_calls, 0); + ASSERT_EQ(callbacks_called.on_error_calls_, 0); } TEST_P(ClientTest, Encode100Continue) { // Create a stream, and set up request_decoder_ and response_encoder_ - createStream(); + StreamCallbacksCalled callbacks_called; + createStream(createDefaultStreamCallbacks(callbacks_called)); // Send request headers. EXPECT_CALL(dispatcher_, pushTrackedObject(_)); @@ -631,10 +624,11 @@ TEST_P(ClientTest, Encode100Continue) { } TEST_P(ClientTest, EncodeMetadata) { - cc_.end_stream_with_headers_ = false; + StreamCallbacksCalled callbacks_called; + callbacks_called.end_stream_with_headers_ = false; // Create a stream, and set up request_decoder_ and response_encoder_ - createStream(); + createStream(createDefaultStreamCallbacks(callbacks_called)); // Send request headers. EXPECT_CALL(dispatcher_, pushTrackedObject(_)); @@ -647,7 +641,7 @@ TEST_P(ClientTest, EncodeMetadata) { EXPECT_CALL(dispatcher_, popTrackedObject(_)); TestResponseHeaderMapImpl response_headers{{":status", "200"}}; response_encoder_->encodeHeaders(response_headers, false); - ASSERT_EQ(cc_.on_headers_calls, 1); + ASSERT_EQ(callbacks_called.on_headers_calls_, 1); MetadataMap metadata_map = {{"key", "value"}}; MetadataMapPtr metadata_map_ptr = std::make_unique(metadata_map); @@ -661,7 +655,6 @@ TEST_P(ClientTest, EncodeMetadata) { TEST_P(ClientTest, NullAccessors) { envoy_stream_t stream = 1; - envoy_http_callbacks bridge_callbacks; // Create a stream. ON_CALL(dispatcher_, isThreadSafe()).WillByDefault(Return(true)); @@ -674,7 +667,9 @@ TEST_P(ClientTest, NullAccessors) { response_encoder_ = &encoder; return std::make_unique(*request_decoder_); })); - http_client_.startStream(stream, bridge_callbacks, explicit_flow_control_); + StreamCallbacksCalled callbacks_called; + http_client_.startStream(stream, createDefaultStreamCallbacks(callbacks_called), + explicit_flow_control_); EXPECT_FALSE(response_encoder_->http1StreamEncoderOptions().has_value()); EXPECT_FALSE(response_encoder_->streamErrorOnInvalidHttpMessage()); @@ -684,10 +679,11 @@ using ExplicitFlowControlTest = ClientTest; INSTANTIATE_TEST_SUITE_P(TestExplicitFlowControl, ExplicitFlowControlTest, testing::Values(true)); TEST_P(ExplicitFlowControlTest, ShortRead) { - cc_.end_stream_with_headers_ = false; + StreamCallbacksCalled callbacks_called; + callbacks_called.end_stream_with_headers_ = false; // Create a stream, and set up request_decoder_ and response_encoder_ - createStream(); + createStream(createDefaultStreamCallbacks(callbacks_called)); EXPECT_CALL(*request_decoder_, decodeHeaders_(_, true)); http_client_.sendHeaders(stream_, createDefaultRequestHeaders(), true); @@ -704,20 +700,21 @@ TEST_P(ExplicitFlowControlTest, ShortRead) { request_decoder_.reset(); resumeDataIfExplicitFlowControl(3); - EXPECT_EQ("123", cc_.body_data_); - ASSERT_EQ(cc_.on_complete_calls, 0); + EXPECT_EQ("123", callbacks_called.body_data_); + ASSERT_EQ(callbacks_called.on_complete_calls_, 0); // Kick off more data, and the other two and the FIN should arrive. resumeDataIfExplicitFlowControl(3); - EXPECT_EQ("12345", cc_.body_data_); - ASSERT_EQ(cc_.on_complete_calls, 1); + EXPECT_EQ("12345", callbacks_called.body_data_); + ASSERT_EQ(callbacks_called.on_complete_calls_, 1); } TEST_P(ExplicitFlowControlTest, DataArrivedWhileBufferNonempty) { - cc_.end_stream_with_headers_ = false; + StreamCallbacksCalled callbacks_called; + callbacks_called.end_stream_with_headers_ = false; // Create a stream, and set up request_decoder_ and response_encoder_ - createStream(); + createStream(createDefaultStreamCallbacks(callbacks_called)); EXPECT_CALL(*request_decoder_, decodeHeaders_(_, true)); http_client_.sendHeaders(stream_, createDefaultRequestHeaders(), true); @@ -729,8 +726,8 @@ TEST_P(ExplicitFlowControlTest, DataArrivedWhileBufferNonempty) { Buffer::OwnedImpl response_data("12345"); response_encoder_->encodeData(response_data, false); resumeDataIfExplicitFlowControl(3); - EXPECT_EQ("123", cc_.body_data_); - ASSERT_EQ(cc_.on_complete_calls, 0); + EXPECT_EQ("123", callbacks_called.body_data_); + ASSERT_EQ(callbacks_called.on_complete_calls_, 0); Buffer::OwnedImpl response_data2("678910"); response_encoder_->encodeData(response_data2, true); @@ -739,15 +736,16 @@ TEST_P(ExplicitFlowControlTest, DataArrivedWhileBufferNonempty) { request_decoder_.reset(); resumeDataIfExplicitFlowControl(20); - EXPECT_EQ("12345678910", cc_.body_data_); - ASSERT_EQ(cc_.on_complete_calls, 1); + EXPECT_EQ("12345678910", callbacks_called.body_data_); + ASSERT_EQ(callbacks_called.on_complete_calls_, 1); } TEST_P(ExplicitFlowControlTest, ResumeBeforeDataArrives) { - cc_.end_stream_with_headers_ = false; + StreamCallbacksCalled callbacks_called; + callbacks_called.end_stream_with_headers_ = false; // Create a stream, and set up request_decoder_ and response_encoder_ - createStream(); + createStream(createDefaultStreamCallbacks(callbacks_called)); EXPECT_CALL(*request_decoder_, decodeHeaders_(_, true)); http_client_.sendHeaders(stream_, createDefaultRequestHeaders(), true); @@ -764,15 +762,16 @@ TEST_P(ExplicitFlowControlTest, ResumeBeforeDataArrives) { // The stream is closed from Envoy's perspective. Make sure sanitizers will catch // any access to the decoder. request_decoder_.reset(); - EXPECT_EQ("12345", cc_.body_data_); - ASSERT_EQ(cc_.on_complete_calls, true); + EXPECT_EQ("12345", callbacks_called.body_data_); + ASSERT_EQ(callbacks_called.on_complete_calls_, true); } TEST_P(ExplicitFlowControlTest, ResumeWithFin) { - cc_.end_stream_with_headers_ = false; + StreamCallbacksCalled callbacks_called; + callbacks_called.end_stream_with_headers_ = false; // Create a stream, and set up request_decoder_ and response_encoder_ - createStream(); + createStream(createDefaultStreamCallbacks(callbacks_called)); // Send request headers. EXPECT_CALL(*request_decoder_, decodeHeaders_(_, true)); http_client_.sendHeaders(stream_, createDefaultRequestHeaders(), true); @@ -780,12 +779,12 @@ TEST_P(ExplicitFlowControlTest, ResumeWithFin) { // Encode response headers and data. TestResponseHeaderMapImpl response_headers{{":status", "200"}}; response_encoder_->encodeHeaders(response_headers, false); - ASSERT_EQ(cc_.on_headers_calls, 1); + ASSERT_EQ(callbacks_called.on_headers_calls_, 1); Buffer::OwnedImpl response_data("response body"); response_encoder_->encodeData(response_data, false); resumeDataIfExplicitFlowControl(20); - ASSERT_EQ(cc_.on_data_calls, 1); - EXPECT_EQ("response body", cc_.body_data_); + ASSERT_EQ(callbacks_called.on_data_calls_, 1); + EXPECT_EQ("response body", callbacks_called.body_data_); // Make sure end of stream as communicated by an empty data with end stream is // processed correctly if the resume is kicked off before the end stream arrives. @@ -796,17 +795,18 @@ TEST_P(ExplicitFlowControlTest, ResumeWithFin) { // The stream is closed from Envoy's perspective. Make sure sanitizers will catch // any access to the decoder. request_decoder_.reset(); - ASSERT_EQ(cc_.on_data_calls, 2); - EXPECT_EQ("response body", cc_.body_data_); - // Ensure that the callbacks on the bridge_callbacks_ were called. - ASSERT_EQ(cc_.on_complete_calls, 1); + ASSERT_EQ(callbacks_called.on_data_calls_, 2); + EXPECT_EQ("response body", callbacks_called.body_data_); + // Ensure that the callbacks on the EnvoyStreamCallbacks were called. + ASSERT_EQ(callbacks_called.on_complete_calls_, 1); } TEST_P(ExplicitFlowControlTest, ResumeWithDataAndTrailers) { - cc_.end_stream_with_headers_ = false; + StreamCallbacksCalled callbacks_called; + callbacks_called.end_stream_with_headers_ = false; // Create a stream, and set up request_decoder_ and response_encoder_ - createStream(); + createStream(createDefaultStreamCallbacks(callbacks_called)); // Send request headers. EXPECT_CALL(*request_decoder_, decodeHeaders_(_, true)); http_client_.sendHeaders(stream_, createDefaultRequestHeaders(), true); @@ -814,7 +814,7 @@ TEST_P(ExplicitFlowControlTest, ResumeWithDataAndTrailers) { // Encode response headers, data, and trailers. TestResponseHeaderMapImpl response_headers{{":status", "200"}}; response_encoder_->encodeHeaders(response_headers, false); - ASSERT_EQ(cc_.on_headers_calls, 1); + ASSERT_EQ(callbacks_called.on_headers_calls_, 1); Buffer::OwnedImpl response_data("response body"); response_encoder_->encodeData(response_data, false); TestResponseTrailerMapImpl response_trailers{{"x-test-trailer", "test_trailer"}}; @@ -825,24 +825,25 @@ TEST_P(ExplicitFlowControlTest, ResumeWithDataAndTrailers) { // On the resume call, the data should be passed up, but not the trailers. resumeDataIfExplicitFlowControl(20); - ASSERT_EQ(cc_.on_data_calls, 1); - ASSERT_EQ(cc_.on_trailers_calls, 0); - ASSERT_EQ(cc_.on_complete_calls, 0); - EXPECT_EQ("response body", cc_.body_data_); + ASSERT_EQ(callbacks_called.on_data_calls_, 1); + ASSERT_EQ(callbacks_called.on_trailers_calls_, 0); + ASSERT_EQ(callbacks_called.on_complete_calls_, 0); + EXPECT_EQ("response body", callbacks_called.body_data_); EXPECT_TRUE(dispatcher_.to_delete_.empty()); // On the next resume, trailers should be sent. resumeDataIfExplicitFlowControl(20); - ASSERT_EQ(cc_.on_trailers_calls, 1); - ASSERT_EQ(cc_.on_complete_calls, 1); + ASSERT_EQ(callbacks_called.on_trailers_calls_, 1); + ASSERT_EQ(callbacks_called.on_complete_calls_, 1); } TEST_P(ExplicitFlowControlTest, CancelWithStreamComplete) { - cc_.end_stream_with_headers_ = false; + StreamCallbacksCalled callbacks_called; + callbacks_called.end_stream_with_headers_ = false; // Create a stream, and set up request_decoder_ and response_encoder_ - createStream(); + createStream(createDefaultStreamCallbacks(callbacks_called)); EXPECT_CALL(*request_decoder_, decodeHeaders_(_, true)); http_client_.sendHeaders(stream_, createDefaultRequestHeaders(), true); @@ -856,7 +857,7 @@ TEST_P(ExplicitFlowControlTest, CancelWithStreamComplete) { // The stream is closed from Envoy's perspective. Make sure sanitizers will catch // any access to the decoder. request_decoder_.reset(); - ASSERT_EQ(cc_.on_complete_calls, false); + ASSERT_EQ(callbacks_called.on_complete_calls_, false); MockStreamCallbacks stream_callbacks; response_encoder_->getStream().addCallbacks(stream_callbacks); @@ -866,9 +867,9 @@ TEST_P(ExplicitFlowControlTest, CancelWithStreamComplete) { EXPECT_CALL(dispatcher_, deferredDelete_(_)); EXPECT_CALL(stream_callbacks, onResetStream(_, _)).Times(0); http_client_.cancelStream(stream_); - ASSERT_EQ(cc_.on_cancel_calls, 1); - ASSERT_EQ(cc_.on_error_calls, 0); - ASSERT_EQ(cc_.on_complete_calls, 0); + ASSERT_EQ(callbacks_called.on_cancel_calls_, 1); + ASSERT_EQ(callbacks_called.on_error_calls_, 0); + ASSERT_EQ(callbacks_called.on_complete_calls_, 0); } } // namespace Http diff --git a/mobile/test/common/integration/base_client_integration_test.cc b/mobile/test/common/integration/base_client_integration_test.cc index cc0b3bceb285..ee810a10ca92 100644 --- a/mobile/test/common/integration/base_client_integration_test.cc +++ b/mobile/test/common/integration/base_client_integration_test.cc @@ -7,7 +7,6 @@ #include "absl/synchronization/notification.h" #include "gtest/gtest.h" -#include "library/cc/bridge_utility.h" #include "library/common/http/header_utility.h" #include "library/common/internal_engine.h" #include "spdlog/spdlog.h" @@ -234,4 +233,37 @@ testing::AssertionResult BaseClientIntegrationTest::waitForGaugeGe(const std::st } return testing::AssertionSuccess(); } + +EnvoyStreamCallbacks BaseClientIntegrationTest::createDefaultStreamCallbacks() { + EnvoyStreamCallbacks stream_callbacks; + stream_callbacks.on_headers_ = [this](const Http::ResponseHeaderMap& headers, bool, + envoy_stream_intel intel) { + cc_.on_headers_calls++; + cc_.status = absl::StrCat(headers.getStatusValue()); + cc_.on_header_consumed_bytes_from_response = intel.consumed_bytes_from_response; + }; + stream_callbacks.on_data_ = [this](const Buffer::Instance&, uint64_t /* length */, + bool /* end_stream */, + envoy_stream_intel) { cc_.on_data_calls++; }; + stream_callbacks.on_complete_ = [this](envoy_stream_intel, envoy_final_stream_intel final_intel) { + memcpy(&last_stream_final_intel_, &final_intel, sizeof(envoy_final_stream_intel)); + if (expect_data_streams_) { + validateStreamIntel(final_intel, expect_dns_, upstream_tls_, cc_.on_complete_calls == 0); + } + cc_.on_complete_received_byte_count = final_intel.received_byte_count; + cc_.on_complete_calls++; + cc_.terminal_callback->setReady(); + }; + stream_callbacks.on_error_ = [this](EnvoyError, envoy_stream_intel, envoy_final_stream_intel) { + cc_.on_error_calls++; + cc_.terminal_callback->setReady(); + }; + stream_callbacks.on_cancel_ = [this](envoy_stream_intel, envoy_final_stream_intel final_intel) { + EXPECT_NE(-1, final_intel.stream_start_ms); + cc_.on_cancel_calls++; + cc_.terminal_callback->setReady(); + }; + return stream_callbacks; +} + } // namespace Envoy diff --git a/mobile/test/common/integration/base_client_integration_test.h b/mobile/test/common/integration/base_client_integration_test.h index 91a9d872b38d..c3fc044bd735 100644 --- a/mobile/test/common/integration/base_client_integration_test.h +++ b/mobile/test/common/integration/base_client_integration_test.h @@ -66,8 +66,9 @@ class BaseClientIntegrationTest : public BaseIntegrationTest { ABSL_MUST_USE_RESULT testing::AssertionResult waitForGaugeGe(const std::string& name, uint64_t value); + EnvoyStreamCallbacks createDefaultStreamCallbacks(); + Event::ProvisionalDispatcherPtr dispatcher_ = std::make_unique(); - envoy_http_callbacks bridge_callbacks_; ConditionalInitializer terminal_callback_; callbacks_called cc_{0, 0, 0, 0, 0, 0, 0, "", &terminal_callback_, {}}; Http::TestRequestHeaderMapImpl default_request_headers_; diff --git a/mobile/test/common/integration/client_integration_test.cc b/mobile/test/common/integration/client_integration_test.cc index 35c9fe66dc33..43ed635f6c15 100644 --- a/mobile/test/common/integration/client_integration_test.cc +++ b/mobile/test/common/integration/client_integration_test.cc @@ -201,19 +201,22 @@ void ClientIntegrationTest::basicTest() { default_request_headers_.addCopy(AutonomousStream::EXPECT_REQUEST_SIZE_BYTES, std::to_string(request_data.length())); - stream_prototype_->setOnData([this](envoy_data c_data, bool end_stream) { + EnvoyStreamCallbacks stream_callbacks = createDefaultStreamCallbacks(); + stream_callbacks.on_data_ = [this](const Buffer::Instance& buffer, uint64_t length, + bool end_stream, envoy_stream_intel) { if (end_stream) { - EXPECT_EQ(Data::Utility::copyToString(c_data), ""); + std::string response_body(length, ' '); + buffer.copyOut(0, length, response_body.data()); + EXPECT_EQ(response_body, ""); } cc_.on_data_calls++; - release_envoy_data(c_data); - }); + }; + stream_ = stream_prototype_->start(std::move(stream_callbacks), explicit_flow_control_); stream_->sendHeaders(std::make_unique(default_request_headers_), false); - envoy_data c_data = Data::Utility::toBridgeData(request_data); - stream_->sendData(c_data); + stream_->sendData(std::make_unique(std::move(request_data))); stream_->close(Http::Utility::createRequestTrailerMapPtr()); @@ -273,23 +276,24 @@ void ClientIntegrationTest::trickleTest() { initialize(); - stream_prototype_->setOnData([this](envoy_data c_data, bool) { + EnvoyStreamCallbacks stream_callbacks = createDefaultStreamCallbacks(); + stream_callbacks.on_data_ = [this](const Buffer::Instance&, uint64_t /* length */, + bool /* end_stream */, envoy_stream_intel) { if (explicit_flow_control_) { // Allow reading up to 100 bytes. stream_->readData(100); } cc_.on_data_calls++; - release_envoy_data(c_data); - }); + }; + + stream_ = stream_prototype_->start(std::move(stream_callbacks), explicit_flow_control_); stream_->sendHeaders(std::make_unique(default_request_headers_), false); if (explicit_flow_control_) { // Allow reading up to 100 bytes stream_->readData(100); } - Buffer::OwnedImpl request_data = Buffer::OwnedImpl("request body"); - envoy_data c_data = Data::Utility::toBridgeData(request_data); - stream_->sendData(c_data); + stream_->sendData(std::make_unique("request body")); stream_->close(Http::Utility::createRequestTrailerMapPtr()); ASSERT_TRUE(fake_upstreams_[0]->waitForHttpConnection(*BaseIntegrationTest::dispatcher_, @@ -333,25 +337,28 @@ TEST_P(ClientIntegrationTest, ManyStreamExplicitFlowControl) { absl::MutexLock l(&engine_lock_); stream_prototype = engine_->streamClient()->newStreamPrototype(); } - Platform::StreamSharedPtr stream = (*stream_prototype).start(explicit_flow_control_); - stream_prototype->setOnComplete( - [this, &num_requests](envoy_stream_intel, envoy_final_stream_intel) { - cc_.on_complete_calls++; - if (cc_.on_complete_calls == num_requests) { - cc_.terminal_callback->setReady(); - } - }); - - stream_prototype->setOnData([stream](envoy_data c_data, bool) { - // Allow reading up to 10 bytes. - stream->readData(100); - release_envoy_data(c_data); - }); + + EnvoyStreamCallbacks stream_callbacks = createDefaultStreamCallbacks(); + stream_callbacks.on_complete_ = [this, &num_requests](envoy_stream_intel, + envoy_final_stream_intel) { + cc_.on_complete_calls++; + if (cc_.on_complete_calls == num_requests) { + cc_.terminal_callback->setReady(); + } + }; + + stream_callbacks.on_data_ = [&streams, i](const Buffer::Instance&, uint64_t /* length */, + bool /* end_stream */, envoy_stream_intel) { + // Allow reading up to 100 bytes. + streams[i]->readData(100); + }; + auto stream = stream_prototype->start(std::move(stream_callbacks), explicit_flow_control_); + prototype_streams.push_back(stream_prototype); + streams.push_back(stream); + stream->sendHeaders(std::make_unique(default_request_headers_), true); stream->readData(100); - prototype_streams.push_back(stream_prototype); - streams.push_back(stream); } ASSERT(streams.size() == num_requests); ASSERT(prototype_streams.size() == num_requests); @@ -382,31 +389,32 @@ void ClientIntegrationTest::explicitFlowControlWithCancels(const uint32_t body_s absl::MutexLock l(&engine_lock_); stream_prototype = engine_->streamClient()->newStreamPrototype(); } - Platform::StreamSharedPtr stream = (*stream_prototype).start(explicit_flow_control_); - stream_prototype->setOnComplete( - [this, &num_requests](envoy_stream_intel, envoy_final_stream_intel) { - cc_.on_complete_calls++; - if (cc_.on_complete_calls + cc_.on_cancel_calls == num_requests) { - cc_.terminal_callback->setReady(); - } - }); - stream_prototype->setOnCancel( - [this, &num_requests](envoy_stream_intel, envoy_final_stream_intel) { - cc_.on_cancel_calls++; - if (cc_.on_complete_calls + cc_.on_cancel_calls == num_requests) { - cc_.terminal_callback->setReady(); - } - }); - stream_prototype->setOnData([stream](envoy_data c_data, bool) { - // Allow reading up to 10 bytes. - stream->readData(100); - release_envoy_data(c_data); - }); - stream_prototype_->setOnError( - [](Platform::EnvoyErrorSharedPtr, envoy_stream_intel, envoy_final_stream_intel) { - RELEASE_ASSERT(0, "unexpected"); - }); + EnvoyStreamCallbacks stream_callbacks = createDefaultStreamCallbacks(); + stream_callbacks.on_complete_ = [this, &num_requests](envoy_stream_intel, + envoy_final_stream_intel) { + cc_.on_complete_calls++; + if (cc_.on_complete_calls + cc_.on_cancel_calls == num_requests) { + cc_.terminal_callback->setReady(); + } + }; + stream_callbacks.on_cancel_ = [this, &num_requests](envoy_stream_intel, + envoy_final_stream_intel) { + cc_.on_cancel_calls++; + if (cc_.on_complete_calls + cc_.on_cancel_calls == num_requests) { + cc_.terminal_callback->setReady(); + } + }; + stream_callbacks.on_data_ = [&streams, i](const Buffer::Instance&, uint64_t /* length */, + bool /* end_stream */, envoy_stream_intel) { + // Allow reading up to 100 bytes. + streams[i]->readData(100); + }; + stream_callbacks.on_error_ = [](EnvoyError, envoy_stream_intel, envoy_final_stream_intel) { + RELEASE_ASSERT(0, "unexpected"); + }; + + auto stream = stream_prototype->start(std::move(stream_callbacks), explicit_flow_control_); stream->sendHeaders(std::make_unique(default_request_headers_), true); prototype_streams.push_back(stream_prototype); @@ -468,14 +476,18 @@ TEST_P(ClientIntegrationTest, ClearTextNotPermitted) { default_request_headers_.addCopy(AutonomousStream::EXPECT_REQUEST_SIZE_BYTES, std::to_string(request_data.length())); - stream_prototype_->setOnData([this](envoy_data c_data, bool end_stream) { + EnvoyStreamCallbacks stream_callbacks = createDefaultStreamCallbacks(); + stream_callbacks.on_data_ = [this](const Buffer::Instance& buffer, uint64_t length, + bool end_stream, envoy_stream_intel) { if (end_stream) { - EXPECT_EQ(Data::Utility::copyToString(c_data), "Cleartext is not permitted"); + std::string response_body(length, ' '); + buffer.copyOut(0, length, response_body.data()); + EXPECT_EQ(response_body, "Cleartext is not permitted"); } cc_.on_data_calls++; - release_envoy_data(c_data); - }); + }; + stream_ = stream_prototype_->start(std::move(stream_callbacks), explicit_flow_control_); stream_->sendHeaders(std::make_unique(default_request_headers_), true); @@ -503,21 +515,24 @@ TEST_P(ClientIntegrationTest, BasicHttps) { default_request_headers_.addCopy(AutonomousStream::EXPECT_REQUEST_SIZE_BYTES, std::to_string(request_data.length())); - stream_prototype_->setOnData([this](envoy_data c_data, bool end_stream) { + EnvoyStreamCallbacks stream_callbacks = createDefaultStreamCallbacks(); + stream_callbacks.on_data_ = [this](const Buffer::Instance& buffer, uint64_t length, + bool end_stream, envoy_stream_intel) { if (end_stream) { - EXPECT_EQ(Data::Utility::copyToString(c_data), ""); + std::string response_body(length, ' '); + buffer.copyOut(0, length, response_body.data()); + EXPECT_EQ(response_body, ""); } else { - EXPECT_EQ(c_data.length, 10); + EXPECT_EQ(length, 10); } cc_.on_data_calls++; - release_envoy_data(c_data); - }); + }; + stream_ = stream_prototype_->start(std::move(stream_callbacks), explicit_flow_control_); stream_->sendHeaders(std::make_unique(default_request_headers_), false); - envoy_data c_data = Data::Utility::toBridgeData(request_data); - stream_->sendData(c_data); + stream_->sendData(std::make_unique(std::move(request_data))); stream_->close(Http::Utility::createRequestTrailerMapPtr()); @@ -540,6 +555,7 @@ TEST_P(ClientIntegrationTest, BasicNon2xx) { ->setResponseHeaders(std::make_unique( Http::TestResponseHeaderMapImpl({{":status", "503"}}))); + stream_ = stream_prototype_->start(createDefaultStreamCallbacks(), explicit_flow_control_); stream_->sendHeaders(std::make_unique(default_request_headers_), true); terminal_callback_.waitReady(); @@ -554,6 +570,7 @@ TEST_P(ClientIntegrationTest, InvalidDomain) { initialize(); default_request_headers_.setHost("www.doesnotexist.com"); + stream_ = stream_prototype_->start(createDefaultStreamCallbacks(), explicit_flow_control_); stream_->sendHeaders(std::make_unique(default_request_headers_), true); terminal_callback_.waitReady(); @@ -575,6 +592,7 @@ TEST_P(ClientIntegrationTest, InvalidDomainFakeResolver) { default_request_headers_.setHost( absl::StrCat("www.doesnotexist.com:", fake_upstreams_[0]->localAddress()->ip()->port())); + stream_ = stream_prototype_->start(createDefaultStreamCallbacks(), explicit_flow_control_); stream_->sendHeaders(std::make_unique(default_request_headers_), true); // Force the lookup to resolve to localhost. @@ -662,6 +680,7 @@ TEST_P(ClientIntegrationTest, BasicBeforeResponseHeaders) { default_request_headers_.addCopy(AutonomousStream::RESET_AFTER_REQUEST, "yes"); + stream_ = stream_prototype_->start(createDefaultStreamCallbacks(), explicit_flow_control_); stream_->sendHeaders(std::make_unique(default_request_headers_), true); terminal_callback_.waitReady(); @@ -677,6 +696,7 @@ TEST_P(ClientIntegrationTest, ResetAfterResponseHeaders) { default_request_headers_.addCopy(AutonomousStream::RESET_AFTER_RESPONSE_HEADERS, "yes"); default_request_headers_.addCopy(AutonomousStream::RESPONSE_DATA_BLOCKS, "1"); + stream_ = stream_prototype_->start(createDefaultStreamCallbacks(), explicit_flow_control_); stream_->sendHeaders(std::make_unique(default_request_headers_), true); terminal_callback_.waitReady(); @@ -692,6 +712,7 @@ TEST_P(ClientIntegrationTest, ResetAfterResponseHeadersExplicit) { default_request_headers_.addCopy(AutonomousStream::RESET_AFTER_RESPONSE_HEADERS, "yes"); default_request_headers_.addCopy(AutonomousStream::RESPONSE_DATA_BLOCKS, "1"); + stream_ = stream_prototype_->start(createDefaultStreamCallbacks(), explicit_flow_control_); stream_->sendHeaders(std::make_unique(default_request_headers_), true); // Read the body chunk. This releases the error. @@ -709,6 +730,7 @@ TEST_P(ClientIntegrationTest, ResetAfterHeaderOnlyResponse) { default_request_headers_.addCopy(AutonomousStream::RESET_AFTER_RESPONSE_HEADERS, "yes"); default_request_headers_.addCopy(AutonomousStream::RESPONSE_DATA_BLOCKS, "0"); + stream_ = stream_prototype_->start(createDefaultStreamCallbacks(), explicit_flow_control_); stream_->sendHeaders(std::make_unique(default_request_headers_), false); terminal_callback_.waitReady(); @@ -723,6 +745,7 @@ TEST_P(ClientIntegrationTest, ResetBetweenDataChunks) { default_request_headers_.addCopy(AutonomousStream::RESET_AFTER_RESPONSE_DATA, "yes"); default_request_headers_.addCopy(AutonomousStream::RESPONSE_DATA_BLOCKS, "2"); + stream_ = stream_prototype_->start(createDefaultStreamCallbacks(), explicit_flow_control_); stream_->sendHeaders(std::make_unique(default_request_headers_), true); terminal_callback_.waitReady(); @@ -737,6 +760,7 @@ TEST_P(ClientIntegrationTest, ResetAfterData) { default_request_headers_.addCopy(AutonomousStream::RESET_AFTER_RESPONSE_DATA, "yes"); default_request_headers_.addCopy(AutonomousStream::RESPONSE_DATA_BLOCKS, "1"); + stream_ = stream_prototype_->start(createDefaultStreamCallbacks(), explicit_flow_control_); stream_->sendHeaders(std::make_unique(default_request_headers_), true); terminal_callback_.waitReady(); @@ -748,6 +772,7 @@ TEST_P(ClientIntegrationTest, CancelBeforeRequestHeadersSent) { autonomous_upstream_ = false; initialize(); + stream_ = stream_prototype_->start(createDefaultStreamCallbacks(), explicit_flow_control_); stream_->cancel(); terminal_callback_.waitReady(); @@ -760,6 +785,7 @@ TEST_P(ClientIntegrationTest, CancelAfterRequestHeadersSent) { default_request_headers_.addCopy(AutonomousStream::RESPOND_AFTER_REQUEST_HEADERS, "yes"); + stream_ = stream_prototype_->start(createDefaultStreamCallbacks(), explicit_flow_control_); stream_->sendHeaders(std::make_unique(default_request_headers_), false); stream_->cancel(); @@ -771,6 +797,7 @@ TEST_P(ClientIntegrationTest, CancelAfterRequestComplete) { autonomous_upstream_ = false; initialize(); + stream_ = stream_prototype_->start(createDefaultStreamCallbacks(), explicit_flow_control_); stream_->sendHeaders(std::make_unique(default_request_headers_), true); stream_->cancel(); @@ -783,15 +810,17 @@ TEST_P(ClientIntegrationTest, CancelDuringResponse) { initialize(); ConditionalInitializer headers_callback; - stream_prototype_->setOnHeaders( - [this, &headers_callback](Platform::ResponseHeadersSharedPtr headers, bool, - envoy_stream_intel) { - cc_.status = absl::StrCat(headers->httpStatus()); - cc_.on_headers_calls++; - headers_callback.setReady(); - return nullptr; - }); - + EnvoyStreamCallbacks stream_callbacks = createDefaultStreamCallbacks(); + stream_callbacks.on_headers_ = [this, &headers_callback](const Http::ResponseHeaderMap& headers, + bool /* end_stream */, + envoy_stream_intel) { + cc_.status = headers.getStatusValue(); + cc_.on_headers_calls++; + headers_callback.setReady(); + return nullptr; + }; + + stream_ = stream_prototype_->start(std::move(stream_callbacks), explicit_flow_control_); stream_->sendHeaders(std::make_unique(default_request_headers_), true); @@ -840,6 +869,7 @@ TEST_P(ClientIntegrationTest, BasicCancelWithCompleteStream) { initialize(); + stream_ = stream_prototype_->start(createDefaultStreamCallbacks(), explicit_flow_control_); stream_->sendHeaders(std::make_unique(default_request_headers_), true); @@ -865,15 +895,17 @@ TEST_P(ClientIntegrationTest, CancelWithPartialStream) { initialize(); ConditionalInitializer headers_callback; - stream_prototype_->setOnHeaders( - [this, &headers_callback](Platform::ResponseHeadersSharedPtr headers, bool, - envoy_stream_intel) { - cc_.status = absl::StrCat(headers->httpStatus()); - cc_.on_headers_calls++; - headers_callback.setReady(); - return nullptr; - }); - + EnvoyStreamCallbacks stream_callbacks = createDefaultStreamCallbacks(); + stream_callbacks.on_headers_ = [this, &headers_callback](const Http::ResponseHeaderMap& headers, + bool /* end_stream */, + envoy_stream_intel) { + cc_.status = headers.getStatusValue(); + cc_.on_headers_calls++; + headers_callback.setReady(); + return nullptr; + }; + + stream_ = stream_prototype_->start(std::move(stream_callbacks), explicit_flow_control_); stream_->sendHeaders(std::make_unique(default_request_headers_), true); @@ -920,14 +952,17 @@ TEST_P(ClientIntegrationTest, CaseSensitive) { formatter.processKey("FoO"); headers->addCopy(Http::LowerCaseString("FoO"), "bar"); - stream_prototype_->setOnHeaders( - [this](Platform::ResponseHeadersSharedPtr headers, bool, envoy_stream_intel) { - cc_.status = absl::StrCat(headers->httpStatus()); - cc_.on_headers_calls++; - EXPECT_TRUE(headers->contains("My-ResponsE-Header")); - EXPECT_TRUE((*headers)["My-ResponsE-Header"][0] == "foo"); - return nullptr; - }); + EnvoyStreamCallbacks stream_callbacks = createDefaultStreamCallbacks(); + stream_callbacks.on_headers_ = [this](const Http::ResponseHeaderMap& headers, bool, + envoy_stream_intel) { + cc_.status = headers.getStatusValue(); + cc_.on_headers_calls++; + auto result = headers.get(Http::LowerCaseString("My-ResponsE-Header")); + ASSERT_FALSE(result.empty()); + EXPECT_TRUE(result[0]->value() == "foo"); + }; + + stream_ = stream_prototype_->start(std::move(stream_callbacks), explicit_flow_control_); stream_->sendHeaders(std::move(headers), true); Envoy::FakeRawConnectionPtr upstream_connection; @@ -957,6 +992,7 @@ TEST_P(ClientIntegrationTest, TimeoutOnRequestPath) { autonomous_upstream_ = false; initialize(); + stream_ = stream_prototype_->start(createDefaultStreamCallbacks(), explicit_flow_control_); stream_->sendHeaders(std::make_unique(default_request_headers_), false); @@ -984,6 +1020,7 @@ TEST_P(ClientIntegrationTest, TimeoutOnResponsePath) { autonomous_upstream_ = false; initialize(); + stream_ = stream_prototype_->start(createDefaultStreamCallbacks(), explicit_flow_control_); stream_->sendHeaders(std::make_unique(default_request_headers_), true); @@ -1014,15 +1051,17 @@ TEST_P(ClientIntegrationTest, ResetWithBidiTraffic) { initialize(); ConditionalInitializer headers_callback; - stream_prototype_->setOnHeaders( - [this, &headers_callback](Platform::ResponseHeadersSharedPtr headers, bool, - envoy_stream_intel) { - cc_.status = absl::StrCat(headers->httpStatus()); - cc_.on_headers_calls++; - headers_callback.setReady(); - return nullptr; - }); - + EnvoyStreamCallbacks stream_callbacks = createDefaultStreamCallbacks(); + stream_callbacks.on_headers_ = [this, &headers_callback](const Http::ResponseHeaderMap& headers, + bool /* end_stream */, + envoy_stream_intel) { + cc_.status = headers.getStatusValue(); + cc_.on_headers_calls++; + headers_callback.setReady(); + return nullptr; + }; + + stream_ = stream_prototype_->start(std::move(stream_callbacks), explicit_flow_control_); stream_->sendHeaders(std::make_unique(default_request_headers_), false); @@ -1039,9 +1078,7 @@ TEST_P(ClientIntegrationTest, ResetWithBidiTraffic) { upstream_request_->encodeResetStream(); // Encoding data should not be problematic. - Buffer::OwnedImpl request_data = Buffer::OwnedImpl("request body"); - envoy_data c_data = Data::Utility::toBridgeData(request_data); - stream_->sendData(c_data); + stream_->sendData(std::make_unique("request body")); // Make sure cancel isn't problematic. stream_->cancel(); } @@ -1053,15 +1090,17 @@ TEST_P(ClientIntegrationTest, ResetWithBidiTrafficExplicitData) { initialize(); ConditionalInitializer headers_callback; - stream_prototype_->setOnHeaders( - [this, &headers_callback](Platform::ResponseHeadersSharedPtr headers, bool, - envoy_stream_intel) { - cc_.status = absl::StrCat(headers->httpStatus()); - cc_.on_headers_calls++; - headers_callback.setReady(); - return nullptr; - }); - + EnvoyStreamCallbacks stream_callbacks = createDefaultStreamCallbacks(); + stream_callbacks.on_headers_ = [this, &headers_callback](const Http::ResponseHeaderMap& headers, + bool /* end_stream */, + envoy_stream_intel) { + cc_.status = headers.getStatusValue(); + cc_.on_headers_calls++; + headers_callback.setReady(); + return nullptr; + }; + + stream_ = stream_prototype_->start(std::move(stream_callbacks), explicit_flow_control_); stream_->sendHeaders(std::make_unique(default_request_headers_), false); @@ -1078,9 +1117,7 @@ TEST_P(ClientIntegrationTest, ResetWithBidiTrafficExplicitData) { headers_callback.waitReady(); // Encoding data should not be problematic. - Buffer::OwnedImpl request_data = Buffer::OwnedImpl("request body"); - envoy_data c_data = Data::Utility::toBridgeData(request_data); - stream_->sendData(c_data); + stream_->sendData(std::make_unique("request body")); // Make sure cancel isn't problematic. stream_->cancel(); } @@ -1095,6 +1132,8 @@ TEST_P(ClientIntegrationTest, Proxying) { engine_->engine()->setProxySettings(fake_upstreams_[0]->localAddress()->asString().c_str(), fake_upstreams_[0]->localAddress()->ip()->port()); } + + stream_ = stream_prototype_->start(createDefaultStreamCallbacks(), explicit_flow_control_); // The initial request will do the DNS lookup. stream_->sendHeaders(std::make_unique(default_request_headers_), true); @@ -1104,7 +1143,7 @@ TEST_P(ClientIntegrationTest, Proxying) { stream_.reset(); // The second request will use the cached DNS entry and should succeed as well. - stream_ = (*stream_prototype_).start(explicit_flow_control_); + stream_ = stream_prototype_->start(createDefaultStreamCallbacks(), explicit_flow_control_); stream_->sendHeaders(std::make_unique(default_request_headers_), true); terminal_callback_.waitReady(); @@ -1116,16 +1155,17 @@ TEST_P(ClientIntegrationTest, DirectResponse) { initialize(); // Override to not validate stream intel. - stream_prototype_->setOnComplete( - [this](envoy_stream_intel, envoy_final_stream_intel final_intel) { - cc_.on_complete_received_byte_count = final_intel.received_byte_count; - cc_.on_complete_calls++; - cc_.terminal_callback->setReady(); - }); + EnvoyStreamCallbacks stream_callbacks = createDefaultStreamCallbacks(); + stream_callbacks.on_complete_ = [this](envoy_stream_intel, envoy_final_stream_intel final_intel) { + cc_.on_complete_received_byte_count = final_intel.received_byte_count; + cc_.on_complete_calls++; + cc_.terminal_callback->setReady(); + }; default_request_headers_.setHost("127.0.0.1"); default_request_headers_.setPath("/"); + stream_ = stream_prototype_->start(std::move(stream_callbacks), explicit_flow_control_); stream_->sendHeaders(std::make_unique(default_request_headers_), true); terminal_callback_.waitReady(); diff --git a/mobile/test/common/internal_engine_test.cc b/mobile/test/common/internal_engine_test.cc index 9497a1bcaf08..5367c3c2f8f7 100644 --- a/mobile/test/common/internal_engine_test.cc +++ b/mobile/test/common/internal_engine_test.cc @@ -13,7 +13,6 @@ #include "gtest/gtest.h" #include "library/cc/engine_builder.h" #include "library/common/api/external.h" -#include "library/common/bridge/utility.h" #include "library/common/data/utility.h" #include "library/common/http/header_utility.h" #include "library/common/internal_engine.h" @@ -322,28 +321,18 @@ TEST_F(InternalEngineTest, BasicStream) { ASSERT_TRUE(test_context.on_engine_running.WaitForNotificationWithTimeout(absl::Seconds(10))); absl::Notification on_complete_notification; - envoy_http_callbacks stream_cbs{ - [](envoy_headers c_headers, bool, envoy_stream_intel, void*) -> void { - auto response_headers = toResponseHeaders(c_headers); - EXPECT_EQ(response_headers->Status()->value().getStringView(), "200"); - } /* on_headers */, - [](envoy_data data, bool, envoy_stream_intel, void*) -> void { - data.release(data.context); - } /* on_data */, - nullptr /* on_metadata */, - [](envoy_headers, envoy_stream_intel, void*) -> void {} /* on_trailers */, - nullptr /* on_error */, - [](envoy_stream_intel, envoy_final_stream_intel, void* context) -> void { - auto* on_complete_notification = static_cast(context); - on_complete_notification->Notify(); - } /* on_complete */, - nullptr /* on_cancel */, - nullptr /* on_send_window_available*/, - &on_complete_notification /* context */}; + EnvoyStreamCallbacks stream_callbacks; + stream_callbacks.on_headers_ = [&](const Http::ResponseHeaderMap& headers, bool /* end_stream */, + envoy_stream_intel) { + EXPECT_EQ(headers.Status()->value().getStringView(), "200"); + }; + stream_callbacks.on_complete_ = [&](envoy_stream_intel, envoy_final_stream_intel) { + on_complete_notification.Notify(); + }; envoy_stream_t stream = engine->initStream(); - engine->startStream(stream, stream_cbs, false); + engine->startStream(stream, std::move(stream_callbacks), false); engine->sendHeaders(stream, createLocalhostRequestHeaders(test_server.getAddress()), false); engine->sendData(stream, std::make_unique("request body"), false); @@ -370,23 +359,14 @@ TEST_F(InternalEngineTest, ResetStream) { ASSERT_TRUE(test_context.on_engine_running.WaitForNotificationWithTimeout(absl::Seconds(10))); absl::Notification on_cancel_notification; - envoy_http_callbacks stream_cbs{ - nullptr /* on_headers */, - nullptr /* on_data */, - nullptr /* on_metadata */, - nullptr /* on_trailers */, - nullptr /* on_error */, - nullptr /* on_complete */, - [](envoy_stream_intel, envoy_final_stream_intel, void* context) -> void { - auto* on_cancel_notification = static_cast(context); - on_cancel_notification->Notify(); - } /* on_cancel */, - nullptr /* on_send_window_available */, - &on_cancel_notification /* context */}; + EnvoyStreamCallbacks stream_callbacks; + stream_callbacks.on_cancel_ = [&](envoy_stream_intel, envoy_final_stream_intel) { + on_cancel_notification.Notify(); + }; envoy_stream_t stream = engine->initStream(); - engine->startStream(stream, stream_cbs, false); + engine->startStream(stream, std::move(stream_callbacks), false); engine->cancelStream(stream); @@ -464,29 +444,18 @@ class ThreadPriorityInternalEngineTest : public InternalEngineTest { }; CallbackContext context; - envoy_http_callbacks stream_cbs{ - [](envoy_headers c_headers, bool, envoy_stream_intel, void* context) -> void { - release_envoy_map(c_headers); - // Gets the thread priority, so we can check that it's the same thread priority we set. - auto* callback_context = static_cast(context); - callback_context->thread_priority = getpriority(PRIO_PROCESS, 0); - } /* on_headers */, - [](envoy_data data, bool, envoy_stream_intel, void*) -> void { - data.release(data.context); - } /* on_data */, - nullptr /* on_metadata */, - [](envoy_headers, envoy_stream_intel, void*) -> void {} /* on_trailers */, - nullptr /* on_error */, - [](envoy_stream_intel, envoy_final_stream_intel, void* context) -> void { - auto* callback_context = static_cast(context); - callback_context->on_complete_notification.Notify(); - } /* on_complete */, - nullptr /* on_cancel */, - nullptr /* on_send_window_available*/, - &context}; + EnvoyStreamCallbacks stream_callbacks; + stream_callbacks.on_headers_ = [&](const Http::ResponseHeaderMap&, bool /* end_stream */, + envoy_stream_intel) { + // Gets the thread priority, so we can check that it's the same thread priority we set. + context.thread_priority = getpriority(PRIO_PROCESS, 0); + }; + stream_callbacks.on_complete_ = [&](envoy_stream_intel, envoy_final_stream_intel) { + context.on_complete_notification.Notify(); + }; envoy_stream_t stream = engine->initStream(); - engine->startStream(stream, stream_cbs, false); + engine->startStream(stream, std::move(stream_callbacks), false); engine->sendHeaders(stream, createLocalhostRequestHeaders(test_server.getAddress()), false); engine->sendData(stream, std::make_unique("request body"), true); From 07a93b384d228ceea6320ecc4154a9a2f0d62569 Mon Sep 17 00:00:00 2001 From: "dependency-envoy[bot]" <148525496+dependency-envoy[bot]@users.noreply.github.com> Date: Thu, 9 May 2024 15:23:16 +0000 Subject: [PATCH 06/20] deps: Bump `aspect_bazel_lib` -> 2.7.3 (#34047) 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 8619e3376f23..160ebf41ba2b 100644 --- a/bazel/repository_locations.bzl +++ b/bazel/repository_locations.bzl @@ -148,12 +148,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.7.1", - sha256 = "b554eb7942a5ab44c90077df6a0c76fc67c5874c9446a007e9ba68be82bd4796", + version = "2.7.3", + sha256 = "87ab4ec479ebeb00d286266aca2068caeef1bb0b1765e8f71c7b6cfee6af4226", strip_prefix = "bazel-lib-{version}", urls = ["https://github.com/aspect-build/bazel-lib/archive/v{version}.tar.gz"], use_category = ["build"], - release_date = "2024-04-20", + release_date = "2024-05-08", cpe = "N/A", license = "Apache-2.0", license_url = "https://github.com/aspect-build/bazel-lib/blob/v{version}/LICENSE", From c2a137b46b844e06e8fc81eeeee7e562c857b5ed Mon Sep 17 00:00:00 2001 From: "dependency-envoy[bot]" <148525496+dependency-envoy[bot]@users.noreply.github.com> Date: Thu, 9 May 2024 15:36:53 +0000 Subject: [PATCH 07/20] deps/api: Bump `opentelemetry_proto` -> 1.3.1 (#34048) 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 147342fc07f6..daae34baff21 100644 --- a/api/bazel/repository_locations.bzl +++ b/api/bazel/repository_locations.bzl @@ -118,9 +118,9 @@ REPOSITORY_LOCATIONS_SPEC = dict( project_name = "OpenTelemetry Proto", project_desc = "Language Independent Interface Types For OpenTelemetry", project_url = "https://github.com/open-telemetry/opentelemetry-proto", - version = "1.3.0", - sha256 = "73a678b0ff7a29b581381566a2230fe2a00b864608786c99c050a4492e2bbafc", - release_date = "2024-04-24", + version = "1.3.1", + sha256 = "bed250ceec8e4a83aa5604d7d5595a61945059dc662edd058a9da082283f7a00", + release_date = "2024-05-07", strip_prefix = "opentelemetry-proto-{version}", urls = ["https://github.com/open-telemetry/opentelemetry-proto/archive/v{version}.tar.gz"], use_category = ["api"], From 948954020077ca5f0de134812347c0b858be3633 Mon Sep 17 00:00:00 2001 From: "dependency-envoy[bot]" <148525496+dependency-envoy[bot]@users.noreply.github.com> Date: Thu, 9 May 2024 15:41:48 +0000 Subject: [PATCH 08/20] deps/api: Bump `bazel_skylib` -> 1.6.1 (#34049) 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 daae34baff21..bdb9d43106fe 100644 --- a/api/bazel/repository_locations.bzl +++ b/api/bazel/repository_locations.bzl @@ -4,9 +4,9 @@ REPOSITORY_LOCATIONS_SPEC = dict( project_name = "bazel-skylib", project_desc = "Common useful functions and rules for Bazel", project_url = "https://github.com/bazelbuild/bazel-skylib", - version = "1.5.0", - sha256 = "cd55a062e763b9349921f0f5db8c3933288dc8ba4f76dd9416aac68acee3cb94", - release_date = "2023-11-06", + version = "1.6.1", + sha256 = "9f38886a40548c6e96c106b752f242130ee11aaa068a56ba7e56f4511f33e4f2", + release_date = "2024-04-25", urls = ["https://github.com/bazelbuild/bazel-skylib/releases/download/{version}/bazel-skylib-{version}.tar.gz"], use_category = ["api"], license = "Apache-2.0", From 1ffd4522cdb86ac62ad307d8f28a166e5261411b Mon Sep 17 00:00:00 2001 From: Fredy Wijaya Date: Thu, 9 May 2024 11:52:54 -0500 Subject: [PATCH 09/20] mobile: Fix merge race conflict (#34056) Fix race merge conflict Signed-off-by: Fredy Wijaya --- .../base_client_integration_test.cc | 107 +++++++----------- .../base_client_integration_test.h | 6 +- .../integration/client_integration_test.cc | 5 +- 3 files changed, 45 insertions(+), 73 deletions(-) diff --git a/mobile/test/common/integration/base_client_integration_test.cc b/mobile/test/common/integration/base_client_integration_test.cc index ee810a10ca92..bcddc80a527e 100644 --- a/mobile/test/common/integration/base_client_integration_test.cc +++ b/mobile/test/common/integration/base_client_integration_test.cc @@ -79,53 +79,56 @@ BaseClientIntegrationTest::BaseClientIntegrationTest(Network::Address::IpVersion void BaseClientIntegrationTest::initialize() { BaseIntegrationTest::initialize(); + { + absl::MutexLock l(&engine_lock_); + stream_prototype_ = engine_->streamClient()->newStreamPrototype(); + } HttpTestUtility::addDefaultHeaders(default_request_headers_); default_request_headers_.setHost(fake_upstreams_[0]->localAddress()->asStringView()); +} - createNewStream(stream_prototype_, cc_, stream_); +EnvoyStreamCallbacks BaseClientIntegrationTest::createDefaultStreamCallbacks() { + EnvoyStreamCallbacks stream_callbacks; + stream_callbacks.on_headers_ = [this](const Http::ResponseHeaderMap& headers, bool, + envoy_stream_intel intel) { + cc_.on_headers_calls++; + cc_.status = absl::StrCat(headers.getStatusValue()); + cc_.on_header_consumed_bytes_from_response = intel.consumed_bytes_from_response; + }; + stream_callbacks.on_data_ = [this](const Buffer::Instance&, uint64_t /* length */, + bool /* end_stream */, + envoy_stream_intel) { cc_.on_data_calls++; }; + stream_callbacks.on_complete_ = [this](envoy_stream_intel, envoy_final_stream_intel final_intel) { + memcpy(&last_stream_final_intel_, &final_intel, sizeof(envoy_final_stream_intel)); + if (expect_data_streams_) { + validateStreamIntel(final_intel, expect_dns_, upstream_tls_, cc_.on_complete_calls == 0); + } + cc_.on_complete_received_byte_count = final_intel.received_byte_count; + cc_.on_complete_calls++; + cc_.terminal_callback->setReady(); + }; + stream_callbacks.on_error_ = [this](EnvoyError, envoy_stream_intel, envoy_final_stream_intel) { + cc_.on_error_calls++; + cc_.terminal_callback->setReady(); + }; + stream_callbacks.on_cancel_ = [this](envoy_stream_intel, envoy_final_stream_intel final_intel) { + EXPECT_NE(-1, final_intel.stream_start_ms); + cc_.on_cancel_calls++; + cc_.terminal_callback->setReady(); + }; + return stream_callbacks; } -void BaseClientIntegrationTest::createNewStream( - Platform::StreamPrototypeSharedPtr& stream_prototype, callbacks_called& cc, - Platform::StreamSharedPtr& stream) { +Platform::StreamSharedPtr +BaseClientIntegrationTest::createNewStream(Platform::StreamPrototypeSharedPtr& stream_prototype, + EnvoyStreamCallbacks&& stream_callbacks) { { absl::MutexLock l(&engine_lock_); stream_prototype = engine_->streamClient()->newStreamPrototype(); } - - stream_prototype->setOnHeaders( - [&](Platform::ResponseHeadersSharedPtr headers, bool, envoy_stream_intel intel) { - cc.on_headers_calls++; - cc.status = absl::StrCat(headers->httpStatus()); - cc.on_header_consumed_bytes_from_response = intel.consumed_bytes_from_response; - }); - stream_prototype->setOnData([&](envoy_data c_data, bool) { - cc.on_data_calls++; - release_envoy_data(c_data); - }); - stream_prototype->setOnComplete([&](envoy_stream_intel, envoy_final_stream_intel final_intel) { - memcpy(&last_stream_final_intel_, &final_intel, sizeof(envoy_final_stream_intel)); - if (expect_data_streams_) { - validateStreamIntel(final_intel, expect_dns_, upstream_tls_, cc.on_complete_calls == 0); - } - cc.on_complete_received_byte_count = final_intel.received_byte_count; - cc.on_complete_calls++; - cc.terminal_callback->setReady(); - }); - stream_prototype->setOnError( - [&](Platform::EnvoyErrorSharedPtr, envoy_stream_intel, envoy_final_stream_intel) { - cc.on_error_calls++; - cc.terminal_callback->setReady(); - }); - stream_prototype->setOnCancel([&](envoy_stream_intel, envoy_final_stream_intel final_intel) { - EXPECT_NE(-1, final_intel.stream_start_ms); - cc.on_cancel_calls++; - cc.terminal_callback->setReady(); - }); - - stream = (*stream_prototype).start(explicit_flow_control_); + return stream_prototype->start(std::move(stream_callbacks), explicit_flow_control_); } void BaseClientIntegrationTest::threadRoutine(absl::Notification& engine_running) { @@ -234,36 +237,4 @@ testing::AssertionResult BaseClientIntegrationTest::waitForGaugeGe(const std::st return testing::AssertionSuccess(); } -EnvoyStreamCallbacks BaseClientIntegrationTest::createDefaultStreamCallbacks() { - EnvoyStreamCallbacks stream_callbacks; - stream_callbacks.on_headers_ = [this](const Http::ResponseHeaderMap& headers, bool, - envoy_stream_intel intel) { - cc_.on_headers_calls++; - cc_.status = absl::StrCat(headers.getStatusValue()); - cc_.on_header_consumed_bytes_from_response = intel.consumed_bytes_from_response; - }; - stream_callbacks.on_data_ = [this](const Buffer::Instance&, uint64_t /* length */, - bool /* end_stream */, - envoy_stream_intel) { cc_.on_data_calls++; }; - stream_callbacks.on_complete_ = [this](envoy_stream_intel, envoy_final_stream_intel final_intel) { - memcpy(&last_stream_final_intel_, &final_intel, sizeof(envoy_final_stream_intel)); - if (expect_data_streams_) { - validateStreamIntel(final_intel, expect_dns_, upstream_tls_, cc_.on_complete_calls == 0); - } - cc_.on_complete_received_byte_count = final_intel.received_byte_count; - cc_.on_complete_calls++; - cc_.terminal_callback->setReady(); - }; - stream_callbacks.on_error_ = [this](EnvoyError, envoy_stream_intel, envoy_final_stream_intel) { - cc_.on_error_calls++; - cc_.terminal_callback->setReady(); - }; - stream_callbacks.on_cancel_ = [this](envoy_stream_intel, envoy_final_stream_intel final_intel) { - EXPECT_NE(-1, final_intel.stream_start_ms); - cc_.on_cancel_calls++; - cc_.terminal_callback->setReady(); - }; - return stream_callbacks; -} - } // namespace Envoy diff --git a/mobile/test/common/integration/base_client_integration_test.h b/mobile/test/common/integration/base_client_integration_test.h index c3fc044bd735..7026780ee654 100644 --- a/mobile/test/common/integration/base_client_integration_test.h +++ b/mobile/test/common/integration/base_client_integration_test.h @@ -50,9 +50,9 @@ class BaseClientIntegrationTest : public BaseIntegrationTest { absl::MutexLock l(&engine_lock_); return reinterpret_cast(engine_->engine_); } - virtual void initialize() override; - void createNewStream(Platform::StreamPrototypeSharedPtr& stream_prototype, callbacks_called& cc, - Platform::StreamSharedPtr& stream_); + void initialize() override; + Platform::StreamSharedPtr createNewStream(Platform::StreamPrototypeSharedPtr& stream_prototype, + EnvoyStreamCallbacks&& stream_callbacks); void createEnvoy() override; void threadRoutine(absl::Notification& engine_running); diff --git a/mobile/test/common/integration/client_integration_test.cc b/mobile/test/common/integration/client_integration_test.cc index 43ed635f6c15..92f3cab3b42b 100644 --- a/mobile/test/common/integration/client_integration_test.cc +++ b/mobile/test/common/integration/client_integration_test.cc @@ -635,6 +635,7 @@ TEST_P(ClientIntegrationTest, ReresolveAndDrain) { // Send a request. The original upstream should be used because of DNS block. default_request_headers_.setHost( absl::StrCat("www.lyft.com:", fake_upstreams_[0]->localAddress()->ip()->port())); + stream_ = createNewStream(stream_prototype_, createDefaultStreamCallbacks()); stream_->sendHeaders(std::make_unique(default_request_headers_), true); terminal_callback_.waitReady(); @@ -654,7 +655,7 @@ TEST_P(ClientIntegrationTest, ReresolveAndDrain) { ASSERT_TRUE(waitForCounterGe("dns_cache.base_dns_cache.dns_query_attempt", 1)); EXPECT_EQ(0, getCounterValue("dns_cache.base_dns_cache.dns_query_success")); // The next request should go to the original upstream as there's been no drain. - createNewStream(stream_prototype_, cc_, stream_); + stream_ = createNewStream(stream_prototype_, createDefaultStreamCallbacks()); stream_->sendHeaders(std::make_unique(default_request_headers_), true); terminal_callback_.waitReady(); @@ -668,7 +669,7 @@ TEST_P(ClientIntegrationTest, ReresolveAndDrain) { ASSERT_TRUE(waitForCounterGe("dns_cache.base_dns_cache.dns_query_success", 1)); // Do one final request. It should go to the second upstream and return 202 - createNewStream(stream_prototype_, cc_, stream_); + stream_ = createNewStream(stream_prototype_, createDefaultStreamCallbacks()); stream_->sendHeaders(std::make_unique(default_request_headers_), true); terminal_callback_.waitReady(); From 02c9e1552d9bd72850b07f9a68bbcff2549f1103 Mon Sep 17 00:00:00 2001 From: Fredy Wijaya Date: Thu, 9 May 2024 12:48:53 -0500 Subject: [PATCH 10/20] mobile: Remove unused files (#34030) Risk Level: low (unused) Testing: CI Docs Changes: n/a Release Notes: n/a Platform Specific Features: mobile Signed-off-by: Fredy Wijaya --- mobile/library/cc/BUILD | 27 ------- mobile/library/cc/bridge_utility.cc | 27 ------- mobile/library/cc/bridge_utility.h | 12 --- mobile/library/cc/headers.cc | 23 ------ mobile/library/cc/headers.h | 66 ---------------- mobile/library/cc/headers_builder.cc | 44 ----------- mobile/library/cc/headers_builder.h | 28 ------- mobile/library/cc/request_headers.cc | 29 ------- mobile/library/cc/request_headers.h | 35 --------- mobile/library/cc/request_headers_builder.cc | 42 ---------- mobile/library/cc/request_headers_builder.h | 34 -------- mobile/library/cc/request_method.cc | 46 ----------- mobile/library/cc/request_method.h | 23 ------ mobile/library/cc/request_trailers.cc | 15 ---- mobile/library/cc/request_trailers.h | 24 ------ mobile/library/cc/request_trailers_builder.cc | 9 --- mobile/library/cc/request_trailers_builder.h | 21 ----- mobile/library/cc/response_headers.cc | 25 ------ mobile/library/cc/response_headers.h | 26 ------- mobile/library/cc/response_headers_builder.cc | 17 ---- mobile/library/cc/response_headers_builder.h | 23 ------ mobile/library/cc/response_trailers.cc | 15 ---- mobile/library/cc/response_trailers.h | 24 ------ .../library/cc/response_trailers_builder.cc | 12 --- mobile/library/cc/response_trailers_builder.h | 22 ------ mobile/library/cc/retry_policy.cc | 78 ------------------- mobile/library/cc/retry_policy.h | 29 ------- mobile/library/cc/trailers.h | 14 ---- .../extensions/filters/http/local_error/BUILD | 1 - .../filters/http/network_configuration/BUILD | 1 - .../filters/http/platform_bridge/BUILD | 1 - .../filters/http/platform_bridge/filter.cc | 8 +- .../extensions/filters/http/socket_tag/BUILD | 1 - mobile/library/common/http/BUILD | 11 --- mobile/library/common/http/headers.h | 20 ----- mobile/test/cc/integration/lifetimes_test.cc | 1 - mobile/test/cc/unit/BUILD | 10 --- .../cc/unit/request_headers_builder_test.cc | 58 -------------- .../http/filters/test_remote_response/BUILD | 1 - 39 files changed, 2 insertions(+), 901 deletions(-) delete mode 100644 mobile/library/cc/bridge_utility.cc delete mode 100644 mobile/library/cc/bridge_utility.h delete mode 100644 mobile/library/cc/headers.cc delete mode 100644 mobile/library/cc/headers.h delete mode 100644 mobile/library/cc/headers_builder.cc delete mode 100644 mobile/library/cc/headers_builder.h delete mode 100644 mobile/library/cc/request_headers.cc delete mode 100644 mobile/library/cc/request_headers.h delete mode 100644 mobile/library/cc/request_headers_builder.cc delete mode 100644 mobile/library/cc/request_headers_builder.h delete mode 100644 mobile/library/cc/request_method.cc delete mode 100644 mobile/library/cc/request_method.h delete mode 100644 mobile/library/cc/request_trailers.cc delete mode 100644 mobile/library/cc/request_trailers.h delete mode 100644 mobile/library/cc/request_trailers_builder.cc delete mode 100644 mobile/library/cc/request_trailers_builder.h delete mode 100644 mobile/library/cc/response_headers.cc delete mode 100644 mobile/library/cc/response_headers.h delete mode 100644 mobile/library/cc/response_headers_builder.cc delete mode 100644 mobile/library/cc/response_headers_builder.h delete mode 100644 mobile/library/cc/response_trailers.cc delete mode 100644 mobile/library/cc/response_trailers.h delete mode 100644 mobile/library/cc/response_trailers_builder.cc delete mode 100644 mobile/library/cc/response_trailers_builder.h delete mode 100644 mobile/library/cc/retry_policy.cc delete mode 100644 mobile/library/cc/retry_policy.h delete mode 100644 mobile/library/cc/trailers.h delete mode 100644 mobile/library/common/http/headers.h delete mode 100644 mobile/test/cc/unit/request_headers_builder_test.cc diff --git a/mobile/library/cc/BUILD b/mobile/library/cc/BUILD index 163646756e8e..ba06a1e3b58c 100644 --- a/mobile/library/cc/BUILD +++ b/mobile/library/cc/BUILD @@ -59,48 +59,21 @@ envoy_cc_library( envoy_cc_library( name = "envoy_engine_cc_lib_no_stamp", srcs = [ - "bridge_utility.cc", "engine.cc", - "headers.cc", - "headers_builder.cc", "key_value_store.cc", - "request_headers.cc", - "request_headers_builder.cc", - "request_method.cc", - "request_trailers.cc", - "request_trailers_builder.cc", - "response_headers.cc", - "response_headers_builder.cc", - "response_trailers.cc", - "response_trailers_builder.cc", - "retry_policy.cc", "stream.cc", "stream_client.cc", "stream_prototype.cc", "string_accessor.cc", ], hdrs = [ - "bridge_utility.h", "direct_response_testing.h", "engine.h", - "headers.h", - "headers_builder.h", "key_value_store.h", - "request_headers.h", - "request_headers_builder.h", - "request_method.h", - "request_trailers.h", - "request_trailers_builder.h", - "response_headers.h", - "response_headers_builder.h", - "response_trailers.h", - "response_trailers_builder.h", - "retry_policy.h", "stream.h", "stream_client.h", "stream_prototype.h", "string_accessor.h", - "trailers.h", ], external_deps = ["abseil_optional"], repository = "@envoy", diff --git a/mobile/library/cc/bridge_utility.cc b/mobile/library/cc/bridge_utility.cc deleted file mode 100644 index 886598d5fee2..000000000000 --- a/mobile/library/cc/bridge_utility.cc +++ /dev/null @@ -1,27 +0,0 @@ -#include "bridge_utility.h" - -#include "library/common/data/utility.h" - -namespace Envoy { -namespace Platform { - -RawHeaderMap envoyHeadersAsRawHeaderMap(envoy_headers raw_headers) { - RawHeaderMap headers; - for (auto i = 0; i < raw_headers.length; i++) { - auto key = Data::Utility::copyToString(raw_headers.entries[i].key); - auto value = Data::Utility::copyToString(raw_headers.entries[i].value); - - if (!headers.contains(key)) { - headers.emplace(key, std::vector()); - } - headers[key].push_back(value); - } - // free instead of release_envoy_headers - // because we already free each envoy_data individually - // during calls to envoy_data_as_string - release_envoy_headers(raw_headers); - return headers; -} - -} // namespace Platform -} // namespace Envoy diff --git a/mobile/library/cc/bridge_utility.h b/mobile/library/cc/bridge_utility.h deleted file mode 100644 index 6a88f1641eaa..000000000000 --- a/mobile/library/cc/bridge_utility.h +++ /dev/null @@ -1,12 +0,0 @@ -#pragma once - -#include "library/cc/headers.h" -#include "library/common/types/c_types.h" - -namespace Envoy { -namespace Platform { - -RawHeaderMap envoyHeadersAsRawHeaderMap(envoy_headers raw_headers); - -} // namespace Platform -} // namespace Envoy diff --git a/mobile/library/cc/headers.cc b/mobile/library/cc/headers.cc deleted file mode 100644 index dd8c5f10a0bc..000000000000 --- a/mobile/library/cc/headers.cc +++ /dev/null @@ -1,23 +0,0 @@ -#include "library/cc/headers.h" - -namespace Envoy { -namespace Platform { - -Headers::const_iterator Headers::begin() const { - return Headers::const_iterator(allHeaders().begin()); -} - -Headers::const_iterator Headers::end() const { return Headers::const_iterator(allHeaders().end()); } - -const std::vector& Headers::operator[](absl::string_view key) const { - return headers_.at(key); -} - -const RawHeaderMap& Headers::allHeaders() const { return headers_; } - -bool Headers::contains(const std::string& key) const { return headers_.contains(key); } - -Headers::Headers(const RawHeaderMap& headers) : headers_(headers) {} - -} // namespace Platform -} // namespace Envoy diff --git a/mobile/library/cc/headers.h b/mobile/library/cc/headers.h deleted file mode 100644 index ed7b5c3eb2e9..000000000000 --- a/mobile/library/cc/headers.h +++ /dev/null @@ -1,66 +0,0 @@ -#pragma once - -#include -#include - -#include "absl/container/flat_hash_map.h" - -namespace Envoy { -namespace Platform { - -using RawHeaderMap = absl::flat_hash_map>; - -class Headers { -public: - class const_iterator { - public: - const_iterator(RawHeaderMap::const_iterator position) : position_(position){}; - - using iterator_category = RawHeaderMap::const_iterator::iterator_category; - using value_type = std::string; - using reference = const value_type&; - using pointer = const value_type*; - using difference_type = std::ptrdiff_t; - - reference operator*() const { return position_->first; } - pointer operator->() { return &position_->first; } - - const_iterator& operator++() { - position_++; - return *this; - } - const_iterator operator++(int) { - auto tmp = *this; - ++(*this); - return tmp; - } - - friend bool operator==(const const_iterator& a, const const_iterator& b) { - return a.position_ == b.position_; - } - friend bool operator!=(const const_iterator& a, const const_iterator& b) { - return a.position_ != b.position_; - } - - private: - RawHeaderMap::const_iterator position_; - }; - - virtual ~Headers() {} - - const_iterator begin() const; - const_iterator end() const; - - const std::vector& operator[](absl::string_view key) const; - const RawHeaderMap& allHeaders() const; - bool contains(const std::string& key) const; - -protected: - Headers(const RawHeaderMap& headers); - -private: - RawHeaderMap headers_; -}; - -} // namespace Platform -} // namespace Envoy diff --git a/mobile/library/cc/headers_builder.cc b/mobile/library/cc/headers_builder.cc deleted file mode 100644 index 55595a22b0f3..000000000000 --- a/mobile/library/cc/headers_builder.cc +++ /dev/null @@ -1,44 +0,0 @@ -#include "library/cc/headers_builder.h" - -namespace Envoy { -namespace Platform { - -HeadersBuilder& HeadersBuilder::add(std::string name, std::string value) { - if (isRestrictedHeader(name)) { - return *this; - } - headers_[std::move(name)].push_back(std::move(value)); - return *this; -} - -HeadersBuilder& HeadersBuilder::set(std::string name, std::vector values) { - if (isRestrictedHeader(name)) { - return *this; - } - headers_[std::move(name)] = std::move(values); - return *this; -} - -HeadersBuilder& HeadersBuilder::remove(absl::string_view name) { - if (isRestrictedHeader(name)) { - return *this; - } - headers_.erase(name); - return *this; -} - -HeadersBuilder::HeadersBuilder() {} - -HeadersBuilder& HeadersBuilder::internalSet(std::string name, std::vector values) { - headers_[std::move(name)] = std::move(values); - return *this; -} - -const RawHeaderMap& HeadersBuilder::allHeaders() const { return headers_; } - -bool HeadersBuilder::isRestrictedHeader(absl::string_view name) const { - return name.find(':') == 0 || name.find("x-envoy-mobile") == 0; -} - -} // namespace Platform -} // namespace Envoy diff --git a/mobile/library/cc/headers_builder.h b/mobile/library/cc/headers_builder.h deleted file mode 100644 index 06a1aa9fefdf..000000000000 --- a/mobile/library/cc/headers_builder.h +++ /dev/null @@ -1,28 +0,0 @@ -#pragma once - -#include "headers.h" - -namespace Envoy { -namespace Platform { - -class HeadersBuilder { -public: - virtual ~HeadersBuilder() {} - - HeadersBuilder& add(std::string name, std::string value); - HeadersBuilder& set(std::string name, std::vector values); - HeadersBuilder& remove(absl::string_view name); - -protected: - HeadersBuilder(); - HeadersBuilder& internalSet(std::string name, std::vector values); - const RawHeaderMap& allHeaders() const; - -private: - bool isRestrictedHeader(absl::string_view name) const; - - RawHeaderMap headers_; -}; - -} // namespace Platform -} // namespace Envoy diff --git a/mobile/library/cc/request_headers.cc b/mobile/library/cc/request_headers.cc deleted file mode 100644 index 1257e0e621a0..000000000000 --- a/mobile/library/cc/request_headers.cc +++ /dev/null @@ -1,29 +0,0 @@ -#include "library/cc/request_headers.h" - -namespace Envoy { -namespace Platform { - -RequestMethod RequestHeaders::requestMethod() const { - return requestMethodFromString((*this)[":method"][0]); -} - -const std::string& RequestHeaders::scheme() const { return (*this)[":scheme"][0]; } - -const std::string& RequestHeaders::authority() const { return (*this)[":authority"][0]; } - -const std::string& RequestHeaders::path() const { return (*this)[":path"][0]; } - -absl::optional RequestHeaders::retryPolicy() const { - return absl::optional(RetryPolicy::fromRawHeaderMap(allHeaders())); -} - -RequestHeadersBuilder RequestHeaders::toRequestHeadersBuilder() const { - RequestHeadersBuilder builder(requestMethod(), scheme(), authority(), path()); - for (const auto& pair : allHeaders()) { - builder.set(pair.first, pair.second); - } - return builder; -} - -} // namespace Platform -} // namespace Envoy diff --git a/mobile/library/cc/request_headers.h b/mobile/library/cc/request_headers.h deleted file mode 100644 index 1a88c10f4f2d..000000000000 --- a/mobile/library/cc/request_headers.h +++ /dev/null @@ -1,35 +0,0 @@ -#pragma once - -#include - -#include "absl/types/optional.h" -#include "library/cc/headers.h" -#include "library/cc/request_headers_builder.h" -#include "library/cc/request_method.h" -#include "library/cc/retry_policy.h" - -namespace Envoy { -namespace Platform { - -class RequestHeadersBuilder; - -class RequestHeaders : public Headers { -public: - RequestMethod requestMethod() const; - const std::string& scheme() const; - const std::string& authority() const; - const std::string& path() const; - absl::optional retryPolicy() const; - - RequestHeadersBuilder toRequestHeadersBuilder() const; - -private: - RequestHeaders(RawHeaderMap headers) : Headers(std::move(headers)) {} - - friend class RequestHeadersBuilder; -}; - -using RequestHeadersSharedPtr = std::shared_ptr; - -} // namespace Platform -} // namespace Envoy diff --git a/mobile/library/cc/request_headers_builder.cc b/mobile/library/cc/request_headers_builder.cc deleted file mode 100644 index ca1193acfdc1..000000000000 --- a/mobile/library/cc/request_headers_builder.cc +++ /dev/null @@ -1,42 +0,0 @@ -#include "request_headers_builder.h" - -#include "source/common/http/utility.h" - -namespace Envoy { -namespace Platform { - -RequestHeadersBuilder::RequestHeadersBuilder(RequestMethod request_method, std::string scheme, - std::string authority, std::string path) { - initialize(request_method, std::move(scheme), std::move(authority), std::move(path)); -} - -RequestHeadersBuilder::RequestHeadersBuilder(RequestMethod request_method, absl::string_view url) { - Envoy::Http::Utility::Url parsed_url; - if (!parsed_url.initialize(url, /*is_connect_request=*/false)) { - initialize(request_method, "", "", ""); - return; - } - initialize(request_method, std::string(parsed_url.scheme()), - std::string(parsed_url.hostAndPort()), std::string(parsed_url.pathAndQueryParams())); -} - -void RequestHeadersBuilder::initialize(RequestMethod request_method, std::string scheme, - std::string authority, std::string path) { - internalSet(":method", {std::string(requestMethodToString(request_method))}); - internalSet(":scheme", {std::move(scheme)}); - internalSet(":authority", {std::move(authority)}); - internalSet(":path", {std::move(path)}); -} - -RequestHeadersBuilder& RequestHeadersBuilder::addRetryPolicy(const RetryPolicy& retry_policy) { - const RawHeaderMap retry_policy_headers = retry_policy.asRawHeaderMap(); - for (const auto& pair : retry_policy_headers) { - internalSet(pair.first, pair.second); - } - return *this; -} - -RequestHeaders RequestHeadersBuilder::build() const { return RequestHeaders(allHeaders()); } - -} // namespace Platform -} // namespace Envoy diff --git a/mobile/library/cc/request_headers_builder.h b/mobile/library/cc/request_headers_builder.h deleted file mode 100644 index db565ce2a83a..000000000000 --- a/mobile/library/cc/request_headers_builder.h +++ /dev/null @@ -1,34 +0,0 @@ -#pragma once - -#include - -#include "library/cc/headers_builder.h" -#include "library/cc/request_headers.h" -#include "library/cc/request_method.h" -#include "retry_policy.h" - -namespace Envoy { -namespace Platform { - -class RequestHeaders; -struct RetryPolicy; - -class RequestHeadersBuilder : public HeadersBuilder { -public: - RequestHeadersBuilder(RequestMethod request_method, std::string scheme, std::string authority, - std::string path); - RequestHeadersBuilder(RequestMethod request_method, absl::string_view url); - - RequestHeadersBuilder& addRetryPolicy(const RetryPolicy& retry_policy); - - RequestHeaders build() const; - -private: - void initialize(RequestMethod request_method, std::string scheme, std::string authority, - std::string path); -}; - -using RequestHeadersBuilderSharedPtr = std::shared_ptr; - -} // namespace Platform -} // namespace Envoy diff --git a/mobile/library/cc/request_method.cc b/mobile/library/cc/request_method.cc deleted file mode 100644 index 5fe3913be8cc..000000000000 --- a/mobile/library/cc/request_method.cc +++ /dev/null @@ -1,46 +0,0 @@ -#include "request_method.h" - -#include - -#include "source/common/common/assert.h" - -#include "absl/strings/string_view.h" - -namespace Envoy { -namespace Platform { - -namespace { - -const std::pair REQUEST_METHOD_LOOKUP[]{ - {RequestMethod::DELETE, "DELETE"}, {RequestMethod::GET, "GET"}, - {RequestMethod::HEAD, "HEAD"}, {RequestMethod::OPTIONS, "OPTIONS"}, - {RequestMethod::PATCH, "PATCH"}, {RequestMethod::POST, "POST"}, - {RequestMethod::PUT, "PUT"}, {RequestMethod::TRACE, "TRACE"}, -}; - -} // namespace - -absl::string_view requestMethodToString(RequestMethod method) { - for (const auto& pair : REQUEST_METHOD_LOOKUP) { - if (pair.first == method) { - return pair.second; - } - } - - IS_ENVOY_BUG("unknown method"); - return ""; -} - -RequestMethod requestMethodFromString(absl::string_view str) { - for (const auto& pair : REQUEST_METHOD_LOOKUP) { - if (pair.second == str) { - return pair.first; - } - } - - IS_ENVOY_BUG("unknown method"); - return REQUEST_METHOD_LOOKUP[0].first; -} - -} // namespace Platform -} // namespace Envoy diff --git a/mobile/library/cc/request_method.h b/mobile/library/cc/request_method.h deleted file mode 100644 index de248151b533..000000000000 --- a/mobile/library/cc/request_method.h +++ /dev/null @@ -1,23 +0,0 @@ -#pragma once - -#include "absl/strings/string_view.h" - -namespace Envoy { -namespace Platform { - -enum RequestMethod { - DELETE, - GET, - HEAD, - OPTIONS, - PATCH, - POST, - PUT, - TRACE, -}; - -absl::string_view requestMethodToString(RequestMethod method); -RequestMethod requestMethodFromString(absl::string_view str); - -} // namespace Platform -} // namespace Envoy diff --git a/mobile/library/cc/request_trailers.cc b/mobile/library/cc/request_trailers.cc deleted file mode 100644 index 6aac02c3dc80..000000000000 --- a/mobile/library/cc/request_trailers.cc +++ /dev/null @@ -1,15 +0,0 @@ -#include "request_trailers.h" - -namespace Envoy { -namespace Platform { - -RequestTrailersBuilder RequestTrailers::toRequestTrailersBuilder() const { - RequestTrailersBuilder builder; - for (const auto& pair : allHeaders()) { - builder.set(pair.first, pair.second); - } - return builder; -} - -} // namespace Platform -} // namespace Envoy diff --git a/mobile/library/cc/request_trailers.h b/mobile/library/cc/request_trailers.h deleted file mode 100644 index bf3cb548c1db..000000000000 --- a/mobile/library/cc/request_trailers.h +++ /dev/null @@ -1,24 +0,0 @@ -#pragma once - -#include "library/cc/request_trailers_builder.h" -#include "library/cc/trailers.h" - -namespace Envoy { -namespace Platform { - -class RequestTrailersBuilder; - -class RequestTrailers : public Trailers { -public: - RequestTrailersBuilder toRequestTrailersBuilder() const; - -private: - RequestTrailers(RawHeaderMap headers) : Trailers(std::move(headers)) {} - - friend class RequestTrailersBuilder; -}; - -using RequestTrailersSharedPtr = std::shared_ptr; - -} // namespace Platform -} // namespace Envoy diff --git a/mobile/library/cc/request_trailers_builder.cc b/mobile/library/cc/request_trailers_builder.cc deleted file mode 100644 index eb4a3f144426..000000000000 --- a/mobile/library/cc/request_trailers_builder.cc +++ /dev/null @@ -1,9 +0,0 @@ -#include "library/cc/request_trailers_builder.h" - -namespace Envoy { -namespace Platform { - -RequestTrailers RequestTrailersBuilder::build() const { return RequestTrailers(allHeaders()); } - -} // namespace Platform -} // namespace Envoy diff --git a/mobile/library/cc/request_trailers_builder.h b/mobile/library/cc/request_trailers_builder.h deleted file mode 100644 index 77df313df198..000000000000 --- a/mobile/library/cc/request_trailers_builder.h +++ /dev/null @@ -1,21 +0,0 @@ -#pragma once - -#include "library/cc/headers_builder.h" -#include "library/cc/request_trailers.h" - -namespace Envoy { -namespace Platform { - -class RequestTrailers; - -class RequestTrailersBuilder : public HeadersBuilder { -public: - RequestTrailersBuilder() : HeadersBuilder() {} - - RequestTrailers build() const; -}; - -using RequestTrailersBuilderSharedPtr = std::shared_ptr; - -} // namespace Platform -} // namespace Envoy diff --git a/mobile/library/cc/response_headers.cc b/mobile/library/cc/response_headers.cc deleted file mode 100644 index dadac12c53ae..000000000000 --- a/mobile/library/cc/response_headers.cc +++ /dev/null @@ -1,25 +0,0 @@ -#include "library/cc/response_headers.h" - -namespace Envoy { -namespace Platform { - -int ResponseHeaders::httpStatus() const { - if (!contains(":status")) { - return 0; - } - return stoi((*this)[":status"][0]); -} - -ResponseHeadersBuilder ResponseHeaders::toResponseHeadersBuilder() { - ResponseHeadersBuilder builder; - if (contains(":status")) { - builder.addHttpStatus(httpStatus()); - } - for (const auto& pair : allHeaders()) { - builder.set(pair.first, pair.second); - } - return builder; -} - -} // namespace Platform -} // namespace Envoy diff --git a/mobile/library/cc/response_headers.h b/mobile/library/cc/response_headers.h deleted file mode 100644 index 34f4d11c955e..000000000000 --- a/mobile/library/cc/response_headers.h +++ /dev/null @@ -1,26 +0,0 @@ -#pragma once - -#include "library/cc/headers.h" -#include "library/cc/response_headers_builder.h" - -namespace Envoy { -namespace Platform { - -class ResponseHeadersBuilder; - -class ResponseHeaders : public Headers { -public: - int httpStatus() const; - - ResponseHeadersBuilder toResponseHeadersBuilder(); - -private: - ResponseHeaders(RawHeaderMap headers) : Headers(std::move(headers)) {} - - friend class ResponseHeadersBuilder; -}; - -using ResponseHeadersSharedPtr = std::shared_ptr; - -} // namespace Platform -} // namespace Envoy diff --git a/mobile/library/cc/response_headers_builder.cc b/mobile/library/cc/response_headers_builder.cc deleted file mode 100644 index a92887e59f8c..000000000000 --- a/mobile/library/cc/response_headers_builder.cc +++ /dev/null @@ -1,17 +0,0 @@ -#include "library/cc/response_headers_builder.h" - -namespace Envoy { -namespace Platform { - -ResponseHeadersBuilder& ResponseHeadersBuilder::addHttpStatus(int status) { - internalSet(":status", std::vector{std::to_string(status)}); - return *this; -} - -ResponseHeadersSharedPtr ResponseHeadersBuilder::build() const { - ResponseHeaders* headers = new ResponseHeaders(allHeaders()); - return ResponseHeadersSharedPtr(headers); -} - -} // namespace Platform -} // namespace Envoy diff --git a/mobile/library/cc/response_headers_builder.h b/mobile/library/cc/response_headers_builder.h deleted file mode 100644 index 8b33c4cd719d..000000000000 --- a/mobile/library/cc/response_headers_builder.h +++ /dev/null @@ -1,23 +0,0 @@ -#pragma once - -#include "library/cc/headers_builder.h" -#include "library/cc/response_headers.h" - -namespace Envoy { -namespace Platform { - -class ResponseHeaders; -using ResponseHeadersSharedPtr = std::shared_ptr; - -class ResponseHeadersBuilder : public HeadersBuilder { -public: - ResponseHeadersBuilder() {} - - ResponseHeadersBuilder& addHttpStatus(int status); - ResponseHeadersSharedPtr build() const; -}; - -using ResponseHeadersBuilderSharedPtr = std::shared_ptr; - -} // namespace Platform -} // namespace Envoy diff --git a/mobile/library/cc/response_trailers.cc b/mobile/library/cc/response_trailers.cc deleted file mode 100644 index 47869d8a6193..000000000000 --- a/mobile/library/cc/response_trailers.cc +++ /dev/null @@ -1,15 +0,0 @@ -#include "library/cc/response_trailers.h" - -namespace Envoy { -namespace Platform { - -ResponseTrailersBuilder ResponseTrailers::toResponseTrailersBuilder() { - ResponseTrailersBuilder builder; - for (const auto& pair : allHeaders()) { - builder.set(pair.first, pair.second); - } - return builder; -} - -} // namespace Platform -} // namespace Envoy diff --git a/mobile/library/cc/response_trailers.h b/mobile/library/cc/response_trailers.h deleted file mode 100644 index 8e4a61713a77..000000000000 --- a/mobile/library/cc/response_trailers.h +++ /dev/null @@ -1,24 +0,0 @@ -#pragma once - -#include "library/cc/response_trailers_builder.h" -#include "library/cc/trailers.h" - -namespace Envoy { -namespace Platform { - -class ResponseTrailersBuilder; - -class ResponseTrailers : public Trailers { -public: - ResponseTrailersBuilder toResponseTrailersBuilder(); - -private: - ResponseTrailers(RawHeaderMap trailers) : Trailers(std::move(trailers)) {} - - friend class ResponseTrailersBuilder; -}; - -using ResponseTrailersSharedPtr = std::shared_ptr; - -} // namespace Platform -} // namespace Envoy diff --git a/mobile/library/cc/response_trailers_builder.cc b/mobile/library/cc/response_trailers_builder.cc deleted file mode 100644 index 0ec526f23a80..000000000000 --- a/mobile/library/cc/response_trailers_builder.cc +++ /dev/null @@ -1,12 +0,0 @@ -#include "library/cc/response_trailers_builder.h" - -namespace Envoy { -namespace Platform { - -ResponseTrailersSharedPtr ResponseTrailersBuilder::build() const { - ResponseTrailers* trailers = new ResponseTrailers(allHeaders()); - return ResponseTrailersSharedPtr(trailers); -} - -} // namespace Platform -} // namespace Envoy diff --git a/mobile/library/cc/response_trailers_builder.h b/mobile/library/cc/response_trailers_builder.h deleted file mode 100644 index 668b5593180b..000000000000 --- a/mobile/library/cc/response_trailers_builder.h +++ /dev/null @@ -1,22 +0,0 @@ -#pragma once - -#include "library/cc/headers_builder.h" -#include "library/cc/response_trailers.h" - -namespace Envoy { -namespace Platform { - -class ResponseTrailers; -using ResponseTrailersSharedPtr = std::shared_ptr; - -class ResponseTrailersBuilder : public HeadersBuilder { -public: - ResponseTrailersBuilder() {} - - ResponseTrailersSharedPtr build() const; -}; - -using ResponseTrailersBuilderSharedPtr = std::shared_ptr; - -} // namespace Platform -} // namespace Envoy diff --git a/mobile/library/cc/retry_policy.cc b/mobile/library/cc/retry_policy.cc deleted file mode 100644 index c24642a52bc6..000000000000 --- a/mobile/library/cc/retry_policy.cc +++ /dev/null @@ -1,78 +0,0 @@ -#include "library/cc/retry_policy.h" - -namespace Envoy { -namespace Platform { - -RawHeaderMap RetryPolicy::asRawHeaderMap() const { - RawHeaderMap outbound_headers{ - {"x-envoy-max-retries", {std::to_string(max_retry_count)}}, - {"x-envoy-upstream-rq-timeout-ms", {std::to_string(total_upstream_timeout_ms.value_or(0))}}, - }; - - if (per_try_timeout_ms.has_value()) { - outbound_headers["x-envoy-upstream-rq-per-try-timeout-ms"] = - std::vector{std::to_string(per_try_timeout_ms.value())}; - } - - std::vector retry_on_copy; - retry_on_copy.reserve(retry_on.size()); - for (const auto& retry_rule : retry_on) { - retry_on_copy.push_back(retry_rule); - } - - if (!retry_status_codes.empty()) { - retry_on_copy.push_back("retriable-status-codes"); - std::vector retry_status_codes_copy; - retry_status_codes_copy.reserve(retry_status_codes.size()); - for (const auto& status_code : retry_status_codes) { - retry_status_codes_copy.push_back(std::to_string(status_code)); - } - outbound_headers["x-envoy-retriable-status-codes"] = retry_status_codes_copy; - } - - if (!retry_on.empty()) { - outbound_headers["x-envoy-retry-on"] = retry_on_copy; - } - - return outbound_headers; -} - -RetryPolicy RetryPolicy::fromRawHeaderMap(const RawHeaderMap& headers) { - RetryPolicy retry_policy; - - if (headers.contains("x-envoy-max-retries")) { - retry_policy.max_retry_count = std::stoi(headers.at("x-envoy-max-retries")[0]); - } - - if (headers.contains("x-envoy-upstream-rq-timeout-ms")) { - retry_policy.total_upstream_timeout_ms = - std::stoi(headers.at("x-envoy-upstream-rq-timeout-ms")[0]); - } - - if (headers.contains("x-envoy-upstream-rq-per-try-timeout-ms")) { - retry_policy.per_try_timeout_ms = - std::stoi(headers.at("x-envoy-upstream-rq-per-try-timeout-ms")[0]); - } - - bool has_retriable_status_codes = false; - if (headers.contains("x-envoy-retry-on")) { - for (const auto& retry_rule_str : headers.at("x-envoy-retry-on")) { - if (retry_rule_str == "retriable-status_codes") { - has_retriable_status_codes = true; - continue; - } - retry_policy.retry_on.push_back(retry_rule_str); - } - } - - if (has_retriable_status_codes && headers.contains("x-envoy-retriable-status-codes")) { - for (const auto& status_code_str : headers.at("x-envoy-retriable-status-codes")) { - retry_policy.retry_status_codes.push_back(std::stoi(status_code_str)); - } - } - - return retry_policy; -} - -} // namespace Platform -} // namespace Envoy diff --git a/mobile/library/cc/retry_policy.h b/mobile/library/cc/retry_policy.h deleted file mode 100644 index edfd91379869..000000000000 --- a/mobile/library/cc/retry_policy.h +++ /dev/null @@ -1,29 +0,0 @@ -#pragma once - -#include -#include - -#include "absl/types/optional.h" -#include "library/cc/headers.h" -#include "library/cc/request_headers.h" - -namespace Envoy { -namespace Platform { - -class RequestHeaders; - -struct RetryPolicy { - int max_retry_count; - std::vector retry_on; - std::vector retry_status_codes; - absl::optional per_try_timeout_ms; - absl::optional total_upstream_timeout_ms; - - RawHeaderMap asRawHeaderMap() const; - static RetryPolicy fromRawHeaderMap(const RawHeaderMap& headers); -}; - -using RetryPolicySharedPtr = std::shared_ptr; - -} // namespace Platform -} // namespace Envoy diff --git a/mobile/library/cc/trailers.h b/mobile/library/cc/trailers.h deleted file mode 100644 index ba60592b7b43..000000000000 --- a/mobile/library/cc/trailers.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include "library/cc/headers.h" - -namespace Envoy { -namespace Platform { - -class Trailers : public Headers { -public: - Trailers(const RawHeaderMap& headers) : Headers(headers) {} -}; - -} // namespace Platform -} // namespace Envoy diff --git a/mobile/library/common/extensions/filters/http/local_error/BUILD b/mobile/library/common/extensions/filters/http/local_error/BUILD index 3c3b8248a208..ebd849217293 100644 --- a/mobile/library/common/extensions/filters/http/local_error/BUILD +++ b/mobile/library/common/extensions/filters/http/local_error/BUILD @@ -22,7 +22,6 @@ envoy_cc_extension( deps = [ ":filter_cc_proto", "//library/common/http:header_utility_lib", - "//library/common/http:internal_headers_lib", "//library/common/types:c_types_lib", "@envoy//envoy/http:codes_interface", "@envoy//envoy/http:filter_interface", diff --git a/mobile/library/common/extensions/filters/http/network_configuration/BUILD b/mobile/library/common/extensions/filters/http/network_configuration/BUILD index 2360408a9028..743db28725fb 100644 --- a/mobile/library/common/extensions/filters/http/network_configuration/BUILD +++ b/mobile/library/common/extensions/filters/http/network_configuration/BUILD @@ -23,7 +23,6 @@ envoy_cc_extension( ":filter_cc_proto", "//library/common/api:external_api_lib", "//library/common/http:header_utility_lib", - "//library/common/http:internal_headers_lib", "//library/common/network:connectivity_manager_lib", "//library/common/network:proxy_api_lib", "//library/common/network:proxy_resolver_interface_lib", diff --git a/mobile/library/common/extensions/filters/http/platform_bridge/BUILD b/mobile/library/common/extensions/filters/http/platform_bridge/BUILD index b6d20209859c..7b2a9622d743 100644 --- a/mobile/library/common/extensions/filters/http/platform_bridge/BUILD +++ b/mobile/library/common/extensions/filters/http/platform_bridge/BUILD @@ -31,7 +31,6 @@ envoy_cc_extension( "//library/common/bridge:utility_lib", "//library/common/data:utility_lib", "//library/common/http:header_utility_lib", - "//library/common/http:internal_headers_lib", "//library/common/stream_info:extra_stream_info_lib", "//library/common/types:c_types_lib", "@envoy//envoy/common:scope_tracker_interface", diff --git a/mobile/library/common/extensions/filters/http/platform_bridge/filter.cc b/mobile/library/common/extensions/filters/http/platform_bridge/filter.cc index 6d374cfc62ae..ac27ada6e586 100644 --- a/mobile/library/common/extensions/filters/http/platform_bridge/filter.cc +++ b/mobile/library/common/extensions/filters/http/platform_bridge/filter.cc @@ -1,12 +1,9 @@ #include "library/common/extensions/filters/http/platform_bridge/filter.h" -#include "envoy/server/filter_config.h" - #include "source/common/buffer/buffer_impl.h" #include "source/common/common/assert.h" #include "source/common/common/dump_state_utils.h" #include "source/common/common/scope_tracker.h" -#include "source/common/common/utility.h" #include "library/common/api/external.h" #include "library/common/bridge/utility.h" @@ -14,7 +11,6 @@ #include "library/common/data/utility.h" #include "library/common/extensions/filters/http/platform_bridge/c_type_definitions.h" #include "library/common/http/header_utility.h" -#include "library/common/http/headers.h" #include "library/common/stream_info/extra_stream_info.h" namespace Envoy { @@ -509,7 +505,7 @@ Http::FilterHeadersStatus PlatformBridgeFilter::encodeHeaders(Http::ResponseHead // Presence of internal error header indicates an error that should be surfaced as an // error callback (rather than an HTTP response). - const auto error_code_header = headers.get(Http::InternalHeaders::get().ErrorCode); + const auto error_code_header = headers.get(Http::LowerCaseString("x-internal-error-code")); if (error_code_header.empty()) { // No error, so delegate to base implementation for request and response path. return response_filter_base_->onHeaders(headers, end_stream); @@ -524,7 +520,7 @@ Http::FilterHeadersStatus PlatformBridgeFilter::encodeHeaders(Http::ResponseHead RELEASE_ASSERT(parsed_code, "parse error reading error code"); envoy_data error_message = envoy_nodata; - const auto error_message_header = headers.get(Http::InternalHeaders::get().ErrorMessage); + const auto error_message_header = headers.get(Http::LowerCaseString("x-internal-error-message")); if (!error_message_header.empty()) { error_message = Data::Utility::copyToBridgeData(error_message_header[0]->value().getStringView()); diff --git a/mobile/library/common/extensions/filters/http/socket_tag/BUILD b/mobile/library/common/extensions/filters/http/socket_tag/BUILD index 60045880c279..6b7e50503d87 100644 --- a/mobile/library/common/extensions/filters/http/socket_tag/BUILD +++ b/mobile/library/common/extensions/filters/http/socket_tag/BUILD @@ -21,7 +21,6 @@ envoy_cc_extension( repository = "@envoy", deps = [ ":filter_cc_proto", - "//library/common/http:internal_headers_lib", "//library/common/network:socket_tag_socket_option_lib", "//library/common/types:c_types_lib", "@envoy//envoy/http:codes_interface", diff --git a/mobile/library/common/http/BUILD b/mobile/library/common/http/BUILD index 8df8c651b643..49e7c223ed72 100644 --- a/mobile/library/common/http/BUILD +++ b/mobile/library/common/http/BUILD @@ -62,14 +62,3 @@ envoy_cc_library( "@envoy//source/extensions/http/header_formatters/preserve_case:preserve_case_formatter", ], ) - -envoy_cc_library( - name = "internal_headers_lib", - hdrs = ["headers.h"], - repository = "@envoy", - deps = [ - "@envoy//envoy/http:header_map_interface", - "@envoy//source/common/singleton:const_singleton", - "@envoy//source/common/singleton:threadsafe_singleton", - ], -) diff --git a/mobile/library/common/http/headers.h b/mobile/library/common/http/headers.h deleted file mode 100644 index 85786eea48dd..000000000000 --- a/mobile/library/common/http/headers.h +++ /dev/null @@ -1,20 +0,0 @@ -#pragma once - -#include "envoy/http/header_map.h" - -namespace Envoy { -namespace Http { - -/** - * Constant HTTP headers used internally for in-band signalling in the request/response path. - */ -class InternalHeaderValues { -public: - const LowerCaseString ErrorCode{"x-internal-error-code"}; - const LowerCaseString ErrorMessage{"x-internal-error-message"}; -}; - -using InternalHeaders = ConstSingleton; - -} // namespace Http -} // namespace Envoy diff --git a/mobile/test/cc/integration/lifetimes_test.cc b/mobile/test/cc/integration/lifetimes_test.cc index 6e3111aacacc..fc057d7396f3 100644 --- a/mobile/test/cc/integration/lifetimes_test.cc +++ b/mobile/test/cc/integration/lifetimes_test.cc @@ -4,7 +4,6 @@ #include "absl/synchronization/notification.h" #include "gtest/gtest.h" #include "library/cc/engine_builder.h" -#include "library/cc/request_headers.h" #include "library/common/engine_types.h" #include "library/common/http/header_utility.h" diff --git a/mobile/test/cc/unit/BUILD b/mobile/test/cc/unit/BUILD index d63465680b5b..53ef9a35620e 100644 --- a/mobile/test/cc/unit/BUILD +++ b/mobile/test/cc/unit/BUILD @@ -27,16 +27,6 @@ envoy_cc_test( ], ) -envoy_cc_test( - name = "request_headers_builder_test", - srcs = ["request_headers_builder_test.cc"], - repository = "@envoy", - deps = [ - "//library/cc:envoy_engine_cc_lib_no_stamp", - "@envoy_build_config//:extension_registry", - ], -) - envoy_cc_test( name = "fetch_client_test", srcs = ["fetch_client_test.cc"], diff --git a/mobile/test/cc/unit/request_headers_builder_test.cc b/mobile/test/cc/unit/request_headers_builder_test.cc deleted file mode 100644 index ce55a3e8a4b3..000000000000 --- a/mobile/test/cc/unit/request_headers_builder_test.cc +++ /dev/null @@ -1,58 +0,0 @@ -#include -#include - -#include "gtest/gtest.h" -#include "library/cc/request_headers_builder.h" - -namespace Envoy { -namespace Platform { -namespace { - -TEST(RequestHeadersBuilderTest, ConstructsFromPieces) { - RequestHeadersBuilder builder(RequestMethod::POST, "https", "www.example.com", "/"); - RequestHeaders headers = builder.build(); - EXPECT_EQ(RequestMethod::POST, headers.requestMethod()); - EXPECT_EQ("https", headers.scheme()); - EXPECT_EQ("www.example.com", headers.authority()); - EXPECT_EQ("/", headers.path()); -} - -TEST(RequestHeadersBuilderTest, ConstructsFromUrl) { - RequestHeadersBuilder builder(RequestMethod::POST, "https://www.example.com/"); - RequestHeaders headers = builder.build(); - EXPECT_EQ(RequestMethod::POST, headers.requestMethod()); - EXPECT_EQ("https", headers.scheme()); - EXPECT_EQ("www.example.com", headers.authority()); - EXPECT_EQ("/", headers.path()); -} - -TEST(RequestHeadersBuilderTest, ConstructsFromInvalidUrl) { - RequestHeadersBuilder builder(RequestMethod::POST, "root@example.com"); - RequestHeaders headers = builder.build(); - EXPECT_EQ(RequestMethod::POST, headers.requestMethod()); - EXPECT_EQ("", headers.scheme()); - EXPECT_EQ("", headers.authority()); - EXPECT_EQ("", headers.path()); -} - -TEST(RequestHeadersBuilderTest, AddHeader) { - RequestHeadersBuilder builder(RequestMethod::POST, "root@example.com"); - builder.add("foo", "bar"); - RequestHeaders headers = builder.build(); - EXPECT_EQ(RequestMethod::POST, headers.requestMethod()); - ASSERT_TRUE(headers.contains("foo")); - EXPECT_EQ("bar", headers["foo"][0]); -} - -TEST(RequestHeadersBuilderTest, AddAndRemoveHeader) { - RequestHeadersBuilder builder(RequestMethod::POST, "root@example.com"); - builder.add("foo", "bar"); - builder.remove("foo"); - RequestHeaders headers = builder.build(); - EXPECT_EQ(RequestMethod::POST, headers.requestMethod()); - ASSERT_FALSE(headers.contains("foo")); -} - -} // namespace -} // namespace Platform -} // namespace Envoy diff --git a/mobile/test/common/http/filters/test_remote_response/BUILD b/mobile/test/common/http/filters/test_remote_response/BUILD index ef75ddc881a9..5b6b44643d54 100644 --- a/mobile/test/common/http/filters/test_remote_response/BUILD +++ b/mobile/test/common/http/filters/test_remote_response/BUILD @@ -22,7 +22,6 @@ envoy_cc_library( deps = [ ":filter_cc_proto", "//library/common/http:header_utility_lib", - "//library/common/http:internal_headers_lib", "//library/common/types:c_types_lib", "@envoy//envoy/http:codes_interface", "@envoy//envoy/http:filter_interface", From b015974153c5a05b4d7219c13490cc0c30bbc4e1 Mon Sep 17 00:00:00 2001 From: Fredy Wijaya Date: Thu, 9 May 2024 12:54:52 -0500 Subject: [PATCH 11/20] mobile: ClientIntegrationTest cleanup (#34057) This PR updates the code to follow Envoy coding style as well as using the createNewStream helper for consistency with the rest of the code. Risk Level: low (tests only) Testing: unit tests Docs Changes: n/a Release Notes: n/a Platform Specific Features: n/a Signed-off-by: Fredy Wijaya --- .../base_client_integration_test.cc | 34 +- .../base_client_integration_test.h | 29 +- .../integration/client_integration_test.cc | 290 +++++++++--------- .../integration/rtds_integration_test.cc | 14 +- 4 files changed, 180 insertions(+), 187 deletions(-) diff --git a/mobile/test/common/integration/base_client_integration_test.cc b/mobile/test/common/integration/base_client_integration_test.cc index bcddc80a527e..2c2439c1bd39 100644 --- a/mobile/test/common/integration/base_client_integration_test.cc +++ b/mobile/test/common/integration/base_client_integration_test.cc @@ -92,43 +92,37 @@ EnvoyStreamCallbacks BaseClientIntegrationTest::createDefaultStreamCallbacks() { EnvoyStreamCallbacks stream_callbacks; stream_callbacks.on_headers_ = [this](const Http::ResponseHeaderMap& headers, bool, envoy_stream_intel intel) { - cc_.on_headers_calls++; - cc_.status = absl::StrCat(headers.getStatusValue()); - cc_.on_header_consumed_bytes_from_response = intel.consumed_bytes_from_response; + cc_.on_headers_calls_++; + cc_.status_ = absl::StrCat(headers.getStatusValue()); + cc_.on_header_consumed_bytes_from_response_ = intel.consumed_bytes_from_response; }; stream_callbacks.on_data_ = [this](const Buffer::Instance&, uint64_t /* length */, bool /* end_stream */, - envoy_stream_intel) { cc_.on_data_calls++; }; + envoy_stream_intel) { cc_.on_data_calls_++; }; stream_callbacks.on_complete_ = [this](envoy_stream_intel, envoy_final_stream_intel final_intel) { memcpy(&last_stream_final_intel_, &final_intel, sizeof(envoy_final_stream_intel)); if (expect_data_streams_) { - validateStreamIntel(final_intel, expect_dns_, upstream_tls_, cc_.on_complete_calls == 0); + validateStreamIntel(final_intel, expect_dns_, upstream_tls_, cc_.on_complete_calls_ == 0); } - cc_.on_complete_received_byte_count = final_intel.received_byte_count; - cc_.on_complete_calls++; - cc_.terminal_callback->setReady(); + cc_.on_complete_received_byte_count_ = final_intel.received_byte_count; + cc_.on_complete_calls_++; + cc_.terminal_callback_->setReady(); }; stream_callbacks.on_error_ = [this](EnvoyError, envoy_stream_intel, envoy_final_stream_intel) { - cc_.on_error_calls++; - cc_.terminal_callback->setReady(); + cc_.on_error_calls_++; + cc_.terminal_callback_->setReady(); }; stream_callbacks.on_cancel_ = [this](envoy_stream_intel, envoy_final_stream_intel final_intel) { EXPECT_NE(-1, final_intel.stream_start_ms); - cc_.on_cancel_calls++; - cc_.terminal_callback->setReady(); + cc_.on_cancel_calls_++; + cc_.terminal_callback_->setReady(); }; return stream_callbacks; } Platform::StreamSharedPtr -BaseClientIntegrationTest::createNewStream(Platform::StreamPrototypeSharedPtr& stream_prototype, - EnvoyStreamCallbacks&& stream_callbacks) { - - { - absl::MutexLock l(&engine_lock_); - stream_prototype = engine_->streamClient()->newStreamPrototype(); - } - return stream_prototype->start(std::move(stream_callbacks), explicit_flow_control_); +BaseClientIntegrationTest::createNewStream(EnvoyStreamCallbacks&& stream_callbacks) { + return stream_prototype_->start(std::move(stream_callbacks), explicit_flow_control_); } void BaseClientIntegrationTest::threadRoutine(absl::Notification& engine_running) { diff --git a/mobile/test/common/integration/base_client_integration_test.h b/mobile/test/common/integration/base_client_integration_test.h index 7026780ee654..59ca94d41db1 100644 --- a/mobile/test/common/integration/base_client_integration_test.h +++ b/mobile/test/common/integration/base_client_integration_test.h @@ -11,18 +11,18 @@ namespace Envoy { // Maintains statistics and status data obtained from the Http::Client callbacks. -typedef struct { - uint32_t on_headers_calls; - uint32_t on_data_calls; - uint32_t on_complete_calls; - uint32_t on_error_calls; - uint32_t on_cancel_calls; - uint64_t on_header_consumed_bytes_from_response; - uint64_t on_complete_received_byte_count; - std::string status; - ConditionalInitializer* terminal_callback; - envoy_final_stream_intel final_intel; -} callbacks_called; +struct CallbacksCalled { + uint32_t on_headers_calls_; + uint32_t on_data_calls_; + uint32_t on_complete_calls_; + uint32_t on_error_calls_; + uint32_t on_cancel_calls_; + uint64_t on_header_consumed_bytes_from_response_; + uint64_t on_complete_received_byte_count_; + std::string status_; + ConditionalInitializer* terminal_callback_; + envoy_final_stream_intel final_intel_; +}; // Based on Http::Utility::toRequestHeaders() but only used for these tests. Http::ResponseHeaderMapPtr toResponseHeaders(envoy_headers headers); @@ -51,8 +51,7 @@ class BaseClientIntegrationTest : public BaseIntegrationTest { return reinterpret_cast(engine_->engine_); } void initialize() override; - Platform::StreamSharedPtr createNewStream(Platform::StreamPrototypeSharedPtr& stream_prototype, - EnvoyStreamCallbacks&& stream_callbacks); + Platform::StreamSharedPtr createNewStream(EnvoyStreamCallbacks&& stream_callbacks); void createEnvoy() override; void threadRoutine(absl::Notification& engine_running); @@ -70,7 +69,7 @@ class BaseClientIntegrationTest : public BaseIntegrationTest { Event::ProvisionalDispatcherPtr dispatcher_ = std::make_unique(); ConditionalInitializer terminal_callback_; - callbacks_called cc_{0, 0, 0, 0, 0, 0, 0, "", &terminal_callback_, {}}; + CallbacksCalled cc_{0, 0, 0, 0, 0, 0, 0, "", &terminal_callback_, {}}; Http::TestRequestHeaderMapImpl default_request_headers_; Event::DispatcherPtr full_dispatcher_; Platform::StreamPrototypeSharedPtr stream_prototype_; diff --git a/mobile/test/common/integration/client_integration_test.cc b/mobile/test/common/integration/client_integration_test.cc index 92f3cab3b42b..9b6f3f76b83f 100644 --- a/mobile/test/common/integration/client_integration_test.cc +++ b/mobile/test/common/integration/client_integration_test.cc @@ -209,10 +209,10 @@ void ClientIntegrationTest::basicTest() { buffer.copyOut(0, length, response_body.data()); EXPECT_EQ(response_body, ""); } - cc_.on_data_calls++; + cc_.on_data_calls_++; }; - stream_ = stream_prototype_->start(std::move(stream_callbacks), explicit_flow_control_); + stream_ = createNewStream(std::move(stream_callbacks)); stream_->sendHeaders(std::make_unique(default_request_headers_), false); @@ -222,12 +222,12 @@ void ClientIntegrationTest::basicTest() { terminal_callback_.waitReady(); - ASSERT_EQ(cc_.on_headers_calls, 1); - ASSERT_EQ(cc_.status, "200"); - ASSERT_GE(cc_.on_data_calls, 1); - ASSERT_EQ(cc_.on_complete_calls, 1); + ASSERT_EQ(cc_.on_headers_calls_, 1); + ASSERT_EQ(cc_.status_, "200"); + ASSERT_GE(cc_.on_data_calls_, 1); + ASSERT_EQ(cc_.on_complete_calls_, 1); if (upstreamProtocol() == Http::CodecType::HTTP1) { - ASSERT_EQ(cc_.on_header_consumed_bytes_from_response, 27); + ASSERT_EQ(cc_.on_header_consumed_bytes_from_response_, 27); // HTTP/1 ASSERT_EQ(1, last_stream_final_intel_.upstream_protocol); } else if (upstreamProtocol() == Http::CodecType::HTTP2) { @@ -246,7 +246,7 @@ TEST_P(ClientIntegrationTest, Basic) { initialize(); basicTest(); if (upstreamProtocol() == Http::CodecType::HTTP1) { - ASSERT_EQ(cc_.on_complete_received_byte_count, 67); + ASSERT_EQ(cc_.on_complete_received_byte_count_, 67); } } @@ -255,7 +255,7 @@ TEST_P(ClientIntegrationTest, BasicWithCares) { initialize(); basicTest(); if (upstreamProtocol() == Http::CodecType::HTTP1) { - ASSERT_EQ(cc_.on_complete_received_byte_count, 67); + ASSERT_EQ(cc_.on_complete_received_byte_count_, 67); } } @@ -265,9 +265,9 @@ TEST_P(ClientIntegrationTest, LargeResponse) { reinterpret_cast(fake_upstreams_.front().get())->setResponseBody(data); basicTest(); if (upstreamProtocol() == Http::CodecType::HTTP1) { - ASSERT_EQ(cc_.on_complete_received_byte_count, 32828); + ASSERT_EQ(cc_.on_complete_received_byte_count_, 32828); } else { - ASSERT_GE(cc_.on_complete_received_byte_count, 32000); + ASSERT_GE(cc_.on_complete_received_byte_count_, 32000); } } @@ -283,10 +283,10 @@ void ClientIntegrationTest::trickleTest() { // Allow reading up to 100 bytes. stream_->readData(100); } - cc_.on_data_calls++; + cc_.on_data_calls_++; }; - stream_ = stream_prototype_->start(std::move(stream_callbacks), explicit_flow_control_); + stream_ = createNewStream(std::move(stream_callbacks)); stream_->sendHeaders(std::make_unique(default_request_headers_), false); if (explicit_flow_control_) { @@ -312,13 +312,13 @@ void ClientIntegrationTest::trickleTest() { TEST_P(ClientIntegrationTest, Trickle) { trickleTest(); - ASSERT_LE(cc_.on_data_calls, 11); + ASSERT_LE(cc_.on_data_calls_, 11); } TEST_P(ClientIntegrationTest, TrickleExplicitFlowControl) { explicit_flow_control_ = true; trickleTest(); - ASSERT_LE(cc_.on_data_calls, 11); + ASSERT_LE(cc_.on_data_calls_, 11); } TEST_P(ClientIntegrationTest, ManyStreamExplicitFlowControl) { @@ -341,9 +341,9 @@ TEST_P(ClientIntegrationTest, ManyStreamExplicitFlowControl) { EnvoyStreamCallbacks stream_callbacks = createDefaultStreamCallbacks(); stream_callbacks.on_complete_ = [this, &num_requests](envoy_stream_intel, envoy_final_stream_intel) { - cc_.on_complete_calls++; - if (cc_.on_complete_calls == num_requests) { - cc_.terminal_callback->setReady(); + cc_.on_complete_calls_++; + if (cc_.on_complete_calls_ == num_requests) { + cc_.terminal_callback_->setReady(); } }; @@ -352,7 +352,7 @@ TEST_P(ClientIntegrationTest, ManyStreamExplicitFlowControl) { // Allow reading up to 100 bytes. streams[i]->readData(100); }; - auto stream = stream_prototype->start(std::move(stream_callbacks), explicit_flow_control_); + auto stream = createNewStream(std::move(stream_callbacks)); prototype_streams.push_back(stream_prototype); streams.push_back(stream); @@ -364,7 +364,7 @@ TEST_P(ClientIntegrationTest, ManyStreamExplicitFlowControl) { ASSERT(prototype_streams.size() == num_requests); terminal_callback_.waitReady(); - ASSERT_EQ(num_requests, cc_.on_complete_calls); + ASSERT_EQ(num_requests, cc_.on_complete_calls_); } void ClientIntegrationTest::explicitFlowControlWithCancels(const uint32_t body_size, @@ -393,16 +393,16 @@ void ClientIntegrationTest::explicitFlowControlWithCancels(const uint32_t body_s EnvoyStreamCallbacks stream_callbacks = createDefaultStreamCallbacks(); stream_callbacks.on_complete_ = [this, &num_requests](envoy_stream_intel, envoy_final_stream_intel) { - cc_.on_complete_calls++; - if (cc_.on_complete_calls + cc_.on_cancel_calls == num_requests) { - cc_.terminal_callback->setReady(); + cc_.on_complete_calls_++; + if (cc_.on_complete_calls_ + cc_.on_cancel_calls_ == num_requests) { + cc_.terminal_callback_->setReady(); } }; stream_callbacks.on_cancel_ = [this, &num_requests](envoy_stream_intel, envoy_final_stream_intel) { - cc_.on_cancel_calls++; - if (cc_.on_complete_calls + cc_.on_cancel_calls == num_requests) { - cc_.terminal_callback->setReady(); + cc_.on_cancel_calls_++; + if (cc_.on_complete_calls_ + cc_.on_cancel_calls_ == num_requests) { + cc_.terminal_callback_->setReady(); } }; stream_callbacks.on_data_ = [&streams, i](const Buffer::Instance&, uint64_t /* length */, @@ -414,7 +414,7 @@ void ClientIntegrationTest::explicitFlowControlWithCancels(const uint32_t body_s RELEASE_ASSERT(0, "unexpected"); }; - auto stream = stream_prototype->start(std::move(stream_callbacks), explicit_flow_control_); + auto stream = createNewStream(std::move(stream_callbacks)); stream->sendHeaders(std::make_unique(default_request_headers_), true); prototype_streams.push_back(stream_prototype); @@ -435,13 +435,13 @@ void ClientIntegrationTest::explicitFlowControlWithCancels(const uint32_t body_s if (terminate_engine) { // Only the cancel calls are guaranteed to have completed when engine->terminate() is called. - EXPECT_GE(cc_.on_cancel_calls, request_for_engine_termination / 2); + EXPECT_GE(cc_.on_cancel_calls_, request_for_engine_termination / 2); } else { ASSERT(streams.size() == num_requests); ASSERT(prototype_streams.size() == num_requests); terminal_callback_.waitReady(); - EXPECT_EQ(num_requests / 2, cc_.on_complete_calls); - EXPECT_EQ(num_requests / 2, cc_.on_cancel_calls); + EXPECT_EQ(num_requests / 2, cc_.on_complete_calls_); + EXPECT_EQ(num_requests / 2, cc_.on_cancel_calls_); } } @@ -484,19 +484,19 @@ TEST_P(ClientIntegrationTest, ClearTextNotPermitted) { buffer.copyOut(0, length, response_body.data()); EXPECT_EQ(response_body, "Cleartext is not permitted"); } - cc_.on_data_calls++; + cc_.on_data_calls_++; }; - stream_ = stream_prototype_->start(std::move(stream_callbacks), explicit_flow_control_); + stream_ = createNewStream(std::move(stream_callbacks)); stream_->sendHeaders(std::make_unique(default_request_headers_), true); terminal_callback_.waitReady(); - ASSERT_EQ(cc_.on_headers_calls, 1); - ASSERT_EQ(cc_.status, "400"); - ASSERT_EQ(cc_.on_data_calls, 1); - ASSERT_EQ(cc_.on_complete_calls, 1); + ASSERT_EQ(cc_.on_headers_calls_, 1); + ASSERT_EQ(cc_.status_, "400"); + ASSERT_EQ(cc_.on_data_calls_, 1); + ASSERT_EQ(cc_.on_complete_calls_, 1); } TEST_P(ClientIntegrationTest, BasicHttps) { @@ -525,10 +525,10 @@ TEST_P(ClientIntegrationTest, BasicHttps) { } else { EXPECT_EQ(length, 10); } - cc_.on_data_calls++; + cc_.on_data_calls_++; }; - stream_ = stream_prototype_->start(std::move(stream_callbacks), explicit_flow_control_); + stream_ = createNewStream(std::move(stream_callbacks)); stream_->sendHeaders(std::make_unique(default_request_headers_), false); @@ -538,12 +538,12 @@ TEST_P(ClientIntegrationTest, BasicHttps) { terminal_callback_.waitReady(); - ASSERT_EQ(cc_.on_headers_calls, 1); - ASSERT_EQ(cc_.status, "200"); - ASSERT_GE(cc_.on_data_calls, 1); - ASSERT_EQ(cc_.on_complete_calls, 1); + ASSERT_EQ(cc_.on_headers_calls_, 1); + ASSERT_EQ(cc_.status_, "200"); + ASSERT_GE(cc_.on_data_calls_, 1); + ASSERT_EQ(cc_.on_complete_calls_, 1); if (upstreamProtocol() == Http::CodecType::HTTP1) { - ASSERT_EQ(cc_.on_complete_received_byte_count, 67); + ASSERT_EQ(cc_.on_complete_received_byte_count_, 67); } } @@ -555,28 +555,28 @@ TEST_P(ClientIntegrationTest, BasicNon2xx) { ->setResponseHeaders(std::make_unique( Http::TestResponseHeaderMapImpl({{":status", "503"}}))); - stream_ = stream_prototype_->start(createDefaultStreamCallbacks(), explicit_flow_control_); + stream_ = createNewStream(createDefaultStreamCallbacks()); stream_->sendHeaders(std::make_unique(default_request_headers_), true); terminal_callback_.waitReady(); - ASSERT_EQ(cc_.on_error_calls, 0); - ASSERT_EQ(cc_.status, "503"); - ASSERT_EQ(cc_.on_headers_calls, 1); - ASSERT_EQ(cc_.on_complete_calls, 1); + ASSERT_EQ(cc_.on_error_calls_, 0); + ASSERT_EQ(cc_.status_, "503"); + ASSERT_EQ(cc_.on_headers_calls_, 1); + ASSERT_EQ(cc_.on_complete_calls_, 1); } TEST_P(ClientIntegrationTest, InvalidDomain) { initialize(); default_request_headers_.setHost("www.doesnotexist.com"); - stream_ = stream_prototype_->start(createDefaultStreamCallbacks(), explicit_flow_control_); + stream_ = createNewStream(createDefaultStreamCallbacks()); stream_->sendHeaders(std::make_unique(default_request_headers_), true); terminal_callback_.waitReady(); - ASSERT_EQ(cc_.on_error_calls, 1); - ASSERT_EQ(cc_.on_headers_calls, 0); + ASSERT_EQ(cc_.on_error_calls_, 1); + ASSERT_EQ(cc_.on_headers_calls_, 0); } TEST_P(ClientIntegrationTest, InvalidDomainFakeResolver) { @@ -592,7 +592,7 @@ TEST_P(ClientIntegrationTest, InvalidDomainFakeResolver) { default_request_headers_.setHost( absl::StrCat("www.doesnotexist.com:", fake_upstreams_[0]->localAddress()->ip()->port())); - stream_ = stream_prototype_->start(createDefaultStreamCallbacks(), explicit_flow_control_); + stream_ = createNewStream(createDefaultStreamCallbacks()); stream_->sendHeaders(std::make_unique(default_request_headers_), true); // Force the lookup to resolve to localhost. @@ -600,9 +600,9 @@ TEST_P(ClientIntegrationTest, InvalidDomainFakeResolver) { terminal_callback_.waitReady(); // Instead of an error we should get a 200 ok from the fake upstream. - ASSERT_EQ(cc_.on_error_calls, 0); - ASSERT_EQ(cc_.on_headers_calls, 1); - ASSERT_EQ(cc_.status, "200"); + ASSERT_EQ(cc_.on_error_calls_, 0); + ASSERT_EQ(cc_.on_headers_calls_, 1); + ASSERT_EQ(cc_.status_, "200"); } TEST_P(ClientIntegrationTest, ReresolveAndDrain) { @@ -635,11 +635,11 @@ TEST_P(ClientIntegrationTest, ReresolveAndDrain) { // Send a request. The original upstream should be used because of DNS block. default_request_headers_.setHost( absl::StrCat("www.lyft.com:", fake_upstreams_[0]->localAddress()->ip()->port())); - stream_ = createNewStream(stream_prototype_, createDefaultStreamCallbacks()); + stream_ = createNewStream(createDefaultStreamCallbacks()); stream_->sendHeaders(std::make_unique(default_request_headers_), true); terminal_callback_.waitReady(); - ASSERT_EQ(cc_.status, "201"); + ASSERT_EQ(cc_.status_, "201"); // No DNS queries, because of the initial cache load. EXPECT_EQ(0, getCounterValue("dns_cache.base_dns_cache.dns_query_attempt")); EXPECT_EQ(1, getCounterValue("dns_cache.base_dns_cache.cache_load")); @@ -655,11 +655,11 @@ TEST_P(ClientIntegrationTest, ReresolveAndDrain) { ASSERT_TRUE(waitForCounterGe("dns_cache.base_dns_cache.dns_query_attempt", 1)); EXPECT_EQ(0, getCounterValue("dns_cache.base_dns_cache.dns_query_success")); // The next request should go to the original upstream as there's been no drain. - stream_ = createNewStream(stream_prototype_, createDefaultStreamCallbacks()); + stream_ = createNewStream(createDefaultStreamCallbacks()); stream_->sendHeaders(std::make_unique(default_request_headers_), true); terminal_callback_.waitReady(); - ASSERT_EQ(cc_.status, "201"); + ASSERT_EQ(cc_.status_, "201"); // No DNS query should have finished. EXPECT_EQ(0, getCounterValue("dns_cache.base_dns_cache.dns_query_success")); @@ -669,11 +669,11 @@ TEST_P(ClientIntegrationTest, ReresolveAndDrain) { ASSERT_TRUE(waitForCounterGe("dns_cache.base_dns_cache.dns_query_success", 1)); // Do one final request. It should go to the second upstream and return 202 - stream_ = createNewStream(stream_prototype_, createDefaultStreamCallbacks()); + stream_ = createNewStream(createDefaultStreamCallbacks()); stream_->sendHeaders(std::make_unique(default_request_headers_), true); terminal_callback_.waitReady(); - ASSERT_EQ(cc_.status, "202"); + ASSERT_EQ(cc_.status_, "202"); } TEST_P(ClientIntegrationTest, BasicBeforeResponseHeaders) { @@ -681,13 +681,13 @@ TEST_P(ClientIntegrationTest, BasicBeforeResponseHeaders) { default_request_headers_.addCopy(AutonomousStream::RESET_AFTER_REQUEST, "yes"); - stream_ = stream_prototype_->start(createDefaultStreamCallbacks(), explicit_flow_control_); + stream_ = createNewStream(createDefaultStreamCallbacks()); stream_->sendHeaders(std::make_unique(default_request_headers_), true); terminal_callback_.waitReady(); - ASSERT_EQ(cc_.on_error_calls, 1); - ASSERT_EQ(cc_.on_headers_calls, 0); + ASSERT_EQ(cc_.on_error_calls_, 1); + ASSERT_EQ(cc_.on_headers_calls_, 0); } TEST_P(ClientIntegrationTest, ResetAfterResponseHeaders) { @@ -697,12 +697,12 @@ TEST_P(ClientIntegrationTest, ResetAfterResponseHeaders) { default_request_headers_.addCopy(AutonomousStream::RESET_AFTER_RESPONSE_HEADERS, "yes"); default_request_headers_.addCopy(AutonomousStream::RESPONSE_DATA_BLOCKS, "1"); - stream_ = stream_prototype_->start(createDefaultStreamCallbacks(), explicit_flow_control_); + stream_ = createNewStream(createDefaultStreamCallbacks()); stream_->sendHeaders(std::make_unique(default_request_headers_), true); terminal_callback_.waitReady(); - ASSERT_EQ(cc_.on_error_calls, 1); + ASSERT_EQ(cc_.on_error_calls_, 1); } TEST_P(ClientIntegrationTest, ResetAfterResponseHeadersExplicit) { @@ -713,7 +713,7 @@ TEST_P(ClientIntegrationTest, ResetAfterResponseHeadersExplicit) { default_request_headers_.addCopy(AutonomousStream::RESET_AFTER_RESPONSE_HEADERS, "yes"); default_request_headers_.addCopy(AutonomousStream::RESPONSE_DATA_BLOCKS, "1"); - stream_ = stream_prototype_->start(createDefaultStreamCallbacks(), explicit_flow_control_); + stream_ = createNewStream(createDefaultStreamCallbacks()); stream_->sendHeaders(std::make_unique(default_request_headers_), true); // Read the body chunk. This releases the error. @@ -721,7 +721,7 @@ TEST_P(ClientIntegrationTest, ResetAfterResponseHeadersExplicit) { terminal_callback_.waitReady(); - ASSERT_EQ(cc_.on_error_calls, 1); + ASSERT_EQ(cc_.on_error_calls_, 1); } TEST_P(ClientIntegrationTest, ResetAfterHeaderOnlyResponse) { @@ -731,12 +731,12 @@ TEST_P(ClientIntegrationTest, ResetAfterHeaderOnlyResponse) { default_request_headers_.addCopy(AutonomousStream::RESET_AFTER_RESPONSE_HEADERS, "yes"); default_request_headers_.addCopy(AutonomousStream::RESPONSE_DATA_BLOCKS, "0"); - stream_ = stream_prototype_->start(createDefaultStreamCallbacks(), explicit_flow_control_); + stream_ = createNewStream(createDefaultStreamCallbacks()); stream_->sendHeaders(std::make_unique(default_request_headers_), false); terminal_callback_.waitReady(); - ASSERT_EQ(cc_.on_error_calls, 1); + ASSERT_EQ(cc_.on_error_calls_, 1); } TEST_P(ClientIntegrationTest, ResetBetweenDataChunks) { @@ -746,12 +746,12 @@ TEST_P(ClientIntegrationTest, ResetBetweenDataChunks) { default_request_headers_.addCopy(AutonomousStream::RESET_AFTER_RESPONSE_DATA, "yes"); default_request_headers_.addCopy(AutonomousStream::RESPONSE_DATA_BLOCKS, "2"); - stream_ = stream_prototype_->start(createDefaultStreamCallbacks(), explicit_flow_control_); + stream_ = createNewStream(createDefaultStreamCallbacks()); stream_->sendHeaders(std::make_unique(default_request_headers_), true); terminal_callback_.waitReady(); - ASSERT_EQ(cc_.on_error_calls, 1); + ASSERT_EQ(cc_.on_error_calls_, 1); } TEST_P(ClientIntegrationTest, ResetAfterData) { @@ -761,24 +761,24 @@ TEST_P(ClientIntegrationTest, ResetAfterData) { default_request_headers_.addCopy(AutonomousStream::RESET_AFTER_RESPONSE_DATA, "yes"); default_request_headers_.addCopy(AutonomousStream::RESPONSE_DATA_BLOCKS, "1"); - stream_ = stream_prototype_->start(createDefaultStreamCallbacks(), explicit_flow_control_); + stream_ = createNewStream(createDefaultStreamCallbacks()); stream_->sendHeaders(std::make_unique(default_request_headers_), true); terminal_callback_.waitReady(); - ASSERT_EQ(cc_.on_error_calls, 1); + ASSERT_EQ(cc_.on_error_calls_, 1); } TEST_P(ClientIntegrationTest, CancelBeforeRequestHeadersSent) { autonomous_upstream_ = false; initialize(); - stream_ = stream_prototype_->start(createDefaultStreamCallbacks(), explicit_flow_control_); + stream_ = createNewStream(createDefaultStreamCallbacks()); stream_->cancel(); terminal_callback_.waitReady(); - ASSERT_EQ(cc_.on_cancel_calls, 1); + ASSERT_EQ(cc_.on_cancel_calls_, 1); } TEST_P(ClientIntegrationTest, CancelAfterRequestHeadersSent) { @@ -786,24 +786,24 @@ TEST_P(ClientIntegrationTest, CancelAfterRequestHeadersSent) { default_request_headers_.addCopy(AutonomousStream::RESPOND_AFTER_REQUEST_HEADERS, "yes"); - stream_ = stream_prototype_->start(createDefaultStreamCallbacks(), explicit_flow_control_); + stream_ = createNewStream(createDefaultStreamCallbacks()); stream_->sendHeaders(std::make_unique(default_request_headers_), false); stream_->cancel(); terminal_callback_.waitReady(); - ASSERT_EQ(cc_.on_cancel_calls, 1); + ASSERT_EQ(cc_.on_cancel_calls_, 1); } TEST_P(ClientIntegrationTest, CancelAfterRequestComplete) { autonomous_upstream_ = false; initialize(); - stream_ = stream_prototype_->start(createDefaultStreamCallbacks(), explicit_flow_control_); + stream_ = createNewStream(createDefaultStreamCallbacks()); stream_->sendHeaders(std::make_unique(default_request_headers_), true); stream_->cancel(); terminal_callback_.waitReady(); - ASSERT_EQ(cc_.on_cancel_calls, 1); + ASSERT_EQ(cc_.on_cancel_calls_, 1); } TEST_P(ClientIntegrationTest, CancelDuringResponse) { @@ -815,13 +815,13 @@ TEST_P(ClientIntegrationTest, CancelDuringResponse) { stream_callbacks.on_headers_ = [this, &headers_callback](const Http::ResponseHeaderMap& headers, bool /* end_stream */, envoy_stream_intel) { - cc_.status = headers.getStatusValue(); - cc_.on_headers_calls++; + cc_.status_ = headers.getStatusValue(); + cc_.on_headers_calls_++; headers_callback.setReady(); return nullptr; }; - stream_ = stream_prototype_->start(std::move(stream_callbacks), explicit_flow_control_); + stream_ = createNewStream(std::move(stream_callbacks)); stream_->sendHeaders(std::make_unique(default_request_headers_), true); @@ -833,21 +833,21 @@ TEST_P(ClientIntegrationTest, CancelDuringResponse) { upstream_request_->encodeHeaders(Http::TestResponseHeaderMapImpl{{":status", "200"}}, false); headers_callback.waitReady(); - ASSERT_EQ(cc_.on_headers_calls, 1); - ASSERT_EQ(cc_.status, "200"); - ASSERT_EQ(cc_.on_data_calls, 0); - ASSERT_EQ(cc_.on_complete_calls, 0); + ASSERT_EQ(cc_.on_headers_calls_, 1); + ASSERT_EQ(cc_.status_, "200"); + ASSERT_EQ(cc_.on_data_calls_, 0); + ASSERT_EQ(cc_.on_complete_calls_, 0); // Now cancel, and make sure the cancel is received. stream_->cancel(); - memset(&cc_.final_intel, 0, sizeof(cc_.final_intel)); + memset(&cc_.final_intel_, 0, sizeof(cc_.final_intel_)); terminal_callback_.waitReady(); - ASSERT_EQ(cc_.on_headers_calls, 1); - ASSERT_EQ(cc_.status, "200"); - ASSERT_EQ(cc_.on_data_calls, 0); - ASSERT_EQ(cc_.on_complete_calls, 0); - ASSERT_EQ(cc_.on_cancel_calls, 1); + ASSERT_EQ(cc_.on_headers_calls_, 1); + ASSERT_EQ(cc_.status_, "200"); + ASSERT_EQ(cc_.on_data_calls_, 0); + ASSERT_EQ(cc_.on_complete_calls_, 0); + ASSERT_EQ(cc_.on_cancel_calls_, 1); if (upstreamProtocol() != Http::CodecType::HTTP1) { ASSERT_TRUE(upstream_request_->waitForReset()); @@ -870,7 +870,7 @@ TEST_P(ClientIntegrationTest, BasicCancelWithCompleteStream) { initialize(); - stream_ = stream_prototype_->start(createDefaultStreamCallbacks(), explicit_flow_control_); + stream_ = createNewStream(createDefaultStreamCallbacks()); stream_->sendHeaders(std::make_unique(default_request_headers_), true); @@ -881,9 +881,9 @@ TEST_P(ClientIntegrationTest, BasicCancelWithCompleteStream) { upstream_request_->encodeHeaders(Http::TestResponseHeaderMapImpl{{":status", "200"}}, true); terminal_callback_.waitReady(); - ASSERT_EQ(cc_.on_headers_calls, 1); - ASSERT_EQ(cc_.status, "200"); - ASSERT_EQ(cc_.on_complete_calls, 1); + ASSERT_EQ(cc_.on_headers_calls_, 1); + ASSERT_EQ(cc_.status_, "200"); + ASSERT_EQ(cc_.on_complete_calls_, 1); // Now cancel. As on_complete has been called cancel is a no-op but is // non-problematic. @@ -900,13 +900,13 @@ TEST_P(ClientIntegrationTest, CancelWithPartialStream) { stream_callbacks.on_headers_ = [this, &headers_callback](const Http::ResponseHeaderMap& headers, bool /* end_stream */, envoy_stream_intel) { - cc_.status = headers.getStatusValue(); - cc_.on_headers_calls++; + cc_.status_ = headers.getStatusValue(); + cc_.on_headers_calls_++; headers_callback.setReady(); return nullptr; }; - stream_ = stream_prototype_->start(std::move(stream_callbacks), explicit_flow_control_); + stream_ = createNewStream(std::move(stream_callbacks)); stream_->sendHeaders(std::make_unique(default_request_headers_), true); @@ -920,10 +920,10 @@ TEST_P(ClientIntegrationTest, CancelWithPartialStream) { upstream_request_->encodeData(1, true); headers_callback.waitReady(); - ASSERT_EQ(cc_.on_headers_calls, 1); - ASSERT_EQ(cc_.status, "200"); - ASSERT_EQ(cc_.on_data_calls, 0); - ASSERT_EQ(cc_.on_complete_calls, 0); + ASSERT_EQ(cc_.on_headers_calls_, 1); + ASSERT_EQ(cc_.status_, "200"); + ASSERT_EQ(cc_.on_data_calls_, 0); + ASSERT_EQ(cc_.on_complete_calls_, 0); // Due to explicit flow control, the upstream stream is complete, but the // callbacks will not be called for data and completion. Cancel the stream @@ -931,11 +931,11 @@ TEST_P(ClientIntegrationTest, CancelWithPartialStream) { stream_->cancel(); terminal_callback_.waitReady(); - ASSERT_EQ(cc_.on_headers_calls, 1); - ASSERT_EQ(cc_.status, "200"); - ASSERT_EQ(cc_.on_data_calls, 0); - ASSERT_EQ(cc_.on_complete_calls, 0); - ASSERT_EQ(cc_.on_cancel_calls, 1); + ASSERT_EQ(cc_.on_headers_calls_, 1); + ASSERT_EQ(cc_.status_, "200"); + ASSERT_EQ(cc_.on_data_calls_, 0); + ASSERT_EQ(cc_.on_complete_calls_, 0); + ASSERT_EQ(cc_.on_cancel_calls_, 1); } // Test header key case sensitivity. @@ -956,14 +956,14 @@ TEST_P(ClientIntegrationTest, CaseSensitive) { EnvoyStreamCallbacks stream_callbacks = createDefaultStreamCallbacks(); stream_callbacks.on_headers_ = [this](const Http::ResponseHeaderMap& headers, bool, envoy_stream_intel) { - cc_.status = headers.getStatusValue(); - cc_.on_headers_calls++; + cc_.status_ = headers.getStatusValue(); + cc_.on_headers_calls_++; auto result = headers.get(Http::LowerCaseString("My-ResponsE-Header")); ASSERT_FALSE(result.empty()); EXPECT_TRUE(result[0]->value() == "foo"); }; - stream_ = stream_prototype_->start(std::move(stream_callbacks), explicit_flow_control_); + stream_ = createNewStream(std::move(stream_callbacks)); stream_->sendHeaders(std::move(headers), true); Envoy::FakeRawConnectionPtr upstream_connection; @@ -981,10 +981,10 @@ TEST_P(ClientIntegrationTest, CaseSensitive) { terminal_callback_.waitReady(); - ASSERT_EQ(cc_.on_headers_calls, 1); - ASSERT_EQ(cc_.status, "200"); - ASSERT_EQ(cc_.on_data_calls, 0); - ASSERT_EQ(cc_.on_complete_calls, 1); + ASSERT_EQ(cc_.on_headers_calls_, 1); + ASSERT_EQ(cc_.status_, "200"); + ASSERT_EQ(cc_.on_data_calls_, 0); + ASSERT_EQ(cc_.on_complete_calls_, 1); } TEST_P(ClientIntegrationTest, TimeoutOnRequestPath) { @@ -993,7 +993,7 @@ TEST_P(ClientIntegrationTest, TimeoutOnRequestPath) { autonomous_upstream_ = false; initialize(); - stream_ = stream_prototype_->start(createDefaultStreamCallbacks(), explicit_flow_control_); + stream_ = createNewStream(createDefaultStreamCallbacks()); stream_->sendHeaders(std::make_unique(default_request_headers_), false); @@ -1004,10 +1004,10 @@ TEST_P(ClientIntegrationTest, TimeoutOnRequestPath) { terminal_callback_.waitReady(); - ASSERT_EQ(cc_.on_headers_calls, 0); - ASSERT_EQ(cc_.on_data_calls, 0); - ASSERT_EQ(cc_.on_complete_calls, 0); - ASSERT_EQ(cc_.on_error_calls, 1); + ASSERT_EQ(cc_.on_headers_calls_, 0); + ASSERT_EQ(cc_.on_data_calls_, 0); + ASSERT_EQ(cc_.on_complete_calls_, 0); + ASSERT_EQ(cc_.on_error_calls_, 1); if (getCodecType() != Http::CodecType::HTTP1) { ASSERT_TRUE(upstream_request_->waitForReset()); @@ -1021,7 +1021,7 @@ TEST_P(ClientIntegrationTest, TimeoutOnResponsePath) { autonomous_upstream_ = false; initialize(); - stream_ = stream_prototype_->start(createDefaultStreamCallbacks(), explicit_flow_control_); + stream_ = createNewStream(createDefaultStreamCallbacks()); stream_->sendHeaders(std::make_unique(default_request_headers_), true); @@ -1036,11 +1036,11 @@ TEST_P(ClientIntegrationTest, TimeoutOnResponsePath) { // Wait for timeout. terminal_callback_.waitReady(); - ASSERT_EQ(cc_.on_headers_calls, 1); - ASSERT_EQ(cc_.status, "200"); - ASSERT_EQ(cc_.on_data_calls, 0); - ASSERT_EQ(cc_.on_complete_calls, 0); - ASSERT_EQ(cc_.on_error_calls, 1); + ASSERT_EQ(cc_.on_headers_calls_, 1); + ASSERT_EQ(cc_.status_, "200"); + ASSERT_EQ(cc_.on_data_calls_, 0); + ASSERT_EQ(cc_.on_complete_calls_, 0); + ASSERT_EQ(cc_.on_error_calls_, 1); if (upstreamProtocol() != Http::CodecType::HTTP1) { ASSERT_TRUE(upstream_request_->waitForReset()); @@ -1056,13 +1056,13 @@ TEST_P(ClientIntegrationTest, ResetWithBidiTraffic) { stream_callbacks.on_headers_ = [this, &headers_callback](const Http::ResponseHeaderMap& headers, bool /* end_stream */, envoy_stream_intel) { - cc_.status = headers.getStatusValue(); - cc_.on_headers_calls++; + cc_.status_ = headers.getStatusValue(); + cc_.on_headers_calls_++; headers_callback.setReady(); return nullptr; }; - stream_ = stream_prototype_->start(std::move(stream_callbacks), explicit_flow_control_); + stream_ = createNewStream(std::move(stream_callbacks)); stream_->sendHeaders(std::make_unique(default_request_headers_), false); @@ -1095,13 +1095,13 @@ TEST_P(ClientIntegrationTest, ResetWithBidiTrafficExplicitData) { stream_callbacks.on_headers_ = [this, &headers_callback](const Http::ResponseHeaderMap& headers, bool /* end_stream */, envoy_stream_intel) { - cc_.status = headers.getStatusValue(); - cc_.on_headers_calls++; + cc_.status_ = headers.getStatusValue(); + cc_.on_headers_calls_++; headers_callback.setReady(); return nullptr; }; - stream_ = stream_prototype_->start(std::move(stream_callbacks), explicit_flow_control_); + stream_ = createNewStream(std::move(stream_callbacks)); stream_->sendHeaders(std::make_unique(default_request_headers_), false); @@ -1134,22 +1134,22 @@ TEST_P(ClientIntegrationTest, Proxying) { fake_upstreams_[0]->localAddress()->ip()->port()); } - stream_ = stream_prototype_->start(createDefaultStreamCallbacks(), explicit_flow_control_); + stream_ = createNewStream(createDefaultStreamCallbacks()); // The initial request will do the DNS lookup. stream_->sendHeaders(std::make_unique(default_request_headers_), true); terminal_callback_.waitReady(); - ASSERT_EQ(cc_.status, "200"); - ASSERT_EQ(cc_.on_complete_calls, 1); + ASSERT_EQ(cc_.status_, "200"); + ASSERT_EQ(cc_.on_complete_calls_, 1); stream_.reset(); // The second request will use the cached DNS entry and should succeed as well. - stream_ = stream_prototype_->start(createDefaultStreamCallbacks(), explicit_flow_control_); + stream_ = createNewStream(createDefaultStreamCallbacks()); stream_->sendHeaders(std::make_unique(default_request_headers_), true); terminal_callback_.waitReady(); - ASSERT_EQ(cc_.status, "200"); - ASSERT_EQ(cc_.on_complete_calls, 2); + ASSERT_EQ(cc_.status_, "200"); + ASSERT_EQ(cc_.on_complete_calls_, 2); } TEST_P(ClientIntegrationTest, DirectResponse) { @@ -1158,20 +1158,20 @@ TEST_P(ClientIntegrationTest, DirectResponse) { // Override to not validate stream intel. EnvoyStreamCallbacks stream_callbacks = createDefaultStreamCallbacks(); stream_callbacks.on_complete_ = [this](envoy_stream_intel, envoy_final_stream_intel final_intel) { - cc_.on_complete_received_byte_count = final_intel.received_byte_count; - cc_.on_complete_calls++; - cc_.terminal_callback->setReady(); + cc_.on_complete_received_byte_count_ = final_intel.received_byte_count; + cc_.on_complete_calls_++; + cc_.terminal_callback_->setReady(); }; default_request_headers_.setHost("127.0.0.1"); default_request_headers_.setPath("/"); - stream_ = stream_prototype_->start(std::move(stream_callbacks), explicit_flow_control_); + stream_ = createNewStream(std::move(stream_callbacks)); stream_->sendHeaders(std::make_unique(default_request_headers_), true); terminal_callback_.waitReady(); - ASSERT_EQ(cc_.status, "404"); - ASSERT_EQ(cc_.on_headers_calls, 1); + ASSERT_EQ(cc_.status_, "404"); + ASSERT_EQ(cc_.on_headers_calls_, 1); stream_.reset(); // Verify the default runtime values. diff --git a/mobile/test/common/integration/rtds_integration_test.cc b/mobile/test/common/integration/rtds_integration_test.cc index 76bf6994b807..e9c009df141f 100644 --- a/mobile/test/common/integration/rtds_integration_test.cc +++ b/mobile/test/common/integration/rtds_integration_test.cc @@ -41,14 +41,14 @@ class RtdsIntegrationTest : public XdsIntegrationTest { stream_->sendHeaders(std::make_unique(default_request_headers_), true); terminal_callback_.waitReady(); - EXPECT_EQ(cc_.on_headers_calls, 1); + EXPECT_EQ(cc_.on_headers_calls_, 1); EXPECT_EQ(cc_.status, "200"); - EXPECT_EQ(cc_.on_data_calls, 2); - EXPECT_EQ(cc_.on_complete_calls, 1); - EXPECT_EQ(cc_.on_cancel_calls, 0); - EXPECT_EQ(cc_.on_error_calls, 0); - EXPECT_EQ(cc_.on_header_consumed_bytes_from_response, 27); - EXPECT_EQ(cc_.on_complete_received_byte_count, 67); + EXPECT_EQ(cc_.on_data_calls_, 2); + EXPECT_EQ(cc_.on_complete_calls_, 1); + EXPECT_EQ(cc_.on_cancel_calls_, 0); + EXPECT_EQ(cc_.on_error_calls_, 0); + EXPECT_EQ(cc_.on_header_consumed_bytes_from_response_, 27); + EXPECT_EQ(cc_.on_complete_received_byte_count_, 67); // Check that the Runtime config is from the static layer. EXPECT_FALSE(Runtime::runtimeFeatureEnabled("envoy.reloadable_features.test_feature_false")); From 7b7ab06de635f830529cc54a807073a2db2c4c38 Mon Sep 17 00:00:00 2001 From: Fredy Wijaya Date: Thu, 9 May 2024 13:48:48 -0500 Subject: [PATCH 12/20] mobile: Remove the deprecated Stream::sendData and Stream::close (#34059) Risk Level: low Testing: CI Docs Changes: n/a Release Notes: n/a Platform Specific Features: mobile Signed-off-by: Fredy Wijaya --- mobile/library/cc/stream.cc | 10 ---------- mobile/library/cc/stream.h | 10 ++++++---- 2 files changed, 6 insertions(+), 14 deletions(-) diff --git a/mobile/library/cc/stream.cc b/mobile/library/cc/stream.cc index dd2a49e6e024..33832db8520a 100644 --- a/mobile/library/cc/stream.cc +++ b/mobile/library/cc/stream.cc @@ -15,11 +15,6 @@ Stream& Stream::sendHeaders(Http::RequestHeaderMapPtr headers, bool end_stream) return *this; } -Stream& Stream::sendData(envoy_data data) { - Buffer::InstancePtr buffer = Data::Utility::toInternalData(data); - return sendData(std::move(buffer)); -} - Stream& Stream::sendData(Buffer::InstancePtr buffer) { engine_->sendData(handle_, std::move(buffer), false); return *this; @@ -34,11 +29,6 @@ void Stream::close(Http::RequestTrailerMapPtr trailers) { engine_->sendTrailers(handle_, std::move(trailers)); } -void Stream::close(envoy_data data) { - Buffer::InstancePtr buffer = Data::Utility::toInternalData(data); - close(std::move(buffer)); -} - void Stream::close(Buffer::InstancePtr buffer) { engine_->sendData(handle_, std::move(buffer), true); } diff --git a/mobile/library/cc/stream.h b/mobile/library/cc/stream.h index 3221ef7f1dbe..36e4c40e183c 100644 --- a/mobile/library/cc/stream.h +++ b/mobile/library/cc/stream.h @@ -24,8 +24,6 @@ class Stream { */ Stream& sendHeaders(Http::RequestHeaderMapPtr headers, bool end_stream); - [[deprecated]] Stream& sendData(envoy_data data); - /** * Send data over an open HTTP stream. This method can be invoked multiple times. * @@ -33,6 +31,11 @@ class Stream { */ Stream& sendData(Buffer::InstancePtr buffer); + /** + * Reads the data up to the number of `bytes_to_read`. + * + * @param bytes_to_read the number of bytes read + */ Stream& readData(size_t bytes_to_read); /** @@ -43,8 +46,6 @@ class Stream { */ void close(Http::RequestTrailerMapPtr trailers); - [[deprecated]] void close(envoy_data data); - /** * Send data over an open HTTP stream and closes the stream.. This method can only be invoked * once. @@ -53,6 +54,7 @@ class Stream { */ void close(Buffer::InstancePtr buffer); + /** Cancels the stream. */ void cancel(); private: From cd5ef906026160ec2cd766d8d18217e668c256d8 Mon Sep 17 00:00:00 2001 From: alyssawilk Date: Thu, 9 May 2024 21:45:22 -0400 Subject: [PATCH 13/20] load balancers: removing exceptions from thread aware LB (#34032) Risk Level: low Testing: updated tests Docs Changes: n/a Release Notes: n/a envoyproxy/envoy-mobile#176 Signed-off-by: Alyssa Wilk --- envoy/upstream/load_balancer.h | 2 +- .../common/upstream/cluster_manager_impl.cc | 2 +- .../extensions/clusters/aggregate/cluster.h | 2 +- .../clusters/dynamic_forward_proxy/cluster.h | 2 +- .../original_dst/original_dst_cluster.h | 2 +- .../clusters/redis/redis_cluster_lb.h | 2 +- .../common/factory_base.h | 2 +- .../common/thread_aware_lb_impl.cc | 64 ++++++++++--------- .../common/thread_aware_lb_impl.h | 4 +- .../load_balancing_policies/subset/config.cc | 2 +- .../subset/subset_lb.cc | 2 +- .../upstream/load_balancer_benchmark.cc | 20 +++--- .../clusters/redis/redis_cluster_lb_test.cc | 2 +- .../least_request/config_test.cc | 2 +- .../maglev/config_test.cc | 2 +- .../maglev/maglev_lb_test.cc | 2 +- .../random/config_test.cc | 2 +- .../ring_hash/config_test.cc | 2 +- .../ring_hash/ring_hash_lb_test.cc | 2 +- .../round_robin/config_test.cc | 2 +- .../subset/config_test.cc | 2 +- .../load_balancers/custom_lb_policy.h | 2 +- .../upstream/thread_aware_load_balancer.h | 2 +- tools/code_format/config.yaml | 1 - 24 files changed, 67 insertions(+), 62 deletions(-) diff --git a/envoy/upstream/load_balancer.h b/envoy/upstream/load_balancer.h index d9cb0728432f..c4b31ec27d2c 100644 --- a/envoy/upstream/load_balancer.h +++ b/envoy/upstream/load_balancer.h @@ -229,7 +229,7 @@ class ThreadAwareLoadBalancer { * instantiate any needed structured and prepare for further updates. The cluster manager * will do this at the appropriate time. */ - virtual void initialize() PURE; + virtual absl::Status initialize() PURE; }; using ThreadAwareLoadBalancerPtr = std::unique_ptr; diff --git a/source/common/upstream/cluster_manager_impl.cc b/source/common/upstream/cluster_manager_impl.cc index 1679e15f24c3..cdeecfe1a3a8 100644 --- a/source/common/upstream/cluster_manager_impl.cc +++ b/source/common/upstream/cluster_manager_impl.cc @@ -604,7 +604,7 @@ void ClusterManagerImpl::onClusterInit(ClusterManagerCluster& cm_cluster) { cluster_data = active_clusters_.find(cluster.info()->name()); if (cluster_data->second->thread_aware_lb_ != nullptr) { - cluster_data->second->thread_aware_lb_->initialize(); + THROW_IF_NOT_OK(cluster_data->second->thread_aware_lb_->initialize()); } // Now setup for cross-thread updates. diff --git a/source/extensions/clusters/aggregate/cluster.h b/source/extensions/clusters/aggregate/cluster.h index 18c084c38457..e691465b83c6 100644 --- a/source/extensions/clusters/aggregate/cluster.h +++ b/source/extensions/clusters/aggregate/cluster.h @@ -156,7 +156,7 @@ struct AggregateThreadAwareLoadBalancer : public Upstream::ThreadAwareLoadBalanc // Upstream::ThreadAwareLoadBalancer Upstream::LoadBalancerFactorySharedPtr factory() override { return factory_; } - void initialize() override {} + absl::Status initialize() override { return absl::OkStatus(); } std::shared_ptr factory_; }; diff --git a/source/extensions/clusters/dynamic_forward_proxy/cluster.h b/source/extensions/clusters/dynamic_forward_proxy/cluster.h index f974474b3e90..a6b6d4a776ca 100644 --- a/source/extensions/clusters/dynamic_forward_proxy/cluster.h +++ b/source/extensions/clusters/dynamic_forward_proxy/cluster.h @@ -153,7 +153,7 @@ class Cluster : public Upstream::BaseDynamicClusterImpl, Upstream::LoadBalancerFactorySharedPtr factory() override { return std::make_shared(cluster_); } - void initialize() override {} + absl::Status initialize() override { return absl::OkStatus(); } private: Cluster& cluster_; diff --git a/source/extensions/clusters/original_dst/original_dst_cluster.h b/source/extensions/clusters/original_dst/original_dst_cluster.h index 68a44cf5b945..1a73d779ac5b 100644 --- a/source/extensions/clusters/original_dst/original_dst_cluster.h +++ b/source/extensions/clusters/original_dst/original_dst_cluster.h @@ -151,7 +151,7 @@ class OriginalDstCluster : public ClusterImplBase { Upstream::LoadBalancerFactorySharedPtr factory() override { return std::make_shared(cluster_); } - void initialize() override {} + absl::Status initialize() override { return absl::OkStatus(); } const OriginalDstClusterHandleSharedPtr cluster_; }; diff --git a/source/extensions/clusters/redis/redis_cluster_lb.h b/source/extensions/clusters/redis/redis_cluster_lb.h index b3b9725e0d91..bd86f8e07398 100644 --- a/source/extensions/clusters/redis/redis_cluster_lb.h +++ b/source/extensions/clusters/redis/redis_cluster_lb.h @@ -235,7 +235,7 @@ class RedisClusterThreadAwareLoadBalancer : public Upstream::ThreadAwareLoadBala // Upstream::ThreadAwareLoadBalancer Upstream::LoadBalancerFactorySharedPtr factory() override { return factory_; } - void initialize() override{}; + absl::Status initialize() override { return absl::OkStatus(); } private: Upstream::LoadBalancerFactorySharedPtr factory_; diff --git a/source/extensions/load_balancing_policies/common/factory_base.h b/source/extensions/load_balancing_policies/common/factory_base.h index 5d6ed144a796..b2216ac66581 100644 --- a/source/extensions/load_balancing_policies/common/factory_base.h +++ b/source/extensions/load_balancing_policies/common/factory_base.h @@ -59,7 +59,7 @@ class FactoryBase : public Upstream::TypedLoadBalancerFactoryBase { ThreadAwareLb(Upstream::LoadBalancerFactorySharedPtr factory) : factory_(std::move(factory)) {} Upstream::LoadBalancerFactorySharedPtr factory() override { return factory_; } - void initialize() override {} + absl::Status initialize() override { return absl::OkStatus(); } private: Upstream::LoadBalancerFactorySharedPtr factory_; diff --git a/source/extensions/load_balancing_policies/common/thread_aware_lb_impl.cc b/source/extensions/load_balancing_policies/common/thread_aware_lb_impl.cc index e77ed4d50729..b9b052db15dc 100644 --- a/source/extensions/load_balancing_policies/common/thread_aware_lb_impl.cc +++ b/source/extensions/load_balancing_policies/common/thread_aware_lb_impl.cc @@ -10,16 +10,16 @@ namespace Upstream { // HostSetImpl::effectiveLocalityWeight. namespace { -void normalizeHostWeights(const HostVector& hosts, double normalized_locality_weight, - NormalizedHostWeightVector& normalized_host_weights, - double& min_normalized_weight, double& max_normalized_weight) { +absl::Status normalizeHostWeights(const HostVector& hosts, double normalized_locality_weight, + NormalizedHostWeightVector& normalized_host_weights, + double& min_normalized_weight, double& max_normalized_weight) { // sum should be at most uint32_t max value, so we can validate it by accumulating into unit64_t // and making sure there was no overflow uint64_t sum = 0; for (const auto& host : hosts) { sum += host->weight(); if (sum > std::numeric_limits::max()) { - throwEnvoyExceptionOrPanic( + return absl::InvalidArgumentError( fmt::format("The sum of weights of all upstream hosts in a locality exceeds {}", std::numeric_limits::max())); } @@ -31,12 +31,14 @@ void normalizeHostWeights(const HostVector& hosts, double normalized_locality_we min_normalized_weight = std::min(min_normalized_weight, weight); max_normalized_weight = std::max(max_normalized_weight, weight); } + return absl::OkStatus(); } -void normalizeLocalityWeights(const HostsPerLocality& hosts_per_locality, - const LocalityWeights& locality_weights, - NormalizedHostWeightVector& normalized_host_weights, - double& min_normalized_weight, double& max_normalized_weight) { +absl::Status normalizeLocalityWeights(const HostsPerLocality& hosts_per_locality, + const LocalityWeights& locality_weights, + NormalizedHostWeightVector& normalized_host_weights, + double& min_normalized_weight, + double& max_normalized_weight) { ASSERT(locality_weights.size() == hosts_per_locality.get().size()); // sum should be at most uint32_t max value, so we can validate it by accumulating into unit64_t @@ -45,7 +47,7 @@ void normalizeLocalityWeights(const HostsPerLocality& hosts_per_locality, for (const auto weight : locality_weights) { sum += weight; if (sum > std::numeric_limits::max()) { - throwEnvoyExceptionOrPanic( + return absl::InvalidArgumentError( fmt::format("The sum of weights of all localities at the same priority exceeds {}", std::numeric_limits::max())); } @@ -53,7 +55,7 @@ void normalizeLocalityWeights(const HostsPerLocality& hosts_per_locality, // Locality weights (unlike host weights) may be 0. If _all_ locality weights were 0, bail out. if (sum == 0) { - return; + return absl::OkStatus(); } // Compute normalized weights for all hosts in each locality. If a locality was assigned zero @@ -62,34 +64,38 @@ void normalizeLocalityWeights(const HostsPerLocality& hosts_per_locality, if (locality_weights[i] != 0) { const HostVector& hosts = hosts_per_locality.get()[i]; const double normalized_locality_weight = static_cast(locality_weights[i]) / sum; - normalizeHostWeights(hosts, normalized_locality_weight, normalized_host_weights, - min_normalized_weight, max_normalized_weight); + RETURN_IF_NOT_OK(normalizeHostWeights(hosts, normalized_locality_weight, + normalized_host_weights, min_normalized_weight, + max_normalized_weight)); } } + return absl::OkStatus(); } -void normalizeWeights(const HostSet& host_set, bool in_panic, - NormalizedHostWeightVector& normalized_host_weights, - double& min_normalized_weight, double& max_normalized_weight, - bool locality_weighted_balancing) { +absl::Status normalizeWeights(const HostSet& host_set, bool in_panic, + NormalizedHostWeightVector& normalized_host_weights, + double& min_normalized_weight, double& max_normalized_weight, + bool locality_weighted_balancing) { if (!locality_weighted_balancing || host_set.localityWeights() == nullptr || host_set.localityWeights()->empty()) { // If we're not dealing with locality weights, just normalize weights for the flat set of hosts. const auto& hosts = in_panic ? host_set.hosts() : host_set.healthyHosts(); - normalizeHostWeights(hosts, 1.0, normalized_host_weights, min_normalized_weight, - max_normalized_weight); + RETURN_IF_NOT_OK(normalizeHostWeights(hosts, 1.0, normalized_host_weights, + min_normalized_weight, max_normalized_weight)); } else { // Otherwise, normalize weights across all localities. const auto& hosts_per_locality = in_panic ? host_set.hostsPerLocality() : host_set.healthyHostsPerLocality(); - normalizeLocalityWeights(hosts_per_locality, *(host_set.localityWeights()), - normalized_host_weights, min_normalized_weight, max_normalized_weight); + RETURN_IF_NOT_OK(normalizeLocalityWeights(hosts_per_locality, *(host_set.localityWeights()), + normalized_host_weights, min_normalized_weight, + max_normalized_weight)); } + return absl::OkStatus(); } } // namespace -void ThreadAwareLoadBalancerBase::initialize() { +absl::Status ThreadAwareLoadBalancerBase::initialize() { // TODO(mattklein123): In the future, once initialized and the initial LB is built, it would be // better to use a background thread for computing LB updates. This has the substantial benefit // that if the LB computation thread falls behind, host set updates can be trivially collapsed. @@ -97,15 +103,12 @@ void ThreadAwareLoadBalancerBase::initialize() { // complicated initialization as the load balancer would need its own initialized callback. I // think the synchronous/asynchronous split is probably the best option. priority_update_cb_ = priority_set_.addPriorityUpdateCb( - [this](uint32_t, const HostVector&, const HostVector&) -> absl::Status { - refresh(); - return absl::OkStatus(); - }); + [this](uint32_t, const HostVector&, const HostVector&) -> absl::Status { return refresh(); }); - refresh(); + return refresh(); } -void ThreadAwareLoadBalancerBase::refresh() { +absl::Status ThreadAwareLoadBalancerBase::refresh() { auto per_priority_state_vector = std::make_shared>( priority_set_.hostSetsPerPriority().size()); auto healthy_per_priority_load = @@ -125,8 +128,10 @@ void ThreadAwareLoadBalancerBase::refresh() { NormalizedHostWeightVector normalized_host_weights; double min_normalized_weight = 1.0; double max_normalized_weight = 0.0; - normalizeWeights(*host_set, per_priority_state->global_panic_, normalized_host_weights, - min_normalized_weight, max_normalized_weight, locality_weighted_balancing_); + absl::Status status = normalizeWeights(*host_set, per_priority_state->global_panic_, + normalized_host_weights, min_normalized_weight, + max_normalized_weight, locality_weighted_balancing_); + RETURN_IF_NOT_OK(status); per_priority_state->current_lb_ = createLoadBalancer( std::move(normalized_host_weights), min_normalized_weight, max_normalized_weight); } @@ -137,6 +142,7 @@ void ThreadAwareLoadBalancerBase::refresh() { factory_->degraded_per_priority_load_ = degraded_per_priority_load; factory_->per_priority_state_ = per_priority_state_vector; } + return absl::OkStatus(); } HostConstSharedPtr diff --git a/source/extensions/load_balancing_policies/common/thread_aware_lb_impl.h b/source/extensions/load_balancing_policies/common/thread_aware_lb_impl.h index f8217218fcc8..70c93013f393 100644 --- a/source/extensions/load_balancing_policies/common/thread_aware_lb_impl.h +++ b/source/extensions/load_balancing_policies/common/thread_aware_lb_impl.h @@ -87,7 +87,7 @@ class ThreadAwareLoadBalancerBase : public LoadBalancerBase, public ThreadAwareL }; // Upstream::ThreadAwareLoadBalancer LoadBalancerFactorySharedPtr factory() override { return factory_; } - void initialize() override; + absl::Status initialize() override; // Upstream::LoadBalancer HostConstSharedPtr chooseHost(LoadBalancerContext*) override { return nullptr; } @@ -165,7 +165,7 @@ class ThreadAwareLoadBalancerBase : public LoadBalancerBase, public ThreadAwareL virtual HashingLoadBalancerSharedPtr createLoadBalancer(const NormalizedHostWeightVector& normalized_host_weights, double min_normalized_weight, double max_normalized_weight) PURE; - void refresh(); + absl::Status refresh(); std::shared_ptr factory_; const bool locality_weighted_balancing_{}; diff --git a/source/extensions/load_balancing_policies/subset/config.cc b/source/extensions/load_balancing_policies/subset/config.cc index cc6873c1c1a2..05eb9588361a 100644 --- a/source/extensions/load_balancing_policies/subset/config.cc +++ b/source/extensions/load_balancing_policies/subset/config.cc @@ -41,7 +41,7 @@ class ThreadAwareLb : public Upstream::ThreadAwareLoadBalancer { ThreadAwareLb(Upstream::LoadBalancerFactorySharedPtr factory) : factory_(std::move(factory)) {} Upstream::LoadBalancerFactorySharedPtr factory() override { return factory_; } - void initialize() override {} + absl::Status initialize() override { return absl::OkStatus(); } private: Upstream::LoadBalancerFactorySharedPtr factory_; diff --git a/source/extensions/load_balancing_policies/subset/subset_lb.cc b/source/extensions/load_balancing_policies/subset/subset_lb.cc index 5d0cd7fd7e44..7242a6f03d77 100644 --- a/source/extensions/load_balancing_policies/subset/subset_lb.cc +++ b/source/extensions/load_balancing_policies/subset/subset_lb.cc @@ -719,7 +719,7 @@ SubsetLoadBalancer::PrioritySubsetImpl::PrioritySubsetImpl(const SubsetLoadBalan subset_lb.lb_config_.createLoadBalancer(subset_lb.cluster_info_, *this, subset_lb.runtime_, subset_lb.random_, subset_lb.time_source_); ASSERT(thread_aware_lb_ != nullptr); - thread_aware_lb_->initialize(); + THROW_IF_NOT_OK(thread_aware_lb_->initialize()); lb_ = thread_aware_lb_->factory()->create({*this, original_local_priority_set_}); triggerCallbacks(); diff --git a/test/common/upstream/load_balancer_benchmark.cc b/test/common/upstream/load_balancer_benchmark.cc index d4b51fe18e0a..fc71d28decf9 100644 --- a/test/common/upstream/load_balancer_benchmark.cc +++ b/test/common/upstream/load_balancer_benchmark.cc @@ -207,7 +207,7 @@ void benchmarkRingHashLoadBalancerBuildRing(::benchmark::State& state) { // We are only interested in timing the initial ring build. state.ResumeTiming(); - tester.ring_hash_lb_->initialize(); + ASSERT_TRUE(tester.ring_hash_lb_->initialize().ok()); state.PauseTiming(); const size_t end_mem = Memory::Stats::totalCurrentlyAllocated(); state.counters["memory"] = end_mem - start_mem; @@ -234,7 +234,7 @@ void benchmarkMaglevLoadBalancerBuildTable(::benchmark::State& state) { // We are only interested in timing the initial table build. state.ResumeTiming(); - tester.maglev_lb_->initialize(); + ASSERT_TRUE(tester.maglev_lb_->initialize().ok()); state.PauseTiming(); const size_t end_mem = Memory::Stats::totalCurrentlyAllocated(); state.counters["memory"] = end_mem - start_mem; @@ -326,7 +326,7 @@ void benchmarkRingHashLoadBalancerChooseHost(::benchmark::State& state) { const uint64_t min_ring_size = state.range(1); const uint64_t keys_to_simulate = state.range(2); RingHashTester tester(num_hosts, min_ring_size); - tester.ring_hash_lb_->initialize(); + ASSERT_TRUE(tester.ring_hash_lb_->initialize().ok()); LoadBalancerPtr lb = tester.ring_hash_lb_->factory()->create(tester.lb_params_); absl::node_hash_map hit_counter; TestLoadBalancerContext context; @@ -364,7 +364,7 @@ void benchmarkMaglevLoadBalancerChooseHost(::benchmark::State& state) { const uint64_t num_hosts = state.range(0); const uint64_t keys_to_simulate = state.range(1); MaglevTester tester(num_hosts); - tester.maglev_lb_->initialize(); + ASSERT_TRUE(tester.maglev_lb_->initialize().ok()); LoadBalancerPtr lb = tester.maglev_lb_->factory()->create(tester.lb_params_); absl::node_hash_map hit_counter; TestLoadBalancerContext context; @@ -403,7 +403,7 @@ void benchmarkRingHashLoadBalancerHostLoss(::benchmark::State& state) { for (auto _ : state) { // NOLINT: Silences warning about dead store RingHashTester tester(num_hosts, min_ring_size); - tester.ring_hash_lb_->initialize(); + ASSERT_TRUE(tester.ring_hash_lb_->initialize().ok()); LoadBalancerPtr lb = tester.ring_hash_lb_->factory()->create(tester.lb_params_); std::vector hosts; TestLoadBalancerContext context; @@ -413,7 +413,7 @@ void benchmarkRingHashLoadBalancerHostLoss(::benchmark::State& state) { } RingHashTester tester2(num_hosts - hosts_to_lose, min_ring_size); - tester2.ring_hash_lb_->initialize(); + ASSERT_TRUE(tester2.ring_hash_lb_->initialize().ok()); lb = tester2.ring_hash_lb_->factory()->create(tester2.lb_params_); std::vector hosts2; for (uint64_t i = 0; i < keys_to_simulate; i++) { @@ -451,7 +451,7 @@ void benchmarkMaglevLoadBalancerHostLoss(::benchmark::State& state) { const uint64_t keys_to_simulate = state.range(2); MaglevTester tester(num_hosts); - tester.maglev_lb_->initialize(); + ASSERT_TRUE(tester.maglev_lb_->initialize().ok()); LoadBalancerPtr lb = tester.maglev_lb_->factory()->create(tester.lb_params_); std::vector hosts; TestLoadBalancerContext context; @@ -461,7 +461,7 @@ void benchmarkMaglevLoadBalancerHostLoss(::benchmark::State& state) { } MaglevTester tester2(num_hosts - hosts_to_lose); - tester2.maglev_lb_->initialize(); + ASSERT_TRUE(tester2.maglev_lb_->initialize().ok()); lb = tester2.maglev_lb_->factory()->create(tester2.lb_params_); std::vector hosts2; for (uint64_t i = 0; i < keys_to_simulate; i++) { @@ -498,7 +498,7 @@ void benchmarkMaglevLoadBalancerWeighted(::benchmark::State& state) { const uint64_t keys_to_simulate = state.range(4); MaglevTester tester(num_hosts, weighted_subset_percent, before_weight); - tester.maglev_lb_->initialize(); + ASSERT_TRUE(tester.maglev_lb_->initialize().ok()); LoadBalancerPtr lb = tester.maglev_lb_->factory()->create(tester.lb_params_); std::vector hosts; TestLoadBalancerContext context; @@ -508,7 +508,7 @@ void benchmarkMaglevLoadBalancerWeighted(::benchmark::State& state) { } MaglevTester tester2(num_hosts, weighted_subset_percent, after_weight); - tester2.maglev_lb_->initialize(); + ASSERT_TRUE(tester2.maglev_lb_->initialize().ok()); lb = tester2.maglev_lb_->factory()->create(tester2.lb_params_); std::vector hosts2; for (uint64_t i = 0; i < keys_to_simulate; i++) { diff --git a/test/extensions/clusters/redis/redis_cluster_lb_test.cc b/test/extensions/clusters/redis/redis_cluster_lb_test.cc index eb3b005080ba..f837f774f059 100644 --- a/test/extensions/clusters/redis/redis_cluster_lb_test.cc +++ b/test/extensions/clusters/redis/redis_cluster_lb_test.cc @@ -45,7 +45,7 @@ class RedisClusterLoadBalancerTest : public Event::TestUsingSimulatedTime, publi void init() { factory_ = std::make_shared(random_); lb_ = std::make_unique(factory_); - lb_->initialize(); + EXPECT_TRUE(lb_->initialize().ok()); factory_->onHostHealthUpdate(); } diff --git a/test/extensions/load_balancing_policies/least_request/config_test.cc b/test/extensions/load_balancing_policies/least_request/config_test.cc index d4869da78e53..078eb4320a23 100644 --- a/test/extensions/load_balancing_policies/least_request/config_test.cc +++ b/test/extensions/load_balancing_policies/least_request/config_test.cc @@ -35,7 +35,7 @@ TEST(LeastRequestConfigTest, ValidateFail) { context.api_.random_, context.time_system_); EXPECT_NE(nullptr, thread_aware_lb); - thread_aware_lb->initialize(); + ASSERT_TRUE(thread_aware_lb->initialize().ok()); auto thread_local_lb_factory = thread_aware_lb->factory(); EXPECT_NE(nullptr, thread_local_lb_factory); diff --git a/test/extensions/load_balancing_policies/maglev/config_test.cc b/test/extensions/load_balancing_policies/maglev/config_test.cc index 65d2c8402fe6..4a35ed7f2c46 100644 --- a/test/extensions/load_balancing_policies/maglev/config_test.cc +++ b/test/extensions/load_balancing_policies/maglev/config_test.cc @@ -37,7 +37,7 @@ TEST(MaglevConfigTest, Validate) { context.api_.random_, context.time_system_); EXPECT_NE(nullptr, thread_aware_lb); - thread_aware_lb->initialize(); + ASSERT_TRUE(thread_aware_lb->initialize().ok()); auto thread_local_lb_factory = thread_aware_lb->factory(); EXPECT_NE(nullptr, thread_local_lb_factory); diff --git a/test/extensions/load_balancing_policies/maglev/maglev_lb_test.cc b/test/extensions/load_balancing_policies/maglev/maglev_lb_test.cc index e36cd294c016..bf19f39327de 100644 --- a/test/extensions/load_balancing_policies/maglev/maglev_lb_test.cc +++ b/test/extensions/load_balancing_policies/maglev/maglev_lb_test.cc @@ -68,7 +68,7 @@ class MaglevLoadBalancerTest : public Event::TestUsingSimulatedTime, public test } createLb(); - lb_->initialize(); + EXPECT_TRUE(lb_->initialize().ok()); } NiceMock priority_set_; diff --git a/test/extensions/load_balancing_policies/random/config_test.cc b/test/extensions/load_balancing_policies/random/config_test.cc index b115469b9ed0..ceba884544c4 100644 --- a/test/extensions/load_balancing_policies/random/config_test.cc +++ b/test/extensions/load_balancing_policies/random/config_test.cc @@ -35,7 +35,7 @@ TEST(RandomConfigTest, ValidateFail) { context.api_.random_, context.time_system_); EXPECT_NE(nullptr, thread_aware_lb); - thread_aware_lb->initialize(); + ASSERT_TRUE(thread_aware_lb->initialize().ok()); auto thread_local_lb_factory = thread_aware_lb->factory(); EXPECT_NE(nullptr, thread_local_lb_factory); diff --git a/test/extensions/load_balancing_policies/ring_hash/config_test.cc b/test/extensions/load_balancing_policies/ring_hash/config_test.cc index 2d69ff02226e..f94ffc01649f 100644 --- a/test/extensions/load_balancing_policies/ring_hash/config_test.cc +++ b/test/extensions/load_balancing_policies/ring_hash/config_test.cc @@ -38,7 +38,7 @@ TEST(RingHashConfigTest, Validate) { context.api_.random_, context.time_system_); EXPECT_NE(nullptr, thread_aware_lb); - thread_aware_lb->initialize(); + ASSERT_TRUE(thread_aware_lb->initialize().ok()); auto thread_local_lb_factory = thread_aware_lb->factory(); EXPECT_NE(nullptr, thread_local_lb_factory); diff --git a/test/extensions/load_balancing_policies/ring_hash/ring_hash_lb_test.cc b/test/extensions/load_balancing_policies/ring_hash/ring_hash_lb_test.cc index cd06d11e0194..696b170fb853 100644 --- a/test/extensions/load_balancing_policies/ring_hash/ring_hash_lb_test.cc +++ b/test/extensions/load_balancing_policies/ring_hash/ring_hash_lb_test.cc @@ -73,7 +73,7 @@ class RingHashLoadBalancerTest : public Event::TestUsingSimulatedTime, config_.value()) : absl::nullopt, common_config_); - lb_->initialize(); + EXPECT_TRUE(lb_->initialize().ok()); } // Run all tests against both priority 0 and priority 1 host sets, to ensure diff --git a/test/extensions/load_balancing_policies/round_robin/config_test.cc b/test/extensions/load_balancing_policies/round_robin/config_test.cc index 6b2263b9771c..81a51c2b45ed 100644 --- a/test/extensions/load_balancing_policies/round_robin/config_test.cc +++ b/test/extensions/load_balancing_policies/round_robin/config_test.cc @@ -36,7 +36,7 @@ TEST(RoundRobinConfigTest, ValidateFail) { context.api_.random_, context.time_system_); EXPECT_NE(nullptr, thread_aware_lb); - thread_aware_lb->initialize(); + ASSERT_TRUE(thread_aware_lb->initialize().ok()); auto thread_local_lb_factory = thread_aware_lb->factory(); EXPECT_NE(nullptr, thread_local_lb_factory); diff --git a/test/extensions/load_balancing_policies/subset/config_test.cc b/test/extensions/load_balancing_policies/subset/config_test.cc index fdc45f97b19d..fa021bc962fc 100644 --- a/test/extensions/load_balancing_policies/subset/config_test.cc +++ b/test/extensions/load_balancing_policies/subset/config_test.cc @@ -57,7 +57,7 @@ TEST(SubsetConfigTest, SubsetConfigTest) { context.api_.random_, context.time_system_); EXPECT_NE(nullptr, thread_aware_lb); - thread_aware_lb->initialize(); + ASSERT_TRUE(thread_aware_lb->initialize().ok()); auto thread_local_lb_factory = thread_aware_lb->factory(); EXPECT_NE(nullptr, thread_local_lb_factory); diff --git a/test/integration/load_balancers/custom_lb_policy.h b/test/integration/load_balancers/custom_lb_policy.h index 57be537f90d0..e7e129852b41 100644 --- a/test/integration/load_balancers/custom_lb_policy.h +++ b/test/integration/load_balancers/custom_lb_policy.h @@ -17,7 +17,7 @@ class ThreadAwareLbImpl : public Upstream::ThreadAwareLoadBalancer { Upstream::LoadBalancerFactorySharedPtr factory() override { return std::make_shared(host_); } - void initialize() override {} + absl::Status initialize() override { return absl::OkStatus(); } private: class LbImpl : public Upstream::LoadBalancer { diff --git a/test/mocks/upstream/thread_aware_load_balancer.h b/test/mocks/upstream/thread_aware_load_balancer.h index 49b0cea8176f..5f1913f19c9c 100644 --- a/test/mocks/upstream/thread_aware_load_balancer.h +++ b/test/mocks/upstream/thread_aware_load_balancer.h @@ -14,7 +14,7 @@ class MockThreadAwareLoadBalancer : public ThreadAwareLoadBalancer { // Upstream::ThreadAwareLoadBalancer MOCK_METHOD(LoadBalancerFactorySharedPtr, factory, ()); - MOCK_METHOD(void, initialize, ()); + MOCK_METHOD(absl::Status, initialize, ()); }; } // namespace Upstream } // namespace Envoy diff --git a/tools/code_format/config.yaml b/tools/code_format/config.yaml index 66f8bed3f7fa..11802d3e1be9 100644 --- a/tools/code_format/config.yaml +++ b/tools/code_format/config.yaml @@ -100,7 +100,6 @@ paths: - source/common/listener_manager/listener_impl.cc - source/common/listener_manager/listener_manager_impl.cc - source/common/listener_manager/filter_chain_manager_impl.cc - - source/common/upstream/thread_aware_lb_impl.cc - source/common/upstream/subset_lb_config.cc - source/common/upstream/cluster_manager_impl.cc - source/common/upstream/upstream_impl.cc From df7a921194d267e8597a6004088f0584fe58b754 Mon Sep 17 00:00:00 2001 From: Greg Greenway Date: Fri, 10 May 2024 02:32:10 -0700 Subject: [PATCH 14/20] build: fix macOS build with most recent toolchain (#34070) Fixes #33225 Signed-off-by: Greg Greenway --- .bazelrc | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.bazelrc b/.bazelrc index b693a9029424..1c11582a3b60 100644 --- a/.bazelrc +++ b/.bazelrc @@ -148,6 +148,12 @@ build:macos --action_env=PATH=/opt/homebrew/bin:/opt/local/bin:/usr/local/bin:/u build:macos --host_action_env=PATH=/opt/homebrew/bin:/opt/local/bin:/usr/local/bin:/usr/bin:/bin build:macos --define tcmalloc=disabled +# Workaround issue with pkgconfig, see https://github.com/envoyproxy/envoy/issues/33225 +build:macos --host_action_env=CXXFLAGS=-Wno-int-conversion +build:macos --action_env=CXXFLAGS=-Wno-int-conversion +build:macos --host_action_env=CFLAGS=-Wno-int-conversion +build:macos --action_env=CFLAGS=-Wno-int-conversion + # macOS ASAN/UBSAN build:macos-asan --config=asan # Workaround, see https://github.com/bazelbuild/bazel/issues/6932 From cec9b8c217025afb02648ccf5244bdc1bc308e8a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 10 May 2024 10:36:09 +0100 Subject: [PATCH 15/20] build(deps-dev): bump eslint-plugin-react-refresh from 0.4.6 to 0.4.7 in /examples/single-page-app/ui (#34077) build(deps-dev): bump eslint-plugin-react-refresh Bumps [eslint-plugin-react-refresh](https://github.com/ArnaudBarre/eslint-plugin-react-refresh) from 0.4.6 to 0.4.7. - [Release notes](https://github.com/ArnaudBarre/eslint-plugin-react-refresh/releases) - [Changelog](https://github.com/ArnaudBarre/eslint-plugin-react-refresh/blob/main/CHANGELOG.md) - [Commits](https://github.com/ArnaudBarre/eslint-plugin-react-refresh/compare/v0.4.6...v0.4.7) --- updated-dependencies: - dependency-name: eslint-plugin-react-refresh dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/single-page-app/ui/package.json | 2 +- examples/single-page-app/ui/yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/examples/single-page-app/ui/package.json b/examples/single-page-app/ui/package.json index 75407fa008e9..8581bec6c656 100644 --- a/examples/single-page-app/ui/package.json +++ b/examples/single-page-app/ui/package.json @@ -33,7 +33,7 @@ "eslint-plugin-promise": "^6.0.0", "eslint-plugin-react": "^7.34.1", "eslint-plugin-react-hooks": "^4.6.2", - "eslint-plugin-react-refresh": "^0.4.6", + "eslint-plugin-react-refresh": "^0.4.7", "typescript": "*", "vite": "^5.2.11" } diff --git a/examples/single-page-app/ui/yarn.lock b/examples/single-page-app/ui/yarn.lock index c09d38f28d42..fd092b531374 100644 --- a/examples/single-page-app/ui/yarn.lock +++ b/examples/single-page-app/ui/yarn.lock @@ -2445,10 +2445,10 @@ eslint-plugin-react-hooks@^4.6.2: resolved "https://registry.yarnpkg.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.2.tgz#c829eb06c0e6f484b3fbb85a97e57784f328c596" integrity sha512-QzliNJq4GinDBcD8gPB5v0wh6g8q3SUi6EFF0x8N/BL9PoVs0atuGc47ozMRyOWAKdwaZ5OnbOEa3WR+dSGKuQ== -eslint-plugin-react-refresh@^0.4.6: - version "0.4.6" - resolved "https://registry.yarnpkg.com/eslint-plugin-react-refresh/-/eslint-plugin-react-refresh-0.4.6.tgz#e8e8accab681861baed00c5c12da70267db0936f" - integrity sha512-NjGXdm7zgcKRkKMua34qVO9doI7VOxZ6ancSvBELJSSoX97jyndXcSoa8XBh69JoB31dNz3EEzlMcizZl7LaMA== +eslint-plugin-react-refresh@^0.4.7: + version "0.4.7" + resolved "https://registry.yarnpkg.com/eslint-plugin-react-refresh/-/eslint-plugin-react-refresh-0.4.7.tgz#1f597f9093b254f10ee0961c139a749acb19af7d" + integrity sha512-yrj+KInFmwuQS2UQcg1SF83ha1tuHC1jMQbRNyuWtlEzzKRDgAl7L4Yp4NlDUZTZNlWvHEzOtJhMi40R7JxcSw== eslint-plugin-react@^7.34.1: version "7.34.1" From 38eed4b6beccedad560edfbc870f3536b610cf55 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 10 May 2024 10:36:24 +0100 Subject: [PATCH 16/20] build(deps): bump ossf/scorecard-action from 2.3.1 to 2.3.3 (#34075) Bumps [ossf/scorecard-action](https://github.com/ossf/scorecard-action) from 2.3.1 to 2.3.3. - [Release notes](https://github.com/ossf/scorecard-action/releases) - [Changelog](https://github.com/ossf/scorecard-action/blob/main/RELEASE.md) - [Commits](https://github.com/ossf/scorecard-action/compare/0864cf19026789058feabb7e87baa5f140aac736...dc50aa9510b46c811795eb24b2f1ba02a914e534) --- updated-dependencies: - dependency-name: ossf/scorecard-action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/scorecard.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index 35a15413b83e..a3f529310a1f 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -26,7 +26,7 @@ jobs: persist-credentials: false - name: "Run analysis" - uses: ossf/scorecard-action@0864cf19026789058feabb7e87baa5f140aac736 # v2.3.1 + uses: ossf/scorecard-action@dc50aa9510b46c811795eb24b2f1ba02a914e534 # v2.3.3 with: results_file: results.sarif results_format: sarif From bbdf4463915f701b0c8be8ef6a85e10002b62b31 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 10 May 2024 10:36:38 +0100 Subject: [PATCH 17/20] build(deps): bump mysql from `e4054c2` to `4a4e5e2` in /examples/mysql (#34073) Bumps mysql from `e4054c2` to `4a4e5e2`. --- updated-dependencies: - dependency-name: mysql dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/mysql/Dockerfile-mysql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/mysql/Dockerfile-mysql b/examples/mysql/Dockerfile-mysql index d7ede3db6595..ec303395908e 100644 --- a/examples/mysql/Dockerfile-mysql +++ b/examples/mysql/Dockerfile-mysql @@ -1 +1 @@ -FROM mysql:8.4.0@sha256:e4054c2973be8766370769312786404fbb4557fb591d9ad37beb2d00a2c574a6 +FROM mysql:8.4.0@sha256:4a4e5e2a19aab7a67870588952e8f401e17a330466ecfc55c9acf51196da5bd0 From 6ee26edd722008b89cd0057a77ec3b2b3dbcd608 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 10 May 2024 10:36:57 +0100 Subject: [PATCH 18/20] build(deps): bump postgres from `4aea012` to `ba727f7` in /examples/shared/postgres (#34074) build(deps): bump postgres in /examples/shared/postgres Bumps postgres from `4aea012` to `ba727f7`. --- updated-dependencies: - dependency-name: postgres dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/shared/postgres/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/shared/postgres/Dockerfile b/examples/shared/postgres/Dockerfile index e02bcb92d63a..489e67fb857e 100644 --- a/examples/shared/postgres/Dockerfile +++ b/examples/shared/postgres/Dockerfile @@ -1,3 +1,3 @@ -FROM postgres:latest@sha256:4aea012537edfad80f98d870a36e6b90b4c09b27be7f4b4759d72db863baeebb +FROM postgres:latest@sha256:ba727f758a75cdd503c6b63db66a5fbc22ded0a228952e9d88e601621ad4de64 COPY docker-healthcheck.sh /usr/local/bin/ HEALTHCHECK CMD ["docker-healthcheck.sh"] From c3dd81da68af54844c85da0942bddb4787bd5624 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 10 May 2024 10:38:53 +0100 Subject: [PATCH 19/20] build(deps): bump elasticsearch from 8.13.3 to 8.13.4 in /examples/skywalking (#34076) build(deps): bump elasticsearch in /examples/skywalking Bumps elasticsearch from 8.13.3 to 8.13.4. --- updated-dependencies: - dependency-name: elasticsearch dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/skywalking/Dockerfile-elasticsearch | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/skywalking/Dockerfile-elasticsearch b/examples/skywalking/Dockerfile-elasticsearch index 2f9591e2edc9..3942fa1cf21f 100644 --- a/examples/skywalking/Dockerfile-elasticsearch +++ b/examples/skywalking/Dockerfile-elasticsearch @@ -1 +1 @@ -FROM elasticsearch:8.13.3@sha256:9ab33024ebd4a478c4d71dfed52cb06a30b04cd97fdc7a74ad7ed16cc91ab647 +FROM elasticsearch:8.13.4@sha256:11e1717dd78f46fbecf64f7f27a358d331abb5e95b5451c00730243ee44fb665 From a1ce0ee2a0f6773f0320e82511217a18c6bc7d39 Mon Sep 17 00:00:00 2001 From: Raven Black Date: Fri, 10 May 2024 10:24:43 -0400 Subject: [PATCH 20/20] Modify flake threshold for hotrestart_handoff_test (#33966) Modify flake threshold for hotrestart_handoff_test Signed-off-by: Raven Black --- test/integration/python/BUILD | 4 +++- test/integration/python/hotrestart_handoff_test.py | 13 ++++++++----- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/test/integration/python/BUILD b/test/integration/python/BUILD index 8d824bbdad99..5f1e42517986 100644 --- a/test/integration/python/BUILD +++ b/test/integration/python/BUILD @@ -7,7 +7,9 @@ envoy_package() envoy_py_test( name = "hotrestart_handoff_test", - size = "medium", + # This is not actually large, but setting large makes the test skip for + # asan and tsan. + size = "large", srcs = select({ "//bazel:disable_hot_restart_or_admin": ["null_test.py"], "//conditions:default": ["hotrestart_handoff_test.py"], diff --git a/test/integration/python/hotrestart_handoff_test.py b/test/integration/python/hotrestart_handoff_test.py index 9627b24b2696..913ed959940a 100644 --- a/test/integration/python/hotrestart_handoff_test.py +++ b/test/integration/python/hotrestart_handoff_test.py @@ -33,7 +33,7 @@ def random_loopback_host(): # This is a timeout that must be long enough that the hot restarted # instance can reliably be fully started up within this many seconds, or the # test will be flaky. 3 seconds is enough on a not-busy host with a non-tsan -# non-coverage build; 10 seconds should be enough to be not flaky in most +# non-coverage build; 6 seconds should be enough to be not flaky in most # configurations. # # Unfortunately, because the test is verifying the behavior of a connection @@ -41,10 +41,13 @@ def random_loopback_host(): # so increasing this value increases the duration of the test. For this # reason we want to keep it as low as possible without causing flaky failure. # -# Ideally this would be adjusted (3x) for tsan and coverage runs, but making that -# possible for python is outside the scope of this test, so we're stuck using the -# 3x value for all tests. -STARTUP_TOLERANCE_SECONDS = 10 +# If this goes longer than 10 seconds connections start timing out which +# causes the test to get stuck and time out. Unfortunately for tsan or asan +# runs the "long enough to start up" constraint fights with the "too long for +# connections to be idle" constraint. Ideally this test would be disabled for +# those slower test contexts, but we don't currently have infrastructure for +# that. +STARTUP_TOLERANCE_SECONDS = 6 # We send multiple requests in parallel and require them all to function correctly # - this makes it so if something is flaky we're more likely to encounter it, and