20 #include <gmock/gmock.h>
21 #include <gtest/gtest.h>
23 #include "absl/memory/memory.h"
24 #include "absl/strings/str_cat.h"
31 #include "src/proto/grpc/testing/xds/v3/cluster.grpc.pb.h"
32 #include "src/proto/grpc/testing/xds/v3/endpoint.grpc.pb.h"
33 #include "src/proto/grpc/testing/xds/v3/http_connection_manager.grpc.pb.h"
34 #include "src/proto/grpc/testing/xds/v3/listener.grpc.pb.h"
35 #include "src/proto/grpc/testing/xds/v3/route.grpc.pb.h"
39 #ifndef DISABLED_XDS_PROTO_IN_CC
42 #include "src/proto/grpc/testing/xds/v3/csds.grpc.pb.h"
48 using ::envoy::admin::v3::ClientResourceStatus;
49 using ::envoy::config::cluster::v3::Cluster;
50 using ::envoy::config::endpoint::v3::ClusterLoadAssignment;
52 using ::envoy::config::route::v3::RouteConfiguration;
53 using ::envoy::extensions::filters::network::http_connection_manager::v3::
54 HttpConnectionManager;
56 MATCHER_P4(EqNode,
id, user_agent_name, user_agent_version, client_features,
63 user_agent_version,
arg.user_agent_version(), result_listener);
70 client_status, error_state,
"equals GenericXdsConfig") {
90 api_listener,
arg.api_listener().api_listener(), result_listener);
94 MATCHER_P(EqHttpConnectionManagerNotRds, route_config,
95 "equals HttpConnectionManager") {
102 MATCHER_P(EqRouteConfigurationName,
name,
"equals RouteConfiguration") {
109 "equals RouteConfiguration") {
120 arg.virtual_hosts(), result_listener);
133 port,
arg.address().socket_address().port_value(), result_listener);
141 &envoy::config::endpoint::v3::LbEndpoint::endpoint,
143 arg.lb_endpoints(), result_listener);
150 "equals ClusterLoadAssignment") {
158 "equals ClusterLoadAssignment") {
164 arg.endpoints(), result_listener);
169 "equals UpdateFailureState") {
177 MATCHER_P(UnpackListener, matcher,
"is a Listener") {
186 MATCHER_P(UnpackRouteConfiguration, matcher,
"is a RouteConfiguration") {
187 RouteConfiguration
config;
195 MATCHER_P(UnpackHttpConnectionManager, matcher,
"is a HttpConnectionManager") {
196 HttpConnectionManager
config;
204 MATCHER_P(UnpackCluster, matcher,
"is a Cluster") {
213 MATCHER_P(UnpackClusterLoadAssignment, matcher,
"is a ClusterLoadAssignment") {
214 ClusterLoadAssignment
config;
222 MATCHER(IsRdsEnabledHCM,
"is a RDS enabled HttpConnectionManager") {
224 UnpackHttpConnectionManager(
226 arg, result_listener);
230 "equals RDS disabled HttpConnectionManager") {
232 UnpackHttpConnectionManager(EqHttpConnectionManagerNotRds(
233 EqRouteConfiguration(route_configuration_name,
cluster_name))),
234 arg, result_listener);
237 class ClientStatusDiscoveryServiceTest :
public XdsEnd2endTest {
239 ClientStatusDiscoveryServiceTest() {
245 admin_server_address,
246 std::make_shared<SecureChannelCredentials>(
249 envoy::service::status::v3::ClientStatusDiscoveryService::NewStub(
251 if (GetParam().use_csds_streaming()) {
256 ~ClientStatusDiscoveryServiceTest()
override {
261 <<
" message=" <<
status.error_message();
266 envoy::service::status::v3::ClientStatusResponse FetchCsdsResponse() {
267 envoy::service::status::v3::ClientStatusResponse
response;
268 if (!GetParam().use_csds_streaming()) {
272 &
context, envoy::service::status::v3::ClientStatusRequest(),
275 <<
" message=" <<
status.error_message();
279 stream_->Write(envoy::service::status::v3::ClientStatusRequest()));
287 class AdminServerThread :
public ServerThread {
289 explicit AdminServerThread(XdsEnd2endTest* test_obj)
290 : ServerThread(test_obj) {}
293 const char*
Type()
override {
return "Admin"; }
295 void RegisterAllServices(ServerBuilder*
builder)
override {
298 void StartAllServices()
override {}
299 void ShutdownAllServices()
override {}
307 envoy::service::status::v3::ClientStatusDiscoveryService::Stub>
311 ClientReaderWriter<envoy::service::status::v3::ClientStatusRequest,
312 envoy::service::status::v3::ClientStatusResponse>>
320 XdsTest, ClientStatusDiscoveryServiceTest,
325 .set_enable_rds_testing(),
328 .set_use_csds_streaming(),
331 .set_enable_rds_testing()
332 .set_use_csds_streaming()),
335 TEST_P(ClientStatusDiscoveryServiceTest, XdsConfigDumpVanilla) {
336 CreateAndStartBackends(1);
338 EdsResourceArgs
args({{
"locality0", CreateEndpointsForBackends(0, 1)}});
339 balancer_->ads_service()->SetEdsResource(BuildEdsResource(
args));
343 auto csds_response = FetchCsdsResponse();
344 gpr_log(
GPR_INFO,
"xDS config dump: %s", csds_response.DebugString().c_str());
345 EXPECT_EQ(1, csds_response.config_size());
346 const auto& client_config = csds_response.config(0);
352 "envoy.lb.does_not_support_overprovisioning")));
355 if (GetParam().enable_rds_testing()) {
356 api_listener_matcher = IsRdsEnabledHCM();
358 api_listener_matcher =
359 EqNoRdsHCM(kDefaultRouteConfigurationName, kDefaultClusterName);
363 envoy::service::status::v3::ClientConfig_GenericXdsConfig>>
368 UnpackListener(EqListener(kServerName, api_listener_matcher)),
371 EqGenericXdsConfig(
kCdsTypeUrl, kDefaultClusterName,
"1",
372 UnpackCluster(EqCluster(kDefaultClusterName)),
377 UnpackClusterLoadAssignment(EqClusterLoadAssignment(
379 kDefaultLocalityWeight)),
383 if (GetParam().enable_rds_testing()) {
384 matchers.push_back(EqGenericXdsConfig(
386 UnpackRouteConfiguration(EqRouteConfiguration(
387 kDefaultRouteConfigurationName, kDefaultClusterName)),
393 <<
"Actual: " << client_config.DebugString();
396 TEST_P(ClientStatusDiscoveryServiceTest, XdsConfigDumpEmpty) {
402 TEST_P(ClientStatusDiscoveryServiceTest, XdsConfigDumpListenerError) {
403 CreateAndStartBackends(1);
404 int kFetchConfigRetries = 3;
405 int kFetchIntervalMilliseconds = 200;
406 EdsResourceArgs
args({{
"locality0", CreateEndpointsForBackends(0, 1)}});
407 balancer_->ads_service()->SetEdsResource(BuildEdsResource(
args));
412 listener.set_name(kServerName);
413 balancer_->ads_service()->SetLdsResource(listener);
417 if (GetParam().enable_rds_testing()) {
418 api_listener_matcher = IsRdsEnabledHCM();
420 api_listener_matcher =
421 EqNoRdsHCM(kDefaultRouteConfigurationName, kDefaultClusterName);
423 for (
int i = 0;
i < kFetchConfigRetries; ++
i) {
424 auto csds_response = FetchCsdsResponse();
427 csds_response.config(0).generic_xds_configs(),
430 UnpackListener(EqListener(kServerName, api_listener_matcher)),
431 ClientResourceStatus::NACKED,
432 EqUpdateFailureState(
434 "Listener has neither address nor ApiListener"),
440 FAIL() <<
"error_state not seen in CSDS responses";
443 TEST_P(ClientStatusDiscoveryServiceTest, XdsConfigDumpRouteError) {
444 CreateAndStartBackends(1);
445 int kFetchConfigRetries = 3;
446 int kFetchIntervalMilliseconds = 200;
447 EdsResourceArgs
args({{
"locality0", CreateEndpointsForBackends(0, 1)}});
448 balancer_->ads_service()->SetEdsResource(BuildEdsResource(
args));
452 RouteConfiguration route_config;
453 route_config.set_name(kDefaultRouteConfigurationName);
454 route_config.add_virtual_hosts();
455 SetRouteConfiguration(balancer_.get(), route_config);
458 for (
int i = 0;
i < kFetchConfigRetries; ++
i) {
459 auto csds_response = FetchCsdsResponse();
461 if (GetParam().enable_rds_testing()) {
463 csds_response.config(0).generic_xds_configs(),
466 UnpackRouteConfiguration(EqRouteConfiguration(
467 kDefaultRouteConfigurationName, kDefaultClusterName)),
468 ClientResourceStatus::NACKED,
469 EqUpdateFailureState(
473 csds_response.config(0).generic_xds_configs(),
476 UnpackListener(EqListener(
477 kServerName, EqNoRdsHCM(kDefaultRouteConfigurationName,
478 kDefaultClusterName))),
479 ClientResourceStatus::NACKED,
480 EqUpdateFailureState(
487 FAIL() <<
"error_state not seen in CSDS responses";
490 TEST_P(ClientStatusDiscoveryServiceTest, XdsConfigDumpClusterError) {
491 CreateAndStartBackends(1);
492 int kFetchConfigRetries = 3;
493 int kFetchIntervalMilliseconds = 200;
494 EdsResourceArgs
args({{
"locality0", CreateEndpointsForBackends(0, 1)}});
495 balancer_->ads_service()->SetEdsResource(BuildEdsResource(
args));
500 cluster.set_name(kDefaultClusterName);
501 balancer_->ads_service()->SetCdsResource(
cluster);
504 for (
int i = 0;
i < kFetchConfigRetries; ++
i) {
505 auto csds_response = FetchCsdsResponse();
508 csds_response.config(0).generic_xds_configs(),
511 UnpackCluster(EqCluster(kDefaultClusterName)),
512 ClientResourceStatus::NACKED,
513 EqUpdateFailureState(
519 FAIL() <<
"error_state not seen in CSDS responses";
522 TEST_P(ClientStatusDiscoveryServiceTest, XdsConfigDumpEndpointError) {
523 CreateAndStartBackends(1);
524 int kFetchConfigRetries = 3;
525 int kFetchIntervalMilliseconds = 200;
526 EdsResourceArgs
args({{
"locality0", CreateEndpointsForBackends(0, 1)}});
527 balancer_->ads_service()->SetEdsResource(BuildEdsResource(
args));
531 ClusterLoadAssignment cluster_load_assignment;
532 cluster_load_assignment.set_cluster_name(kDefaultEdsServiceName);
533 auto* endpoints = cluster_load_assignment.add_endpoints();
534 endpoints->mutable_load_balancing_weight()->set_value(1);
535 auto* endpoint = endpoints->add_lb_endpoints()->mutable_endpoint();
536 endpoint->mutable_address()->mutable_socket_address()->set_port_value(1 << 1);
537 balancer_->ads_service()->SetEdsResource(cluster_load_assignment);
540 for (
int i = 0;
i < kFetchConfigRetries; ++
i) {
541 auto csds_response = FetchCsdsResponse();
544 csds_response.config(0).generic_xds_configs(),
547 UnpackClusterLoadAssignment(EqClusterLoadAssignment(
549 kDefaultLocalityWeight)),
550 ClientResourceStatus::NACKED,
557 FAIL() <<
"error_state not seen in CSDS responses";
560 TEST_P(ClientStatusDiscoveryServiceTest, XdsConfigDumpListenerRequested) {
561 int kTimeoutMillisecond = 1000;
562 balancer_->ads_service()->UnsetResource(
kLdsTypeUrl, kServerName);
565 RpcOptions().set_timeout_ms(kTimeoutMillisecond));
566 auto csds_response = FetchCsdsResponse();
567 EXPECT_THAT(csds_response.config(0).generic_xds_configs(),
570 ClientResourceStatus::REQUESTED, ::
testing::_)));
573 TEST_P(ClientStatusDiscoveryServiceTest, XdsConfigDumpClusterRequested) {
574 int kTimeoutMillisecond = 1000;
578 RouteConfiguration route_config;
579 route_config.set_name(kDefaultRouteConfigurationName);
580 auto* vh = route_config.add_virtual_hosts();
583 vh->add_domains(
"*");
584 auto* routes1 = vh->add_routes();
585 routes1->mutable_match()->set_prefix(
"");
586 routes1->mutable_route()->set_cluster(kClusterName1);
587 auto* routes2 = vh->add_routes();
588 routes2->mutable_match()->set_prefix(
"");
589 routes2->mutable_route()->set_cluster(kClusterName2);
590 SetRouteConfiguration(balancer_.get(), route_config);
594 RpcOptions().set_timeout_ms(kTimeoutMillisecond));
595 auto csds_response = FetchCsdsResponse();
596 EXPECT_THAT(csds_response.config(0).generic_xds_configs(),
600 ClientResourceStatus::REQUESTED, ::
testing::_)),
603 ClientResourceStatus::REQUESTED, ::
testing::_))));
606 class CsdsShortAdsTimeoutTest :
public ClientStatusDiscoveryServiceTest {
608 void SetUp()
override {
610 InitClient(BootstrapBuilder(),
"",
619 XdsTest, CsdsShortAdsTimeoutTest,
624 .set_enable_rds_testing(),
627 .set_use_csds_streaming(),
630 .set_enable_rds_testing()
631 .set_use_csds_streaming()),
634 TEST_P(CsdsShortAdsTimeoutTest, XdsConfigDumpListenerDoesNotExist) {
635 int kTimeoutMillisecond = 1000000;
636 balancer_->ads_service()->UnsetResource(
kLdsTypeUrl, kServerName);
639 ": xDS listener resource does not exist"),
640 RpcOptions().set_timeout_ms(kTimeoutMillisecond));
641 auto csds_response = FetchCsdsResponse();
642 EXPECT_THAT(csds_response.config(0).generic_xds_configs(),
645 ClientResourceStatus::DOES_NOT_EXIST, ::
testing::_)));
648 TEST_P(CsdsShortAdsTimeoutTest, XdsConfigDumpRouteConfigDoesNotExist) {
649 if (!GetParam().enable_rds_testing())
return;
650 int kTimeoutMillisecond = 1000000;
651 balancer_->ads_service()->UnsetResource(
kRdsTypeUrl,
652 kDefaultRouteConfigurationName);
655 absl::StrCat(
"empty address list: ", kDefaultRouteConfigurationName,
656 ": xDS route configuration resource does not exist"),
657 RpcOptions().set_timeout_ms(kTimeoutMillisecond));
658 auto csds_response = FetchCsdsResponse();
660 csds_response.config(0).generic_xds_configs(),
666 TEST_P(CsdsShortAdsTimeoutTest, XdsConfigDumpClusterDoesNotExist) {
667 int kTimeoutMillisecond = 1000000;
668 balancer_->ads_service()->UnsetResource(
kCdsTypeUrl, kDefaultClusterName);
671 absl::StrCat(
"CDS resource \"", kDefaultClusterName,
"\" does not exist"),
672 RpcOptions().set_timeout_ms(kTimeoutMillisecond));
673 auto csds_response = FetchCsdsResponse();
674 EXPECT_THAT(csds_response.config(0).generic_xds_configs(),
677 ClientResourceStatus::DOES_NOT_EXIST, ::
testing::_)));
680 TEST_P(CsdsShortAdsTimeoutTest, XdsConfigDumpEndpointDoesNotExist) {
681 int kTimeoutMillisecond = 1000000;
682 balancer_->ads_service()->UnsetResource(
kEdsTypeUrl, kDefaultEdsServiceName);
686 "no children in weighted_target policy: ",
687 RpcOptions().set_timeout_ms(kTimeoutMillisecond));
688 auto csds_response = FetchCsdsResponse();
690 csds_response.config(0).generic_xds_configs(),
693 ClientResourceStatus::DOES_NOT_EXIST, ::
testing::_)));
700 #endif // DISABLED_XDS_PROTO_IN_CC
702 int main(
int argc,
char** argv) {