diff --git a/test/common/upstream/health_checker_impl_test.cc b/test/common/upstream/health_checker_impl_test.cc index 769f041e2ae24..3ee6cd1244012 100644 --- a/test/common/upstream/health_checker_impl_test.cc +++ b/test/common/upstream/health_checker_impl_test.cc @@ -100,6 +100,452 @@ TEST(HealthCheckerFactoryTest, CreateGrpc) { .get())); } +class HttpHealthCheckerImplTest : public testing::Test, public HttpHealthCheckerImplTestBase { +public: + void allocHealthChecker(const std::string& yaml, bool avoid_boosting = true) { + health_checker_ = std::make_shared( + *cluster_, parseHealthCheckFromV3Yaml(yaml, avoid_boosting), dispatcher_, runtime_, random_, + HealthCheckEventLoggerPtr(event_logger_storage_.release())); + } + + void addCompletionCallback() { + health_checker_->addHostCheckCompleteCb( + [this](HostSharedPtr host, HealthTransition changed_state) -> void { + onHostStatus(host, changed_state); + }); + } + + void setupNoServiceValidationHCWithHttp2() { + const std::string yaml = R"EOF( + timeout: 1s + interval: 1s + no_traffic_interval: 5s + interval_jitter: 1s + unhealthy_threshold: 2 + healthy_threshold: 2 + http_health_check: + service_name_matcher: + prefix: locations + path: /healthcheck + codec_client_type: Http2 + )EOF"; + + allocHealthChecker(yaml); + addCompletionCallback(); + } + + void setupInitialJitter() { + const std::string yaml = R"EOF( + timeout: 1s + interval: 1s + no_traffic_interval: 5s + initial_jitter: 5s + interval_jitter_percent: 40 + unhealthy_threshold: 2 + healthy_threshold: 2 + http_health_check: + service_name_matcher: + prefix: locations + path: /healthcheck + )EOF"; + + allocHealthChecker(yaml); + addCompletionCallback(); + } + + void setupIntervalJitterPercent() { + const std::string yaml = R"EOF( + timeout: 1s + interval: 1s + no_traffic_interval: 5s + interval_jitter_percent: 40 + unhealthy_threshold: 2 + healthy_threshold: 2 + http_health_check: + service_name_matcher: + prefix: locations + path: /healthcheck + )EOF"; + + allocHealthChecker(yaml); + addCompletionCallback(); + } + + void setupNoServiceValidationHC() { + const std::string yaml = R"EOF( + timeout: 1s + interval: 1s + no_traffic_interval: 5s + interval_jitter: 1s + unhealthy_threshold: 2 + healthy_threshold: 2 + http_health_check: + service_name_matcher: + prefix: locations + path: /healthcheck + )EOF"; + + allocHealthChecker(yaml); + addCompletionCallback(); + } + + void setupNoServiceValidationHCOneUnhealthy() { + const std::string yaml = R"EOF( + timeout: 1s + interval: 1s + no_traffic_interval: 5s + interval_jitter: 1s + unhealthy_threshold: 1 + healthy_threshold: 2 + http_health_check: + service_name_matcher: + prefix: locations + path: /healthcheck + )EOF"; + + allocHealthChecker(yaml); + addCompletionCallback(); + } + + void setupNoServiceValidationHCAlwaysLogFailure() { + const std::string yaml = R"EOF( + timeout: 1s + interval: 1s + no_traffic_interval: 5s + interval_jitter: 1s + unhealthy_threshold: 2 + healthy_threshold: 2 + http_health_check: + service_name_matcher: + prefix: locations + path: /healthcheck + always_log_health_check_failures: true + )EOF"; + + allocHealthChecker(yaml); + addCompletionCallback(); + } + + void setupNoServiceValidationNoReuseConnectionHC() { + std::string yaml = R"EOF( + timeout: 1s + interval: 1s + interval_jitter: 1s + unhealthy_threshold: 2 + healthy_threshold: 2 + reuse_connection: false + http_health_check: + path: /healthcheck + )EOF"; + + allocHealthChecker(yaml); + addCompletionCallback(); + } + + void setupHealthCheckIntervalOverridesHC() { + const std::string yaml = R"EOF( + timeout: 1s + interval: 1s + unhealthy_interval: 2s + unhealthy_edge_interval: 3s + healthy_edge_interval: 4s + no_traffic_interval: 5s + interval_jitter: 0s + unhealthy_threshold: 3 + healthy_threshold: 3 + http_health_check: + service_name_matcher: + prefix: locations + path: /healthcheck + )EOF"; + + allocHealthChecker(yaml); + addCompletionCallback(); + } + + void setupServiceValidationHC() { + std::string yaml = R"EOF( + timeout: 1s + interval: 1s + interval_jitter: 1s + unhealthy_threshold: 2 + healthy_threshold: 2 + http_health_check: + service_name_matcher: + prefix: locations + path: /healthcheck + )EOF"; + + allocHealthChecker(yaml); + addCompletionCallback(); + } + + void setupDeprecatedServiceNameValidationHC(const std::string& prefix) { + std::string yaml = fmt::format(R"EOF( + timeout: 1s + interval: 1s + interval_jitter: 1s + unhealthy_threshold: 2 + healthy_threshold: 2 + http_health_check: + service_name_matcher: + prefix: {0} + path: /healthcheck + )EOF", + prefix); + + allocHealthChecker(yaml); + addCompletionCallback(); + } + + void setupServicePrefixPatternValidationHC() { + std::string yaml = R"EOF( + timeout: 1s + interval: 1s + interval_jitter: 1s + unhealthy_threshold: 2 + healthy_threshold: 2 + http_health_check: + service_name_matcher: + prefix: locations + path: /healthcheck + )EOF"; + + allocHealthChecker(yaml); + addCompletionCallback(); + } + + void setupServiceExactPatternValidationHC() { + std::string yaml = R"EOF( + timeout: 1s + interval: 1s + interval_jitter: 1s + unhealthy_threshold: 2 + healthy_threshold: 2 + http_health_check: + service_name_matcher: + exact: locations-production-iad + path: /healthcheck + )EOF"; + + allocHealthChecker(yaml); + addCompletionCallback(); + } + + void setupServiceRegexPatternValidationHC() { + std::string yaml = R"EOF( + timeout: 1s + interval: 1s + interval_jitter: 1s + unhealthy_threshold: 2 + healthy_threshold: 2 + http_health_check: + service_name_matcher: + safe_regex: + google_re2: {} + regex: 'locations-.*-.*$' + path: /healthcheck + )EOF"; + + allocHealthChecker(yaml); + addCompletionCallback(); + } + + void setupServiceValidationWithCustomHostValueHC(const std::string& host) { + std::string yaml = fmt::format(R"EOF( + timeout: 1s + interval: 1s + interval_jitter: 1s + unhealthy_threshold: 2 + healthy_threshold: 2 + http_health_check: + service_name_matcher: + prefix: locations + path: /healthcheck + host: {0} + )EOF", + host); + + allocHealthChecker(yaml); + addCompletionCallback(); + } + + const envoy::config::endpoint::v3::Endpoint::HealthCheckConfig + makeHealthCheckConfig(const uint32_t port_value) { + envoy::config::endpoint::v3::Endpoint::HealthCheckConfig config; + config.set_port_value(port_value); + return config; + } + + void appendTestHosts(std::shared_ptr cluster, + const HostWithHealthCheckMap& hosts, const std::string& protocol = "tcp://", + const uint32_t priority = 0) { + for (const auto& host : hosts) { + cluster->prioritySet().getMockHostSet(priority)->hosts_.emplace_back( + makeTestHost(cluster->info_, fmt::format("{}{}", protocol, host.first), host.second)); + } + } + + void setupServiceValidationWithAdditionalHeaders() { + std::string yaml = R"EOF( + timeout: 1s + interval: 1s + interval_jitter: 1s + unhealthy_threshold: 2 + healthy_threshold: 2 + http_health_check: + service_name_matcher: + prefix: locations + path: /healthcheck + host: "www.envoyproxy.io" + request_headers_to_add: + - header: + key: x-envoy-ok + value: ok + - header: + key: x-envoy-cool + value: cool + - header: + key: x-envoy-awesome + value: awesome + # The following entry replaces the current user-agent. + - header: + key: user-agent + value: CoolEnvoy/HC + append: false + - header: + key: x-protocol + value: "%PROTOCOL%" + - header: + key: x-upstream-metadata + value: "%UPSTREAM_METADATA([\"namespace\", \"key\"])%" + - header: + key: x-downstream-remote-address + value: "%DOWNSTREAM_REMOTE_ADDRESS%" + - header: + key: x-downstream-remote-address-without-port + value: "%DOWNSTREAM_REMOTE_ADDRESS_WITHOUT_PORT%" + - header: + key: x-downstream-local-address + value: "%DOWNSTREAM_LOCAL_ADDRESS%" + - header: + key: x-downstream-local-address-without-port + value: "%DOWNSTREAM_LOCAL_ADDRESS_WITHOUT_PORT%" + - header: + key: x-start-time + value: "%START_TIME(%s.%9f)%" + )EOF"; + + allocHealthChecker(yaml); + addCompletionCallback(); + } + + void setupServiceValidationWithoutUserAgent() { + std::string yaml = R"EOF( + timeout: 1s + interval: 1s + interval_jitter: 1s + unhealthy_threshold: 2 + healthy_threshold: 2 + http_health_check: + service_name_matcher: + prefix: locations + path: /healthcheck + host: "www.envoyproxy.io" + # The following entry removes the default "user-agent" header. + request_headers_to_remove: ["user-agent"] + )EOF"; + + allocHealthChecker(yaml); + addCompletionCallback(); + } + + void respond(size_t index, const std::string& code, bool conn_close, bool proxy_close = false, + bool body = false, bool trailers = false, + const absl::optional& service_cluster = absl::optional(), + bool degraded = false) { + std::unique_ptr response_headers( + new Http::TestResponseHeaderMapImpl{{":status", code}}); + + if (degraded) { + response_headers->setEnvoyDegraded(1); + } + + if (service_cluster) { + response_headers->addCopy(Http::Headers::get().EnvoyUpstreamHealthCheckedCluster, + service_cluster.value()); + } + if (conn_close) { + response_headers->addCopy("connection", "close"); + } + if (proxy_close) { + response_headers->addCopy("proxy-connection", "close"); + } + + test_sessions_[index]->stream_response_callbacks_->decodeHeaders(std::move(response_headers), + !body && !trailers); + if (body) { + Buffer::OwnedImpl response_data; + test_sessions_[index]->stream_response_callbacks_->decodeData(response_data, !trailers); + } + + if (trailers) { + test_sessions_[index]->stream_response_callbacks_->decodeTrailers( + Http::ResponseTrailerMapPtr{new Http::TestResponseTrailerMapImpl{{"some", "trailer"}}}); + } + } + + void expectSuccessStartFailedFailFirst( + const absl::optional& health_checked_cluster = absl::optional()) { + cluster_->prioritySet().getMockHostSet(0)->hosts_ = { + makeTestHost(cluster_->info_, "tcp://127.0.0.1:80")}; + cluster_->prioritySet().getMockHostSet(0)->hosts_[0]->healthFlagSet( + Host::HealthFlag::FAILED_ACTIVE_HC); + expectSessionCreate(); + expectStreamCreate(0); + EXPECT_CALL(*test_sessions_[0]->timeout_timer_, enableTimer(_, _)); + health_checker_->start(); + + // Test that failing first disables fast success. + EXPECT_CALL(*this, onHostStatus(_, HealthTransition::Unchanged)); + EXPECT_CALL(*test_sessions_[0]->interval_timer_, enableTimer(_, _)); + EXPECT_CALL(*test_sessions_[0]->timeout_timer_, disableTimer()); + EXPECT_CALL(event_logger_, logUnhealthy(_, _, _, true)); + respond(0, "503", false, false, false, false, health_checked_cluster); + EXPECT_TRUE(cluster_->prioritySet().getMockHostSet(0)->hosts_[0]->healthFlagGet( + Host::HealthFlag::FAILED_ACTIVE_HC)); + EXPECT_EQ(Host::Health::Unhealthy, + cluster_->prioritySet().getMockHostSet(0)->hosts_[0]->health()); + + EXPECT_CALL(*test_sessions_[0]->timeout_timer_, enableTimer(_, _)); + expectStreamCreate(0); + test_sessions_[0]->interval_timer_->invokeCallback(); + + EXPECT_CALL(*this, onHostStatus(_, HealthTransition::ChangePending)); + EXPECT_CALL(*test_sessions_[0]->interval_timer_, enableTimer(_, _)); + EXPECT_CALL(*test_sessions_[0]->timeout_timer_, disableTimer()); + respond(0, "200", false, false, false, false, health_checked_cluster); + EXPECT_TRUE(cluster_->prioritySet().getMockHostSet(0)->hosts_[0]->healthFlagGet( + Host::HealthFlag::FAILED_ACTIVE_HC)); + EXPECT_EQ(Host::Health::Unhealthy, + cluster_->prioritySet().getMockHostSet(0)->hosts_[0]->health()); + + EXPECT_CALL(*test_sessions_[0]->timeout_timer_, enableTimer(_, _)); + expectStreamCreate(0); + test_sessions_[0]->interval_timer_->invokeCallback(); + + EXPECT_CALL(*this, onHostStatus(_, HealthTransition::Changed)); + EXPECT_CALL(event_logger_, logAddHealthy(_, _, false)); + EXPECT_CALL(*test_sessions_[0]->interval_timer_, enableTimer(_, _)); + EXPECT_CALL(*test_sessions_[0]->timeout_timer_, disableTimer()); + respond(0, "200", false, false, false, false, health_checked_cluster); + EXPECT_EQ(Host::Health::Healthy, + cluster_->prioritySet().getMockHostSet(0)->hosts_[0]->health()); + } + + MOCK_METHOD(void, onHostStatus, (HostSharedPtr host, HealthTransition changed_state)); +}; + TEST_F(HttpHealthCheckerImplTest, Success) { setupNoServiceValidationHC(); EXPECT_CALL(*this, onHostStatus(_, HealthTransition::Unchanged)).Times(1); diff --git a/test/common/upstream/health_checker_impl_test_utils.cc b/test/common/upstream/health_checker_impl_test_utils.cc index 763ab236a7ad4..f0ad4d9e19ac3 100644 --- a/test/common/upstream/health_checker_impl_test_utils.cc +++ b/test/common/upstream/health_checker_impl_test_utils.cc @@ -9,367 +9,7 @@ namespace Envoy { namespace Upstream { -void HttpHealthCheckerImplTest::allocHealthChecker(const std::string& yaml, bool avoid_boosting) { - health_checker_ = std::make_shared( - *cluster_, parseHealthCheckFromV3Yaml(yaml, avoid_boosting), dispatcher_, runtime_, random_, - HealthCheckEventLoggerPtr(event_logger_storage_.release())); -} - -void HttpHealthCheckerImplTest::addCompletionCallback() { - health_checker_->addHostCheckCompleteCb( - [this](HostSharedPtr host, HealthTransition changed_state) -> void { - onHostStatus(host, changed_state); - }); -} - -void HttpHealthCheckerImplTest::setupNoServiceValidationHCWithHttp2() { - const std::string yaml = R"EOF( - timeout: 1s - interval: 1s - no_traffic_interval: 5s - interval_jitter: 1s - unhealthy_threshold: 2 - healthy_threshold: 2 - http_health_check: - service_name_matcher: - prefix: locations - path: /healthcheck - codec_client_type: Http2 - )EOF"; - - allocHealthChecker(yaml); - addCompletionCallback(); -} - -void HttpHealthCheckerImplTest::setupInitialJitter() { - const std::string yaml = R"EOF( - timeout: 1s - interval: 1s - no_traffic_interval: 5s - initial_jitter: 5s - interval_jitter_percent: 40 - unhealthy_threshold: 2 - healthy_threshold: 2 - http_health_check: - service_name_matcher: - prefix: locations - path: /healthcheck - )EOF"; - - allocHealthChecker(yaml); - addCompletionCallback(); -} - -void HttpHealthCheckerImplTest::setupIntervalJitterPercent() { - const std::string yaml = R"EOF( - timeout: 1s - interval: 1s - no_traffic_interval: 5s - interval_jitter_percent: 40 - unhealthy_threshold: 2 - healthy_threshold: 2 - http_health_check: - service_name_matcher: - prefix: locations - path: /healthcheck - )EOF"; - - allocHealthChecker(yaml); - addCompletionCallback(); -} - -void HttpHealthCheckerImplTest::setupNoServiceValidationHC() { - const std::string yaml = R"EOF( - timeout: 1s - interval: 1s - no_traffic_interval: 5s - interval_jitter: 1s - unhealthy_threshold: 2 - healthy_threshold: 2 - http_health_check: - service_name_matcher: - prefix: locations - path: /healthcheck - )EOF"; - - allocHealthChecker(yaml); - addCompletionCallback(); -} - -void HttpHealthCheckerImplTest::setupNoServiceValidationHCOneUnhealthy() { - const std::string yaml = R"EOF( - timeout: 1s - interval: 1s - no_traffic_interval: 5s - interval_jitter: 1s - unhealthy_threshold: 1 - healthy_threshold: 2 - http_health_check: - service_name_matcher: - prefix: locations - path: /healthcheck - )EOF"; - - allocHealthChecker(yaml); - addCompletionCallback(); -} - -void HttpHealthCheckerImplTest::setupNoServiceValidationHCAlwaysLogFailure() { - const std::string yaml = R"EOF( - timeout: 1s - interval: 1s - no_traffic_interval: 5s - interval_jitter: 1s - unhealthy_threshold: 2 - healthy_threshold: 2 - http_health_check: - service_name_matcher: - prefix: locations - path: /healthcheck - always_log_health_check_failures: true - )EOF"; - - allocHealthChecker(yaml); - addCompletionCallback(); -} - -void HttpHealthCheckerImplTest::setupNoServiceValidationNoReuseConnectionHC() { - std::string yaml = R"EOF( - timeout: 1s - interval: 1s - interval_jitter: 1s - unhealthy_threshold: 2 - healthy_threshold: 2 - reuse_connection: false - http_health_check: - path: /healthcheck - )EOF"; - - allocHealthChecker(yaml); - addCompletionCallback(); -} - -void HttpHealthCheckerImplTest::setupHealthCheckIntervalOverridesHC() { - const std::string yaml = R"EOF( - timeout: 1s - interval: 1s - unhealthy_interval: 2s - unhealthy_edge_interval: 3s - healthy_edge_interval: 4s - no_traffic_interval: 5s - interval_jitter: 0s - unhealthy_threshold: 3 - healthy_threshold: 3 - http_health_check: - service_name_matcher: - prefix: locations - path: /healthcheck - )EOF"; - - allocHealthChecker(yaml); - addCompletionCallback(); -} - -void HttpHealthCheckerImplTest::setupServiceValidationHC() { - std::string yaml = R"EOF( - timeout: 1s - interval: 1s - interval_jitter: 1s - unhealthy_threshold: 2 - healthy_threshold: 2 - http_health_check: - service_name_matcher: - prefix: locations - path: /healthcheck - )EOF"; - - allocHealthChecker(yaml); - addCompletionCallback(); -} - -void HttpHealthCheckerImplTest::setupDeprecatedServiceNameValidationHC(const std::string& prefix) { - std::string yaml = fmt::format(R"EOF( - timeout: 1s - interval: 1s - interval_jitter: 1s - unhealthy_threshold: 2 - healthy_threshold: 2 - http_health_check: - service_name_matcher: - prefix: {0} - path: /healthcheck - )EOF", - prefix); - - allocHealthChecker(yaml); - addCompletionCallback(); -} - -void HttpHealthCheckerImplTest::setupServicePrefixPatternValidationHC() { - std::string yaml = R"EOF( - timeout: 1s - interval: 1s - interval_jitter: 1s - unhealthy_threshold: 2 - healthy_threshold: 2 - http_health_check: - service_name_matcher: - prefix: locations - path: /healthcheck - )EOF"; - - allocHealthChecker(yaml); - addCompletionCallback(); -} - -void HttpHealthCheckerImplTest::setupServiceExactPatternValidationHC() { - std::string yaml = R"EOF( - timeout: 1s - interval: 1s - interval_jitter: 1s - unhealthy_threshold: 2 - healthy_threshold: 2 - http_health_check: - service_name_matcher: - exact: locations-production-iad - path: /healthcheck - )EOF"; - - allocHealthChecker(yaml); - addCompletionCallback(); -} - -void HttpHealthCheckerImplTest::setupServiceRegexPatternValidationHC() { - std::string yaml = R"EOF( - timeout: 1s - interval: 1s - interval_jitter: 1s - unhealthy_threshold: 2 - healthy_threshold: 2 - http_health_check: - service_name_matcher: - safe_regex: - google_re2: {} - regex: 'locations-.*-.*$' - path: /healthcheck - )EOF"; - - allocHealthChecker(yaml); - addCompletionCallback(); -} - -void HttpHealthCheckerImplTest::setupServiceValidationWithCustomHostValueHC( - const std::string& host) { - std::string yaml = fmt::format(R"EOF( - timeout: 1s - interval: 1s - interval_jitter: 1s - unhealthy_threshold: 2 - healthy_threshold: 2 - http_health_check: - service_name_matcher: - prefix: locations - path: /healthcheck - host: {0} - )EOF", - host); - - allocHealthChecker(yaml); - addCompletionCallback(); -} - -const envoy::config::endpoint::v3::Endpoint::HealthCheckConfig -HttpHealthCheckerImplTest::makeHealthCheckConfig(const uint32_t port_value) { - envoy::config::endpoint::v3::Endpoint::HealthCheckConfig config; - config.set_port_value(port_value); - return config; -} - -void HttpHealthCheckerImplTest::appendTestHosts(std::shared_ptr cluster, - const HostWithHealthCheckMap& hosts, - const std::string& protocol, - const uint32_t priority) { - for (const auto& host : hosts) { - cluster->prioritySet().getMockHostSet(priority)->hosts_.emplace_back( - makeTestHost(cluster->info_, fmt::format("{}{}", protocol, host.first), host.second)); - } -} - -void HttpHealthCheckerImplTest::setupServiceValidationWithAdditionalHeaders() { - std::string yaml = R"EOF( - timeout: 1s - interval: 1s - interval_jitter: 1s - unhealthy_threshold: 2 - healthy_threshold: 2 - http_health_check: - service_name_matcher: - prefix: locations - path: /healthcheck - host: "www.envoyproxy.io" - request_headers_to_add: - - header: - key: x-envoy-ok - value: ok - - header: - key: x-envoy-cool - value: cool - - header: - key: x-envoy-awesome - value: awesome - # The following entry replaces the current user-agent. - - header: - key: user-agent - value: CoolEnvoy/HC - append: false - - header: - key: x-protocol - value: "%PROTOCOL%" - - header: - key: x-upstream-metadata - value: "%UPSTREAM_METADATA([\"namespace\", \"key\"])%" - - header: - key: x-downstream-remote-address - value: "%DOWNSTREAM_REMOTE_ADDRESS%" - - header: - key: x-downstream-remote-address-without-port - value: "%DOWNSTREAM_REMOTE_ADDRESS_WITHOUT_PORT%" - - header: - key: x-downstream-local-address - value: "%DOWNSTREAM_LOCAL_ADDRESS%" - - header: - key: x-downstream-local-address-without-port - value: "%DOWNSTREAM_LOCAL_ADDRESS_WITHOUT_PORT%" - - header: - key: x-start-time - value: "%START_TIME(%s.%9f)%" - )EOF"; - - allocHealthChecker(yaml); - addCompletionCallback(); -} - -void HttpHealthCheckerImplTest::setupServiceValidationWithoutUserAgent() { - std::string yaml = R"EOF( - timeout: 1s - interval: 1s - interval_jitter: 1s - unhealthy_threshold: 2 - healthy_threshold: 2 - http_health_check: - service_name_matcher: - prefix: locations - path: /healthcheck - host: "www.envoyproxy.io" - # The following entry removes the default "user-agent" header. - request_headers_to_remove: ["user-agent"] - )EOF"; - - allocHealthChecker(yaml); - addCompletionCallback(); -} - -void HttpHealthCheckerImplTest::expectSessionCreate( +void HttpHealthCheckerImplTestBase::expectSessionCreate( const HostWithHealthCheckMap& health_check_map) { // Expectations are in LIFO order. TestSessionPtr new_test_session(new TestSession()); @@ -380,8 +20,8 @@ void HttpHealthCheckerImplTest::expectSessionCreate( expectClientCreate(test_sessions_.size() - 1, health_check_map); } -void HttpHealthCheckerImplTest::expectClientCreate(size_t index, - const HostWithHealthCheckMap& health_check_map) { +void HttpHealthCheckerImplTestBase::expectClientCreate( + size_t index, const HostWithHealthCheckMap& health_check_map) { TestSession& test_session = *test_sessions_[index]; test_session.codec_ = new NiceMock(); ON_CALL(*test_session.codec_, protocol()).WillByDefault(testing::Return(Http::Protocol::Http11)); @@ -419,99 +59,19 @@ void HttpHealthCheckerImplTest::expectClientCreate(size_t index, })); } -void HttpHealthCheckerImplTest::expectStreamCreate(size_t index) { +void HttpHealthCheckerImplTestBase::expectStreamCreate(size_t index) { test_sessions_[index]->request_encoder_.stream_.callbacks_.clear(); EXPECT_CALL(*test_sessions_[index]->codec_, newStream(_)) .WillOnce(DoAll(SaveArgAddress(&test_sessions_[index]->stream_response_callbacks_), ReturnRef(test_sessions_[index]->request_encoder_))); } -void HttpHealthCheckerImplTest::respond(size_t index, const std::string& code, bool conn_close, - bool proxy_close, bool body, bool trailers, - const absl::optional& service_cluster, - bool degraded) { - std::unique_ptr response_headers( - new Http::TestResponseHeaderMapImpl{{":status", code}}); - - if (degraded) { - response_headers->setEnvoyDegraded(1); - } - - if (service_cluster) { - response_headers->addCopy(Http::Headers::get().EnvoyUpstreamHealthCheckedCluster, - service_cluster.value()); - } - if (conn_close) { - response_headers->addCopy("connection", "close"); - } - if (proxy_close) { - response_headers->addCopy("proxy-connection", "close"); - } - - test_sessions_[index]->stream_response_callbacks_->decodeHeaders(std::move(response_headers), - !body && !trailers); - if (body) { - Buffer::OwnedImpl response_data; - test_sessions_[index]->stream_response_callbacks_->decodeData(response_data, !trailers); - } - - if (trailers) { - test_sessions_[index]->stream_response_callbacks_->decodeTrailers( - Http::ResponseTrailerMapPtr{new Http::TestResponseTrailerMapImpl{{"some", "trailer"}}}); - } +void HttpHealthCheckerImplTestBase::expectSessionCreate() { + expectSessionCreate(health_checker_map_); } - -void HttpHealthCheckerImplTest::expectSessionCreate() { expectSessionCreate(health_checker_map_); } -void HttpHealthCheckerImplTest::expectClientCreate(size_t index) { +void HttpHealthCheckerImplTestBase::expectClientCreate(size_t index) { expectClientCreate(index, health_checker_map_); } -void HttpHealthCheckerImplTest::expectSuccessStartFailedFailFirst( - const absl::optional& health_checked_cluster) { - cluster_->prioritySet().getMockHostSet(0)->hosts_ = { - makeTestHost(cluster_->info_, "tcp://127.0.0.1:80")}; - cluster_->prioritySet().getMockHostSet(0)->hosts_[0]->healthFlagSet( - Host::HealthFlag::FAILED_ACTIVE_HC); - expectSessionCreate(); - expectStreamCreate(0); - EXPECT_CALL(*test_sessions_[0]->timeout_timer_, enableTimer(_, _)); - health_checker_->start(); - - // Test that failing first disables fast success. - EXPECT_CALL(*this, onHostStatus(_, HealthTransition::Unchanged)); - EXPECT_CALL(*test_sessions_[0]->interval_timer_, enableTimer(_, _)); - EXPECT_CALL(*test_sessions_[0]->timeout_timer_, disableTimer()); - EXPECT_CALL(event_logger_, logUnhealthy(_, _, _, true)); - respond(0, "503", false, false, false, false, health_checked_cluster); - EXPECT_TRUE(cluster_->prioritySet().getMockHostSet(0)->hosts_[0]->healthFlagGet( - Host::HealthFlag::FAILED_ACTIVE_HC)); - EXPECT_EQ(Host::Health::Unhealthy, - cluster_->prioritySet().getMockHostSet(0)->hosts_[0]->health()); - - EXPECT_CALL(*test_sessions_[0]->timeout_timer_, enableTimer(_, _)); - expectStreamCreate(0); - test_sessions_[0]->interval_timer_->invokeCallback(); - - EXPECT_CALL(*this, onHostStatus(_, HealthTransition::ChangePending)); - EXPECT_CALL(*test_sessions_[0]->interval_timer_, enableTimer(_, _)); - EXPECT_CALL(*test_sessions_[0]->timeout_timer_, disableTimer()); - respond(0, "200", false, false, false, false, health_checked_cluster); - EXPECT_TRUE(cluster_->prioritySet().getMockHostSet(0)->hosts_[0]->healthFlagGet( - Host::HealthFlag::FAILED_ACTIVE_HC)); - EXPECT_EQ(Host::Health::Unhealthy, - cluster_->prioritySet().getMockHostSet(0)->hosts_[0]->health()); - - EXPECT_CALL(*test_sessions_[0]->timeout_timer_, enableTimer(_, _)); - expectStreamCreate(0); - test_sessions_[0]->interval_timer_->invokeCallback(); - - EXPECT_CALL(*this, onHostStatus(_, HealthTransition::Changed)); - EXPECT_CALL(event_logger_, logAddHealthy(_, _, false)); - EXPECT_CALL(*test_sessions_[0]->interval_timer_, enableTimer(_, _)); - EXPECT_CALL(*test_sessions_[0]->timeout_timer_, disableTimer()); - respond(0, "200", false, false, false, false, health_checked_cluster); - EXPECT_EQ(Host::Health::Healthy, cluster_->prioritySet().getMockHostSet(0)->hosts_[0]->health()); -} - } // namespace Upstream } // namespace Envoy diff --git a/test/common/upstream/health_checker_impl_test_utils.h b/test/common/upstream/health_checker_impl_test_utils.h index bb6213ae2fec8..61ad75860e0ea 100644 --- a/test/common/upstream/health_checker_impl_test_utils.h +++ b/test/common/upstream/health_checker_impl_test_utils.h @@ -37,7 +37,7 @@ class TestHttpHealthCheckerImpl : public HttpHealthCheckerImpl { Http::CodecClient::Type codecClientType() { return codec_client_type_; } }; -class HttpHealthCheckerImplTest : public testing::Test, public HealthCheckerTestBase { +class HttpHealthCheckerImplTestBase : public HealthCheckerTestBase { public: struct TestSession { Event::MockTimer* interval_timer_{}; @@ -54,68 +54,15 @@ class HttpHealthCheckerImplTest : public testing::Test, public HealthCheckerTest absl::node_hash_map; - void allocHealthChecker(const std::string& yaml, bool avoid_boosting = true); - - void addCompletionCallback(); - - void setupNoServiceValidationHCWithHttp2(); - - void setupInitialJitter(); - - void setupIntervalJitterPercent(); - - void setupNoServiceValidationHC(); - - void setupNoServiceValidationHCOneUnhealthy(); - - void setupNoServiceValidationHCAlwaysLogFailure(); - - void setupNoServiceValidationNoReuseConnectionHC(); - - void setupHealthCheckIntervalOverridesHC(); - - void setupServiceValidationHC(); - - void setupDeprecatedServiceNameValidationHC(const std::string& prefix); - - void setupServicePrefixPatternValidationHC(); - - void setupServiceExactPatternValidationHC(); - - void setupServiceRegexPatternValidationHC(); - - void setupServiceValidationWithCustomHostValueHC(const std::string& host); - - const envoy::config::endpoint::v3::Endpoint::HealthCheckConfig - makeHealthCheckConfig(const uint32_t port_value); - - void appendTestHosts(std::shared_ptr cluster, - const HostWithHealthCheckMap& hosts, const std::string& protocol = "tcp://", - const uint32_t priority = 0); - - void setupServiceValidationWithAdditionalHeaders(); - - void setupServiceValidationWithoutUserAgent(); - void expectSessionCreate(const HostWithHealthCheckMap& health_check_map); void expectClientCreate(size_t index, const HostWithHealthCheckMap& health_check_map); void expectStreamCreate(size_t index); - void respond(size_t index, const std::string& code, bool conn_close, bool proxy_close = false, - bool body = false, bool trailers = false, - const absl::optional& service_cluster = absl::optional(), - bool degraded = false); - void expectSessionCreate(); void expectClientCreate(size_t index); - void expectSuccessStartFailedFailFirst( - const absl::optional& health_checked_cluster = absl::optional()); - - MOCK_METHOD(void, onHostStatus, (HostSharedPtr host, HealthTransition changed_state)); - std::vector test_sessions_; std::shared_ptr health_checker_; std::list connection_index_{};