|
|
|
@ -148,6 +148,21 @@ MATCHER_P2(AdjustedClockInRange, t1, t2, "equals time") { |
|
|
|
|
return ok; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
TEST_P(LdsRdsTest, DefaultRouteSpecifiesSlashPrefix) { |
|
|
|
|
CreateAndStartBackends(1); |
|
|
|
|
RouteConfiguration route_config = default_route_config_; |
|
|
|
|
route_config.mutable_virtual_hosts(0) |
|
|
|
|
->mutable_routes(0) |
|
|
|
|
->mutable_match() |
|
|
|
|
->set_prefix("/"); |
|
|
|
|
SetListenerAndRouteConfiguration(balancer_.get(), default_listener_, |
|
|
|
|
route_config); |
|
|
|
|
EdsResourceArgs args({{"locality0", CreateEndpointsForBackends()}}); |
|
|
|
|
balancer_->ads_service()->SetEdsResource(BuildEdsResource(args)); |
|
|
|
|
// We need to wait for all backends to come online.
|
|
|
|
|
WaitForAllBackends(DEBUG_LOCATION); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Tests that LDS client ACKs but fails if matching domain can't be found in
|
|
|
|
|
// the LDS response.
|
|
|
|
|
TEST_P(LdsRdsTest, NoMatchedDomain) { |
|
|
|
@ -216,31 +231,165 @@ TEST_P(LdsRdsTest, NoMatchingRoute) { |
|
|
|
|
EXPECT_EQ(response_state->state, AdsServiceImpl::ResponseState::ACKED); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Testing just one example of an invalid resource here.
|
|
|
|
|
// Unit tests for XdsRouteConfigResourceType have exhaustive tests for all
|
|
|
|
|
// of the invalid cases.
|
|
|
|
|
TEST_P(LdsRdsTest, NacksInvalidRouteConfig) { |
|
|
|
|
// Tests that LDS client should ignore route which has query_parameters.
|
|
|
|
|
TEST_P(LdsRdsTest, RouteMatchHasQueryParameters) { |
|
|
|
|
RouteConfiguration route_config = default_route_config_; |
|
|
|
|
auto* route1 = route_config.mutable_virtual_hosts(0)->mutable_routes(0); |
|
|
|
|
route1->mutable_match()->set_prefix("/grpc.testing.EchoTest1Service/"); |
|
|
|
|
route1->mutable_match()->add_query_parameters(); |
|
|
|
|
SetRouteConfiguration(balancer_.get(), route_config); |
|
|
|
|
const auto response_state = WaitForRdsNack(DEBUG_LOCATION); |
|
|
|
|
ASSERT_TRUE(response_state.has_value()) << "timed out waiting for NACK"; |
|
|
|
|
EXPECT_THAT(response_state->error_message, |
|
|
|
|
::testing::HasSubstr("No valid routes specified.")); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Tests that LDS client should send a ACK if route match has a prefix
|
|
|
|
|
// that is either empty or a single slash
|
|
|
|
|
TEST_P(LdsRdsTest, RouteMatchHasValidPrefixEmptyOrSingleSlash) { |
|
|
|
|
RouteConfiguration route_config = default_route_config_; |
|
|
|
|
auto* route1 = route_config.mutable_virtual_hosts(0)->mutable_routes(0); |
|
|
|
|
route1->mutable_match()->set_prefix(""); |
|
|
|
|
auto* default_route = route_config.mutable_virtual_hosts(0)->add_routes(); |
|
|
|
|
default_route->mutable_match()->set_prefix("/"); |
|
|
|
|
default_route->mutable_route()->set_cluster(kDefaultClusterName); |
|
|
|
|
SetRouteConfiguration(balancer_.get(), route_config); |
|
|
|
|
(void)SendRpc(); |
|
|
|
|
const auto response_state = RouteConfigurationResponseState(balancer_.get()); |
|
|
|
|
ASSERT_TRUE(response_state.has_value()); |
|
|
|
|
EXPECT_EQ(response_state->state, AdsServiceImpl::ResponseState::ACKED); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Tests that LDS client should ignore route which has a path
|
|
|
|
|
// prefix string does not start with "/".
|
|
|
|
|
TEST_P(LdsRdsTest, RouteMatchHasInvalidPrefixNoLeadingSlash) { |
|
|
|
|
RouteConfiguration route_config = default_route_config_; |
|
|
|
|
auto* route1 = route_config.mutable_virtual_hosts(0)->mutable_routes(0); |
|
|
|
|
route1->mutable_match()->set_prefix("grpc.testing.EchoTest1Service/"); |
|
|
|
|
SetRouteConfiguration(balancer_.get(), route_config); |
|
|
|
|
const auto response_state = WaitForRdsNack(DEBUG_LOCATION); |
|
|
|
|
ASSERT_TRUE(response_state.has_value()) << "timed out waiting for NACK"; |
|
|
|
|
EXPECT_EQ( |
|
|
|
|
response_state->error_message, |
|
|
|
|
absl::StrCat( |
|
|
|
|
"xDS response validation errors: [resource index 0: ", |
|
|
|
|
GetParam().enable_rds_testing() |
|
|
|
|
? "route_config_name: INVALID_ARGUMENT: " |
|
|
|
|
"errors validating RouteConfiguration resource: [" |
|
|
|
|
"field:" |
|
|
|
|
: "server.example.com: INVALID_ARGUMENT: " |
|
|
|
|
"errors validating ApiListener: [" |
|
|
|
|
"field:api_listener.api_listener.value[" |
|
|
|
|
"envoy.extensions.filters.network.http_connection_manager.v3" |
|
|
|
|
".HttpConnectionManager].route_config.", |
|
|
|
|
"virtual_hosts[0].routes " |
|
|
|
|
"error:no valid routes in VirtualHost]]")); |
|
|
|
|
EXPECT_THAT(response_state->error_message, |
|
|
|
|
::testing::HasSubstr("No valid routes specified.")); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Tests that LDS client should ignore route which has a prefix
|
|
|
|
|
// string with more than 2 slashes.
|
|
|
|
|
TEST_P(LdsRdsTest, RouteMatchHasInvalidPrefixExtraContent) { |
|
|
|
|
RouteConfiguration route_config = default_route_config_; |
|
|
|
|
auto* route1 = route_config.mutable_virtual_hosts(0)->mutable_routes(0); |
|
|
|
|
route1->mutable_match()->set_prefix("/grpc.testing.EchoTest1Service/Echo1/"); |
|
|
|
|
SetRouteConfiguration(balancer_.get(), route_config); |
|
|
|
|
const auto response_state = WaitForRdsNack(DEBUG_LOCATION); |
|
|
|
|
ASSERT_TRUE(response_state.has_value()) << "timed out waiting for NACK"; |
|
|
|
|
EXPECT_THAT(response_state->error_message, |
|
|
|
|
::testing::HasSubstr("No valid routes specified.")); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Tests that LDS client should ignore route which has a prefix
|
|
|
|
|
// string "//".
|
|
|
|
|
TEST_P(LdsRdsTest, RouteMatchHasInvalidPrefixDoubleSlash) { |
|
|
|
|
RouteConfiguration route_config = default_route_config_; |
|
|
|
|
auto* route1 = route_config.mutable_virtual_hosts(0)->mutable_routes(0); |
|
|
|
|
route1->mutable_match()->set_prefix("//"); |
|
|
|
|
SetRouteConfiguration(balancer_.get(), route_config); |
|
|
|
|
const auto response_state = WaitForRdsNack(DEBUG_LOCATION); |
|
|
|
|
ASSERT_TRUE(response_state.has_value()) << "timed out waiting for NACK"; |
|
|
|
|
EXPECT_THAT(response_state->error_message, |
|
|
|
|
::testing::HasSubstr("No valid routes specified.")); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Tests that LDS client should ignore route which has path
|
|
|
|
|
// but it's empty.
|
|
|
|
|
TEST_P(LdsRdsTest, RouteMatchHasInvalidPathEmptyPath) { |
|
|
|
|
RouteConfiguration route_config = default_route_config_; |
|
|
|
|
auto* route1 = route_config.mutable_virtual_hosts(0)->mutable_routes(0); |
|
|
|
|
route1->mutable_match()->set_path(""); |
|
|
|
|
SetRouteConfiguration(balancer_.get(), route_config); |
|
|
|
|
const auto response_state = WaitForRdsNack(DEBUG_LOCATION); |
|
|
|
|
ASSERT_TRUE(response_state.has_value()) << "timed out waiting for NACK"; |
|
|
|
|
EXPECT_THAT(response_state->error_message, |
|
|
|
|
::testing::HasSubstr("No valid routes specified.")); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Tests that LDS client should ignore route which has path
|
|
|
|
|
// string does not start with "/".
|
|
|
|
|
TEST_P(LdsRdsTest, RouteMatchHasInvalidPathNoLeadingSlash) { |
|
|
|
|
RouteConfiguration route_config = default_route_config_; |
|
|
|
|
auto* route1 = route_config.mutable_virtual_hosts(0)->mutable_routes(0); |
|
|
|
|
route1->mutable_match()->set_path("grpc.testing.EchoTest1Service/Echo1"); |
|
|
|
|
SetRouteConfiguration(balancer_.get(), route_config); |
|
|
|
|
const auto response_state = WaitForRdsNack(DEBUG_LOCATION); |
|
|
|
|
ASSERT_TRUE(response_state.has_value()) << "timed out waiting for NACK"; |
|
|
|
|
EXPECT_THAT(response_state->error_message, |
|
|
|
|
::testing::HasSubstr("No valid routes specified.")); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Tests that LDS client should ignore route which has path
|
|
|
|
|
// string that has too many slashes; for example, ends with "/".
|
|
|
|
|
TEST_P(LdsRdsTest, RouteMatchHasInvalidPathTooManySlashes) { |
|
|
|
|
RouteConfiguration route_config = default_route_config_; |
|
|
|
|
auto* route1 = route_config.mutable_virtual_hosts(0)->mutable_routes(0); |
|
|
|
|
route1->mutable_match()->set_path("/grpc.testing.EchoTest1Service/Echo1/"); |
|
|
|
|
SetRouteConfiguration(balancer_.get(), route_config); |
|
|
|
|
const auto response_state = WaitForRdsNack(DEBUG_LOCATION); |
|
|
|
|
ASSERT_TRUE(response_state.has_value()) << "timed out waiting for NACK"; |
|
|
|
|
EXPECT_THAT(response_state->error_message, |
|
|
|
|
::testing::HasSubstr("No valid routes specified.")); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Tests that LDS client should ignore route which has path
|
|
|
|
|
// string that has only 1 slash: missing "/" between service and method.
|
|
|
|
|
TEST_P(LdsRdsTest, RouteMatchHasInvalidPathOnlyOneSlash) { |
|
|
|
|
RouteConfiguration route_config = default_route_config_; |
|
|
|
|
auto* route1 = route_config.mutable_virtual_hosts(0)->mutable_routes(0); |
|
|
|
|
route1->mutable_match()->set_path("/grpc.testing.EchoTest1Service.Echo1"); |
|
|
|
|
SetRouteConfiguration(balancer_.get(), route_config); |
|
|
|
|
const auto response_state = WaitForRdsNack(DEBUG_LOCATION); |
|
|
|
|
ASSERT_TRUE(response_state.has_value()) << "timed out waiting for NACK"; |
|
|
|
|
EXPECT_THAT(response_state->error_message, |
|
|
|
|
::testing::HasSubstr("No valid routes specified.")); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Tests that LDS client should ignore route which has path
|
|
|
|
|
// string that is missing service.
|
|
|
|
|
TEST_P(LdsRdsTest, RouteMatchHasInvalidPathMissingService) { |
|
|
|
|
RouteConfiguration route_config = default_route_config_; |
|
|
|
|
auto* route1 = route_config.mutable_virtual_hosts(0)->mutable_routes(0); |
|
|
|
|
route1->mutable_match()->set_path("//Echo1"); |
|
|
|
|
SetRouteConfiguration(balancer_.get(), route_config); |
|
|
|
|
const auto response_state = WaitForRdsNack(DEBUG_LOCATION); |
|
|
|
|
ASSERT_TRUE(response_state.has_value()) << "timed out waiting for NACK"; |
|
|
|
|
EXPECT_THAT(response_state->error_message, |
|
|
|
|
::testing::HasSubstr("No valid routes specified.")); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Tests that LDS client should ignore route which has path
|
|
|
|
|
// string that is missing method.
|
|
|
|
|
TEST_P(LdsRdsTest, RouteMatchHasInvalidPathMissingMethod) { |
|
|
|
|
RouteConfiguration route_config = default_route_config_; |
|
|
|
|
auto* route1 = route_config.mutable_virtual_hosts(0)->mutable_routes(0); |
|
|
|
|
route1->mutable_match()->set_path("/grpc.testing.EchoTest1Service/"); |
|
|
|
|
SetRouteConfiguration(balancer_.get(), route_config); |
|
|
|
|
const auto response_state = WaitForRdsNack(DEBUG_LOCATION); |
|
|
|
|
ASSERT_TRUE(response_state.has_value()) << "timed out waiting for NACK"; |
|
|
|
|
EXPECT_THAT(response_state->error_message, |
|
|
|
|
::testing::HasSubstr("No valid routes specified.")); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Test that LDS client should reject route which has invalid path regex.
|
|
|
|
|
TEST_P(LdsRdsTest, RouteMatchHasInvalidPathRegex) { |
|
|
|
|
const char* kNewCluster1Name = "new_cluster_1"; |
|
|
|
|
RouteConfiguration route_config = default_route_config_; |
|
|
|
|
auto* route1 = route_config.mutable_virtual_hosts(0)->mutable_routes(0); |
|
|
|
|
route1->mutable_match()->mutable_safe_regex()->set_regex("a[z-a]"); |
|
|
|
|
route1->mutable_route()->set_cluster(kNewCluster1Name); |
|
|
|
|
SetRouteConfiguration(balancer_.get(), route_config); |
|
|
|
|
const auto response_state = WaitForRdsNack(DEBUG_LOCATION); |
|
|
|
|
ASSERT_TRUE(response_state.has_value()) << "timed out waiting for NACK"; |
|
|
|
|
EXPECT_THAT(response_state->error_message, |
|
|
|
|
::testing::HasSubstr( |
|
|
|
|
"path matcher: Invalid regex string specified in matcher.")); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Tests that LDS client should fail RPCs with UNAVAILABLE status code if the
|
|
|
|
@ -260,6 +409,158 @@ TEST_P(LdsRdsTest, MatchingRouteHasNoRouteAction) { |
|
|
|
|
"Matching route has inappropriate action"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
TEST_P(LdsRdsTest, RouteActionClusterHasEmptyClusterName) { |
|
|
|
|
RouteConfiguration route_config = default_route_config_; |
|
|
|
|
auto* route1 = route_config.mutable_virtual_hosts(0)->mutable_routes(0); |
|
|
|
|
route1->mutable_match()->set_prefix("/grpc.testing.EchoTest1Service/"); |
|
|
|
|
route1->mutable_route()->set_cluster(""); |
|
|
|
|
auto* default_route = route_config.mutable_virtual_hosts(0)->add_routes(); |
|
|
|
|
default_route->mutable_match()->set_prefix(""); |
|
|
|
|
default_route->mutable_route()->set_cluster(kDefaultClusterName); |
|
|
|
|
SetRouteConfiguration(balancer_.get(), route_config); |
|
|
|
|
const auto response_state = WaitForRdsNack(DEBUG_LOCATION); |
|
|
|
|
ASSERT_TRUE(response_state.has_value()) << "timed out waiting for NACK"; |
|
|
|
|
EXPECT_THAT( |
|
|
|
|
response_state->error_message, |
|
|
|
|
::testing::HasSubstr("RouteAction cluster contains empty cluster name.")); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
TEST_P(LdsRdsTest, RouteActionWeightedTargetHasIncorrectTotalWeightSet) { |
|
|
|
|
const size_t kWeight75 = 75; |
|
|
|
|
const char* kNewCluster1Name = "new_cluster_1"; |
|
|
|
|
RouteConfiguration route_config = default_route_config_; |
|
|
|
|
auto* route1 = route_config.mutable_virtual_hosts(0)->mutable_routes(0); |
|
|
|
|
route1->mutable_match()->set_prefix("/grpc.testing.EchoTest1Service/"); |
|
|
|
|
auto* weighted_cluster1 = |
|
|
|
|
route1->mutable_route()->mutable_weighted_clusters()->add_clusters(); |
|
|
|
|
weighted_cluster1->set_name(kNewCluster1Name); |
|
|
|
|
weighted_cluster1->mutable_weight()->set_value(kWeight75); |
|
|
|
|
route1->mutable_route() |
|
|
|
|
->mutable_weighted_clusters() |
|
|
|
|
->mutable_total_weight() |
|
|
|
|
->set_value(kWeight75 + 1); |
|
|
|
|
auto* default_route = route_config.mutable_virtual_hosts(0)->add_routes(); |
|
|
|
|
default_route->mutable_match()->set_prefix(""); |
|
|
|
|
default_route->mutable_route()->set_cluster(kDefaultClusterName); |
|
|
|
|
SetRouteConfiguration(balancer_.get(), route_config); |
|
|
|
|
const auto response_state = WaitForRdsNack(DEBUG_LOCATION); |
|
|
|
|
ASSERT_TRUE(response_state.has_value()) << "timed out waiting for NACK"; |
|
|
|
|
EXPECT_THAT(response_state->error_message, |
|
|
|
|
::testing::HasSubstr( |
|
|
|
|
"RouteAction weighted_cluster has incorrect total weight")); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
TEST_P(LdsRdsTest, RouteActionWeightedClusterHasZeroTotalWeight) { |
|
|
|
|
const char* kNewCluster1Name = "new_cluster_1"; |
|
|
|
|
RouteConfiguration route_config = default_route_config_; |
|
|
|
|
auto* route1 = route_config.mutable_virtual_hosts(0)->mutable_routes(0); |
|
|
|
|
route1->mutable_match()->set_prefix("/grpc.testing.EchoTest1Service/"); |
|
|
|
|
auto* weighted_cluster1 = |
|
|
|
|
route1->mutable_route()->mutable_weighted_clusters()->add_clusters(); |
|
|
|
|
weighted_cluster1->set_name(kNewCluster1Name); |
|
|
|
|
weighted_cluster1->mutable_weight()->set_value(0); |
|
|
|
|
route1->mutable_route() |
|
|
|
|
->mutable_weighted_clusters() |
|
|
|
|
->mutable_total_weight() |
|
|
|
|
->set_value(0); |
|
|
|
|
auto* default_route = route_config.mutable_virtual_hosts(0)->add_routes(); |
|
|
|
|
default_route->mutable_match()->set_prefix(""); |
|
|
|
|
default_route->mutable_route()->set_cluster(kDefaultClusterName); |
|
|
|
|
SetRouteConfiguration(balancer_.get(), route_config); |
|
|
|
|
const auto response_state = WaitForRdsNack(DEBUG_LOCATION); |
|
|
|
|
ASSERT_TRUE(response_state.has_value()) << "timed out waiting for NACK"; |
|
|
|
|
EXPECT_THAT( |
|
|
|
|
response_state->error_message, |
|
|
|
|
::testing::HasSubstr( |
|
|
|
|
"RouteAction weighted_cluster has no valid clusters specified.")); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
TEST_P(LdsRdsTest, RouteActionWeightedTargetClusterHasEmptyClusterName) { |
|
|
|
|
const size_t kWeight75 = 75; |
|
|
|
|
RouteConfiguration route_config = default_route_config_; |
|
|
|
|
auto* route1 = route_config.mutable_virtual_hosts(0)->mutable_routes(0); |
|
|
|
|
route1->mutable_match()->set_prefix("/grpc.testing.EchoTest1Service/"); |
|
|
|
|
auto* weighted_cluster1 = |
|
|
|
|
route1->mutable_route()->mutable_weighted_clusters()->add_clusters(); |
|
|
|
|
weighted_cluster1->set_name(""); |
|
|
|
|
weighted_cluster1->mutable_weight()->set_value(kWeight75); |
|
|
|
|
route1->mutable_route() |
|
|
|
|
->mutable_weighted_clusters() |
|
|
|
|
->mutable_total_weight() |
|
|
|
|
->set_value(kWeight75); |
|
|
|
|
auto* default_route = route_config.mutable_virtual_hosts(0)->add_routes(); |
|
|
|
|
default_route->mutable_match()->set_prefix(""); |
|
|
|
|
default_route->mutable_route()->set_cluster(kDefaultClusterName); |
|
|
|
|
SetRouteConfiguration(balancer_.get(), route_config); |
|
|
|
|
const auto response_state = WaitForRdsNack(DEBUG_LOCATION); |
|
|
|
|
ASSERT_TRUE(response_state.has_value()) << "timed out waiting for NACK"; |
|
|
|
|
EXPECT_THAT(response_state->error_message, |
|
|
|
|
::testing::HasSubstr("RouteAction weighted_cluster cluster " |
|
|
|
|
"contains empty cluster name.")); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
TEST_P(LdsRdsTest, RouteActionWeightedTargetClusterHasNoWeight) { |
|
|
|
|
const size_t kWeight75 = 75; |
|
|
|
|
const char* kNewCluster1Name = "new_cluster_1"; |
|
|
|
|
RouteConfiguration route_config = default_route_config_; |
|
|
|
|
auto* route1 = route_config.mutable_virtual_hosts(0)->mutable_routes(0); |
|
|
|
|
route1->mutable_match()->set_prefix("/grpc.testing.EchoTest1Service/"); |
|
|
|
|
auto* weighted_cluster1 = |
|
|
|
|
route1->mutable_route()->mutable_weighted_clusters()->add_clusters(); |
|
|
|
|
weighted_cluster1->set_name(kNewCluster1Name); |
|
|
|
|
route1->mutable_route() |
|
|
|
|
->mutable_weighted_clusters() |
|
|
|
|
->mutable_total_weight() |
|
|
|
|
->set_value(kWeight75); |
|
|
|
|
auto* default_route = route_config.mutable_virtual_hosts(0)->add_routes(); |
|
|
|
|
default_route->mutable_match()->set_prefix(""); |
|
|
|
|
default_route->mutable_route()->set_cluster(kDefaultClusterName); |
|
|
|
|
SetRouteConfiguration(balancer_.get(), route_config); |
|
|
|
|
const auto response_state = WaitForRdsNack(DEBUG_LOCATION); |
|
|
|
|
ASSERT_TRUE(response_state.has_value()) << "timed out waiting for NACK"; |
|
|
|
|
EXPECT_THAT(response_state->error_message, |
|
|
|
|
::testing::HasSubstr( |
|
|
|
|
"RouteAction weighted_cluster cluster missing weight")); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
TEST_P(LdsRdsTest, RouteHeaderMatchInvalidRegex) { |
|
|
|
|
const char* kNewCluster1Name = "new_cluster_1"; |
|
|
|
|
RouteConfiguration route_config = default_route_config_; |
|
|
|
|
auto* route1 = route_config.mutable_virtual_hosts(0)->mutable_routes(0); |
|
|
|
|
route1->mutable_match()->set_prefix("/grpc.testing.EchoTest1Service/"); |
|
|
|
|
auto* header_matcher1 = route1->mutable_match()->add_headers(); |
|
|
|
|
header_matcher1->set_name("header1"); |
|
|
|
|
header_matcher1->mutable_safe_regex_match()->set_regex("a[z-a]"); |
|
|
|
|
route1->mutable_route()->set_cluster(kNewCluster1Name); |
|
|
|
|
SetRouteConfiguration(balancer_.get(), route_config); |
|
|
|
|
const auto response_state = WaitForRdsNack(DEBUG_LOCATION); |
|
|
|
|
ASSERT_TRUE(response_state.has_value()) << "timed out waiting for NACK"; |
|
|
|
|
EXPECT_THAT( |
|
|
|
|
response_state->error_message, |
|
|
|
|
::testing::HasSubstr( |
|
|
|
|
"header matcher: Invalid regex string specified in matcher.")); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
TEST_P(LdsRdsTest, RouteHeaderMatchInvalidRange) { |
|
|
|
|
const char* kNewCluster1Name = "new_cluster_1"; |
|
|
|
|
RouteConfiguration route_config = default_route_config_; |
|
|
|
|
auto* route1 = route_config.mutable_virtual_hosts(0)->mutable_routes(0); |
|
|
|
|
route1->mutable_match()->set_prefix("/grpc.testing.EchoTest1Service/"); |
|
|
|
|
auto* header_matcher1 = route1->mutable_match()->add_headers(); |
|
|
|
|
header_matcher1->set_name("header1"); |
|
|
|
|
header_matcher1->mutable_range_match()->set_start(1001); |
|
|
|
|
header_matcher1->mutable_range_match()->set_end(1000); |
|
|
|
|
route1->mutable_route()->set_cluster(kNewCluster1Name); |
|
|
|
|
SetRouteConfiguration(balancer_.get(), route_config); |
|
|
|
|
const auto response_state = WaitForRdsNack(DEBUG_LOCATION); |
|
|
|
|
ASSERT_TRUE(response_state.has_value()) << "timed out waiting for NACK"; |
|
|
|
|
EXPECT_THAT( |
|
|
|
|
response_state->error_message, |
|
|
|
|
::testing::HasSubstr( |
|
|
|
|
"header matcher: Invalid range specifier specified: end cannot be " |
|
|
|
|
"smaller than start.")); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Tests that LDS client should choose the default route (with no matching
|
|
|
|
|
// specified) after unable to find a match with previous routes.
|
|
|
|
|
TEST_P(LdsRdsTest, XdsRoutingPathMatching) { |
|
|
|
@ -1641,6 +1942,55 @@ TEST_P(LdsRdsTest, |
|
|
|
|
EXPECT_EQ(1, backends_[0]->backend_service()->request_count()); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
TEST_P(LdsRdsTest, XdsRetryPolicyInvalidNumRetriesZero) { |
|
|
|
|
CreateAndStartBackends(1); |
|
|
|
|
// Populate new EDS resources.
|
|
|
|
|
EdsResourceArgs args({ |
|
|
|
|
{"locality0", CreateEndpointsForBackends(0, 1)}, |
|
|
|
|
}); |
|
|
|
|
balancer_->ads_service()->SetEdsResource(BuildEdsResource(args)); |
|
|
|
|
// Construct route config to set retry policy.
|
|
|
|
|
RouteConfiguration new_route_config = default_route_config_; |
|
|
|
|
auto* route1 = new_route_config.mutable_virtual_hosts(0)->mutable_routes(0); |
|
|
|
|
auto* retry_policy = route1->mutable_route()->mutable_retry_policy(); |
|
|
|
|
retry_policy->set_retry_on("deadline-exceeded"); |
|
|
|
|
// Setting num_retries to zero is not valid.
|
|
|
|
|
retry_policy->mutable_num_retries()->set_value(0); |
|
|
|
|
SetRouteConfiguration(balancer_.get(), new_route_config); |
|
|
|
|
const auto response_state = WaitForRdsNack(DEBUG_LOCATION); |
|
|
|
|
ASSERT_TRUE(response_state.has_value()) << "timed out waiting for NACK"; |
|
|
|
|
EXPECT_THAT( |
|
|
|
|
response_state->error_message, |
|
|
|
|
::testing::HasSubstr( |
|
|
|
|
"RouteAction RetryPolicy num_retries set to invalid value 0.")); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
TEST_P(LdsRdsTest, XdsRetryPolicyRetryBackOffMissingBaseInterval) { |
|
|
|
|
CreateAndStartBackends(1); |
|
|
|
|
// Populate new EDS resources.
|
|
|
|
|
EdsResourceArgs args({ |
|
|
|
|
{"locality0", CreateEndpointsForBackends(0, 1)}, |
|
|
|
|
}); |
|
|
|
|
balancer_->ads_service()->SetEdsResource(BuildEdsResource(args)); |
|
|
|
|
// Construct route config to set retry policy.
|
|
|
|
|
RouteConfiguration new_route_config = default_route_config_; |
|
|
|
|
auto* route1 = new_route_config.mutable_virtual_hosts(0)->mutable_routes(0); |
|
|
|
|
auto* retry_policy = route1->mutable_route()->mutable_retry_policy(); |
|
|
|
|
retry_policy->set_retry_on("deadline-exceeded"); |
|
|
|
|
retry_policy->mutable_num_retries()->set_value(1); |
|
|
|
|
// RetryBackoff is there but base interval is missing.
|
|
|
|
|
SetProtoDuration( |
|
|
|
|
grpc_core::Duration::Milliseconds(250), |
|
|
|
|
retry_policy->mutable_retry_back_off()->mutable_max_interval()); |
|
|
|
|
SetRouteConfiguration(balancer_.get(), new_route_config); |
|
|
|
|
const auto response_state = WaitForRdsNack(DEBUG_LOCATION); |
|
|
|
|
ASSERT_TRUE(response_state.has_value()) << "timed out waiting for NACK"; |
|
|
|
|
EXPECT_THAT( |
|
|
|
|
response_state->error_message, |
|
|
|
|
::testing::HasSubstr( |
|
|
|
|
"RouteAction RetryPolicy RetryBackoff missing base interval.")); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
TEST_P(LdsRdsTest, XdsRoutingHeadersMatching) { |
|
|
|
|
CreateAndStartBackends(2); |
|
|
|
|
const char* kNewClusterName = "new_cluster"; |
|
|
|
@ -2051,6 +2401,354 @@ TEST_P(LdsRdsTest, XdsRoutingChangeRoutesWithoutChangingClusters) { |
|
|
|
|
EXPECT_EQ(1, backends_[1]->backend_service2()->request_count()); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Test that we NACK unknown filter types in VirtualHost.
|
|
|
|
|
TEST_P(LdsRdsTest, RejectsUnknownHttpFilterTypeInVirtualHost) { |
|
|
|
|
RouteConfiguration route_config = default_route_config_; |
|
|
|
|
auto* per_filter_config = |
|
|
|
|
route_config.mutable_virtual_hosts(0)->mutable_typed_per_filter_config(); |
|
|
|
|
(*per_filter_config)["unknown"].PackFrom(Listener()); |
|
|
|
|
SetListenerAndRouteConfiguration(balancer_.get(), default_listener_, |
|
|
|
|
route_config); |
|
|
|
|
const auto response_state = WaitForRdsNack(DEBUG_LOCATION); |
|
|
|
|
ASSERT_TRUE(response_state.has_value()) << "timed out waiting for NACK"; |
|
|
|
|
EXPECT_THAT(response_state->error_message, |
|
|
|
|
::testing::HasSubstr("no filter registered for config type " |
|
|
|
|
"envoy.config.listener.v3.Listener")); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Test that we ignore optional unknown filter types in VirtualHost.
|
|
|
|
|
TEST_P(LdsRdsTest, IgnoresOptionalUnknownHttpFilterTypeInVirtualHost) { |
|
|
|
|
CreateAndStartBackends(1); |
|
|
|
|
RouteConfiguration route_config = default_route_config_; |
|
|
|
|
auto* per_filter_config = |
|
|
|
|
route_config.mutable_virtual_hosts(0)->mutable_typed_per_filter_config(); |
|
|
|
|
::envoy::config::route::v3::FilterConfig filter_config; |
|
|
|
|
filter_config.mutable_config()->PackFrom(Listener()); |
|
|
|
|
filter_config.set_is_optional(true); |
|
|
|
|
(*per_filter_config)["unknown"].PackFrom(filter_config); |
|
|
|
|
SetListenerAndRouteConfiguration(balancer_.get(), default_listener_, |
|
|
|
|
route_config); |
|
|
|
|
EdsResourceArgs args({{"locality0", CreateEndpointsForBackends()}}); |
|
|
|
|
balancer_->ads_service()->SetEdsResource(BuildEdsResource(args)); |
|
|
|
|
WaitForAllBackends(DEBUG_LOCATION); |
|
|
|
|
auto response_state = RouteConfigurationResponseState(balancer_.get()); |
|
|
|
|
ASSERT_TRUE(response_state.has_value()); |
|
|
|
|
EXPECT_EQ(response_state->state, AdsServiceImpl::ResponseState::ACKED); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Test that we NACK filters without configs in VirtualHost.
|
|
|
|
|
TEST_P(LdsRdsTest, RejectsHttpFilterWithoutConfigInVirtualHost) { |
|
|
|
|
RouteConfiguration route_config = default_route_config_; |
|
|
|
|
auto* per_filter_config = |
|
|
|
|
route_config.mutable_virtual_hosts(0)->mutable_typed_per_filter_config(); |
|
|
|
|
(*per_filter_config)["unknown"]; |
|
|
|
|
SetListenerAndRouteConfiguration(balancer_.get(), default_listener_, |
|
|
|
|
route_config); |
|
|
|
|
const auto response_state = WaitForRdsNack(DEBUG_LOCATION); |
|
|
|
|
ASSERT_TRUE(response_state.has_value()) << "timed out waiting for NACK"; |
|
|
|
|
EXPECT_THAT(response_state->error_message, |
|
|
|
|
::testing::HasSubstr( |
|
|
|
|
"no filter config specified for filter name unknown")); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Test that we NACK filters without configs in FilterConfig in VirtualHost.
|
|
|
|
|
TEST_P(LdsRdsTest, RejectsHttpFilterWithoutConfigInFilterConfigInVirtualHost) { |
|
|
|
|
RouteConfiguration route_config = default_route_config_; |
|
|
|
|
auto* per_filter_config = |
|
|
|
|
route_config.mutable_virtual_hosts(0)->mutable_typed_per_filter_config(); |
|
|
|
|
(*per_filter_config)["unknown"].PackFrom( |
|
|
|
|
::envoy::config::route::v3::FilterConfig()); |
|
|
|
|
SetListenerAndRouteConfiguration(balancer_.get(), default_listener_, |
|
|
|
|
route_config); |
|
|
|
|
const auto response_state = WaitForRdsNack(DEBUG_LOCATION); |
|
|
|
|
ASSERT_TRUE(response_state.has_value()) << "timed out waiting for NACK"; |
|
|
|
|
EXPECT_THAT(response_state->error_message, |
|
|
|
|
::testing::HasSubstr( |
|
|
|
|
"no filter config specified for filter name unknown")); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Test that we ignore optional filters without configs in VirtualHost.
|
|
|
|
|
TEST_P(LdsRdsTest, IgnoresOptionalHttpFilterWithoutConfigInVirtualHost) { |
|
|
|
|
CreateAndStartBackends(1); |
|
|
|
|
RouteConfiguration route_config = default_route_config_; |
|
|
|
|
auto* per_filter_config = |
|
|
|
|
route_config.mutable_virtual_hosts(0)->mutable_typed_per_filter_config(); |
|
|
|
|
::envoy::config::route::v3::FilterConfig filter_config; |
|
|
|
|
filter_config.set_is_optional(true); |
|
|
|
|
(*per_filter_config)["unknown"].PackFrom(filter_config); |
|
|
|
|
SetListenerAndRouteConfiguration(balancer_.get(), default_listener_, |
|
|
|
|
route_config); |
|
|
|
|
EdsResourceArgs args({ |
|
|
|
|
{"locality0", CreateEndpointsForBackends()}, |
|
|
|
|
}); |
|
|
|
|
balancer_->ads_service()->SetEdsResource(BuildEdsResource(args)); |
|
|
|
|
WaitForAllBackends(DEBUG_LOCATION); |
|
|
|
|
auto response_state = RouteConfigurationResponseState(balancer_.get()); |
|
|
|
|
ASSERT_TRUE(response_state.has_value()); |
|
|
|
|
EXPECT_EQ(response_state->state, AdsServiceImpl::ResponseState::ACKED); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Test that we NACK unparseable filter types in VirtualHost.
|
|
|
|
|
TEST_P(LdsRdsTest, RejectsUnparseableHttpFilterTypeInVirtualHost) { |
|
|
|
|
RouteConfiguration route_config = default_route_config_; |
|
|
|
|
auto* per_filter_config = |
|
|
|
|
route_config.mutable_virtual_hosts(0)->mutable_typed_per_filter_config(); |
|
|
|
|
(*per_filter_config)["unknown"].PackFrom( |
|
|
|
|
envoy::extensions::filters::http::router::v3::Router()); |
|
|
|
|
SetListenerAndRouteConfiguration(balancer_.get(), default_listener_, |
|
|
|
|
route_config); |
|
|
|
|
const auto response_state = WaitForRdsNack(DEBUG_LOCATION); |
|
|
|
|
ASSERT_TRUE(response_state.has_value()) << "timed out waiting for NACK"; |
|
|
|
|
EXPECT_THAT( |
|
|
|
|
response_state->error_message, |
|
|
|
|
::testing::HasSubstr("router filter does not support config override")); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Test that we NACK unknown filter types in Route.
|
|
|
|
|
TEST_P(LdsRdsTest, RejectsUnknownHttpFilterTypeInRoute) { |
|
|
|
|
RouteConfiguration route_config = default_route_config_; |
|
|
|
|
auto* per_filter_config = route_config.mutable_virtual_hosts(0) |
|
|
|
|
->mutable_routes(0) |
|
|
|
|
->mutable_typed_per_filter_config(); |
|
|
|
|
(*per_filter_config)["unknown"].PackFrom(Listener()); |
|
|
|
|
SetListenerAndRouteConfiguration(balancer_.get(), default_listener_, |
|
|
|
|
route_config); |
|
|
|
|
const auto response_state = WaitForRdsNack(DEBUG_LOCATION); |
|
|
|
|
ASSERT_TRUE(response_state.has_value()) << "timed out waiting for NACK"; |
|
|
|
|
EXPECT_THAT(response_state->error_message, |
|
|
|
|
::testing::HasSubstr("no filter registered for config type " |
|
|
|
|
"envoy.config.listener.v3.Listener")); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Test that we ignore optional unknown filter types in Route.
|
|
|
|
|
TEST_P(LdsRdsTest, IgnoresOptionalUnknownHttpFilterTypeInRoute) { |
|
|
|
|
CreateAndStartBackends(1); |
|
|
|
|
RouteConfiguration route_config = default_route_config_; |
|
|
|
|
auto* per_filter_config = route_config.mutable_virtual_hosts(0) |
|
|
|
|
->mutable_routes(0) |
|
|
|
|
->mutable_typed_per_filter_config(); |
|
|
|
|
::envoy::config::route::v3::FilterConfig filter_config; |
|
|
|
|
filter_config.mutable_config()->PackFrom(Listener()); |
|
|
|
|
filter_config.set_is_optional(true); |
|
|
|
|
(*per_filter_config)["unknown"].PackFrom(filter_config); |
|
|
|
|
SetListenerAndRouteConfiguration(balancer_.get(), default_listener_, |
|
|
|
|
route_config); |
|
|
|
|
EdsResourceArgs args({{"locality0", CreateEndpointsForBackends()}}); |
|
|
|
|
balancer_->ads_service()->SetEdsResource(BuildEdsResource(args)); |
|
|
|
|
WaitForAllBackends(DEBUG_LOCATION); |
|
|
|
|
auto response_state = RouteConfigurationResponseState(balancer_.get()); |
|
|
|
|
ASSERT_TRUE(response_state.has_value()); |
|
|
|
|
EXPECT_EQ(response_state->state, AdsServiceImpl::ResponseState::ACKED); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Test that we NACK filters without configs in Route.
|
|
|
|
|
TEST_P(LdsRdsTest, RejectsHttpFilterWithoutConfigInRoute) { |
|
|
|
|
RouteConfiguration route_config = default_route_config_; |
|
|
|
|
auto* per_filter_config = route_config.mutable_virtual_hosts(0) |
|
|
|
|
->mutable_routes(0) |
|
|
|
|
->mutable_typed_per_filter_config(); |
|
|
|
|
(*per_filter_config)["unknown"]; |
|
|
|
|
SetListenerAndRouteConfiguration(balancer_.get(), default_listener_, |
|
|
|
|
route_config); |
|
|
|
|
const auto response_state = WaitForRdsNack(DEBUG_LOCATION); |
|
|
|
|
ASSERT_TRUE(response_state.has_value()) << "timed out waiting for NACK"; |
|
|
|
|
EXPECT_THAT(response_state->error_message, |
|
|
|
|
::testing::HasSubstr( |
|
|
|
|
"no filter config specified for filter name unknown")); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Test that we NACK filters without configs in FilterConfig in Route.
|
|
|
|
|
TEST_P(LdsRdsTest, RejectsHttpFilterWithoutConfigInFilterConfigInRoute) { |
|
|
|
|
RouteConfiguration route_config = default_route_config_; |
|
|
|
|
auto* per_filter_config = route_config.mutable_virtual_hosts(0) |
|
|
|
|
->mutable_routes(0) |
|
|
|
|
->mutable_typed_per_filter_config(); |
|
|
|
|
(*per_filter_config)["unknown"].PackFrom( |
|
|
|
|
::envoy::config::route::v3::FilterConfig()); |
|
|
|
|
SetListenerAndRouteConfiguration(balancer_.get(), default_listener_, |
|
|
|
|
route_config); |
|
|
|
|
const auto response_state = WaitForRdsNack(DEBUG_LOCATION); |
|
|
|
|
ASSERT_TRUE(response_state.has_value()) << "timed out waiting for NACK"; |
|
|
|
|
EXPECT_THAT(response_state->error_message, |
|
|
|
|
::testing::HasSubstr( |
|
|
|
|
"no filter config specified for filter name unknown")); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Test that we ignore optional filters without configs in Route.
|
|
|
|
|
TEST_P(LdsRdsTest, IgnoresOptionalHttpFilterWithoutConfigInRoute) { |
|
|
|
|
CreateAndStartBackends(1); |
|
|
|
|
RouteConfiguration route_config = default_route_config_; |
|
|
|
|
auto* per_filter_config = route_config.mutable_virtual_hosts(0) |
|
|
|
|
->mutable_routes(0) |
|
|
|
|
->mutable_typed_per_filter_config(); |
|
|
|
|
::envoy::config::route::v3::FilterConfig filter_config; |
|
|
|
|
filter_config.set_is_optional(true); |
|
|
|
|
(*per_filter_config)["unknown"].PackFrom(filter_config); |
|
|
|
|
SetListenerAndRouteConfiguration(balancer_.get(), default_listener_, |
|
|
|
|
route_config); |
|
|
|
|
EdsResourceArgs args({{"locality0", CreateEndpointsForBackends()}}); |
|
|
|
|
balancer_->ads_service()->SetEdsResource(BuildEdsResource(args)); |
|
|
|
|
WaitForAllBackends(DEBUG_LOCATION); |
|
|
|
|
auto response_state = RouteConfigurationResponseState(balancer_.get()); |
|
|
|
|
ASSERT_TRUE(response_state.has_value()); |
|
|
|
|
EXPECT_EQ(response_state->state, AdsServiceImpl::ResponseState::ACKED); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Test that we NACK unparseable filter types in Route.
|
|
|
|
|
TEST_P(LdsRdsTest, RejectsUnparseableHttpFilterTypeInRoute) { |
|
|
|
|
RouteConfiguration route_config = default_route_config_; |
|
|
|
|
auto* per_filter_config = route_config.mutable_virtual_hosts(0) |
|
|
|
|
->mutable_routes(0) |
|
|
|
|
->mutable_typed_per_filter_config(); |
|
|
|
|
(*per_filter_config)["unknown"].PackFrom( |
|
|
|
|
envoy::extensions::filters::http::router::v3::Router()); |
|
|
|
|
SetListenerAndRouteConfiguration(balancer_.get(), default_listener_, |
|
|
|
|
route_config); |
|
|
|
|
const auto response_state = WaitForRdsNack(DEBUG_LOCATION); |
|
|
|
|
ASSERT_TRUE(response_state.has_value()) << "timed out waiting for NACK"; |
|
|
|
|
EXPECT_THAT( |
|
|
|
|
response_state->error_message, |
|
|
|
|
::testing::HasSubstr("router filter does not support config override")); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Test that we NACK unknown filter types in ClusterWeight.
|
|
|
|
|
TEST_P(LdsRdsTest, RejectsUnknownHttpFilterTypeInClusterWeight) { |
|
|
|
|
RouteConfiguration route_config = default_route_config_; |
|
|
|
|
auto* cluster_weight = route_config.mutable_virtual_hosts(0) |
|
|
|
|
->mutable_routes(0) |
|
|
|
|
->mutable_route() |
|
|
|
|
->mutable_weighted_clusters() |
|
|
|
|
->add_clusters(); |
|
|
|
|
cluster_weight->set_name(kDefaultClusterName); |
|
|
|
|
cluster_weight->mutable_weight()->set_value(100); |
|
|
|
|
auto* per_filter_config = cluster_weight->mutable_typed_per_filter_config(); |
|
|
|
|
(*per_filter_config)["unknown"].PackFrom(Listener()); |
|
|
|
|
SetListenerAndRouteConfiguration(balancer_.get(), default_listener_, |
|
|
|
|
route_config); |
|
|
|
|
const auto response_state = WaitForRdsNack(DEBUG_LOCATION); |
|
|
|
|
ASSERT_TRUE(response_state.has_value()) << "timed out waiting for NACK"; |
|
|
|
|
EXPECT_THAT(response_state->error_message, |
|
|
|
|
::testing::HasSubstr("no filter registered for config type " |
|
|
|
|
"envoy.config.listener.v3.Listener")); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Test that we ignore optional unknown filter types in ClusterWeight.
|
|
|
|
|
TEST_P(LdsRdsTest, IgnoresOptionalUnknownHttpFilterTypeInClusterWeight) { |
|
|
|
|
CreateAndStartBackends(1); |
|
|
|
|
RouteConfiguration route_config = default_route_config_; |
|
|
|
|
auto* cluster_weight = route_config.mutable_virtual_hosts(0) |
|
|
|
|
->mutable_routes(0) |
|
|
|
|
->mutable_route() |
|
|
|
|
->mutable_weighted_clusters() |
|
|
|
|
->add_clusters(); |
|
|
|
|
cluster_weight->set_name(kDefaultClusterName); |
|
|
|
|
cluster_weight->mutable_weight()->set_value(100); |
|
|
|
|
auto* per_filter_config = cluster_weight->mutable_typed_per_filter_config(); |
|
|
|
|
::envoy::config::route::v3::FilterConfig filter_config; |
|
|
|
|
filter_config.mutable_config()->PackFrom(Listener()); |
|
|
|
|
filter_config.set_is_optional(true); |
|
|
|
|
(*per_filter_config)["unknown"].PackFrom(filter_config); |
|
|
|
|
SetListenerAndRouteConfiguration(balancer_.get(), default_listener_, |
|
|
|
|
route_config); |
|
|
|
|
EdsResourceArgs args({{"locality0", CreateEndpointsForBackends()}}); |
|
|
|
|
balancer_->ads_service()->SetEdsResource(BuildEdsResource(args)); |
|
|
|
|
WaitForAllBackends(DEBUG_LOCATION); |
|
|
|
|
auto response_state = RouteConfigurationResponseState(balancer_.get()); |
|
|
|
|
ASSERT_TRUE(response_state.has_value()); |
|
|
|
|
EXPECT_EQ(response_state->state, AdsServiceImpl::ResponseState::ACKED); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Test that we NACK filters without configs in ClusterWeight.
|
|
|
|
|
TEST_P(LdsRdsTest, RejectsHttpFilterWithoutConfigInClusterWeight) { |
|
|
|
|
RouteConfiguration route_config = default_route_config_; |
|
|
|
|
auto* cluster_weight = route_config.mutable_virtual_hosts(0) |
|
|
|
|
->mutable_routes(0) |
|
|
|
|
->mutable_route() |
|
|
|
|
->mutable_weighted_clusters() |
|
|
|
|
->add_clusters(); |
|
|
|
|
cluster_weight->set_name(kDefaultClusterName); |
|
|
|
|
cluster_weight->mutable_weight()->set_value(100); |
|
|
|
|
auto* per_filter_config = cluster_weight->mutable_typed_per_filter_config(); |
|
|
|
|
(*per_filter_config)["unknown"]; |
|
|
|
|
SetListenerAndRouteConfiguration(balancer_.get(), default_listener_, |
|
|
|
|
route_config); |
|
|
|
|
const auto response_state = WaitForRdsNack(DEBUG_LOCATION); |
|
|
|
|
ASSERT_TRUE(response_state.has_value()) << "timed out waiting for NACK"; |
|
|
|
|
EXPECT_THAT(response_state->error_message, |
|
|
|
|
::testing::HasSubstr( |
|
|
|
|
"no filter config specified for filter name unknown")); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Test that we NACK filters without configs in FilterConfig in ClusterWeight.
|
|
|
|
|
TEST_P(LdsRdsTest, |
|
|
|
|
RejectsHttpFilterWithoutConfigInFilterConfigInClusterWeight) { |
|
|
|
|
RouteConfiguration route_config = default_route_config_; |
|
|
|
|
auto* cluster_weight = route_config.mutable_virtual_hosts(0) |
|
|
|
|
->mutable_routes(0) |
|
|
|
|
->mutable_route() |
|
|
|
|
->mutable_weighted_clusters() |
|
|
|
|
->add_clusters(); |
|
|
|
|
cluster_weight->set_name(kDefaultClusterName); |
|
|
|
|
cluster_weight->mutable_weight()->set_value(100); |
|
|
|
|
auto* per_filter_config = cluster_weight->mutable_typed_per_filter_config(); |
|
|
|
|
(*per_filter_config)["unknown"].PackFrom( |
|
|
|
|
::envoy::config::route::v3::FilterConfig()); |
|
|
|
|
SetListenerAndRouteConfiguration(balancer_.get(), default_listener_, |
|
|
|
|
route_config); |
|
|
|
|
const auto response_state = WaitForRdsNack(DEBUG_LOCATION); |
|
|
|
|
ASSERT_TRUE(response_state.has_value()) << "timed out waiting for NACK"; |
|
|
|
|
EXPECT_THAT(response_state->error_message, |
|
|
|
|
::testing::HasSubstr( |
|
|
|
|
"no filter config specified for filter name unknown")); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Test that we ignore optional filters without configs in ClusterWeight.
|
|
|
|
|
TEST_P(LdsRdsTest, IgnoresOptionalHttpFilterWithoutConfigInClusterWeight) { |
|
|
|
|
CreateAndStartBackends(1); |
|
|
|
|
RouteConfiguration route_config = default_route_config_; |
|
|
|
|
auto* cluster_weight = route_config.mutable_virtual_hosts(0) |
|
|
|
|
->mutable_routes(0) |
|
|
|
|
->mutable_route() |
|
|
|
|
->mutable_weighted_clusters() |
|
|
|
|
->add_clusters(); |
|
|
|
|
cluster_weight->set_name(kDefaultClusterName); |
|
|
|
|
cluster_weight->mutable_weight()->set_value(100); |
|
|
|
|
auto* per_filter_config = cluster_weight->mutable_typed_per_filter_config(); |
|
|
|
|
::envoy::config::route::v3::FilterConfig filter_config; |
|
|
|
|
filter_config.set_is_optional(true); |
|
|
|
|
(*per_filter_config)["unknown"].PackFrom(filter_config); |
|
|
|
|
SetListenerAndRouteConfiguration(balancer_.get(), default_listener_, |
|
|
|
|
route_config); |
|
|
|
|
EdsResourceArgs args({{"locality0", CreateEndpointsForBackends()}}); |
|
|
|
|
balancer_->ads_service()->SetEdsResource(BuildEdsResource(args)); |
|
|
|
|
WaitForAllBackends(DEBUG_LOCATION); |
|
|
|
|
auto response_state = RouteConfigurationResponseState(balancer_.get()); |
|
|
|
|
ASSERT_TRUE(response_state.has_value()); |
|
|
|
|
EXPECT_EQ(response_state->state, AdsServiceImpl::ResponseState::ACKED); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Test that we NACK unparseable filter types in ClusterWeight.
|
|
|
|
|
TEST_P(LdsRdsTest, RejectsUnparseableHttpFilterTypeInClusterWeight) { |
|
|
|
|
RouteConfiguration route_config = default_route_config_; |
|
|
|
|
auto* cluster_weight = route_config.mutable_virtual_hosts(0) |
|
|
|
|
->mutable_routes(0) |
|
|
|
|
->mutable_route() |
|
|
|
|
->mutable_weighted_clusters() |
|
|
|
|
->add_clusters(); |
|
|
|
|
cluster_weight->set_name(kDefaultClusterName); |
|
|
|
|
cluster_weight->mutable_weight()->set_value(100); |
|
|
|
|
auto* per_filter_config = cluster_weight->mutable_typed_per_filter_config(); |
|
|
|
|
(*per_filter_config)["unknown"].PackFrom( |
|
|
|
|
envoy::extensions::filters::http::router::v3::Router()); |
|
|
|
|
SetListenerAndRouteConfiguration(balancer_.get(), default_listener_, |
|
|
|
|
route_config); |
|
|
|
|
const auto response_state = WaitForRdsNack(DEBUG_LOCATION); |
|
|
|
|
ASSERT_TRUE(response_state.has_value()) << "timed out waiting for NACK"; |
|
|
|
|
EXPECT_THAT( |
|
|
|
|
response_state->error_message, |
|
|
|
|
::testing::HasSubstr("router filter does not support config override")); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} // namespace
|
|
|
|
|
} // namespace testing
|
|
|
|
|
} // namespace grpc
|
|
|
|
|