5#include <gtest/gtest.h>
34 return kcenon::common::make_error<int>(
static_cast<int>(monitoring_error_code::operation_failed),
35 "Simulated failure on attempt " + std::to_string(current_call));
37 return kcenon::common::ok(42);
43 return kcenon::common::make_error<int>(
static_cast<int>(monitoring_error_code::operation_failed),
"Always fails");
49 return kcenon::common::ok(100);
55 throw std::runtime_error(
"Simulated exception");
64 auto result = boundary.
execute([
this]() {
return always_succeeding_operation(); });
66 EXPECT_TRUE(result.is_ok());
67 EXPECT_EQ(result.value(), 100);
69 EXPECT_EQ(call_count.load(), 1);
74 config.
policy = error_boundary_policy::fail_fast;
78 auto result = boundary.
execute([
this]() {
return always_failing_operation(); });
80 EXPECT_TRUE(result.is_err());
81 EXPECT_EQ(result.error().code,
static_cast<int>(monitoring_error_code::operation_failed));
87 config.
policy = error_boundary_policy::isolate;
91 auto result = boundary.
execute([
this]() {
return always_failing_operation(); });
93 EXPECT_TRUE(result.is_err());
94 EXPECT_EQ(result.error().code,
static_cast<int>(monitoring_error_code::service_degraded));
100 config.
policy = error_boundary_policy::degrade;
106 auto result1 = boundary.
execute([
this]() {
return always_failing_operation(); });
107 EXPECT_TRUE(result1.is_err());
110 auto result2 = boundary.
execute([
this]() {
return always_failing_operation(); });
111 EXPECT_TRUE(result2.is_err());
119 config.
policy = error_boundary_policy::fallback;
124 return kcenon::common::ok(999);
127 auto result = boundary.
execute([
this]() {
return always_failing_operation(); },
fallback);
129 EXPECT_TRUE(result.is_ok());
130 EXPECT_EQ(result.value(), 999);
136 auto result = boundary.
execute([
this]() {
return throwing_operation(); });
138 EXPECT_TRUE(result.is_err());
139 EXPECT_EQ(result.error().code,
static_cast<int>(monitoring_error_code::operation_failed));
140 EXPECT_EQ(call_count.load(), 1);
147 boundary.
execute([
this]() {
return always_succeeding_operation(); });
148 boundary.
execute([
this]() {
return always_failing_operation(); });
149 boundary.
execute([
this]() {
return always_succeeding_operation(); });
152 EXPECT_EQ(metrics.total_operations.load(), 3);
153 EXPECT_EQ(metrics.successful_operations.load(), 2);
154 EXPECT_EQ(metrics.failed_operations.load(), 1);
155 EXPECT_NEAR(metrics.get_success_rate(), 2.0/3.0, 0.01);
160 config.
policy = error_boundary_policy::degrade;
168 boundary.
execute([
this]() {
return always_failing_operation(); });
172 std::this_thread::sleep_for(std::chrono::milliseconds(150));
175 auto result = boundary.
execute([
this]() {
return always_succeeding_operation(); });
176 EXPECT_TRUE(result.is_ok());
179 for (
int i = 0; i < 5; ++i) {
180 boundary.
execute([
this]() {
return always_succeeding_operation(); });
184 EXPECT_GT(metrics.recovery_attempts.load(), 0);
191 auto strategy = std::make_shared<default_value_strategy<int>>(777);
195 config.
policy = error_boundary_policy::fallback;
199 auto result = fallback_boundary.
execute([
this]() {
return always_failing_operation(); });
201 EXPECT_TRUE(result.is_ok());
202 EXPECT_EQ(result.value(), 777);
206 auto strategy = std::make_shared<cached_value_strategy<int>>(std::chrono::seconds(1));
209 strategy->update_cache(555);
212 config.
policy = error_boundary_policy::fallback;
216 auto result = boundary.
execute([
this]() {
return always_failing_operation(); });
218 EXPECT_TRUE(result.is_ok());
219 EXPECT_EQ(result.value(), 555);
223 auto alternative_op = []() {
return kcenon::common::ok(888); };
224 auto strategy = std::make_shared<alternative_service_strategy<int>>(alternative_op);
227 config.
policy = error_boundary_policy::fallback;
231 auto result = boundary.
execute([
this]() {
return always_failing_operation(); });
233 EXPECT_TRUE(result.is_ok());
234 EXPECT_EQ(result.value(), 888);
242 auto result = manager->register_service(config);
244 EXPECT_TRUE(result.is_ok());
245 EXPECT_EQ(manager->get_service_level(
"test_service"), degradation_level::normal);
252 manager->register_service(config);
254 auto result = manager->degrade_service(
"test_service", degradation_level::limited,
"Test degradation");
256 EXPECT_TRUE(result.is_ok());
257 EXPECT_EQ(manager->get_service_level(
"test_service"), degradation_level::limited);
271 degradation_level::minimal);
272 manager->add_degradation_plan(plan);
275 auto result = manager->execute_plan(
"emergency_plan",
"Test emergency");
277 EXPECT_TRUE(result.is_ok());
278 EXPECT_EQ(manager->get_service_level(
"service1"), degradation_level::minimal);
279 EXPECT_EQ(manager->get_service_level(
"service2"), degradation_level::emergency);
286 manager->register_service(config);
289 manager->degrade_service(
"test_service", degradation_level::minimal,
"Test degradation");
290 EXPECT_EQ(manager->get_service_level(
"test_service"), degradation_level::minimal);
293 auto result = manager->recover_service(
"test_service");
295 EXPECT_TRUE(result.is_ok());
296 EXPECT_EQ(manager->get_service_level(
"test_service"), degradation_level::normal);
306 manager->degrade_service(
"service1", degradation_level::limited,
"Test");
307 manager->degrade_service(
"service2", degradation_level::minimal,
"Test");
310 auto result = manager->recover_all_services();
312 EXPECT_TRUE(result.is_ok());
313 EXPECT_EQ(manager->get_service_level(
"service1"), degradation_level::normal);
314 EXPECT_EQ(manager->get_service_level(
"service2"), degradation_level::normal);
323 manager->degrade_service(
"service1", degradation_level::limited,
"Test");
324 manager->recover_service(
"service1");
326 auto metrics = manager->get_metrics();
327 EXPECT_GT(metrics.total_degradations.load(), 0);
328 EXPECT_GT(metrics.successful_degradations.load(), 0);
329 EXPECT_GT(metrics.recovery_attempts.load(), 0);
333 auto manager = std::make_shared<graceful_degradation_manager>(
"test_manager");
336 manager->register_service(config);
338 auto normal_op = [
this]() {
return always_succeeding_operation(); };
340 return kcenon::common::ok(
static_cast<int>(level) * 100);
346 auto result1 =
service->execute();
347 EXPECT_TRUE(result1.is_ok());
348 EXPECT_EQ(result1.value(), 100);
351 manager->degrade_service(
"wrapper_service", degradation_level::limited,
"Test");
352 auto result2 =
service->execute();
353 EXPECT_TRUE(result2.is_ok());
354 EXPECT_EQ(result2.value(),
static_cast<int>(degradation_level::limited) * 100);
361 auto boundary = std::make_shared<error_boundary<int>>(
"registry_test");
362 registry.register_boundary<
int>(
"test", boundary);
364 auto retrieved = registry.get_boundary<
int>(
"test");
365 EXPECT_EQ(retrieved, boundary);
367 auto names = registry.get_all_names();
368 EXPECT_EQ(names.size(), 1);
369 EXPECT_EQ(names[0],
"test");
371 registry.remove_boundary(
"test");
372 retrieved = registry.get_boundary<
int>(
"test");
373 EXPECT_EQ(retrieved,
nullptr);
381 config.
name =
"test";
389 config.
name =
"test";
401 config.
name =
"test_service";
409 config.
name =
"test_service";
424 plan.
name =
"test_plan";
440 EXPECT_TRUE(health.is_ok());
441 EXPECT_TRUE(health.value());
452 EXPECT_TRUE(health.is_ok());
464 auto health = manager->is_healthy();
465 EXPECT_TRUE(health.is_ok());
466 EXPECT_TRUE(health.value());
469 manager->degrade_service(
"service1", degradation_level::minimal,
"Test");
470 manager->degrade_service(
"service2", degradation_level::minimal,
"Test");
473 health = manager->is_healthy();
474 EXPECT_TRUE(health.is_ok());
475 EXPECT_FALSE(health.value());
485 auto result = manager->unregister_service(
"nonexistent");
486 EXPECT_TRUE(result.is_err());
492 auto result = manager->degrade_service(
"nonexistent", degradation_level::limited,
"test");
493 EXPECT_TRUE(result.is_err());
495 auto metrics = manager->get_metrics();
496 EXPECT_EQ(metrics.failed_degradations.load(), 1);
502 auto result = manager->recover_service(
"nonexistent");
503 EXPECT_TRUE(result.is_err());
509 auto result = manager->execute_plan(
"nonexistent_plan",
"reason");
510 EXPECT_TRUE(result.is_err());
518 auto result = manager->add_degradation_plan(plan);
519 EXPECT_TRUE(result.is_err());
526 auto result1 = manager->register_service(config);
527 EXPECT_TRUE(result1.is_ok());
529 auto result2 = manager->register_service(config);
530 EXPECT_TRUE(result2.is_err());
539 EXPECT_EQ(manager->get_name(),
"my_manager");
542 EXPECT_EQ(default_mgr.
get_name(),
"default");
549 auto names = manager->get_service_names();
550 EXPECT_TRUE(names.empty());
557 names = manager->get_service_names();
558 EXPECT_EQ(names.size(), 3);
561 std::sort(names.begin(), names.end());
562 EXPECT_EQ(names[0],
"alpha");
563 EXPECT_EQ(names[1],
"beta");
564 EXPECT_EQ(names[2],
"gamma");
573 config.
name =
"test_service";
589 auto normal_op = []() {
return kcenon::common::ok(42); };
596 auto result =
service.execute();
597 EXPECT_TRUE(result.is_ok());
598 EXPECT_EQ(result.value(), 42);
599 EXPECT_EQ(
service.get_name(),
"null_manager_service");
std::atomic< int > call_count
kcenon::common::Result< int > always_succeeding_operation()
std::atomic< int > success_after_attempts
kcenon::common::Result< int > failing_operation()
kcenon::common::Result< int > throwing_operation()
kcenon::common::Result< int > always_failing_operation()
Degradable service wrapper.
Error boundary implementation for resilient operations.
void force_degradation(degradation_level level)
Force degradation to a specific level.
auto execute(Func &&func) -> common::Result< T >
Execute a function within the error boundary.
degradation_level get_degradation_level() const
Get current degradation level.
error_boundary_metrics get_metrics() const
Get metrics.
void set_fallback_strategy(std::shared_ptr< fallback_strategy_interface< T > > strategy)
Set fallback strategy.
common::Result< bool > is_healthy() const
Check if the boundary is healthy.
Graceful degradation manager.
const std::string & get_name() const
Get manager name.
Error boundary with degradation levels for fault isolation.
Service priority levels and graceful degradation strategies.
std::shared_ptr< degradable_service< T > > create_degradable_service(const std::string &name, std::shared_ptr< graceful_degradation_manager > manager, typename degradable_service< T >::normal_operation normal_op, typename degradable_service< T >::degraded_operation degraded_op)
Create a degradable service.
service_config create_service_config(const std::string &name, service_priority priority)
Create a service configuration.
degradation_plan create_degradation_plan(const std::string &name, const std::vector< std::string > &maintain, const std::vector< std::string > &disable, degradation_level level)
Create a degradation plan.
degradation_level
Degradation levels for error boundary.
std::shared_ptr< graceful_degradation_manager > create_degradation_manager(const std::string &name)
Create a graceful degradation manager.
error_boundary_registry & global_error_boundary_registry()
Get global error boundary registry.
Degradation plan for coordinated service degradation.
Error boundary configuration.
bool enable_automatic_recovery
error_boundary_policy policy
std::chrono::milliseconds recovery_timeout
degradation_level max_degradation
Extended error information with context.
Service configuration for graceful degradation.
double error_rate_threshold
TEST_F(ErrorBoundariesTest, ErrorBoundaryNormalOperation)