#[cfg(test)]
mod tests {
use qubit_function::predicates::bi_predicate::{
ArcBiPredicate,
BiPredicate,
BoxBiPredicate,
FnBiPredicateOps,
RcBiPredicate,
};
use std::thread;
mod bi_predicate_trait_tests {
use super::*;
#[test]
fn test_closure_implements_bi_predicate() {
let sum_positive = |x: &i32, y: &i32| x + y > 0;
assert!(sum_positive.test(&5, &3));
assert!(!sum_positive.test(&-5, &-3));
assert!(!sum_positive.test(&5, &-10));
}
#[test]
fn test_function_pointer_implements_bi_predicate() {
fn first_greater_than_second(x: &i32, y: &i32) -> bool {
x > y
}
assert!(first_greater_than_second.test(&10, &5));
assert!(!first_greater_than_second.test(&3, &8));
}
#[test]
fn test_bi_predicate_with_different_types() {
let str_length_greater = |s: &String, len: &usize| s.len() > *len;
assert!(str_length_greater.test(&String::from("hello"), &3));
assert!(!str_length_greater.test(&String::from("hi"), &5));
let contains_prefix = |s: &&str, prefix: &&str| s.starts_with(*prefix);
assert!(contains_prefix.test(&"hello", &"hel"));
assert!(!contains_prefix.test(&"world", &"wor1"));
let within_range = |value: &f64, max: &f64| *value <= *max && *value >= 0.0;
assert!(within_range.test(&5.5, &10.0));
assert!(!within_range.test(&15.5, &10.0));
}
#[test]
fn test_bi_predicate_with_same_type() {
let both_positive = |x: &i32, y: &i32| *x > 0 && *y > 0;
assert!(both_positive.test(&5, &3));
assert!(!both_positive.test(&-5, &3));
assert!(!both_positive.test(&5, &-3));
}
}
mod bi_predicate_ext_tests {
use super::*;
#[test]
fn test_closure_and() {
let sum_positive = |x: &i32, y: &i32| x + y > 0;
let first_positive = |x: &i32, _y: &i32| *x > 0;
let combined = sum_positive.and(first_positive);
assert!(combined.test(&5, &3)); assert!(!combined.test(&-5, &10)); assert!(!combined.test(&5, &-10)); }
#[test]
fn test_closure_or() {
let sum_positive = |x: &i32, y: &i32| x + y > 0;
let first_positive = |x: &i32, _y: &i32| *x > 0;
let combined = sum_positive.or(first_positive);
assert!(combined.test(&5, &3)); assert!(combined.test(&-5, &10)); assert!(combined.test(&5, &-10)); assert!(!combined.test(&-5, &-10)); }
#[test]
fn test_closure_not() {
let sum_positive = |x: &i32, y: &i32| x + y > 0;
let sum_not_positive = sum_positive.not();
assert!(!sum_not_positive.test(&5, &3));
assert!(sum_not_positive.test(&-5, &-3));
}
#[test]
fn test_closure_xor() {
let first_positive = |x: &i32, _y: &i32| *x > 0;
let second_positive = |_x: &i32, y: &i32| *y > 0;
let combined = first_positive.xor(second_positive);
assert!(combined.test(&5, &-3)); assert!(combined.test(&-5, &3)); assert!(!combined.test(&5, &3)); assert!(!combined.test(&-5, &-3)); }
#[test]
fn test_closure_nand() {
let first_positive = |x: &i32, _y: &i32| *x > 0;
let second_positive = |_x: &i32, y: &i32| *y > 0;
let combined = first_positive.nand(second_positive);
assert!(!combined.test(&5, &3)); assert!(combined.test(&5, &-3)); assert!(combined.test(&-5, &3)); assert!(combined.test(&-5, &-3)); }
#[test]
fn test_closure_nor() {
let first_positive = |x: &i32, _y: &i32| *x > 0;
let second_positive = |_x: &i32, y: &i32| *y > 0;
let combined = first_positive.nor(second_positive);
assert!(!combined.test(&5, &3)); assert!(!combined.test(&5, &-3)); assert!(!combined.test(&-5, &3)); assert!(combined.test(&-5, &-3)); }
#[test]
fn test_closure_chain_combination() {
let x_positive = |x: &i32, _y: &i32| *x > 0;
let y_positive = |_x: &i32, y: &i32| *y > 0;
let sum_large = |x: &i32, y: &i32| x + y > 100;
let complex = x_positive.and(y_positive).or(sum_large);
assert!(complex.test(&5, &3)); assert!(complex.test(&50, &60)); assert!(!complex.test(&5, &-3)); }
}
mod box_bi_predicate_tests {
use super::*;
#[test]
fn test_new() {
let pred = BoxBiPredicate::new(|x: &i32, y: &i32| x + y > 0);
assert!(pred.test(&5, &3));
assert!(!pred.test(&-5, &-3));
}
#[test]
fn test_with_name() {
let pred = BoxBiPredicate::new_with_name("sum_positive", |x: &i32, y: &i32| x + y > 0);
assert_eq!(pred.name(), Some("sum_positive"));
assert!(pred.test(&5, &3));
}
#[test]
fn test_always_true() {
let pred: BoxBiPredicate<i32, i32> = BoxBiPredicate::always_true();
assert_eq!(pred.name(), Some("always_true"));
assert!(pred.test(&5, &3));
assert!(pred.test(&-5, &-3));
assert!(pred.test(&0, &0));
assert!(pred.test(&100, &-100));
}
#[test]
fn test_always_false() {
let pred: BoxBiPredicate<i32, i32> = BoxBiPredicate::always_false();
assert_eq!(pred.name(), Some("always_false"));
assert!(!pred.test(&5, &3));
assert!(!pred.test(&-5, &-3));
assert!(!pred.test(&0, &0));
assert!(!pred.test(&100, &-100));
}
#[test]
fn test_always_true_with_composition() {
let always_true: BoxBiPredicate<i32, i32> = BoxBiPredicate::always_true();
let positive_sum = BoxBiPredicate::new(|x: &i32, y: &i32| x + y > 0);
let combined = always_true.and(positive_sum);
assert!(combined.test(&5, &3));
assert!(!combined.test(&-5, &-3));
}
#[test]
fn test_always_false_with_composition() {
let always_false: BoxBiPredicate<i32, i32> = BoxBiPredicate::always_false();
let positive_sum = BoxBiPredicate::new(|x: &i32, y: &i32| x + y > 0);
let combined = always_false.or(positive_sum);
assert!(combined.test(&5, &3));
assert!(!combined.test(&-5, &-3));
}
#[test]
fn test_name_none() {
let pred = BoxBiPredicate::new(|x: &i32, y: &i32| x + y > 0);
assert_eq!(pred.name(), None);
}
#[test]
fn test_test_method() {
let pred = BoxBiPredicate::new(|x: &i32, y: &i32| *x > *y);
assert!(pred.test(&10, &5));
assert!(!pred.test(&3, &8));
assert!(!pred.test(&5, &5));
}
#[test]
fn test_and() {
let sum_positive = BoxBiPredicate::new(|x: &i32, y: &i32| x + y > 0);
let first_positive = |x: &i32, _y: &i32| *x > 0;
let combined = sum_positive.and(first_positive);
assert!(combined.test(&5, &3));
assert!(!combined.test(&-5, &10));
}
#[test]
fn test_or() {
let sum_positive = BoxBiPredicate::new(|x: &i32, y: &i32| x + y > 0);
let first_positive = BoxBiPredicate::new(|x: &i32, _y: &i32| *x > 0);
let combined = sum_positive.or(first_positive);
assert!(combined.test(&5, &3));
assert!(combined.test(&-5, &10));
assert!(combined.test(&5, &-10));
}
#[test]
fn test_not() {
let sum_positive = BoxBiPredicate::new(|x: &i32, y: &i32| x + y > 0);
let sum_not_positive = sum_positive.not();
assert!(!sum_not_positive.test(&5, &3));
assert!(sum_not_positive.test(&-5, &-3));
}
#[test]
fn test_xor() {
let first_positive = BoxBiPredicate::new(|x: &i32, _y: &i32| *x > 0);
let second_positive = BoxBiPredicate::new(|_x: &i32, y: &i32| *y > 0);
let combined = first_positive.xor(second_positive);
assert!(combined.test(&5, &-3));
assert!(combined.test(&-5, &3));
assert!(!combined.test(&5, &3));
}
#[test]
fn test_nand() {
let first_positive = BoxBiPredicate::new(|x: &i32, _y: &i32| *x > 0);
let second_positive = BoxBiPredicate::new(|_x: &i32, y: &i32| *y > 0);
let combined = first_positive.nand(second_positive);
assert!(!combined.test(&5, &3));
assert!(combined.test(&5, &-3));
}
#[test]
fn test_nor() {
let first_positive = BoxBiPredicate::new(|x: &i32, _y: &i32| *x > 0);
let second_positive = BoxBiPredicate::new(|_x: &i32, y: &i32| *y > 0);
let combined = first_positive.nor(second_positive);
assert!(!combined.test(&5, &3));
assert!(combined.test(&-5, &-3));
}
#[test]
fn test_chain_combination() {
let x_positive = BoxBiPredicate::new(|x: &i32, _y: &i32| *x > 0);
let y_positive = BoxBiPredicate::new(|_x: &i32, y: &i32| *y > 0);
let both_positive = x_positive.and(y_positive);
assert!(both_positive.test(&5, &3));
assert!(!both_positive.test(&5, &-3));
}
#[test]
fn test_display() {
let pred = BoxBiPredicate::new_with_name("sum_positive", |x: &i32, y: &i32| x + y > 0);
let display_str = format!("{}", pred);
assert_eq!(display_str, "BoxBiPredicate(sum_positive)");
let unnamed = BoxBiPredicate::new(|x: &i32, y: &i32| x + y > 0);
assert_eq!(format!("{}", unnamed), "BoxBiPredicate(unnamed)");
}
#[test]
fn test_debug() {
let pred = BoxBiPredicate::new_with_name("test_pred", |x: &i32, y: &i32| x + y > 0);
let debug_str = format!("{:?}", pred);
assert!(debug_str.contains("BoxBiPredicate"));
assert!(debug_str.contains("test_pred"));
}
#[test]
fn test_with_different_types() {
let str_len_greater = BoxBiPredicate::new(|s: &String, len: &usize| s.len() > *len);
assert!(str_len_greater.test(&String::from("hello"), &3));
assert!(!str_len_greater.test(&String::from("hi"), &5));
}
#[test]
fn test_and_with_closure() {
let sum_positive = BoxBiPredicate::new(|x: &i32, y: &i32| x + y > 0);
let combined = sum_positive.and(|x: &i32, _y: &i32| *x > 0);
assert!(combined.test(&5, &3));
assert!(!combined.test(&-5, &10));
}
#[test]
fn test_set_name() {
let mut pred = BoxBiPredicate::new(|x: &i32, y: &i32| x + y > 0);
assert_eq!(pred.name(), None);
pred.set_name("sum_positive");
assert_eq!(pred.name(), Some("sum_positive"));
assert!(pred.test(&5, &3));
pred.set_name("updated_name");
assert_eq!(pred.name(), Some("updated_name"));
}
}
mod arc_bi_predicate_tests {
use super::*;
#[test]
fn test_new() {
let pred = ArcBiPredicate::new(|x: &i32, y: &i32| x + y > 0);
assert!(pred.test(&5, &3));
assert!(!pred.test(&-5, &-3));
}
#[test]
fn test_with_name() {
let pred = ArcBiPredicate::new_with_name("sum_positive", |x: &i32, y: &i32| x + y > 0);
assert_eq!(pred.name(), Some("sum_positive"));
assert!(pred.test(&5, &3));
}
#[test]
fn test_always_true() {
let pred: ArcBiPredicate<i32, i32> = ArcBiPredicate::always_true();
assert_eq!(pred.name(), Some("always_true"));
assert!(pred.test(&5, &3));
assert!(pred.test(&-5, &-3));
assert!(pred.test(&0, &0));
assert!(pred.test(&100, &-100));
}
#[test]
fn test_always_false() {
let pred: ArcBiPredicate<i32, i32> = ArcBiPredicate::always_false();
assert_eq!(pred.name(), Some("always_false"));
assert!(!pred.test(&5, &3));
assert!(!pred.test(&-5, &-3));
assert!(!pred.test(&0, &0));
assert!(!pred.test(&100, &-100));
}
#[test]
fn test_always_true_with_composition() {
let always_true: ArcBiPredicate<i32, i32> = ArcBiPredicate::always_true();
let positive_sum = |x: &i32, y: &i32| x + y > 0;
let combined = always_true.and(positive_sum);
assert!(combined.test(&5, &3));
assert!(!combined.test(&-5, &-3));
}
#[test]
fn test_always_false_with_composition() {
let always_false: ArcBiPredicate<i32, i32> = ArcBiPredicate::always_false();
let positive_sum = |x: &i32, y: &i32| x + y > 0;
let combined = always_false.or(positive_sum);
assert!(combined.test(&5, &3));
assert!(!combined.test(&-5, &-3));
}
#[test]
fn test_always_true_clone() {
let pred: ArcBiPredicate<i32, i32> = ArcBiPredicate::always_true();
let cloned = pred.clone();
assert_eq!(cloned.name(), Some("always_true"));
assert!(cloned.test(&5, &3));
assert!(pred.test(&-5, &-3));
}
#[test]
fn test_name_none() {
let pred = ArcBiPredicate::new(|x: &i32, y: &i32| x + y > 0);
assert_eq!(pred.name(), None);
}
#[test]
fn test_test_method() {
let pred = ArcBiPredicate::new(|x: &i32, y: &i32| *x > *y);
assert!(pred.test(&10, &5));
assert!(!pred.test(&3, &8));
}
#[test]
fn test_clone() {
let pred = ArcBiPredicate::new(|x: &i32, y: &i32| x + y > 0);
let cloned = pred.clone();
assert!(pred.test(&5, &3));
assert!(cloned.test(&5, &3));
assert!(!pred.test(&-5, &-3));
assert!(!cloned.test(&-5, &-3));
}
#[test]
fn test_clone_preserves_name() {
let pred = ArcBiPredicate::new_with_name("original", |x: &i32, y: &i32| x + y > 0);
let cloned = pred.clone();
assert_eq!(pred.name(), Some("original"));
assert_eq!(cloned.name(), Some("original"));
}
#[test]
fn test_and() {
let sum_positive = ArcBiPredicate::new(|x: &i32, y: &i32| x + y > 0);
let first_positive = ArcBiPredicate::new(|x: &i32, _y: &i32| *x > 0);
let combined = sum_positive.clone().and(first_positive.clone());
assert!(combined.test(&5, &3));
assert!(!combined.test(&-5, &10));
assert!(sum_positive.test(&-5, &10));
assert!(first_positive.test(&5, &-10));
}
#[test]
fn test_or() {
let sum_positive = ArcBiPredicate::new(|x: &i32, y: &i32| x + y > 0);
let first_positive = ArcBiPredicate::new(|x: &i32, _y: &i32| *x > 0);
let combined = sum_positive.or(first_positive.clone());
assert!(combined.test(&5, &3));
assert!(combined.test(&-5, &10));
}
#[test]
fn test_not() {
let sum_positive = ArcBiPredicate::new(|x: &i32, y: &i32| x + y > 0);
let sum_not_positive = sum_positive.not();
assert!(!sum_not_positive.test(&5, &3));
assert!(sum_not_positive.test(&-5, &-3));
assert!(sum_positive.test(&5, &3));
}
#[test]
fn test_xor() {
let first_positive = ArcBiPredicate::new(|x: &i32, _y: &i32| *x > 0);
let second_positive = ArcBiPredicate::new(|_x: &i32, y: &i32| *y > 0);
let combined = first_positive.xor(second_positive);
assert!(combined.test(&5, &-3));
assert!(!combined.test(&5, &3));
}
#[test]
fn test_nand() {
let first_positive = ArcBiPredicate::new(|x: &i32, _y: &i32| *x > 0);
let second_positive = ArcBiPredicate::new(|_x: &i32, y: &i32| *y > 0);
let combined = first_positive.nand(second_positive);
assert!(!combined.test(&5, &3));
assert!(combined.test(&5, &-3));
}
#[test]
fn test_nor() {
let first_positive = ArcBiPredicate::new(|x: &i32, _y: &i32| *x > 0);
let second_positive = ArcBiPredicate::new(|_x: &i32, y: &i32| *y > 0);
let combined = first_positive.nor(second_positive);
assert!(!combined.test(&5, &3));
assert!(combined.test(&-5, &-3));
}
#[test]
fn test_chain_combination() {
let x_positive = ArcBiPredicate::new(|x: &i32, _y: &i32| *x > 0);
let y_positive = ArcBiPredicate::new(|_x: &i32, y: &i32| *y > 0);
let sum_large = ArcBiPredicate::new(|x: &i32, y: &i32| x + y > 100);
let complex = x_positive.and(y_positive).or(sum_large);
assert!(complex.test(&5, &3)); assert!(complex.test(&50, &60)); }
#[test]
fn test_display() {
let pred = ArcBiPredicate::new_with_name("sum_positive", |x: &i32, y: &i32| x + y > 0);
assert_eq!(format!("{}", pred), "ArcBiPredicate(sum_positive)");
}
#[test]
fn test_debug() {
let pred = ArcBiPredicate::new_with_name("test_pred", |x: &i32, y: &i32| x + y > 0);
let debug_str = format!("{:?}", pred);
assert!(debug_str.contains("ArcBiPredicate"));
}
#[test]
fn test_with_different_types() {
let str_len_greater = ArcBiPredicate::new(|s: &String, len: &usize| s.len() > *len);
assert!(str_len_greater.test(&String::from("hello"), &3));
assert!(!str_len_greater.test(&String::from("hi"), &5));
}
#[test]
fn test_set_name() {
let mut pred = ArcBiPredicate::new(|x: &i32, y: &i32| x + y > 0);
assert_eq!(pred.name(), None);
pred.set_name("sum_positive");
assert_eq!(pred.name(), Some("sum_positive"));
assert!(pred.test(&5, &3));
pred.set_name("updated_name");
assert_eq!(pred.name(), Some("updated_name"));
}
#[test]
fn test_to_box() {
let arc_pred = ArcBiPredicate::new(|x: &i32, y: &i32| x + y > 0);
let box_pred = arc_pred.to_box();
assert!(box_pred.test(&5, &3));
assert!(!box_pred.test(&-5, &-3));
}
#[test]
fn test_to_box_preserves_name() {
let arc_pred = ArcBiPredicate::new_with_name("test", |x: &i32, y: &i32| x + y > 0);
let box_pred = arc_pred.to_box();
assert_eq!(box_pred.name(), Some("test"));
assert!(box_pred.test(&5, &3));
}
#[test]
fn test_thread_safety() {
let pred = ArcBiPredicate::new(|x: &i32, y: &i32| x + y > 0);
let pred_clone = pred.clone();
let handle = thread::spawn(move || pred_clone.test(&5, &3));
assert!(pred.test(&10, &-5));
assert!(handle.join().unwrap());
}
#[test]
fn test_multiple_threads() {
let pred = ArcBiPredicate::new(|x: &i32, y: &i32| x + y > 100);
let handles: Vec<_> = (0..10)
.map(|i| {
let pred_clone = pred.clone();
thread::spawn(move || pred_clone.test(&(i * 10), &20))
})
.collect();
for handle in handles {
let _ = handle.join().unwrap();
}
}
}
mod rc_bi_predicate_tests {
use super::*;
#[test]
fn test_new() {
let pred = RcBiPredicate::new(|x: &i32, y: &i32| x + y > 0);
assert!(pred.test(&5, &3));
assert!(!pred.test(&-5, &-3));
}
#[test]
fn test_with_name() {
let pred = RcBiPredicate::new_with_name("sum_positive", |x: &i32, y: &i32| x + y > 0);
assert_eq!(pred.name(), Some("sum_positive"));
assert!(pred.test(&5, &3));
}
#[test]
fn test_always_true() {
let pred: RcBiPredicate<i32, i32> = RcBiPredicate::always_true();
assert_eq!(pred.name(), Some("always_true"));
assert!(pred.test(&5, &3));
assert!(pred.test(&-5, &-3));
assert!(pred.test(&0, &0));
assert!(pred.test(&100, &-100));
}
#[test]
fn test_always_false() {
let pred: RcBiPredicate<i32, i32> = RcBiPredicate::always_false();
assert_eq!(pred.name(), Some("always_false"));
assert!(!pred.test(&5, &3));
assert!(!pred.test(&-5, &-3));
assert!(!pred.test(&0, &0));
assert!(!pred.test(&100, &-100));
}
#[test]
fn test_always_true_with_composition() {
let always_true: RcBiPredicate<i32, i32> = RcBiPredicate::always_true();
let positive_sum = |x: &i32, y: &i32| x + y > 0;
let combined = always_true.and(positive_sum);
assert!(combined.test(&5, &3));
assert!(!combined.test(&-5, &-3));
}
#[test]
fn test_always_false_with_composition() {
let always_false: RcBiPredicate<i32, i32> = RcBiPredicate::always_false();
let positive_sum = |x: &i32, y: &i32| x + y > 0;
let combined = always_false.or(positive_sum);
assert!(combined.test(&5, &3));
assert!(!combined.test(&-5, &-3));
}
#[test]
fn test_always_true_clone() {
let pred: RcBiPredicate<i32, i32> = RcBiPredicate::always_true();
let cloned = pred.clone();
assert_eq!(cloned.name(), Some("always_true"));
assert!(cloned.test(&5, &3));
assert!(pred.test(&-5, &-3));
}
#[test]
fn test_name_none() {
let pred = RcBiPredicate::new(|x: &i32, y: &i32| x + y > 0);
assert_eq!(pred.name(), None);
}
#[test]
fn test_test_method() {
let pred = RcBiPredicate::new(|x: &i32, y: &i32| *x > *y);
assert!(pred.test(&10, &5));
assert!(!pred.test(&3, &8));
}
#[test]
fn test_clone() {
let pred = RcBiPredicate::new(|x: &i32, y: &i32| x + y > 0);
let cloned = pred.clone();
assert!(pred.test(&5, &3));
assert!(cloned.test(&5, &3));
}
#[test]
fn test_clone_preserves_name() {
let pred = RcBiPredicate::new_with_name("original", |x: &i32, y: &i32| x + y > 0);
let cloned = pred.clone();
assert_eq!(pred.name(), Some("original"));
assert_eq!(cloned.name(), Some("original"));
}
#[test]
fn test_and() {
let sum_positive = RcBiPredicate::new(|x: &i32, y: &i32| x + y > 0);
let first_positive = RcBiPredicate::new(|x: &i32, _y: &i32| *x > 0);
let combined = sum_positive.clone().and(first_positive.clone());
assert!(combined.test(&5, &3));
assert!(!combined.test(&-5, &10));
assert!(sum_positive.test(&-5, &10));
}
#[test]
fn test_or() {
let sum_positive = RcBiPredicate::new(|x: &i32, y: &i32| x + y > 0);
let first_positive = RcBiPredicate::new(|x: &i32, _y: &i32| *x > 0);
let combined = sum_positive.or(first_positive.clone());
assert!(combined.test(&5, &3));
assert!(combined.test(&-5, &10));
}
#[test]
fn test_not() {
let sum_positive = RcBiPredicate::new(|x: &i32, y: &i32| x + y > 0);
let sum_not_positive = sum_positive.not();
assert!(!sum_not_positive.test(&5, &3));
assert!(sum_not_positive.test(&-5, &-3));
}
#[test]
fn test_xor() {
let first_positive = RcBiPredicate::new(|x: &i32, _y: &i32| *x > 0);
let second_positive = RcBiPredicate::new(|_x: &i32, y: &i32| *y > 0);
let combined = first_positive.xor(second_positive);
assert!(combined.test(&5, &-3));
assert!(!combined.test(&5, &3));
}
#[test]
fn test_nand() {
let first_positive = RcBiPredicate::new(|x: &i32, _y: &i32| *x > 0);
let second_positive = RcBiPredicate::new(|_x: &i32, y: &i32| *y > 0);
let combined = first_positive.nand(second_positive);
assert!(!combined.test(&5, &3));
assert!(combined.test(&5, &-3));
}
#[test]
fn test_nor() {
let first_positive = RcBiPredicate::new(|x: &i32, _y: &i32| *x > 0);
let second_positive = RcBiPredicate::new(|_x: &i32, y: &i32| *y > 0);
let combined = first_positive.nor(second_positive);
assert!(!combined.test(&5, &3));
assert!(combined.test(&-5, &-3));
}
#[test]
fn test_chain_combination() {
let x_positive = RcBiPredicate::new(|x: &i32, _y: &i32| *x > 0);
let y_positive = RcBiPredicate::new(|_x: &i32, y: &i32| *y > 0);
let both_positive = x_positive.and(y_positive);
assert!(both_positive.test(&5, &3));
assert!(!both_positive.test(&5, &-3));
}
#[test]
fn test_display() {
let pred = RcBiPredicate::new_with_name("sum_positive", |x: &i32, y: &i32| x + y > 0);
assert_eq!(format!("{}", pred), "RcBiPredicate(sum_positive)");
}
#[test]
fn test_debug() {
let pred = RcBiPredicate::new_with_name("test_pred", |x: &i32, y: &i32| x + y > 0);
let debug_str = format!("{:?}", pred);
assert!(debug_str.contains("RcBiPredicate"));
}
#[test]
fn test_with_different_types() {
let str_len_greater = RcBiPredicate::new(|s: &String, len: &usize| s.len() > *len);
assert!(str_len_greater.test(&String::from("hello"), &3));
assert!(!str_len_greater.test(&String::from("hi"), &5));
}
#[test]
fn test_set_name() {
let mut pred = RcBiPredicate::new(|x: &i32, y: &i32| x + y > 0);
assert_eq!(pred.name(), None);
pred.set_name("sum_positive");
assert_eq!(pred.name(), Some("sum_positive"));
assert!(pred.test(&5, &3));
pred.set_name("updated_name");
assert_eq!(pred.name(), Some("updated_name"));
}
#[test]
fn test_to_box() {
let rc_pred = RcBiPredicate::new(|x: &i32, y: &i32| x + y > 0);
let box_pred = rc_pred.to_box();
assert!(box_pred.test(&5, &3));
assert!(!box_pred.test(&-5, &-3));
}
#[test]
fn test_to_box_preserves_name() {
let rc_pred = RcBiPredicate::new_with_name("test", |x: &i32, y: &i32| x + y > 0);
let box_pred = rc_pred.to_box();
assert_eq!(box_pred.name(), Some("test"));
assert!(box_pred.test(&5, &3));
}
#[test]
fn test_to_box_original_still_usable() {
let rc_pred = RcBiPredicate::new(|x: &i32, y: &i32| x + y > 0);
let _box_pred = rc_pred.to_box();
assert!(rc_pred.test(&5, &3));
assert!(!rc_pred.test(&-5, &-3));
}
#[test]
fn test_to_box_multiple_calls() {
let rc_pred = RcBiPredicate::new(|x: &i32, y: &i32| x % 2 == 0 && y % 2 == 0);
let box_pred1 = rc_pred.to_box();
let box_pred2 = rc_pred.to_box();
assert!(box_pred1.test(&2, &4));
assert!(box_pred2.test(&4, &6));
assert!(!box_pred1.test(&3, &4));
assert!(!box_pred2.test(&2, &5));
assert!(rc_pred.test(&2, &4));
}
#[test]
fn test_to_box_with_different_types() {
let rc_pred = RcBiPredicate::new(|s: &String, len: &usize| s.len() > *len);
let box_pred = rc_pred.to_box();
assert!(box_pred.test(&String::from("hello"), &3));
assert!(!box_pred.test(&String::from("hi"), &5));
assert!(rc_pred.test(&String::from("world"), &3));
}
#[test]
fn test_to_box_and_composition() {
let rc_pred = RcBiPredicate::new(|x: &i32, y: &i32| x + y > 0);
let box_pred = rc_pred.to_box();
let both_positive = |x: &i32, y: &i32| *x > 0 && *y > 0;
let combined = box_pred.and(both_positive);
assert!(combined.test(&5, &3));
assert!(!combined.test(&-5, &10));
}
}
mod conversion_tests {
use super::*;
#[test]
fn test_closure_into_box() {
let closure = |x: &i32, y: &i32| x + y > 0;
let box_pred: BoxBiPredicate<i32, i32> = closure.into_box();
assert!(box_pred.test(&5, &3));
}
#[test]
fn test_closure_into_rc() {
let closure = |x: &i32, y: &i32| x + y > 0;
let rc_pred: RcBiPredicate<i32, i32> = closure.into_rc();
assert!(rc_pred.test(&5, &3));
}
#[test]
fn test_closure_into_arc() {
let closure = |x: &i32, y: &i32| x + y > 0;
let arc_pred: ArcBiPredicate<i32, i32> = closure.into_arc();
assert!(arc_pred.test(&5, &3));
}
#[test]
fn test_box_to_box_zero_cost() {
let pred = BoxBiPredicate::new(|x: &i32, y: &i32| x + y > 0);
let same_pred = pred.into_box();
assert!(same_pred.test(&5, &3));
}
#[test]
fn test_box_to_rc() {
let box_pred = BoxBiPredicate::new(|x: &i32, y: &i32| x + y > 0);
let rc_pred = box_pred.into_rc();
assert!(rc_pred.test(&5, &3));
}
#[test]
fn test_box_to_rc_preserves_name() {
let box_pred = BoxBiPredicate::new_with_name("test", |x: &i32, y: &i32| x + y > 0);
let rc_pred = box_pred.into_rc();
assert_eq!(rc_pred.name(), Some("test"));
}
#[test]
fn test_arc_to_arc_zero_cost() {
let pred = ArcBiPredicate::new(|x: &i32, y: &i32| x + y > 0);
let same_pred = pred.into_arc();
assert!(same_pred.test(&5, &3));
}
#[test]
fn test_arc_to_box() {
let arc_pred = ArcBiPredicate::new(|x: &i32, y: &i32| x + y > 0);
let box_pred = arc_pred.into_box();
assert!(box_pred.test(&5, &3));
}
#[test]
fn test_arc_to_box_preserves_name() {
let arc_pred = ArcBiPredicate::new_with_name("test", |x: &i32, y: &i32| x + y > 0);
let box_pred = arc_pred.into_box();
assert_eq!(box_pred.name(), Some("test"));
}
#[test]
fn test_arc_to_rc() {
let arc_pred = ArcBiPredicate::new(|x: &i32, y: &i32| x + y > 0);
let rc_pred = arc_pred.into_rc();
assert!(rc_pred.test(&5, &3));
}
#[test]
fn test_arc_to_rc_preserves_name() {
let arc_pred = ArcBiPredicate::new_with_name("test", |x: &i32, y: &i32| x + y > 0);
let rc_pred = arc_pred.into_rc();
assert_eq!(rc_pred.name(), Some("test"));
}
#[test]
fn test_arc_to_rc_non_consuming() {
let arc_pred = ArcBiPredicate::new(|x: &i32, y: &i32| x + y > 0);
let rc_pred = arc_pred.to_rc();
assert!(rc_pred.test(&5, &3));
assert!(arc_pred.test(&5, &3));
}
#[test]
fn test_arc_to_rc_non_consuming_preserves_name() {
let arc_pred = ArcBiPredicate::new_with_name("test", |x: &i32, y: &i32| x + y > 0);
let rc_pred = arc_pred.to_rc();
assert_eq!(rc_pred.name(), Some("test"));
assert_eq!(arc_pred.name(), Some("test"));
}
#[test]
fn test_rc_to_rc_zero_cost() {
let pred = RcBiPredicate::new(|x: &i32, y: &i32| x + y > 0);
let same_pred = pred.into_rc();
assert!(same_pred.test(&5, &3));
}
#[test]
fn test_rc_to_box() {
let rc_pred = RcBiPredicate::new(|x: &i32, y: &i32| x + y > 0);
let box_pred = rc_pred.into_box();
assert!(box_pred.test(&5, &3));
}
#[test]
fn test_rc_to_box_preserves_name() {
let rc_pred = RcBiPredicate::new_with_name("test", |x: &i32, y: &i32| x + y > 0);
let box_pred = rc_pred.into_box();
assert_eq!(box_pred.name(), Some("test"));
}
#[test]
fn test_conversion_preserves_behavior() {
let closure = |x: &i32, y: &i32| x + y > 10;
let box_pred = closure.into_box();
assert!(box_pred.test(&5, &6));
assert!(!box_pred.test(&3, &4));
let closure2 = |x: &i32, y: &i32| x + y > 10;
let rc_pred = closure2.into_rc();
assert!(rc_pred.test(&5, &6));
assert!(!rc_pred.test(&3, &4));
}
#[test]
fn test_conversion_chain() {
let arc_pred = ArcBiPredicate::new_with_name("original", |x: &i32, y: &i32| x + y > 0);
let rc_pred = arc_pred.clone().into_rc();
assert_eq!(rc_pred.name(), Some("original"));
assert!(rc_pred.test(&5, &3));
let box_pred = rc_pred.into_box();
assert_eq!(box_pred.name(), Some("original"));
assert!(box_pred.test(&5, &3));
}
#[test]
fn test_arc_bi_predicate_new_instead_of_box() {
let closure = |x: &i32, y: &i32| x + y > 0;
let arc_pred = closure.into_arc();
assert!(arc_pred.test(&5, &3));
let arc_pred2 = ArcBiPredicate::new(|x: &i32, y: &i32| x + y > 0);
assert!(arc_pred2.test(&5, &3));
}
#[test]
fn test_closure_to_arc_instead_of_box_to_arc() {
let closure = |x: &i32, y: &i32| x + y > 0;
let arc_pred = closure.into_arc();
let arc_clone = arc_pred.clone();
let handle = thread::spawn(move || arc_clone.test(&5, &3));
assert!(handle.join().unwrap());
}
#[test]
fn test_struct_storing_arc_bi_predicate() {
struct Validator {
predicate: ArcBiPredicate<i32, i32>,
}
let validator = Validator {
predicate: ArcBiPredicate::new(|x: &i32, y: &i32| x + y > 0),
};
assert!(validator.predicate.test(&5, &3));
}
#[test]
fn test_struct_storing_box_bi_predicate() {
struct Validator {
predicate: BoxBiPredicate<i32, i32>,
}
let validator = Validator {
predicate: BoxBiPredicate::new(|x: &i32, y: &i32| x + y > 0),
};
assert!(validator.predicate.test(&5, &3));
}
}
mod into_fn_tests {
use super::*;
#[test]
fn test_closure_into_fn_with_filter() {
let pairs = [(1, 2), (-1, 3), (5, -6), (3, 4)];
let predicate = |x: &i32, y: &i32| x + y > 0;
let result: Vec<_> = pairs
.iter()
.filter(|(x, y)| predicate.into_fn()(x, y))
.copied()
.collect();
assert_eq!(result, vec![(1, 2), (-1, 3), (3, 4)]);
}
#[test]
fn test_box_bi_predicate_into_fn_with_filter() {
let pairs = [(1, 2), (-1, 3), (5, -6), (3, 4)];
let predicate = BoxBiPredicate::new(|x: &i32, y: &i32| x + y > 0);
let pred_fn = predicate.into_fn();
let result: Vec<_> = pairs
.iter()
.filter(|(x, y)| pred_fn(x, y))
.copied()
.collect();
assert_eq!(result, vec![(1, 2), (-1, 3), (3, 4)]);
}
#[test]
fn test_arc_bi_predicate_into_fn_with_filter() {
let pairs = [(1, 2), (-1, 3), (5, -6), (3, 4)];
let predicate = ArcBiPredicate::new(|x: &i32, y: &i32| x + y > 0);
let pred_fn = predicate.into_fn();
let result: Vec<_> = pairs
.iter()
.filter(|(x, y)| pred_fn(x, y))
.copied()
.collect();
assert_eq!(result, vec![(1, 2), (-1, 3), (3, 4)]);
}
#[test]
fn test_rc_bi_predicate_into_fn_with_filter() {
let pairs = [(1, 2), (-1, 3), (5, -6), (3, 4)];
let predicate = RcBiPredicate::new(|x: &i32, y: &i32| x + y > 0);
let pred_fn = predicate.into_fn();
let result: Vec<_> = pairs
.iter()
.filter(|(x, y)| pred_fn(x, y))
.copied()
.collect();
assert_eq!(result, vec![(1, 2), (-1, 3), (3, 4)]);
}
#[test]
fn test_into_fn_with_complex_composition() {
let x_positive = ArcBiPredicate::new(|x: &i32, _y: &i32| *x > 0);
let y_positive = ArcBiPredicate::new(|_x: &i32, y: &i32| *y > 0);
let predicate = x_positive.and(y_positive);
let pairs = [(1, 2), (-1, 3), (5, -6), (3, 4)];
let pred_fn = predicate.into_fn();
let result: Vec<_> = pairs
.iter()
.filter(|(x, y)| pred_fn(x, y))
.copied()
.collect();
assert_eq!(result, vec![(1, 2), (3, 4)]);
}
#[test]
fn test_into_fn_preserves_closure_semantics() {
let predicate = BoxBiPredicate::new(|x: &i32, y: &i32| *x > *y);
let pred_fn = predicate.into_fn();
assert!(pred_fn(&10, &5));
assert!(!pred_fn(&3, &8));
assert!(!pred_fn(&5, &5));
}
#[test]
fn test_into_fn_with_partition() {
let pairs = [(1, 2), (-1, 3), (5, -6), (3, 4)];
let predicate = BoxBiPredicate::new(|x: &i32, y: &i32| x + y > 0);
let pred_fn = predicate.into_fn();
let positive: Vec<_> = pairs.iter().filter(|(x, y)| pred_fn(x, y)).collect();
let negative: Vec<_> = pairs.iter().filter(|(x, y)| !pred_fn(x, y)).collect();
assert_eq!(positive, vec![&(1, 2), &(-1, 3), &(3, 4)]);
assert_eq!(negative, vec![&(5, -6)]);
}
#[test]
fn test_into_fn_with_string() {
let pairs = Vec::from([
(String::from("hello"), 3),
(String::from("hi"), 5),
(String::from("world"), 4),
]);
let predicate = BoxBiPredicate::new(|s: &String, len: &usize| s.len() > *len);
let pred_fn = predicate.into_fn();
let result: Vec<_> = pairs
.iter()
.filter(|(s, len)| pred_fn(s, len))
.map(|(s, _)| s.clone())
.collect();
assert_eq!(result, vec![String::from("hello"), String::from("world")]);
}
#[test]
fn test_into_fn_with_references() {
let data = [(1, 2), (3, 4), (5, 6)];
let predicate = RcBiPredicate::new(|x: &i32, y: &i32| x + y > 5);
let pred_fn = predicate.into_fn();
let count = data.iter().filter(|(x, y)| pred_fn(x, y)).count();
assert_eq!(count, 2); }
}
mod generic_constraint_tests {
use super::*;
fn filter_pairs<P>(pairs: Vec<(i32, i32)>, predicate: &P) -> Vec<(i32, i32)>
where
P: BiPredicate<i32, i32>,
{
pairs
.into_iter()
.filter(|(x, y)| predicate.test(x, y))
.collect()
}
#[test]
fn test_generic_function_accepts_closure() {
let pairs = vec![(1, 2), (-1, 3), (5, -6)];
let result = filter_pairs(pairs, &|x: &i32, y: &i32| x + y > 0);
assert_eq!(result, vec![(1, 2), (-1, 3)]);
}
#[test]
fn test_generic_function_accepts_box_bi_predicate() {
let pairs = vec![(1, 2), (-1, 3), (5, -6)];
let pred = BoxBiPredicate::new(|x: &i32, y: &i32| x + y > 0);
let result = filter_pairs(pairs, &pred);
assert_eq!(result, vec![(1, 2), (-1, 3)]);
}
#[test]
fn test_generic_function_accepts_arc_bi_predicate() {
let pairs = vec![(1, 2), (-1, 3), (5, -6)];
let pred = ArcBiPredicate::new(|x: &i32, y: &i32| x + y > 0);
let result = filter_pairs(pairs, &pred);
assert_eq!(result, vec![(1, 2), (-1, 3)]);
}
#[test]
fn test_generic_function_accepts_rc_bi_predicate() {
let pairs = vec![(1, 2), (-1, 3), (5, -6)];
let pred = RcBiPredicate::new(|x: &i32, y: &i32| x + y > 0);
let result = filter_pairs(pairs, &pred);
assert_eq!(result, vec![(1, 2), (-1, 3)]);
}
#[test]
fn test_generic_function_accepts_function_pointer() {
fn sum_positive(x: &i32, y: &i32) -> bool {
x + y > 0
}
let pairs = vec![(1, 2), (-1, 3), (5, -6)];
let result = filter_pairs(pairs, &sum_positive);
assert_eq!(result, vec![(1, 2), (-1, 3)]);
}
#[test]
fn test_generic_count_with_different_bi_predicate_types() {
fn count_matching<P>(pairs: &[(i32, i32)], pred: &P) -> usize
where
P: BiPredicate<i32, i32>,
{
pairs.iter().filter(|(x, y)| pred.test(x, y)).count()
}
let pairs = [(1, 2), (-1, 3), (5, -6), (3, 4)];
let box_pred = BoxBiPredicate::new(|x: &i32, y: &i32| x + y > 0);
assert_eq!(count_matching(&pairs, &box_pred), 3);
let arc_pred = ArcBiPredicate::new(|x: &i32, y: &i32| x + y > 0);
assert_eq!(count_matching(&pairs, &arc_pred), 3);
let rc_pred = RcBiPredicate::new(|x: &i32, y: &i32| x + y > 0);
assert_eq!(count_matching(&pairs, &rc_pred), 3);
}
#[test]
fn test_generic_with_combined_bi_predicates() {
let x_positive = ArcBiPredicate::new(|x: &i32, _y: &i32| *x > 0);
let y_positive = ArcBiPredicate::new(|_x: &i32, y: &i32| *y > 0);
let combined = x_positive.and(y_positive);
let pairs = [(1, 2), (-1, 3), (5, -6), (3, 4)];
let result = filter_pairs(pairs.to_vec(), &combined);
assert_eq!(result, vec![(1, 2), (3, 4)]);
}
#[test]
fn test_generic_with_string_bi_predicates() {
fn filter_string_pairs<P>(
pairs: Vec<(String, usize)>,
predicate: &P,
) -> Vec<(String, usize)>
where
P: BiPredicate<String, usize>,
{
pairs
.into_iter()
.filter(|(s, len)| predicate.test(s, len))
.collect()
}
let pairs = vec![
(String::from("hello"), 3),
(String::from("hi"), 5),
(String::from("world"), 4),
];
let pred = BoxBiPredicate::new(|s: &String, len: &usize| s.len() > *len);
let result = filter_string_pairs(pairs, &pred);
assert_eq!(result.len(), 2);
}
#[test]
fn test_bi_predicate_as_struct_field() {
struct Validator<P> {
predicate: P,
}
impl<P> Validator<P>
where
P: BiPredicate<i32, i32>,
{
fn validate(&self, x: i32, y: i32) -> bool {
self.predicate.test(&x, &y)
}
}
let validator = Validator {
predicate: BoxBiPredicate::new(|x: &i32, y: &i32| x + y > 0),
};
assert!(validator.validate(5, 3));
assert!(!validator.validate(-5, -3));
}
#[test]
fn test_returning_bi_predicate_from_function() {
fn create_sum_checker(threshold: i32) -> impl BiPredicate<i32, i32> {
move |x: &i32, y: &i32| x + y > threshold
}
let checker = create_sum_checker(10);
assert!(checker.test(&6, &5));
assert!(!checker.test(&3, &4));
}
#[test]
fn test_thread_safety_with_arc_bi_predicate() {
fn process_in_thread<P>(pred: P, x: i32, y: i32) -> bool
where
P: BiPredicate<i32, i32> + Send + 'static,
{
thread::spawn(move || pred.test(&x, &y)).join().unwrap()
}
let pred = ArcBiPredicate::new(|x: &i32, y: &i32| x + y > 0);
assert!(process_in_thread(pred, 5, 3));
}
#[test]
fn test_mixed_bi_predicate_types_in_sequence() {
let pairs = [(1, 2), (-1, 3), (5, -6), (3, 4)];
let box_pred = BoxBiPredicate::new(|x: &i32, y: &i32| x + y > 0);
let count1 = pairs.iter().filter(|(x, y)| box_pred.test(x, y)).count();
let arc_pred = ArcBiPredicate::new(|x: &i32, _y: &i32| *x > 0);
let count2 = pairs.iter().filter(|(x, y)| arc_pred.test(x, y)).count();
assert_eq!(count1, 3);
assert_eq!(count2, 3);
}
#[test]
fn test_generic_with_custom_types() {
#[derive(Debug, Clone, PartialEq)]
struct Point {
x: i32,
y: i32,
}
fn filter_points<P>(points: Vec<(Point, Point)>, pred: &P) -> Vec<(Point, Point)>
where
P: BiPredicate<Point, Point>,
{
points
.into_iter()
.filter(|(p1, p2)| pred.test(p1, p2))
.collect()
}
let points = vec![
(Point { x: 1, y: 2 }, Point { x: 3, y: 4 }),
(Point { x: -1, y: 2 }, Point { x: 1, y: -4 }),
];
let pred = BoxBiPredicate::new(|p1: &Point, p2: &Point| p1.x + p2.x > 0);
let result = filter_points(points, &pred);
assert_eq!(result.len(), 1);
}
}
mod default_implementation_tests {
use super::*;
#[derive(Clone)]
struct CustomBiPredicate<T, U>
where
T: 'static,
U: 'static,
{
threshold: i32,
_phantom: std::marker::PhantomData<(T, U)>,
}
impl CustomBiPredicate<i32, i32> {
fn new(threshold: i32) -> Self {
Self {
threshold,
_phantom: std::marker::PhantomData,
}
}
}
impl BiPredicate<i32, i32> for CustomBiPredicate<i32, i32> {
fn test(&self, first: &i32, second: &i32) -> bool {
first + second > self.threshold
}
}
#[test]
fn test_custom_type_basic_test() {
let pred = CustomBiPredicate::new(10);
assert!(pred.test(&6, &5));
assert!(pred.test(&10, &1));
assert!(!pred.test(&5, &5));
assert!(!pred.test(&3, &4));
}
#[test]
fn test_custom_type_into_box() {
let pred = CustomBiPredicate::new(10);
let box_pred = pred.into_box();
assert!(box_pred.test(&6, &5));
assert!(box_pred.test(&10, &1));
assert!(!box_pred.test(&5, &5));
assert!(!box_pred.test(&3, &4));
}
#[test]
fn test_custom_type_into_rc() {
let pred = CustomBiPredicate::new(10);
let rc_pred = pred.into_rc();
assert!(rc_pred.test(&6, &5));
assert!(rc_pred.test(&10, &1));
assert!(!rc_pred.test(&5, &5));
assert!(!rc_pred.test(&3, &4));
let cloned = rc_pred.clone();
assert!(cloned.test(&6, &5));
assert!(rc_pred.test(&6, &5));
}
#[test]
fn test_custom_type_into_arc() {
struct ThreadSafePredicate {
threshold: i32,
}
impl ThreadSafePredicate {
fn new(threshold: i32) -> Self {
Self { threshold }
}
}
unsafe impl Send for ThreadSafePredicate {}
unsafe impl Sync for ThreadSafePredicate {}
impl BiPredicate<i32, i32> for ThreadSafePredicate {
fn test(&self, first: &i32, second: &i32) -> bool {
first + second > self.threshold
}
}
let pred = ThreadSafePredicate::new(10);
let arc_pred = pred.into_arc();
assert!(arc_pred.test(&6, &5));
assert!(arc_pred.test(&10, &1));
assert!(!arc_pred.test(&5, &5));
assert!(!arc_pred.test(&3, &4));
let arc_clone = arc_pred.clone();
let handle = thread::spawn(move || arc_clone.test(&6, &5));
assert!(handle.join().unwrap());
assert!(arc_pred.test(&10, &1));
}
#[test]
fn test_custom_type_into_fn() {
let pred = CustomBiPredicate::new(10);
let func = pred.into_fn();
assert!(func(&6, &5));
assert!(func(&10, &1));
assert!(!func(&5, &5));
assert!(!func(&3, &4));
}
#[test]
fn test_custom_type_into_fn_with_filter() {
let pred = CustomBiPredicate::new(10);
let func = pred.into_fn();
let pairs = [(6, 5), (3, 4), (10, 1), (5, 5)];
let result: Vec<_> = pairs.iter().filter(|(x, y)| func(x, y)).collect();
assert_eq!(result, vec![&(6, 5), &(10, 1)]);
}
#[test]
fn test_custom_type_can_be_used_in_generic_context() {
fn accepts_predicate<P>(pred: &P, x: i32, y: i32) -> bool
where
P: BiPredicate<i32, i32>,
{
pred.test(&x, &y)
}
let pred = CustomBiPredicate::new(10);
assert!(accepts_predicate(&pred, 6, 5));
assert!(!accepts_predicate(&pred, 3, 4));
}
#[test]
fn test_custom_type_composition_via_conversion() {
let custom_pred = CustomBiPredicate::new(10);
let box_pred = custom_pred.into_box();
let both_positive = |x: &i32, y: &i32| *x > 0 && *y > 0;
let combined = box_pred.and(both_positive);
assert!(combined.test(&6, &5)); assert!(!combined.test(&-6, &20)); assert!(!combined.test(&3, &4)); }
#[test]
fn test_custom_type_all_conversions_preserve_behavior() {
let threshold = 10;
let custom_pred1 = CustomBiPredicate::new(threshold);
let box_pred = custom_pred1.into_box();
let custom_pred2 = CustomBiPredicate::new(threshold);
let rc_pred = custom_pred2.into_rc();
let test_values = [(6, 5), (3, 4), (10, 1), (5, 5)];
for (x, y) in &test_values {
let expected = x + y > threshold;
assert_eq!(box_pred.test(x, y), expected);
assert_eq!(rc_pred.test(x, y), expected);
}
}
#[test]
fn test_custom_type_to_box() {
let pred = CustomBiPredicate::new(10);
let box_pred = pred.to_box();
assert!(box_pred.test(&6, &5));
assert!(box_pred.test(&10, &1));
assert!(!box_pred.test(&5, &5));
assert!(!box_pred.test(&3, &4));
}
#[test]
fn test_custom_type_to_rc() {
let pred = CustomBiPredicate::new(10);
let rc_pred = pred.to_rc();
assert!(rc_pred.test(&6, &5));
assert!(rc_pred.test(&10, &1));
assert!(!rc_pred.test(&5, &5));
assert!(!rc_pred.test(&3, &4));
let cloned = rc_pred.clone();
assert!(cloned.test(&6, &5));
assert!(rc_pred.test(&6, &5));
}
#[test]
fn test_custom_type_to_arc() {
#[derive(Clone)]
struct ThreadSafePredicate {
threshold: i32,
}
impl ThreadSafePredicate {
fn new(threshold: i32) -> Self {
Self { threshold }
}
}
unsafe impl Send for ThreadSafePredicate {}
unsafe impl Sync for ThreadSafePredicate {}
impl BiPredicate<i32, i32> for ThreadSafePredicate {
fn test(&self, first: &i32, second: &i32) -> bool {
first + second > self.threshold
}
}
let pred = ThreadSafePredicate::new(10);
let arc_pred = pred.to_arc();
assert!(arc_pred.test(&6, &5));
assert!(arc_pred.test(&10, &1));
assert!(!arc_pred.test(&5, &5));
assert!(!arc_pred.test(&3, &4));
let arc_clone = arc_pred.clone();
let handle = thread::spawn(move || arc_clone.test(&6, &5));
assert!(handle.join().unwrap());
assert!(arc_pred.test(&10, &1));
}
#[test]
fn test_custom_type_to_fn() {
let pred = CustomBiPredicate::new(10);
let func = pred.to_fn();
assert!(func(&6, &5));
assert!(func(&10, &1));
assert!(!func(&5, &5));
assert!(!func(&3, &4));
}
#[test]
fn test_custom_type_to_fn_with_filter() {
let pred = CustomBiPredicate::new(10);
let func = pred.to_fn();
let pairs = [(6, 5), (3, 4), (10, 1), (5, 5)];
let result: Vec<_> = pairs.iter().filter(|(x, y)| func(x, y)).collect();
assert_eq!(result, vec![&(6, 5), &(10, 1)]);
}
#[test]
fn test_custom_type_original_still_usable_after_to_box() {
let pred = CustomBiPredicate::new(10);
let _box_pred = pred.to_box();
assert!(pred.test(&6, &5));
assert!(!pred.test(&3, &4));
}
#[test]
fn test_custom_type_original_still_usable_after_to_rc() {
let pred = CustomBiPredicate::new(10);
let _rc_pred = pred.to_rc();
assert!(pred.test(&6, &5));
assert!(!pred.test(&3, &4));
}
#[test]
fn test_custom_type_original_still_usable_after_to_fn() {
let pred = CustomBiPredicate::new(10);
let _func = pred.to_fn();
assert!(pred.test(&6, &5));
assert!(!pred.test(&3, &4));
}
#[test]
fn test_custom_type_all_to_conversions_preserve_behavior() {
let threshold = 10;
let pred = CustomBiPredicate::new(threshold);
let box_pred = pred.to_box();
let rc_pred = pred.to_rc();
let test_values = [(6, 5), (3, 4), (10, 1), (5, 5)];
for (x, y) in &test_values {
let expected = x + y > threshold;
assert_eq!(pred.test(x, y), expected);
assert_eq!(box_pred.test(x, y), expected);
assert_eq!(rc_pred.test(x, y), expected);
}
}
}
mod edge_case_tests {
use super::*;
#[test]
fn test_with_zero() {
let sum_positive = BoxBiPredicate::new(|x: &i32, y: &i32| x + y > 0);
assert!(!sum_positive.test(&0, &0));
assert!(sum_positive.test(&1, &0));
assert!(sum_positive.test(&0, &1));
}
#[test]
fn test_always_true() {
let always_true = BoxBiPredicate::new(|_x: &i32, _y: &i32| true);
assert!(always_true.test(&5, &3));
assert!(always_true.test(&-5, &-3));
assert!(always_true.test(&0, &0));
}
#[test]
fn test_always_false() {
let always_false = BoxBiPredicate::new(|_x: &i32, _y: &i32| false);
assert!(!always_false.test(&5, &3));
assert!(!always_false.test(&-5, &-3));
assert!(!always_false.test(&0, &0));
}
#[test]
fn test_double_negation() {
let sum_positive = BoxBiPredicate::new(|x: &i32, y: &i32| x + y > 0);
let not_not = sum_positive.not().not();
assert!(not_not.test(&5, &3));
assert!(!not_not.test(&-5, &-3));
}
#[test]
fn test_with_empty_string() {
let is_empty =
BoxBiPredicate::new(|s1: &String, s2: &String| s1.is_empty() && s2.is_empty());
assert!(is_empty.test(&String::new(), &String::new()));
assert!(!is_empty.test(&String::from("a"), &String::new()));
}
#[test]
fn test_with_large_numbers() {
let sum_overflow_safe =
BoxBiPredicate::new(|x: &i64, y: &i64| x.checked_add(*y).is_some());
let max_minus_one = i64::MAX - 1;
assert!(sum_overflow_safe.test(&max_minus_one, &1));
assert!(!sum_overflow_safe.test(&i64::MAX, &1));
}
#[test]
fn test_with_floating_point() {
let close_enough = BoxBiPredicate::new(|x: &f64, y: &f64| (*x - *y).abs() < 0.01);
assert!(close_enough.test(&1.0, &1.005));
assert!(!close_enough.test(&1.0, &1.02));
}
#[test]
fn test_complex_chain() {
let p1 = BoxBiPredicate::new(|x: &i32, _y: &i32| *x > 0);
let p2 = BoxBiPredicate::new(|_x: &i32, y: &i32| *y > 0);
let p3 = BoxBiPredicate::new(|x: &i32, y: &i32| x + y > 10);
let complex = p1.and(p2).or(p3);
assert!(complex.test(&5, &3)); assert!(complex.test(&50, &-30)); assert!(!complex.test(&-5, &3)); }
}
mod mixed_type_combination_tests {
use super::*;
#[test]
fn test_closure_to_box() {
let closure = |x: &i32, y: &i32| x + y > 0;
let box_pred = closure.and(|x: &i32, _y: &i32| *x > 0);
assert!(box_pred.test(&5, &3));
assert!(!box_pred.test(&-5, &10));
}
#[test]
fn test_box_with_closure() {
let box_pred = BoxBiPredicate::new(|x: &i32, y: &i32| x + y > 0);
let combined = box_pred.and(|x: &i32, _y: &i32| *x > 0);
assert!(combined.test(&5, &3));
assert!(!combined.test(&-5, &10));
}
#[test]
fn test_arc_preserves_original() {
let arc1 = ArcBiPredicate::new(|x: &i32, y: &i32| x + y > 0);
let arc2 = ArcBiPredicate::new(|x: &i32, _y: &i32| *x > 0);
let _combined = arc1.clone().and(arc2.clone());
assert!(arc1.test(&-5, &10));
assert!(arc2.test(&5, &-10));
}
#[test]
fn test_rc_preserves_original() {
let rc1 = RcBiPredicate::new(|x: &i32, y: &i32| x + y > 0);
let rc2 = RcBiPredicate::new(|x: &i32, _y: &i32| *x > 0);
let _combined = rc1.clone().and(rc2.clone());
assert!(rc1.test(&-5, &10));
assert!(rc2.test(&5, &-10));
}
}
}
#[cfg(test)]
mod to_fn_tests {
use qubit_function::predicates::bi_predicate::{
ArcBiPredicate,
BiPredicate,
RcBiPredicate,
};
#[test]
fn test_rc_to_fn() {
let pred = RcBiPredicate::new(|x: &i32, y: &i32| x + y > 0);
let func = pred.to_fn();
assert!(func(&5, &3));
assert!(!func(&-5, &-3));
assert!(!func(&0, &0));
}
#[test]
fn test_rc_to_fn_multiple_calls() {
let pred = RcBiPredicate::new(|x: &i32, y: &i32| x % 2 == 0 && y % 2 == 0);
let func = pred.to_fn();
assert!(func(&2, &4));
assert!(func(&4, &6));
assert!(!func(&3, &4));
assert!(!func(&2, &5));
}
#[test]
fn test_arc_to_fn() {
let pred = ArcBiPredicate::new(|x: &i32, y: &i32| x + y > 0);
let func = pred.to_fn();
assert!(func(&5, &3));
assert!(!func(&-5, &-3));
assert!(!func(&0, &0));
}
#[test]
fn test_arc_to_fn_multiple_calls() {
let pred = ArcBiPredicate::new(|x: &i32, y: &i32| x % 2 == 0 && y % 2 == 0);
let func = pred.to_fn();
assert!(func(&2, &4));
assert!(func(&4, &6));
assert!(!func(&3, &4));
assert!(!func(&2, &5));
}
#[test]
fn test_rc_to_fn_with_composition() {
let is_sum_positive = RcBiPredicate::new(|x: &i32, y: &i32| x + y > 0);
let is_both_even = RcBiPredicate::new(|x: &i32, y: &i32| x % 2 == 0 && y % 2 == 0);
let combined = is_sum_positive.and(is_both_even);
let func = combined.to_fn();
assert!(func(&2, &4));
assert!(!func(&1, &3));
assert!(!func(&-2, &-4));
}
#[test]
fn test_arc_to_fn_with_composition() {
let is_sum_positive = ArcBiPredicate::new(|x: &i32, y: &i32| x + y > 0);
let is_both_even = ArcBiPredicate::new(|x: &i32, y: &i32| x % 2 == 0 && y % 2 == 0);
let combined = is_sum_positive.and(is_both_even);
let func = combined.to_fn();
assert!(func(&2, &4));
assert!(!func(&1, &3));
assert!(!func(&-2, &-4));
}
#[test]
fn test_rc_to_rc() {
let pred = RcBiPredicate::new(|x: &i32, y: &i32| x + y > 0);
let rc_pred = pred.to_rc();
assert!(rc_pred.test(&5, &3));
assert!(!rc_pred.test(&-5, &-3));
assert!(pred.test(&5, &3));
}
#[test]
fn test_arc_to_arc() {
let pred = ArcBiPredicate::new(|x: &i32, y: &i32| x + y > 0);
let arc_pred = pred.to_arc();
assert!(arc_pred.test(&5, &3));
assert!(!arc_pred.test(&-5, &-3));
assert!(pred.test(&5, &3));
}
#[test]
fn test_rc_to_rc_preserves_name() {
let pred = RcBiPredicate::new_with_name("test_pred", |x: &i32, y: &i32| x + y > 0);
let rc_pred = pred.to_rc();
assert_eq!(rc_pred.name(), Some("test_pred"));
assert!(rc_pred.test(&5, &3));
}
#[test]
fn test_arc_to_arc_preserves_name() {
let pred = ArcBiPredicate::new_with_name("test_pred", |x: &i32, y: &i32| x + y > 0);
let arc_pred = pred.to_arc();
assert_eq!(arc_pred.name(), Some("test_pred"));
assert!(arc_pred.test(&5, &3));
}
#[test]
fn test_closure_to_box() {
let closure = |x: &i32, y: &i32| x + y > 0;
let box_pred = closure.to_box();
assert!(box_pred.test(&5, &3));
assert!(!box_pred.test(&-5, &-3));
}
#[test]
fn test_closure_to_rc() {
let closure = |x: &i32, y: &i32| x + y > 0;
let rc_pred = closure.to_rc();
assert!(rc_pred.test(&5, &3));
assert!(!rc_pred.test(&-5, &-3));
}
#[test]
fn test_closure_to_arc() {
let closure = |x: &i32, y: &i32| x + y > 0;
let arc_pred = closure.to_arc();
assert!(arc_pred.test(&5, &3));
assert!(!arc_pred.test(&-5, &-3));
}
#[test]
fn test_closure_to_fn() {
let closure = |x: &i32, y: &i32| x + y > 0;
let func = closure.to_fn();
assert!(func(&5, &3));
assert!(!func(&-5, &-3));
}
#[test]
fn test_closure_to_box_multiple_calls() {
let closure = |x: &i32, y: &i32| x % 2 == 0 && y % 2 == 0;
let box_pred1 = closure.to_box();
let box_pred2 = closure.to_box();
assert!(box_pred1.test(&2, &4));
assert!(box_pred2.test(&4, &6));
assert!(!box_pred1.test(&3, &4));
}
#[test]
fn test_closure_to_rc_can_clone() {
let closure = |x: &i32, y: &i32| x + y > 0;
let rc_pred = closure.to_rc();
let cloned = rc_pred.clone();
assert!(rc_pred.test(&5, &3));
assert!(cloned.test(&5, &3));
assert!(!rc_pred.test(&-5, &-3));
assert!(!cloned.test(&-5, &-3));
}
#[test]
fn test_closure_to_arc_thread_safe() {
let closure = |x: &i32, y: &i32| x + y > 0;
let arc_pred = closure.to_arc();
let arc_clone = arc_pred.clone();
let handle = std::thread::spawn(move || arc_clone.test(&5, &3));
assert!(arc_pred.test(&10, &5));
assert!(handle.join().unwrap());
}
#[test]
fn test_closure_to_fn_with_filter() {
let closure = |x: &i32, y: &i32| x + y > 0;
let func = closure.to_fn();
let pairs = [(1, 2), (-1, 3), (5, -6), (3, 4)];
let result: Vec<_> = pairs.iter().filter(|(x, y)| func(x, y)).collect();
assert_eq!(result, vec![&(1, 2), &(-1, 3), &(3, 4)]);
}
}