Skip to content

Commit

Permalink
fix tcp proxy coverage (envoyproxy#38245)
Browse files Browse the repository at this point in the history
Resolve envoyproxy#38240 

Commit Message:
Additional Description:
Risk Level:
Testing:
Docs Changes:
Release Notes:
Platform Specific Features:

---------

Signed-off-by: Issa Abu Kalbein <[email protected]>
Co-authored-by: Issa Abu Kalbein <[email protected]>
  • Loading branch information
IssaAbuKalbein and Issa Abu Kalbein authored Jan 29, 2025
1 parent a20dffd commit 8584f9c
Show file tree
Hide file tree
Showing 2 changed files with 82 additions and 3 deletions.
84 changes: 82 additions & 2 deletions test/integration/tcp_tunneling_integration_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2112,8 +2112,9 @@ TEST_P(TcpTunnelingIntegrationTest, UpstreamDisconnectBeforeResponseReceived) {
tcp_client_->close();
}

TEST_P(TcpTunnelingIntegrationTest,
ConnectionAttemptRetryOnUpstreamConnectionCloseBeforeResponseHeadersNoBackoffOptions) {
TEST_P(
TcpTunnelingIntegrationTest,
ConnectionAttemptRetryOnUpstreamConnectionCloseBeforeResponseHeadersNoBackoffOptionsRetryOnDifferentEventLoop) {
const std::string access_log_filename =
TestEnvironment::temporaryPath(TestUtility::uniqueFilename());
config_helper_.addConfigModifier([&](envoy::config::bootstrap::v3::Bootstrap& bootstrap) -> void {
Expand Down Expand Up @@ -2178,6 +2179,85 @@ TEST_P(TcpTunnelingIntegrationTest,
EXPECT_THAT(waitForAccessLog(access_log_filename), testing::HasSubstr(expected_log));
}

TEST_P(
TcpTunnelingIntegrationTest,
ConnectionAttemptRetryOnUpstreamConnectionCloseBeforeResponseHeadersNoBackoffOptionsRetryOnSameEventLoop) {
const std::string access_log_filename =
TestEnvironment::temporaryPath(TestUtility::uniqueFilename());
config_helper_.addRuntimeOverride(
"envoy.reloadable_features.tcp_proxy_retry_on_different_event_loop", "false");
config_helper_.addConfigModifier([&](envoy::config::bootstrap::v3::Bootstrap& bootstrap) -> void {
envoy::extensions::filters::network::tcp_proxy::v3::TcpProxy proxy_config;
proxy_config.set_stat_prefix("tcp_stats");
proxy_config.set_cluster("cluster_0");
proxy_config.mutable_tunneling_config()->set_hostname("foo.lyft.com:80");
proxy_config.mutable_max_connect_attempts()->set_value(2);

envoy::extensions::access_loggers::file::v3::FileAccessLog access_log_config;
access_log_config.mutable_log_format()->mutable_text_format_source()->set_inline_string(
"%UPSTREAM_REQUEST_ATTEMPT_COUNT% %RESPONSE_FLAGS%\n");
access_log_config.set_path(access_log_filename);
proxy_config.add_access_log()->mutable_typed_config()->PackFrom(access_log_config);

auto* listeners = bootstrap.mutable_static_resources()->mutable_listeners();
for (auto& listener : *listeners) {
if (listener.name() != "tcp_proxy") {
continue;
}
auto* filter_chain = listener.mutable_filter_chains(0);
auto* filter = filter_chain->mutable_filters(0);
filter->mutable_typed_config()->PackFrom(proxy_config);
break;
}
});
initialize();

// Start a connection, and verify the upgrade headers are received upstream.
tcp_client_ = makeTcpConnection(lookupPort("tcp_proxy"));

// Send some data straight away.
ASSERT_TRUE(tcp_client_->write("hello", false));

ASSERT_TRUE(fake_upstreams_[0]->waitForHttpConnection(*dispatcher_, fake_upstream_connection_));
ASSERT_TRUE(fake_upstream_connection_->waitForNewStream(*dispatcher_, upstream_request_));
ASSERT_TRUE(upstream_request_->waitForHeadersComplete());

// Close the upstream connection before sending response headers.
ASSERT_TRUE(fake_upstream_connection_->close());
ASSERT_TRUE(fake_upstream_connection_->waitForDisconnect());

if (upstreamProtocol() == Http::CodecType::HTTP2) {
// The connection is not fully closed yet, so the retry will be on the same connection.
tcp_client_->close();
const std::string expected_log =
"2 " + std::string(StreamInfo::ResponseFlagUtils::UPSTREAM_CONNECTION_FAILURE) + "," +
std::string(StreamInfo::ResponseFlagUtils::UPSTREAM_RETRY_LIMIT_EXCEEDED);
EXPECT_THAT(waitForAccessLog(access_log_filename), testing::HasSubstr(expected_log));
return;
}

// Retry to create a new stream on new connection and not the closed one.
ASSERT_TRUE(fake_upstreams_[0]->waitForHttpConnection(*dispatcher_, fake_upstream_connection_));
ASSERT_TRUE(fake_upstream_connection_->waitForNewStream(*dispatcher_, upstream_request_));
ASSERT_TRUE(upstream_request_->waitForHeadersComplete());

upstream_request_->encodeHeaders(default_response_headers_, false);
ASSERT_TRUE(upstream_request_->waitForData(*dispatcher_, 5));

tcp_client_->close();
if (upstreamProtocol() == Http::CodecType::HTTP1) {
ASSERT_TRUE(fake_upstream_connection_->waitForDisconnect());
} else {
ASSERT_TRUE(upstream_request_->waitForEndStream(*dispatcher_));
// If the upstream now sends 'end stream' the connection is fully closed.
upstream_request_->encodeData(0, true);
}

const std::string expected_log =
"2 " + std::string(StreamInfo::ResponseFlagUtils::UPSTREAM_CONNECTION_FAILURE);
EXPECT_THAT(waitForAccessLog(access_log_filename), testing::HasSubstr(expected_log));
}

TEST_P(TcpTunnelingIntegrationTest,
ConnectionAttemptRetryOnUpstreamConnectionCloseBeforeResponseHeadersWithBackoffOptions) {
const std::string access_log_filename =
Expand Down
1 change: 0 additions & 1 deletion test/per_file_coverage.sh
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ declare -a KNOWN_LOW_COVERAGE=(
"source/common/network/dns_resolver:91.4" # A few lines of MacOS code not tested in linux scripts. Tested in MacOS scripts
"source/common/quic:93.3"
"source/common/signal:87.2" # Death tests don't report LCOV
"source/common/tcp_proxy:96.5"
"source/common/thread:0.0" # Death tests don't report LCOV
"source/common/tls:95.5"
"source/common/tls/cert_validator:94.7"
Expand Down

0 comments on commit 8584f9c

Please sign in to comment.