use crate::config::{GlobalState, OpState, ENABLED, STATE};
use crate::types::{ClearedFaults, Fault, InjectionError, Operation};
use alloc::vec;
#[inline]
#[must_use]
pub fn is_enabled() -> bool {
ENABLED.load(core::sync::atomic::Ordering::Relaxed)
}
pub fn try_inject(fault: Fault) -> Result<(), InjectionError> {
ENABLED.store(true, core::sync::atomic::Ordering::Relaxed);
let mut state = STATE.lock();
let (op, mut new_points, prob, persist) = match fault {
Fault::Mmap { fail_after } => (Operation::Mmap, vec![fail_after], None, None),
Fault::Read { fail_after } => (Operation::Read, vec![fail_after], None, None),
Fault::Write { fail_after } => (Operation::Write, vec![fail_after], None, None),
Fault::Alloc { fail_after } => (Operation::Alloc, vec![fail_after], None, None),
Fault::Send { fail_after } => (Operation::Send, vec![fail_after], None, None),
Fault::Probabilistic { op, probability } => (op, vec![], Some(probability), None),
Fault::Persistent { op, fail_after } => (op, vec![], None, Some(fail_after)),
Fault::Multiple { op, fail_points } => (op, fail_points, None, None),
};
let op_state = state.get_mut(op);
for p in new_points.drain(..) {
if op_state.fail_points.contains(&p) {
return Err(InjectionError::DuplicateFailPoint);
}
op_state.fail_points.push(p);
}
if let Some(p) = prob {
op_state.probability = p;
}
if let Some(p) = persist {
op_state.persist_after = Some(p);
}
Ok(())
}
pub fn inject(fault: Fault) -> Result<(), InjectionError> {
try_inject(fault)
}
pub fn clear() -> ClearedFaults {
ENABLED.store(false, core::sync::atomic::Ordering::Relaxed);
let mut state = STATE.lock();
let cleared = ClearedFaults {
mmap: state.mmap.fail_points.len(),
read: state.read.fail_points.len(),
write: state.write.fail_points.len(),
alloc: state.alloc.fail_points.len(),
send: state.send.fail_points.len(),
};
*state = GlobalState {
mmap: OpState::new(),
read: OpState::new(),
write: OpState::new(),
alloc: OpState::new(),
send: OpState::new(),
};
cleared
}
#[inline]
pub fn should_fail_mmap() -> bool {
if !is_enabled() {
return false;
}
STATE.lock().get_mut(Operation::Mmap).check()
}
#[inline]
pub fn should_fail_read() -> bool {
if !is_enabled() {
return false;
}
STATE.lock().get_mut(Operation::Read).check()
}
#[inline]
pub fn should_fail_write() -> bool {
if !is_enabled() {
return false;
}
STATE.lock().get_mut(Operation::Write).check()
}
#[inline]
pub fn should_fail_alloc() -> bool {
if !is_enabled() {
return false;
}
STATE.lock().get_mut(Operation::Alloc).check()
}
#[inline]
pub fn should_fail_send() -> bool {
if !is_enabled() {
return false;
}
STATE.lock().get_mut(Operation::Send).check()
}