use qubit_function::predicates::{
ArcPredicate,
BoxPredicate,
Predicate,
RcPredicate,
};
use std::cell::RefCell;
use std::sync::{
Arc,
Mutex,
};
struct PositivePredicate;
impl Predicate<i32> for PositivePredicate {
fn test(&self, value: &i32) -> bool {
*value > 0
}
}
#[cfg(test)]
mod interior_mutability_tests {
use super::{
Arc,
ArcPredicate,
BoxPredicate,
Mutex,
Predicate,
RcPredicate,
RefCell,
};
#[test]
fn test_box_predicate_with_refcell_counter() {
let count = RefCell::new(0);
let pred = BoxPredicate::new(move |x: &i32| {
*count.borrow_mut() += 1;
*x > 0
});
assert!(pred.test(&5));
assert!(pred.test(&10));
assert!(!pred.test(&-3));
}
#[test]
fn test_arc_predicate_with_mutex_counter() {
let count = Arc::new(Mutex::new(0));
let count_clone = Arc::clone(&count);
let pred = ArcPredicate::new(move |x: &i32| {
let mut c =
count_clone.lock().expect("mutex should not be poisoned");
*c += 1;
*x > 0
});
assert!(pred.test(&5));
assert!(pred.test(&10));
assert!(!pred.test(&-3));
assert_eq!(*count.lock().expect("mutex should not be poisoned"), 3);
}
#[test]
fn test_rc_predicate_with_refcell_cache() {
use std::collections::HashMap;
let cache = RefCell::new(HashMap::new());
let pred = RcPredicate::new(move |x: &i32| {
let mut c = cache.borrow_mut();
*c.entry(*x).or_insert_with(|| *x > 0 && x % 2 == 0)
});
assert!(pred.test(&4));
assert!(pred.test(&4));
assert!(!pred.test(&3));
}
#[test]
fn test_arc_predicate_thread_safe_counter() {
let count = Arc::new(Mutex::new(0));
let pred = ArcPredicate::new({
let count = Arc::clone(&count);
move |x: &i32| {
let mut c = count.lock().expect("mutex should not be poisoned");
*c += 1;
*x > 0
}
});
let pred_clone = pred.clone();
let count_clone = Arc::clone(&count);
let handle = std::thread::spawn(move || {
assert!(pred_clone.test(&5));
assert!(pred_clone.test(&10));
});
assert!(pred.test(&3));
handle.join().expect("thread should not panic");
assert_eq!(
*count_clone.lock().expect("mutex should not be poisoned"),
3
);
}
}