#[cfg(test)]
mod tests {
use std::{
io,
panic::{AssertUnwindSafe, catch_unwind},
};
use qubit_dcl::{
DoubleCheckedLockExecutor,
double_checked::{ExecutionResult, ExecutorError},
};
use qubit_lock::ArcMutex;
mod test_executor_builder {
use super::*;
#[test]
fn test_logger_can_be_configured_in_each_builder_state() {
let data = ArcMutex::new(1);
let executor = DoubleCheckedLockExecutor::builder()
.log_unmet_condition(log::Level::Info, "initial")
.on(data)
.log_unmet_condition(log::Level::Debug, "locked")
.when(|| true)
.log_unmet_condition(log::Level::Warn, "ready")
.build();
let result = executor
.call_with(|value: &mut i32| Ok::<i32, std::io::Error>(*value))
.get_result();
assert!(matches!(result, ExecutionResult::Success(1)));
}
#[test]
fn test_prepare_logger_methods_on_initial_builder_are_chainable() {
let data = ArcMutex::new(1);
let executor = DoubleCheckedLockExecutor::builder()
.log_prepare_failure(log::Level::Warn, "prepare failed")
.log_prepare_commit_failure(log::Level::Error, "prepare commit failed")
.log_prepare_rollback_failure(log::Level::Info, "prepare rollback failed")
.disable_unmet_condition_logging()
.disable_prepare_failure_logging()
.disable_prepare_commit_failure_logging()
.disable_prepare_rollback_failure_logging()
.on(data)
.when(|| true)
.build();
let result = executor
.call_with(|value: &mut i32| Ok::<i32, std::io::Error>(*value))
.get_result();
assert!(matches!(result, ExecutionResult::Success(1)));
}
#[test]
fn test_builder_catches_panics_when_enabled() {
let data = ArcMutex::new(1);
let executor = DoubleCheckedLockExecutor::builder()
.catch_panics()
.on(data)
.when(|| true)
.build();
let result = executor
.execute(|| -> Result<(), std::io::Error> {
panic!("task panic");
})
.get_result();
assert!(matches!(
result,
ExecutionResult::Failed(ExecutorError::Panic(_))
));
}
#[test]
fn test_builder_set_catch_panics_enables_panic_capture() {
let data = ArcMutex::new(1);
let executor = DoubleCheckedLockExecutor::builder()
.set_catch_panics(true)
.on(data)
.when(|| true)
.build();
let result = executor
.call::<fn() -> Result<(), io::Error>, (), io::Error>(|| {
panic!("panic from configured builder");
})
.get_result();
assert!(matches!(
result,
ExecutionResult::Failed(ExecutorError::Panic(_))
));
}
#[test]
fn test_builder_disable_catch_panics_allows_panic_propagation() {
let data = ArcMutex::new(1);
let executor = DoubleCheckedLockExecutor::builder()
.catch_panics()
.disable_catch_panics()
.on(data)
.when(|| true)
.build();
let caught = catch_unwind(AssertUnwindSafe(|| {
executor
.call::<fn() -> Result<(), io::Error>, (), io::Error>(|| {
panic!("panic should propagate");
})
.get_result();
}));
assert!(caught.is_err());
}
}
}