Skip to content

Commit c84604c

Browse files
fredlashtuch
authored andcommitted
test: Add non-aggregated CDS-over-gRPC integration test (envoyproxy#5228)
While trying to implement incremental CDS support in Envoy, I found it extremely difficult to work with the integration tests, which I hoped to adapt/copy for incremental. The only test using gRPC was ADS. I decided that a more manageable first step was to add a test for just (non-incremental) CDS over gRPC. Risk Level: none, just a new test Signed-off-by: Fred Douglas <[email protected]>
1 parent 35827dd commit c84604c

24 files changed

+555
-202
lines changed

docs/root/configuration/cluster_manager/cluster_stats.rst

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,9 @@ General
1010
-------
1111

1212
The cluster manager has a statistics tree rooted at *cluster_manager.* with the following
13-
statistics. Any ``:`` character in the stats name is replaced with ``_``.
13+
statistics. Any ``:`` character in the stats name is replaced with ``_``. Stats include
14+
all clusters managed by the cluster manager, including both clusters used for data plane
15+
upstreams and control plane xDS clusters.
1416

1517
.. csv-table::
1618
:header: Name, Type, Description

test/extensions/filters/http/buffer/buffer_filter_integration_test.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ TEST_P(BufferIntegrationTest, RouterRequestAndResponseWithGiantBodyBuffer) {
2121

2222
TEST_P(BufferIntegrationTest, RouterHeaderOnlyRequestAndResponseBuffer) {
2323
config_helper_.addFilter(ConfigHelper::DEFAULT_BUFFER_FILTER);
24-
testRouterHeaderOnlyRequestAndResponse(true);
24+
testRouterHeaderOnlyRequestAndResponse();
2525
}
2626

2727
TEST_P(BufferIntegrationTest, RouterRequestAndResponseWithBodyBuffer) {

test/integration/BUILD

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ envoy_cc_test(
2424
"//test/config/integration/certs",
2525
],
2626
deps = [
27-
":http_integration_lib",
27+
":xds_integration_test_base",
2828
"//source/common/config:protobuf_link_hacks",
2929
"//source/common/config:resources_lib",
3030
"//source/common/protobuf:utility_lib",
@@ -63,6 +63,27 @@ envoy_proto_library(
6363
require_py = 1,
6464
)
6565

66+
envoy_cc_test(
67+
name = "cds_integration_test",
68+
srcs = ["cds_integration_test.cc"],
69+
data = [
70+
"//test/config/integration/certs",
71+
],
72+
deps = [
73+
":xds_integration_test_base",
74+
"//source/common/config:protobuf_link_hacks",
75+
"//source/common/config:resources_lib",
76+
"//source/common/protobuf:utility_lib",
77+
"//test/common/grpc:grpc_client_integration_lib",
78+
"//test/mocks/runtime:runtime_mocks",
79+
"//test/mocks/server:server_mocks",
80+
"//test/test_common:network_utility_lib",
81+
"//test/test_common:utility_lib",
82+
"@envoy_api//envoy/api/v2:cds_cc",
83+
"@envoy_api//envoy/api/v2:discovery_cc",
84+
],
85+
)
86+
6687
envoy_cc_test(
6788
name = "eds_integration_test",
6889
srcs = ["eds_integration_test.cc"],
@@ -601,11 +622,31 @@ envoy_cc_test(
601622
srcs = ["xds_integration_test.cc"],
602623
data = ["//test/config/integration:server_xds_files"],
603624
deps = [
604-
":http_integration_lib",
625+
":xds_integration_test_base",
605626
"//test/test_common:utility_lib",
606627
],
607628
)
608629

630+
envoy_cc_test_library(
631+
name = "xds_integration_test_base",
632+
srcs = [
633+
"xds_integration_test_base.cc",
634+
],
635+
hdrs = [
636+
"xds_integration_test_base.h",
637+
],
638+
deps = [
639+
":http_integration_lib",
640+
":test_host_predicate_lib",
641+
"//include/envoy/event:timer_interface",
642+
"//source/common/common:thread_annotations",
643+
"//source/extensions/filters/http/router:config",
644+
"//source/extensions/filters/network/http_connection_manager:config",
645+
"//test/common/upstream:utility_lib",
646+
"//test/test_common:registry_lib",
647+
],
648+
)
649+
609650
envoy_cc_test(
610651
name = "xfcc_integration_test",
611652
srcs = [

test/integration/ads_integration_test.cc

Lines changed: 32 additions & 123 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@
1818
#include "common/ssl/ssl_socket.h"
1919

2020
#include "test/common/grpc/grpc_client_integration.h"
21-
#include "test/integration/http_integration.h"
2221
#include "test/integration/utility.h"
22+
#include "test/integration/xds_integration_test_base.h"
2323
#include "test/mocks/server/mocks.h"
2424
#include "test/test_common/network_utility.h"
2525
#include "test/test_common/simulated_time_system.h"
@@ -60,50 +60,20 @@ const std::string config = R"EOF(
6060
port_value: 0
6161
)EOF";
6262

63-
class AdsIntegrationBaseTest : public HttpIntegrationTest {
64-
public:
65-
AdsIntegrationBaseTest(Http::CodecClient::Type downstream_protocol,
66-
Network::Address::IpVersion version,
67-
const std::string& config = ConfigHelper::HTTP_PROXY_CONFIG)
68-
: HttpIntegrationTest(downstream_protocol, version, realTime(), config) {}
69-
70-
void createAdsConnection(FakeUpstream& upstream) {
71-
ads_upstream_ = &upstream;
72-
AssertionResult result = ads_upstream_->waitForHttpConnection(*dispatcher_, ads_connection_);
73-
RELEASE_ASSERT(result, result.message());
74-
}
75-
76-
void cleanUpAdsConnection() {
77-
ASSERT(ads_upstream_ != nullptr);
78-
79-
// Don't ASSERT fail if an ADS reconnect ends up unparented.
80-
ads_upstream_->set_allow_unexpected_disconnects(true);
81-
AssertionResult result = ads_connection_->close();
82-
RELEASE_ASSERT(result, result.message());
83-
result = ads_connection_->waitForDisconnect();
84-
RELEASE_ASSERT(result, result.message());
85-
ads_connection_.reset();
86-
}
87-
88-
protected:
89-
FakeHttpConnectionPtr ads_connection_;
90-
FakeUpstream* ads_upstream_{};
91-
};
92-
93-
class AdsIntegrationTest : public AdsIntegrationBaseTest,
63+
class AdsIntegrationTest : public XdsIntegrationTestBase,
9464
public Grpc::GrpcClientIntegrationParamTest {
9565
public:
9666
AdsIntegrationTest()
97-
: AdsIntegrationBaseTest(Http::CodecClient::Type::HTTP2, ipVersion(), config) {}
67+
: XdsIntegrationTestBase(Http::CodecClient::Type::HTTP2, ipVersion(), config) {}
9868

9969
void TearDown() override {
100-
cleanUpAdsConnection();
70+
cleanUpXdsConnection();
10171
test_server_.reset();
10272
fake_upstreams_.clear();
10373
}
10474

10575
void createUpstreams() override {
106-
AdsIntegrationBaseTest::createUpstreams();
76+
XdsIntegrationTestBase::createUpstreams();
10777
fake_upstreams_.emplace_back(new FakeUpstream(
10878
createUpstreamSslContext(), 0, FakeHttpConnection::Type::HTTP2, version_, timeSystem()));
10979
}
@@ -124,60 +94,6 @@ class AdsIntegrationTest : public AdsIntegrationBaseTest,
12494
std::move(cfg), context_manager_, *upstream_stats_store, std::vector<std::string>{});
12595
}
12696

127-
AssertionResult
128-
compareDiscoveryRequest(const std::string& expected_type_url, const std::string& expected_version,
129-
const std::vector<std::string>& expected_resource_names,
130-
const Protobuf::int32 expected_error_code = Grpc::Status::GrpcStatus::Ok,
131-
const std::string& expected_error_message = "") {
132-
envoy::api::v2::DiscoveryRequest discovery_request;
133-
VERIFY_ASSERTION(ads_stream_->waitForGrpcMessage(*dispatcher_, discovery_request));
134-
135-
EXPECT_TRUE(discovery_request.has_node());
136-
EXPECT_FALSE(discovery_request.node().id().empty());
137-
EXPECT_FALSE(discovery_request.node().cluster().empty());
138-
139-
// TODO(PiotrSikora): Remove this hack once fixed internally.
140-
if (!(expected_type_url == discovery_request.type_url())) {
141-
return AssertionFailure() << fmt::format("type_url {} does not match expected {}",
142-
discovery_request.type_url(), expected_type_url);
143-
}
144-
if (!(expected_error_code == discovery_request.error_detail().code())) {
145-
return AssertionFailure() << fmt::format("error_code {} does not match expected {}",
146-
discovery_request.error_detail().code(),
147-
expected_error_code);
148-
}
149-
EXPECT_TRUE(
150-
IsSubstring("", "", expected_error_message, discovery_request.error_detail().message()));
151-
const std::vector<std::string> resource_names(discovery_request.resource_names().cbegin(),
152-
discovery_request.resource_names().cend());
153-
if (expected_resource_names != resource_names) {
154-
return AssertionFailure() << fmt::format(
155-
"resources {} do not match expected {} in {}",
156-
fmt::join(resource_names.begin(), resource_names.end(), ","),
157-
fmt::join(expected_resource_names.begin(), expected_resource_names.end(), ","),
158-
discovery_request.DebugString());
159-
}
160-
// TODO(PiotrSikora): Remove this hack once fixed internally.
161-
if (!(expected_version == discovery_request.version_info())) {
162-
return AssertionFailure() << fmt::format("version {} does not match expected {} in {}",
163-
discovery_request.version_info(), expected_version,
164-
discovery_request.DebugString());
165-
}
166-
return AssertionSuccess();
167-
}
168-
169-
template <class T>
170-
void sendDiscoveryResponse(const std::string& type_url, const std::vector<T>& messages,
171-
const std::string& version) {
172-
envoy::api::v2::DiscoveryResponse discovery_response;
173-
discovery_response.set_version_info(version);
174-
discovery_response.set_type_url(type_url);
175-
for (const auto& message : messages) {
176-
discovery_response.add_resources()->PackFrom(message);
177-
}
178-
ads_stream_->sendGrpcMessage(discovery_response);
179-
}
180-
18197
envoy::api::v2::Cluster buildCluster(const std::string& name) {
18298
return TestUtility::parseYaml<envoy::api::v2::Cluster>(fmt::format(R"EOF(
18399
name: {}
@@ -245,9 +161,8 @@ class AdsIntegrationTest : public AdsIntegrationBaseTest,
245161

246162
void makeSingleRequest() {
247163
registerTestServerPorts({"http"});
248-
testRouterHeaderOnlyRequestAndResponse(true);
164+
testRouterHeaderOnlyRequestAndResponse();
249165
cleanupUpstreamAndDownstream();
250-
fake_upstream_connection_ = nullptr;
251166
}
252167

253168
void initialize() override { initializeAds(false); }
@@ -278,12 +193,12 @@ class AdsIntegrationTest : public AdsIntegrationBaseTest,
278193
}
279194
});
280195
setUpstreamProtocol(FakeHttpConnection::Type::HTTP2);
281-
AdsIntegrationBaseTest::initialize();
282-
if (ads_stream_ == nullptr) {
283-
createAdsConnection(*(fake_upstreams_[1]));
284-
AssertionResult result = ads_connection_->waitForNewStream(*dispatcher_, ads_stream_);
196+
XdsIntegrationTestBase::initialize();
197+
if (xds_stream_ == nullptr) {
198+
createXdsConnection(*(fake_upstreams_[1]));
199+
AssertionResult result = xds_connection_->waitForNewStream(*dispatcher_, xds_stream_);
285200
RELEASE_ASSERT(result, result.message());
286-
ads_stream_->startGrpcStream();
201+
xds_stream_->startGrpcStream();
287202
}
288203
}
289204

@@ -410,9 +325,7 @@ class AdsIntegrationTest : public AdsIntegrationBaseTest,
410325
return dynamic_cast<const envoy::admin::v2alpha::RoutesConfigDump&>(*message_ptr);
411326
}
412327

413-
testing::NiceMock<Server::Configuration::MockTransportSocketFactoryContext> factory_context_;
414328
Ssl::ContextManagerImpl context_manager_{timeSystem()};
415-
FakeStreamPtr ads_stream_;
416329
};
417330

418331
INSTANTIATE_TEST_CASE_P(IpVersionsClientType, AdsIntegrationTest, GRPC_CLIENT_INTEGRATION_PARAMS);
@@ -653,20 +566,20 @@ TEST_P(AdsIntegrationTest, RdsAfterLdsWithRdsChange) {
653566
makeSingleRequest();
654567
}
655568

656-
class AdsFailIntegrationTest : public AdsIntegrationBaseTest,
569+
class AdsFailIntegrationTest : public XdsIntegrationTestBase,
657570
public Grpc::GrpcClientIntegrationParamTest {
658571
public:
659572
AdsFailIntegrationTest()
660-
: AdsIntegrationBaseTest(Http::CodecClient::Type::HTTP2, ipVersion(), config) {}
573+
: XdsIntegrationTestBase(Http::CodecClient::Type::HTTP2, ipVersion(), config) {}
661574

662575
void TearDown() override {
663-
cleanUpAdsConnection();
576+
cleanUpXdsConnection();
664577
test_server_.reset();
665578
fake_upstreams_.clear();
666579
}
667580

668581
void createUpstreams() override {
669-
AdsIntegrationBaseTest::createUpstreams();
582+
XdsIntegrationTestBase::createUpstreams();
670583
fake_upstreams_.emplace_back(
671584
new FakeUpstream(0, FakeHttpConnection::Type::HTTP2, version_, timeSystem()));
672585
}
@@ -681,10 +594,8 @@ class AdsFailIntegrationTest : public AdsIntegrationBaseTest,
681594
ads_cluster->set_name("ads_cluster");
682595
});
683596
setUpstreamProtocol(FakeHttpConnection::Type::HTTP2);
684-
AdsIntegrationBaseTest::initialize();
597+
XdsIntegrationTestBase::initialize();
685598
}
686-
687-
FakeStreamPtr ads_stream_;
688599
};
689600

690601
INSTANTIATE_TEST_CASE_P(IpVersionsClientType, AdsFailIntegrationTest,
@@ -693,26 +604,26 @@ INSTANTIATE_TEST_CASE_P(IpVersionsClientType, AdsFailIntegrationTest,
693604
// Validate that we don't crash on failed ADS stream.
694605
TEST_P(AdsFailIntegrationTest, ConnectDisconnect) {
695606
initialize();
696-
createAdsConnection(*fake_upstreams_[1]);
697-
ASSERT_TRUE(ads_connection_->waitForNewStream(*dispatcher_, ads_stream_));
698-
ads_stream_->startGrpcStream();
699-
ads_stream_->finishGrpcStream(Grpc::Status::Internal);
607+
createXdsConnection(*fake_upstreams_[1]);
608+
ASSERT_TRUE(xds_connection_->waitForNewStream(*dispatcher_, xds_stream_));
609+
xds_stream_->startGrpcStream();
610+
xds_stream_->finishGrpcStream(Grpc::Status::Internal);
700611
}
701612

702-
class AdsConfigIntegrationTest : public AdsIntegrationBaseTest,
613+
class AdsConfigIntegrationTest : public XdsIntegrationTestBase,
703614
public Grpc::GrpcClientIntegrationParamTest {
704615
public:
705616
AdsConfigIntegrationTest()
706-
: AdsIntegrationBaseTest(Http::CodecClient::Type::HTTP2, ipVersion(), config) {}
617+
: XdsIntegrationTestBase(Http::CodecClient::Type::HTTP2, ipVersion(), config) {}
707618

708619
void TearDown() override {
709-
cleanUpAdsConnection();
620+
cleanUpXdsConnection();
710621
test_server_.reset();
711622
fake_upstreams_.clear();
712623
}
713624

714625
void createUpstreams() override {
715-
AdsIntegrationBaseTest::createUpstreams();
626+
XdsIntegrationTestBase::createUpstreams();
716627
fake_upstreams_.emplace_back(
717628
new FakeUpstream(0, FakeHttpConnection::Type::HTTP2, version_, timeSystem()));
718629
}
@@ -735,10 +646,8 @@ class AdsConfigIntegrationTest : public AdsIntegrationBaseTest,
735646
eds_config->mutable_ads();
736647
});
737648
setUpstreamProtocol(FakeHttpConnection::Type::HTTP2);
738-
AdsIntegrationBaseTest::initialize();
649+
XdsIntegrationTestBase::initialize();
739650
}
740-
741-
FakeStreamPtr ads_stream_;
742651
};
743652

744653
INSTANTIATE_TEST_CASE_P(IpVersionsClientType, AdsConfigIntegrationTest,
@@ -747,10 +656,10 @@ INSTANTIATE_TEST_CASE_P(IpVersionsClientType, AdsConfigIntegrationTest,
747656
// This is s regression validating that we don't crash on EDS static Cluster that uses ADS.
748657
TEST_P(AdsConfigIntegrationTest, EdsClusterWithAdsConfigSource) {
749658
initialize();
750-
createAdsConnection(*fake_upstreams_[1]);
751-
ASSERT_TRUE(ads_connection_->waitForNewStream(*dispatcher_, ads_stream_));
752-
ads_stream_->startGrpcStream();
753-
ads_stream_->finishGrpcStream(Grpc::Status::Ok);
659+
createXdsConnection(*fake_upstreams_[1]);
660+
ASSERT_TRUE(xds_connection_->waitForNewStream(*dispatcher_, xds_stream_));
661+
xds_stream_->startGrpcStream();
662+
xds_stream_->finishGrpcStream(Grpc::Status::Ok);
754663
}
755664

756665
// Validates that the initial xDS request batches all resources referred to in static config
@@ -768,9 +677,9 @@ TEST_P(AdsIntegrationTest, XdsBatching) {
768677
});
769678

770679
pre_worker_start_test_steps_ = [this]() {
771-
createAdsConnection(*fake_upstreams_.back());
772-
ASSERT_TRUE(ads_connection_->waitForNewStream(*dispatcher_, ads_stream_));
773-
ads_stream_->startGrpcStream();
680+
createXdsConnection(*fake_upstreams_.back());
681+
ASSERT_TRUE(xds_connection_->waitForNewStream(*dispatcher_, xds_stream_));
682+
xds_stream_->startGrpcStream();
774683

775684
EXPECT_TRUE(compareDiscoveryRequest(Config::TypeUrl::get().ClusterLoadAssignment, "",
776685
{"eds_cluster2", "eds_cluster"}));

0 commit comments

Comments
 (0)