19 #include <gmock/gmock.h>
20 #include <gtest/gtest.h>
23 #include "src/proto/grpc/testing/xds/v3/cluster.grpc.pb.h"
24 #include "src/proto/grpc/testing/xds/v3/fault.grpc.pb.h"
25 #include "src/proto/grpc/testing/xds/v3/http_connection_manager.grpc.pb.h"
26 #include "src/proto/grpc/testing/xds/v3/router.grpc.pb.h"
34 using ::envoy::config::cluster::v3::RoutingPriority;
35 using ::envoy::extensions::filters::http::fault::v3::HTTPFault;
36 using ::envoy::extensions::filters::network::http_connection_manager::v3::
38 using ::envoy::type::v3::FractionalPercent;
40 class FaultInjectionTest :
public XdsEnd2endTest {
45 static Listener BuildListenerWithFaultInjection(
46 const HTTPFault& http_fault = HTTPFault()) {
47 HttpConnectionManager http_connection_manager;
49 listener.set_name(kServerName);
50 HttpFilter* fault_filter = http_connection_manager.add_http_filters();
51 fault_filter->set_name(
"envoy.fault");
52 fault_filter->mutable_typed_config()->PackFrom(http_fault);
53 HttpFilter* router_filter = http_connection_manager.add_http_filters();
54 router_filter->set_name(
"router");
55 router_filter->mutable_typed_config()->PackFrom(
56 envoy::extensions::filters::http::router::v3::Router());
57 listener.mutable_api_listener()->mutable_api_listener()->PackFrom(
58 http_connection_manager);
62 RouteConfiguration BuildRouteConfigurationWithFaultInjection(
63 const HTTPFault& http_fault) {
68 RouteConfiguration new_route_config = default_route_config_;
69 auto* config_map = new_route_config.mutable_virtual_hosts(0)
71 ->mutable_typed_per_filter_config();
72 (*config_map)[
"envoy.fault"] =
std::move(filter_config);
73 return new_route_config;
76 void SetFilterConfig(HTTPFault& http_fault) {
77 switch (GetParam().filter_config_setup()) {
78 case XdsTestType::HttpFilterConfigLocation::kHttpFilterConfigInRoute: {
79 Listener listener = BuildListenerWithFaultInjection();
80 RouteConfiguration
route =
81 BuildRouteConfigurationWithFaultInjection(http_fault);
82 SetListenerAndRouteConfiguration(balancer_.get(), listener,
route);
85 case XdsTestType::HttpFilterConfigLocation::kHttpFilterConfigInListener: {
86 Listener listener = BuildListenerWithFaultInjection(http_fault);
87 SetListenerAndRouteConfiguration(balancer_.get(), listener,
88 default_route_config_);
97 XdsTest, FaultInjectionTest,
99 XdsTestType(), XdsTestType().set_enable_rds_testing(),
100 XdsTestType().set_filter_config_setup(
101 XdsTestType::HttpFilterConfigLocation::kHttpFilterConfigInRoute),
102 XdsTestType().set_enable_rds_testing().set_filter_config_setup(
103 XdsTestType::HttpFilterConfigLocation::kHttpFilterConfigInRoute)),
107 TEST_P(FaultInjectionTest, XdsFaultInjectionAlwaysAbort) {
108 const uint32_t kAbortPercentagePerHundred = 100;
110 HTTPFault http_fault;
111 auto* abort_percentage = http_fault.mutable_abort()->mutable_percentage();
112 abort_percentage->set_numerator(kAbortPercentagePerHundred);
113 abort_percentage->set_denominator(FractionalPercent::HUNDRED);
114 http_fault.mutable_abort()->set_grpc_status(
117 SetFilterConfig(http_fault);
119 for (
size_t i = 0;
i < 5; ++
i) {
121 RpcOptions().set_wait_for_ready(
true));
126 TEST_P(FaultInjectionTest, XdsFaultInjectionWithoutListenerFilter) {
127 CreateAndStartBackends(1);
128 const uint32_t kAbortPercentagePerHundred = 100;
130 EdsResourceArgs
args({{
"locality0", CreateEndpointsForBackends()}});
131 balancer_->ads_service()->SetEdsResource(BuildEdsResource(
args));
133 HTTPFault http_fault;
134 auto* abort_percentage = http_fault.mutable_abort()->mutable_percentage();
135 abort_percentage->set_numerator(kAbortPercentagePerHundred);
136 abort_percentage->set_denominator(FractionalPercent::HUNDRED);
137 http_fault.mutable_abort()->set_grpc_status(
140 RouteConfiguration
route =
141 BuildRouteConfigurationWithFaultInjection(http_fault);
142 SetListenerAndRouteConfiguration(balancer_.get(), default_listener_,
route);
144 CheckRpcSendOk(
DEBUG_LOCATION, 5, RpcOptions().set_wait_for_ready(
true));
147 TEST_P(FaultInjectionTest, XdsFaultInjectionPercentageAbort) {
148 CreateAndStartBackends(1);
149 const uint32_t kAbortPercentagePerHundred = 50;
150 const double kAbortRate = kAbortPercentagePerHundred / 100.0;
151 const double kErrorTolerance = 0.05;
152 const size_t kNumRpcs = ComputeIdealNumRpcs(kAbortRate, kErrorTolerance);
154 EdsResourceArgs
args({{
"locality0", CreateEndpointsForBackends()}});
155 balancer_->ads_service()->SetEdsResource(BuildEdsResource(
args));
157 HTTPFault http_fault;
158 auto* abort_percentage = http_fault.mutable_abort()->mutable_percentage();
159 abort_percentage->set_numerator(kAbortPercentagePerHundred);
160 abort_percentage->set_denominator(FractionalPercent::HUNDRED);
161 http_fault.mutable_abort()->set_grpc_status(
164 SetFilterConfig(http_fault);
166 size_t num_aborted = SendRpcsAndCountFailuresWithMessage(
169 const double seen_abort_rate =
static_cast<double>(num_aborted) /
kNumRpcs;
174 TEST_P(FaultInjectionTest, XdsFaultInjectionPercentageAbortViaHeaders) {
175 CreateAndStartBackends(1);
176 const uint32_t kAbortPercentageCap = 100;
177 const uint32_t kAbortPercentage = 50;
178 const double kAbortRate = kAbortPercentage / 100.0;
179 const double kErrorTolerance = 0.05;
180 const size_t kNumRpcs = ComputeIdealNumRpcs(kAbortRate, kErrorTolerance);
182 EdsResourceArgs
args({{
"locality0", CreateEndpointsForBackends()}});
183 balancer_->ads_service()->SetEdsResource(BuildEdsResource(
args));
185 HTTPFault http_fault;
186 http_fault.mutable_abort()->mutable_header_abort();
187 http_fault.mutable_abort()->mutable_percentage()->set_numerator(
188 kAbortPercentageCap);
190 SetFilterConfig(http_fault);
192 std::vector<std::pair<std::string, std::string>>
metadata = {
193 {
"x-envoy-fault-abort-grpc-request",
"10"},
194 {
"x-envoy-fault-abort-percentage",
std::to_string(kAbortPercentage)},
196 size_t num_aborted = SendRpcsAndCountFailuresWithMessage(
198 RpcOptions().set_metadata(
metadata));
200 const double seen_abort_rate =
static_cast<double>(num_aborted) /
kNumRpcs;
205 TEST_P(FaultInjectionTest, XdsFaultInjectionPercentageDelay) {
206 CreateAndStartBackends(1);
208 const uint32_t kFixedDelaySeconds = 100;
209 const uint32_t kDelayPercentagePerHundred = 50;
210 const double kDelayRate = kDelayPercentagePerHundred / 100.0;
211 const double kErrorTolerance = 0.05;
212 const size_t kNumRpcs = ComputeIdealNumRpcs(kDelayRate, kErrorTolerance);
213 const size_t kMaxConcurrentRequests =
kNumRpcs;
215 EdsResourceArgs
args({{
"locality0", CreateEndpointsForBackends()}});
216 balancer_->ads_service()->SetEdsResource(BuildEdsResource(
args));
218 Cluster
cluster = default_cluster_;
219 auto* threshold =
cluster.mutable_circuit_breakers()->add_thresholds();
220 threshold->set_priority(RoutingPriority::DEFAULT);
221 threshold->mutable_max_requests()->set_value(kMaxConcurrentRequests);
222 balancer_->ads_service()->SetCdsResource(
cluster);
224 HTTPFault http_fault;
225 auto* delay_percentage = http_fault.mutable_delay()->mutable_percentage();
226 delay_percentage->set_numerator(kDelayPercentagePerHundred);
227 delay_percentage->set_denominator(FractionalPercent::HUNDRED);
228 auto* fixed_delay = http_fault.mutable_delay()->mutable_fixed_delay();
229 fixed_delay->set_seconds(kFixedDelaySeconds);
231 SetFilterConfig(http_fault);
233 RpcOptions rpc_options = RpcOptions()
234 .set_timeout_ms(kRpcTimeoutMilliseconds)
235 .set_skip_cancelled_check(
true);
236 std::vector<ConcurrentRpc> rpcs =
238 size_t num_delayed = 0;
239 for (
auto& rpc : rpcs) {
245 const double seen_delay_rate =
static_cast<double>(num_delayed) /
kNumRpcs;
250 TEST_P(FaultInjectionTest, XdsFaultInjectionPercentageDelayViaHeaders) {
251 CreateAndStartBackends(1);
252 const uint32_t kFixedDelayMilliseconds = 100000;
254 const uint32_t kDelayPercentageCap = 100;
255 const uint32_t kDelayPercentage = 50;
256 const double kDelayRate = kDelayPercentage / 100.0;
257 const double kErrorTolerance = 0.05;
258 const size_t kNumRpcs = ComputeIdealNumRpcs(kDelayRate, kErrorTolerance);
259 const size_t kMaxConcurrentRequests =
kNumRpcs;
261 EdsResourceArgs
args({{
"locality0", CreateEndpointsForBackends()}});
262 balancer_->ads_service()->SetEdsResource(BuildEdsResource(
args));
264 Cluster
cluster = default_cluster_;
265 auto* threshold =
cluster.mutable_circuit_breakers()->add_thresholds();
266 threshold->set_priority(RoutingPriority::DEFAULT);
267 threshold->mutable_max_requests()->set_value(kMaxConcurrentRequests);
268 balancer_->ads_service()->SetCdsResource(
cluster);
270 HTTPFault http_fault;
271 http_fault.mutable_delay()->mutable_header_delay();
272 http_fault.mutable_delay()->mutable_percentage()->set_numerator(
273 kDelayPercentageCap);
275 SetFilterConfig(http_fault);
277 std::vector<std::pair<std::string, std::string>>
metadata = {
278 {
"x-envoy-fault-delay-request",
std::to_string(kFixedDelayMilliseconds)},
279 {
"x-envoy-fault-delay-request-percentage",
282 RpcOptions rpc_options = RpcOptions()
284 .set_timeout_ms(kRpcTimeoutMilliseconds)
285 .set_skip_cancelled_check(
true);
286 std::vector<ConcurrentRpc> rpcs =
288 size_t num_delayed = 0;
289 for (
auto& rpc : rpcs) {
295 const double seen_delay_rate =
static_cast<double>(num_delayed) /
kNumRpcs;
300 TEST_P(FaultInjectionTest, XdsFaultInjectionAbortAfterDelayForStreamCall) {
301 CreateAndStartBackends(1);
302 const uint32_t kFixedDelaySeconds = 1;
303 const uint32_t kRpcTimeoutMilliseconds = 100 * 1000;
305 EdsResourceArgs
args({{
"locality0", CreateEndpointsForBackends()}});
306 balancer_->ads_service()->SetEdsResource(BuildEdsResource(
args));
308 HTTPFault http_fault;
309 auto* abort_percentage = http_fault.mutable_abort()->mutable_percentage();
310 abort_percentage->set_numerator(100);
311 abort_percentage->set_denominator(FractionalPercent::HUNDRED);
312 http_fault.mutable_abort()->set_grpc_status(
314 auto* delay_percentage = http_fault.mutable_delay()->mutable_percentage();
315 delay_percentage->set_numerator(100);
316 delay_percentage->set_denominator(FractionalPercent::HUNDRED);
317 auto* fixed_delay = http_fault.mutable_delay()->mutable_fixed_delay();
318 fixed_delay->set_seconds(kFixedDelaySeconds);
320 SetFilterConfig(http_fault);
329 <<
status.error_message() <<
", " <<
status.error_details() <<
", "
333 TEST_P(FaultInjectionTest, XdsFaultInjectionAlwaysDelayPercentageAbort) {
334 CreateAndStartBackends(1);
335 const uint32_t kAbortPercentagePerHundred = 50;
336 const double kAbortRate = kAbortPercentagePerHundred / 100.0;
337 const uint32_t kFixedDelaySeconds = 1;
338 const uint32_t kRpcTimeoutMilliseconds = 100 * 1000;
339 const uint32_t kConnectionTimeoutMilliseconds =
341 const double kErrorTolerance = 0.05;
342 const size_t kNumRpcs = ComputeIdealNumRpcs(kAbortRate, kErrorTolerance);
343 const size_t kMaxConcurrentRequests =
kNumRpcs;
345 EdsResourceArgs
args({{
"locality0", CreateEndpointsForBackends()}});
346 balancer_->ads_service()->SetEdsResource(BuildEdsResource(
args));
348 Cluster
cluster = default_cluster_;
349 auto* threshold =
cluster.mutable_circuit_breakers()->add_thresholds();
350 threshold->set_priority(RoutingPriority::DEFAULT);
351 threshold->mutable_max_requests()->set_value(kMaxConcurrentRequests);
352 balancer_->ads_service()->SetCdsResource(
cluster);
354 HTTPFault http_fault;
355 auto* abort_percentage = http_fault.mutable_abort()->mutable_percentage();
356 abort_percentage->set_numerator(kAbortPercentagePerHundred);
357 abort_percentage->set_denominator(FractionalPercent::HUNDRED);
358 http_fault.mutable_abort()->set_grpc_status(
360 auto* delay_percentage = http_fault.mutable_delay()->mutable_percentage();
361 delay_percentage->set_numerator(1000000);
362 delay_percentage->set_denominator(FractionalPercent::MILLION);
363 auto* fixed_delay = http_fault.mutable_delay()->mutable_fixed_delay();
364 fixed_delay->set_seconds(kFixedDelaySeconds);
366 SetFilterConfig(http_fault);
374 RpcOptions rpc_options = RpcOptions().set_timeout_ms(kRpcTimeoutMilliseconds);
375 std::vector<ConcurrentRpc> rpcs =
377 for (
auto& rpc : rpcs) {
381 EXPECT_EQ(
"Fault injected", rpc.status.error_message());
385 const double seen_abort_rate =
static_cast<double>(num_aborted) /
kNumRpcs;
393 TEST_P(FaultInjectionTest,
394 XdsFaultInjectionAlwaysDelayPercentageAbortSwitchDenominator) {
395 CreateAndStartBackends(1);
396 const uint32_t kAbortPercentagePerMillion = 500000;
397 const double kAbortRate = kAbortPercentagePerMillion / 1000000.0;
398 const uint32_t kFixedDelaySeconds = 1;
399 const uint32_t kRpcTimeoutMilliseconds = 100 * 1000;
400 const uint32_t kConnectionTimeoutMilliseconds =
402 const double kErrorTolerance = 0.05;
403 const size_t kNumRpcs = ComputeIdealNumRpcs(kAbortRate, kErrorTolerance);
404 const size_t kMaxConcurrentRequests =
kNumRpcs;
406 EdsResourceArgs
args({{
"locality0", CreateEndpointsForBackends()}});
407 balancer_->ads_service()->SetEdsResource(BuildEdsResource(
args));
409 Cluster
cluster = default_cluster_;
410 auto* threshold =
cluster.mutable_circuit_breakers()->add_thresholds();
411 threshold->set_priority(RoutingPriority::DEFAULT);
412 threshold->mutable_max_requests()->set_value(kMaxConcurrentRequests);
413 balancer_->ads_service()->SetCdsResource(
cluster);
415 HTTPFault http_fault;
416 auto* abort_percentage = http_fault.mutable_abort()->mutable_percentage();
417 abort_percentage->set_numerator(kAbortPercentagePerMillion);
418 abort_percentage->set_denominator(FractionalPercent::MILLION);
419 http_fault.mutable_abort()->set_grpc_status(
421 auto* delay_percentage = http_fault.mutable_delay()->mutable_percentage();
422 delay_percentage->set_numerator(100);
423 delay_percentage->set_denominator(FractionalPercent::HUNDRED);
424 auto* fixed_delay = http_fault.mutable_delay()->mutable_fixed_delay();
425 fixed_delay->set_seconds(kFixedDelaySeconds);
427 SetFilterConfig(http_fault);
435 RpcOptions rpc_options = RpcOptions().set_timeout_ms(kRpcTimeoutMilliseconds);
436 std::vector<ConcurrentRpc> rpcs =
438 for (
auto& rpc : rpcs) {
442 EXPECT_EQ(
"Fault injected", rpc.status.error_message());
446 const double seen_abort_rate =
static_cast<double>(num_aborted) /
kNumRpcs;
451 TEST_P(FaultInjectionTest, XdsFaultInjectionMaxFault) {
452 CreateAndStartBackends(1);
455 const uint32_t kRpcTimeoutMs = 4000;
456 const uint32_t kLongDelaySeconds = 100;
457 const uint32_t kAlwaysDelayPercentage = 100;
459 EdsResourceArgs
args({{
"locality0", CreateEndpointsForBackends()}});
460 balancer_->ads_service()->SetEdsResource(BuildEdsResource(
args));
462 HTTPFault http_fault;
463 auto* delay_percentage = http_fault.mutable_delay()->mutable_percentage();
464 delay_percentage->set_numerator(
465 kAlwaysDelayPercentage);
466 delay_percentage->set_denominator(FractionalPercent::HUNDRED);
467 auto* fixed_delay = http_fault.mutable_delay()->mutable_fixed_delay();
468 fixed_delay->set_seconds(kLongDelaySeconds);
469 http_fault.mutable_max_active_faults()->set_value(kMaxFault);
471 SetFilterConfig(http_fault);
475 RpcOptions rpc_options = RpcOptions().set_timeout_ms(kRpcTimeoutMs);
476 std::vector<ConcurrentRpc> rpcs =
478 for (
auto& rpc : rpcs) {
489 for (
auto& rpc : rpcs) {
499 TEST_P(FaultInjectionTest, XdsFaultInjectionBidiStreamDelayOk) {
500 CreateAndStartBackends(1);
503 const uint32_t kFixedDelaySeconds = 1;
504 const uint32_t kDelayPercentagePerHundred = 100;
506 EdsResourceArgs
args({{
"locality0", CreateEndpointsForBackends()}});
507 balancer_->ads_service()->SetEdsResource(BuildEdsResource(
args));
509 HTTPFault http_fault;
510 auto* delay_percentage = http_fault.mutable_delay()->mutable_percentage();
511 delay_percentage->set_numerator(kDelayPercentagePerHundred);
512 delay_percentage->set_denominator(FractionalPercent::HUNDRED);
513 auto* fixed_delay = http_fault.mutable_delay()->mutable_fixed_delay();
514 fixed_delay->set_seconds(kFixedDelaySeconds);
516 SetFilterConfig(http_fault);
524 <<
status.error_details() <<
", "
531 TEST_P(FaultInjectionTest, XdsFaultInjectionBidiStreamDelayError) {
532 CreateAndStartBackends(1);
534 const uint32_t kFixedDelaySeconds = 100;
535 const uint32_t kDelayPercentagePerHundred = 100;
537 EdsResourceArgs
args({{
"locality0", CreateEndpointsForBackends()}});
538 balancer_->ads_service()->SetEdsResource(BuildEdsResource(
args));
540 HTTPFault http_fault;
541 auto* delay_percentage = http_fault.mutable_delay()->mutable_percentage();
542 delay_percentage->set_numerator(kDelayPercentagePerHundred);
543 delay_percentage->set_denominator(FractionalPercent::HUNDRED);
544 auto* fixed_delay = http_fault.mutable_delay()->mutable_fixed_delay();
545 fixed_delay->set_seconds(kFixedDelaySeconds);
547 SetFilterConfig(http_fault);
555 <<
status.error_message() <<
", " <<
status.error_details() <<
", "
563 int main(
int argc,
char** argv) {