use std::sync::atomic::{AtomicBool, Ordering};
static DRY_RUN: AtomicBool = AtomicBool::new(false);
pub fn set_dry_run(enabled: bool) {
DRY_RUN.store(enabled, Ordering::Release);
}
pub fn is_dry_run() -> bool {
DRY_RUN.load(Ordering::Acquire)
}
pub struct DryRunGuard {
previous: bool,
}
impl DryRunGuard {
pub fn new(enabled: bool) -> Self {
let previous = is_dry_run();
set_dry_run(enabled);
Self { previous }
}
}
impl Drop for DryRunGuard {
fn drop(&mut self) {
set_dry_run(self.previous);
}
}
pub(crate) fn effective_dry_run(per_operation: Option<bool>) -> bool {
per_operation.unwrap_or_else(is_dry_run)
}
#[cfg(test)]
mod tests {
use super::*;
use serial_test::serial;
#[test]
#[serial]
fn set_and_get() {
set_dry_run(true);
assert!(is_dry_run());
set_dry_run(false);
assert!(!is_dry_run());
}
#[test]
#[serial]
fn effective_uses_per_operation_when_set() {
set_dry_run(false);
assert!(effective_dry_run(Some(true)));
set_dry_run(true);
assert!(!effective_dry_run(Some(false)));
set_dry_run(false);
}
#[test]
#[serial]
fn effective_falls_back_to_global() {
set_dry_run(true);
assert!(effective_dry_run(None));
set_dry_run(false);
assert!(!effective_dry_run(None));
}
#[test]
#[serial]
fn guard_restores_previous_value() {
set_dry_run(false);
{
let _guard = DryRunGuard::new(true);
assert!(is_dry_run());
}
assert!(!is_dry_run());
}
#[test]
#[serial]
fn guard_nested_restores_correctly() {
set_dry_run(false);
{
let _outer = DryRunGuard::new(true);
assert!(is_dry_run());
{
let _inner = DryRunGuard::new(false);
assert!(!is_dry_run());
}
assert!(is_dry_run());
}
assert!(!is_dry_run());
}
}