remove unused stuff

This commit is contained in:
Christian Schwarz
2025-07-11 15:16:50 +02:00
parent 3a3062d236
commit 9e923bcc9b
4 changed files with 142 additions and 251 deletions

View File

@@ -47,7 +47,7 @@ The probability system uses a counter to track how many times a probability-base
When a failpoint is reconfigured while tasks are waiting on it:
- **Paused tasks** will immediately resume and continue normal execution
- **Sleeping tasks** will wake up early and continue normal execution
- **Sleeping tasks** will wake up early and continue normal execution
- **Removed failpoints** will cause all waiting tasks to resume normally
The new configuration only applies to future hits of the failpoint, not to tasks that are already waiting. This allows for flexible testing scenarios where you can pause execution, inspect state, and then resume execution dynamically.
@@ -139,26 +139,42 @@ The context matching system works as follows:
### Runtime Context Usage
When code hits a failpoint, it provides context using the `failpoint_context!` macro:
When code hits a failpoint, it provides context using a `HashMap<String, String>`:
```rust
use neon_failpoint::{failpoint, failpoint_context, FailpointResult};
use neon_failpoint::{failpoint, FailpointResult};
use std::collections::HashMap;
let context = failpoint_context! {
"tenant_id" => "test_123",
"operation" => "backup",
"user_id" => "user_456",
};
let mut context = HashMap::new();
context.insert("tenant_id".to_string(), "test_123".to_string());
context.insert("operation".to_string(), "backup".to_string());
context.insert("user_id".to_string(), "user_456".to_string());
match failpoint("backup_operation", Some(&context)).await {
FailpointResult::Return(value) => {
// This will only trigger if ALL context matchers match
println!("Backup failed: {}", value);
match failpoint("backup_operation", Some(&context)) {
either::Either::Left(result) => {
match result {
FailpointResult::Return(value) => {
// This will only trigger if ALL context matchers match
println!("Backup failed: {}", value);
}
FailpointResult::Continue => {
// Continue with normal backup operation
}
FailpointResult::Cancelled => {}
}
}
FailpointResult::Continue => {
// Continue with normal backup operation
either::Either::Right(future) => {
match future.await {
FailpointResult::Return(value) => {
// This will only trigger if ALL context matchers match
println!("Backup failed: {}", value);
}
FailpointResult::Continue => {
// Continue with normal backup operation
}
FailpointResult::Cancelled => {}
}
}
FailpointResult::Cancelled => {}
}
```
@@ -173,9 +189,11 @@ matchers.insert("tenant_id".to_string(), "test_.*".to_string());
configure_failpoint_with_context("test_failpoint", "pause", matchers).unwrap();
// This will match
let context = failpoint_context! { "tenant_id" => "test_123" };
// This will NOT match
let context = failpoint_context! { "tenant_id" => "prod_123" };
let mut context = HashMap::new();
context.insert("tenant_id".to_string(), "test_123".to_string());
// This will NOT match
let mut context = HashMap::new();
context.insert("tenant_id".to_string(), "prod_123".to_string());
```
#### Multiple Conditions
@@ -188,16 +206,14 @@ matchers.insert("operation".to_string(), "backup".to_string());
configure_failpoint_with_context("backup_test", "return(failed)", matchers).unwrap();
// This will match (both conditions met)
let context = failpoint_context! {
"tenant_id" => "test_123",
"operation" => "backup",
};
let mut context = HashMap::new();
context.insert("tenant_id".to_string(), "test_123".to_string());
context.insert("operation".to_string(), "backup".to_string());
// This will NOT match (missing operation)
let context = failpoint_context! {
"tenant_id" => "test_123",
"operation" => "restore",
};
let mut context = HashMap::new();
context.insert("tenant_id".to_string(), "test_123".to_string());
context.insert("operation".to_string(), "restore".to_string());
```
#### Exact String Matching
@@ -209,9 +225,11 @@ matchers.insert("env".to_string(), "staging".to_string());
configure_failpoint_with_context("env_specific", "sleep(1000)", matchers).unwrap();
// This will match
let context = failpoint_context! { "env" => "staging" };
let mut context = HashMap::new();
context.insert("env".to_string(), "staging".to_string());
// This will NOT match
let context = failpoint_context! { "env" => "production" };
let mut context = HashMap::new();
context.insert("env".to_string(), "production".to_string());
```
### Benefits of Context-Based Failpoints
@@ -229,7 +247,7 @@ let context = failpoint_context! { "env" => "production" };
## Context-Specific Failpoints
```rust
use neon_failpoint::{configure_failpoint_with_context, failpoint, failpoint_context};
use neon_failpoint::{configure_failpoint_with_context, failpoint};
use std::collections::HashMap;
// Configure a failpoint that only triggers for specific tenants
@@ -238,26 +256,41 @@ context_matchers.insert("tenant_id".to_string(), "test_.*".to_string());
context_matchers.insert("operation".to_string(), "backup".to_string());
configure_failpoint_with_context(
"backup_operation",
"return(simulated_failure)",
"backup_operation",
"return(simulated_failure)",
context_matchers
).unwrap();
// Use with context
let context = failpoint_context! {
"tenant_id" => "test_123",
"operation" => "backup",
};
let mut context = HashMap::new();
context.insert("tenant_id".to_string(), "test_123".to_string());
context.insert("operation".to_string(), "backup".to_string());
match failpoint("backup_operation", Some(&context)).await {
FailpointResult::Return(value) => {
// This will trigger for tenant_id matching "test_.*"
println!("Backup failed: {}", value);
match failpoint("backup_operation", Some(&context)) {
either::Either::Left(result) => {
match result {
FailpointResult::Return(value) => {
// This will trigger for tenant_id matching "test_.*"
println!("Backup failed: {}", value);
}
FailpointResult::Continue => {
// Continue with backup
}
FailpointResult::Cancelled => {}
}
}
FailpointResult::Continue => {
// Continue with backup
either::Either::Right(future) => {
match future.await {
FailpointResult::Return(value) => {
// This will trigger for tenant_id matching "test_.*"
println!("Backup failed: {}", value);
}
FailpointResult::Continue => {
// Continue with backup
}
FailpointResult::Cancelled => {}
}
}
FailpointResult::Cancelled => {}
}
```
@@ -315,12 +348,12 @@ The `fail_point_with_context!` macro has three variants that mirror `fail_point!
3. **Conditional with context** - `fail_point_with_context!(name, context, condition, closure)`
```rust
use neon_failpoint::{fail_point_with_context, failpoint_context};
use neon_failpoint::{fail_point_with_context};
use std::collections::HashMap;
let context = failpoint_context! {
"tenant_id" => "test_123",
"operation" => "backup",
};
let mut context = HashMap::new();
context.insert("tenant_id".to_string(), "test_123".to_string());
context.insert("operation".to_string(), "backup".to_string());
// Simple context failpoint
fail_point_with_context!("backup_failpoint", &context);
@@ -344,7 +377,7 @@ fail_point_with_context!("backup_failpoint", &context, is_test_tenant, |value: O
### Other Utility Macros
```rust
use neon_failpoint::{pausable_failpoint, sleep_millis_async, failpoint_return, failpoint_bail};
use neon_failpoint::{pausable_failpoint, sleep_millis_async};
// Pausable failpoint with cancellation
let cancel_token = CancellationToken::new();
@@ -355,17 +388,10 @@ if let Err(()) = pausable_failpoint!("pause_here", &cancel_token).await {
// Sleep failpoint
sleep_millis_async!("sleep_here", &cancel_token).await;
// Simple return failpoint - automatically parses and returns the value
failpoint_return!("return_early");
// Failpoint that bails with an error
failpoint_bail!("error_point", "Something went wrong");
// Context creation helper
let context = failpoint_context! {
"key1" => "value1",
"key2" => "value2",
};
let mut context = HashMap::new();
context.insert("key1".to_string(), "value1".to_string());
context.insert("key2".to_string(), "value2".to_string());
```
### Argument Reference
@@ -431,4 +457,4 @@ The library integrates with the existing HTTP failpoint configuration API. Send
"actions": "return(42)"
}
]
```
```

View File

@@ -1,5 +1,5 @@
use neon_failpoint::{
configure_failpoint_with_context, failpoint, failpoint_context, FailpointResult,
configure_failpoint_with_context, failpoint, FailpointResult,
};
use std::collections::HashMap;
@@ -21,40 +21,72 @@ async fn main() {
.unwrap();
// Test with matching context
let context = failpoint_context! {
"tenant_id" => "test_123",
"operation" => "backup",
};
let mut context = HashMap::new();
context.insert("tenant_id".to_string(), "test_123".to_string());
context.insert("operation".to_string(), "backup".to_string());
println!("Testing with matching context...");
match failpoint("backup_operation", Some(&context)).await {
FailpointResult::Return(value) => {
println!("Failpoint triggered with value: {:?}", value);
match failpoint("backup_operation", Some(&context)) {
either::Either::Left(result) => {
match result {
FailpointResult::Return(value) => {
println!("Failpoint triggered with value: {:?}", value);
}
FailpointResult::Continue => {
println!("Failpoint not triggered");
}
FailpointResult::Cancelled => {
println!("Failpoint cancelled");
}
}
}
FailpointResult::Continue => {
println!("Failpoint not triggered");
}
FailpointResult::Cancelled => {
println!("Failpoint cancelled");
either::Either::Right(future) => {
match future.await {
FailpointResult::Return(value) => {
println!("Failpoint triggered with value: {:?}", value);
}
FailpointResult::Continue => {
println!("Failpoint not triggered");
}
FailpointResult::Cancelled => {
println!("Failpoint cancelled");
}
}
}
}
// Test with non-matching context
let context = failpoint_context! {
"tenant_id" => "prod_456",
"operation" => "backup",
};
let mut context = HashMap::new();
context.insert("tenant_id".to_string(), "prod_456".to_string());
context.insert("operation".to_string(), "backup".to_string());
println!("Testing with non-matching context...");
match failpoint("backup_operation", Some(&context)).await {
FailpointResult::Return(value) => {
println!("Failpoint triggered with value: {:?}", value);
match failpoint("backup_operation", Some(&context)) {
either::Either::Left(result) => {
match result {
FailpointResult::Return(value) => {
println!("Failpoint triggered with value: {:?}", value);
}
FailpointResult::Continue => {
println!("Failpoint not triggered (expected)");
}
FailpointResult::Cancelled => {
println!("Failpoint cancelled");
}
}
}
FailpointResult::Continue => {
println!("Failpoint not triggered (expected)");
}
FailpointResult::Cancelled => {
println!("Failpoint cancelled");
either::Either::Right(future) => {
match future.await {
FailpointResult::Return(value) => {
println!("Failpoint triggered with value: {:?}", value);
}
FailpointResult::Continue => {
println!("Failpoint not triggered (expected)");
}
FailpointResult::Cancelled => {
println!("Failpoint cancelled");
}
}
}
}
}

View File

@@ -468,16 +468,6 @@ mod tests {
matches!(result, FailpointResult::Continue);
}
#[tokio::test]
async fn test_failpoint_return() {
configure_failpoint("test_return", "return(42)").unwrap();
let result = await_failpoint_result(failpoint("test_return", None)).await;
if let FailpointResult::Return(Some(value)) = result {
assert_eq!(value, "42");
} else {
panic!("Expected return result");
}
}
#[tokio::test]
async fn test_failpoint_sleep() {

View File

@@ -350,167 +350,10 @@ macro_rules! sleep_millis_async {
}};
}
/// Convenience macro for creating failpoint context
#[macro_export]
macro_rules! failpoint_context {
($($key:expr => $value:expr),* $(,)?) => {{
let mut context = ::std::collections::HashMap::new();
$(
context.insert($key.to_string(), $value.to_string());
)*
context
}};
}
/// Macro for simple failpoint calls that might return early
#[macro_export]
macro_rules! failpoint_return {
($name:literal) => {{
if cfg!(feature = "testing") {
match $crate::failpoint($name, None) {
either::Either::Left(result) => {
if let $crate::FailpointResult::Return(Some(value)) = result {
return value.parse().unwrap_or_default();
}
},
either::Either::Right(future) => {
if let $crate::FailpointResult::Return(Some(value)) = future.await {
return value.parse().unwrap_or_default();
}
},
}
}
}};
($name:literal, $context:expr) => {{
if cfg!(feature = "testing") {
match $crate::failpoint($name, Some($context)) {
either::Either::Left(result) => {
if let $crate::FailpointResult::Return(Some(value)) = result {
return value.parse().unwrap_or_default();
}
},
either::Either::Right(future) => {
if let $crate::FailpointResult::Return(Some(value)) = future.await {
return value.parse().unwrap_or_default();
}
},
}
}
}};
}
/// Macro for simple failpoint calls that might return early - sync version
#[macro_export]
macro_rules! failpoint_return_sync {
($name:literal) => {{
if cfg!(feature = "testing") {
match $crate::failpoint($name, None) {
either::Either::Left(result) => {
if let $crate::FailpointResult::Return(Some(value)) = result {
return value.parse().unwrap_or_default();
}
},
either::Either::Right(_) => {
panic!("failpoint '{}' triggered an async action (sleep/pause) but failpoint_return_sync! was used. Use failpoint_return! instead.", $name);
},
}
}
}};
($name:literal, $context:expr) => {{
if cfg!(feature = "testing") {
match $crate::failpoint($name, Some($context)) {
either::Either::Left(result) => {
if let $crate::FailpointResult::Return(Some(value)) = result {
return value.parse().unwrap_or_default();
}
},
either::Either::Right(_) => {
panic!("failpoint '{}' triggered an async action (sleep/pause) but failpoint_return_sync! was used. Use failpoint_return! instead.", $name);
},
}
}
}};
}
/// Macro for failpoint calls that might bail with an error
#[macro_export]
macro_rules! failpoint_bail {
($name:literal, $error_msg:literal) => {{
if cfg!(feature = "testing") {
match $crate::failpoint($name, None) {
either::Either::Left(result) => {
if let $crate::FailpointResult::Return(_) = result {
anyhow::bail!($error_msg);
}
},
either::Either::Right(future) => {
if let $crate::FailpointResult::Return(_) = future.await {
anyhow::bail!($error_msg);
}
},
}
}
}};
($name:literal, $context:expr, $error_msg:literal) => {{
if cfg!(feature = "testing") {
match $crate::failpoint($name, Some($context)) {
either::Either::Left(result) => {
if let $crate::FailpointResult::Return(_) = result {
anyhow::bail!($error_msg);
}
},
either::Either::Right(future) => {
if let $crate::FailpointResult::Return(_) = future.await {
anyhow::bail!($error_msg);
}
},
}
}
}};
}
/// Macro for failpoint calls that might bail with an error - sync version
#[macro_export]
macro_rules! failpoint_bail_sync {
($name:literal, $error_msg:literal) => {{
if cfg!(feature = "testing") {
match $crate::failpoint($name, None) {
either::Either::Left(result) => {
if let $crate::FailpointResult::Return(_) = result {
anyhow::bail!($error_msg);
}
},
either::Either::Right(_) => {
panic!("failpoint '{}' triggered an async action (sleep/pause) but failpoint_bail_sync! was used. Use failpoint_bail! instead.", $name);
},
}
}
}};
($name:literal, $context:expr, $error_msg:literal) => {{
if cfg!(feature = "testing") {
match $crate::failpoint($name, Some($context)) {
either::Either::Left(result) => {
if let $crate::FailpointResult::Return(_) = result {
anyhow::bail!($error_msg);
}
},
either::Either::Right(_) => {
panic!("failpoint '{}' triggered an async action (sleep/pause) but failpoint_bail_sync! was used. Use failpoint_bail! instead.", $name);
},
}
}
}};
}
// Re-export for convenience
pub use fail_point;
pub use fail_point_sync;
pub use fail_point_with_context;
pub use fail_point_with_context_sync;
pub use failpoint_bail;
pub use failpoint_bail_sync;
pub use failpoint_context;
pub use failpoint_return;
pub use failpoint_return_sync;
pub use pausable_failpoint;
pub use sleep_millis_async;