Skip to content

Controlled fault injections for testing your Rust application's error handling

License

Notifications You must be signed in to change notification settings

s0uthview/fallibles

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

39 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

fallibles

Fallibles enables controlled failure injection for testing error handling in Rust applications. Mark functions with #[fallible] and configure when they should fail for comprehensive testing.

Features

  • fallibles-sim - Enable failure injection (required)
  • std - Standard library support (default)
  • anyhow - Support for anyhow::Error
  • eyre - Support for eyre::Report

Quick Start

use fallibles::*;

#[fallible]
fn database_query() -> Result<String, &'static str> {
    Ok("data".to_string())
}

// Enable 30% failure rate
fallibles_core::configure_failures(
    fallibles_core::FailureConfig::new().with_probability(0.3)
);

Examples

Basic Usage

use fallibles::*;

#[fallible]
fn read_config() -> Result<i32, &'static str> {
    Ok(42)
}

// Without config, function always succeeds
assert_eq!(read_config().unwrap(), 42);

// Enable failures with RAII guard
{
    let _guard = fallibles_core::with_config(
        fallibles_core::FailureConfig::new().with_probability(1.0)
    );
    // Now it will fail
    assert!(read_config().is_err());
} // Config automatically cleared

Inline Configuration

use fallibles::*;

#[fallible(probability = 0.2)]  // 20% failure rate
fn flaky_api() -> Result<String, &'static str> {
    Ok("response".to_string())
}

#[fallible(trigger_every = 5)]  // Fail every 5th call
fn periodic_task() -> Result<(), String> {
    Ok(())
}

Policy-Based Testing

use fallibles::fallibles_core::{FailureConfig, with_config};

// Chaos Monkey: 10% random failures
let _guard = with_config(FailureConfig::chaos_monkey());

// Degraded Service: 30% failures
let _guard = with_config(FailureConfig::degraded_service(0.3));

// Circuit Breaker: fail every 5th call
let _guard = with_config(FailureConfig::circuit_breaker(5));

Conditional Failures

use fallibles::fallibles_core::{FailureConfig, with_config};

// Only fail when environment variable is set
let _guard = with_config(
    FailureConfig::new()
        .with_probability(0.5)
        .when(|| std::env::var("CHAOS_MODE").is_ok())
);

Reproducible Testing

use fallibles::fallibles_core::{FailureConfig, with_config};

// Same seed always produces same failure pattern
let _guard = with_config(
    FailureConfig::new()
        .with_probability(0.3)
        .with_seed(12345)
);
// Or from environment: FALLIBLES_SEED=12345 cargo test

Custom Error Types

use fallibles::*;

#[derive(Debug, FallibleError)]
#[fallible(message = "timeout occurred")]
struct TimeoutError {
    message: String,
}

#[fallible]
fn network_call() -> Result<String, TimeoutError> {
    Ok("data".to_string())
}

About

Controlled fault injections for testing your Rust application's error handling

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages