use fluent_test::prelude::*;
use once_cell::sync::Lazy;
use std::cell::RefCell;
use std::sync::{
Mutex,
atomic::{AtomicUsize, Ordering},
};
static SETUP_COUNTER: AtomicUsize = AtomicUsize::new(0);
static TEARDOWN_COUNTER: AtomicUsize = AtomicUsize::new(0);
static TEST_VALUE_MUTEX: Lazy<Mutex<()>> = Lazy::new(|| Mutex::new(()));
thread_local! {
static TEST_VALUE: RefCell<u32> = RefCell::new(0);
}
fn reset_test_value() {
TEST_VALUE.with(|v| {
*v.borrow_mut() = 0;
});
}
fn set_test_value(value: u32) {
TEST_VALUE.with(|v| {
*v.borrow_mut() = value;
});
}
fn get_test_value() -> u32 {
TEST_VALUE.with(|v| *v.borrow())
}
mod main_fixtures {
use super::*;
#[setup]
fn setup_function() {
SETUP_COUNTER.fetch_add(1, Ordering::SeqCst);
}
#[tear_down]
fn teardown_function() {
TEARDOWN_COUNTER.fetch_add(1, Ordering::SeqCst);
}
#[setup]
fn reset_test_state() {
reset_test_value();
}
#[test]
#[with_fixtures]
fn test_fixtures_are_called() {
let _guard = TEST_VALUE_MUTEX.lock().unwrap();
let setup_count = SETUP_COUNTER.load(Ordering::SeqCst);
expect!(setup_count).to_be_greater_than(0);
expect!(get_test_value()).to_equal(0);
set_test_value(42);
expect!(get_test_value()).to_equal(42);
std::thread::sleep(std::time::Duration::from_millis(5));
}
#[test]
#[with_fixtures]
fn test_fixtures_run_for_each_test() {
let _guard = TEST_VALUE_MUTEX.lock().unwrap();
expect!(get_test_value()).to_equal(0);
set_test_value(123);
std::thread::sleep(std::time::Duration::from_millis(5));
expect!(get_test_value()).to_equal(123);
}
#[test]
#[with_fixtures]
fn test_teardown_ran_from_previous_test() {
let _guard = TEST_VALUE_MUTEX.lock().unwrap();
let setup_count = SETUP_COUNTER.load(Ordering::SeqCst);
expect!(setup_count).to_be_greater_than(0);
expect!(get_test_value()).to_equal(0);
let teardown_count = TEARDOWN_COUNTER.load(Ordering::SeqCst);
if setup_count > 1 {
expect!(teardown_count).to_be_greater_than(0);
}
}
}