use qubit_function::{
BiConsumerOnce,
BoxBiConsumerOnce,
FnBiConsumerOnceOps,
};
use std::sync::{
Arc,
Mutex,
};
#[test]
fn test_bi_consumer_once_default_conversions_allow_relaxed_generic_types() {
#[derive(Debug)]
struct BorrowedRc<'a> {
value: &'a str,
}
#[derive(Clone, Debug)]
struct BorrowedRcBiConsumerOnce;
impl<'a> BiConsumerOnce<BorrowedRc<'a>, BorrowedRc<'a>> for BorrowedRcBiConsumerOnce {
fn accept(self, first: &BorrowedRc<'a>, second: &BorrowedRc<'a>) {
assert_eq!(first.value, "left");
assert_eq!(second.value, "right");
}
}
let left = String::from("left");
let right = String::from("right");
let first = BorrowedRc {
value: left.as_str(),
};
let second = BorrowedRc {
value: right.as_str(),
};
let consumer = BorrowedRcBiConsumerOnce;
consumer.clone().into_box().accept(&first, &second);
consumer.clone().into_fn()(&first, &second);
consumer.to_box().accept(&first, &second);
consumer.to_fn()(&first, &second);
}
#[cfg(test)]
mod box_bi_consumer_once_tests {
use super::*;
#[test]
fn test_new_and_accept() {
let log = Arc::new(Mutex::new(Vec::new()));
let l = log.clone();
let consumer = BoxBiConsumerOnce::new(move |x: &i32, y: &i32| {
l.lock().unwrap().push(*x + *y);
});
consumer.accept(&5, &3);
assert_eq!(*log.lock().unwrap(), vec![8]);
}
#[test]
fn test_and_then() {
let log = Arc::new(Mutex::new(Vec::new()));
let l1 = log.clone();
let l2 = log.clone();
let chained = BoxBiConsumerOnce::new(move |x: &i32, y: &i32| {
l1.lock().unwrap().push(*x + *y);
})
.and_then(move |x: &i32, y: &i32| {
l2.lock().unwrap().push(*x * *y);
});
chained.accept(&5, &3);
assert_eq!(*log.lock().unwrap(), vec![8, 15]);
}
#[test]
fn test_noop() {
let noop = BoxBiConsumerOnce::<i32, i32>::noop();
noop.accept(&42, &10);
}
#[test]
fn test_when_true() {
let log = Arc::new(Mutex::new(Vec::new()));
let l = log.clone();
let consumer = BoxBiConsumerOnce::new(move |x: &i32, y: &i32| {
l.lock().unwrap().push(*x + *y);
});
let conditional = consumer.when(|x: &i32, y: &i32| *x > 0 && *y > 0);
conditional.accept(&5, &3);
assert_eq!(*log.lock().unwrap(), vec![8]);
}
#[test]
fn test_when_false() {
let log = Arc::new(Mutex::new(Vec::new()));
let l = log.clone();
let consumer = BoxBiConsumerOnce::new(move |x: &i32, y: &i32| {
l.lock().unwrap().push(*x + *y);
});
let conditional = consumer.when(|x: &i32, y: &i32| *x > 0 && *y > 0);
conditional.accept(&-5, &3);
assert_eq!(*log.lock().unwrap(), vec![]);
}
#[test]
fn test_when_or_else() {
let log = Arc::new(Mutex::new(Vec::new()));
let l1 = log.clone();
let l2 = log.clone();
let consumer = BoxBiConsumerOnce::new(move |x: &i32, _y: &i32| {
l1.lock().unwrap().push(*x);
});
let conditional =
consumer
.when(|x: &i32, y: &i32| *x > *y)
.or_else(move |_x: &i32, y: &i32| {
l2.lock().unwrap().push(*y);
});
conditional.accept(&5, &3);
assert_eq!(*log.lock().unwrap(), vec![5]);
}
#[test]
fn test_when_or_else_false_branch() {
let log = Arc::new(Mutex::new(Vec::new()));
let l1 = log.clone();
let l2 = log.clone();
let consumer = BoxBiConsumerOnce::new(move |x: &i32, _y: &i32| {
l1.lock().unwrap().push(*x);
});
let conditional =
consumer
.when(|x: &i32, y: &i32| *x > *y)
.or_else(move |_x: &i32, y: &i32| {
l2.lock().unwrap().push(*y);
});
conditional.accept(&3, &5);
assert_eq!(*log.lock().unwrap(), vec![5]);
}
#[test]
fn test_into_box() {
let log = Arc::new(Mutex::new(Vec::new()));
let l = log.clone();
let closure = move |x: &i32, y: &i32| {
l.lock().unwrap().push(*x + *y);
};
let box_consumer = closure.into_box();
box_consumer.accept(&5, &3);
assert_eq!(*log.lock().unwrap(), vec![8]);
}
#[test]
fn test_into_fn() {
let log = Arc::new(Mutex::new(Vec::new()));
let l = log.clone();
let consumer = BoxBiConsumerOnce::new(move |x: &i32, y: &i32| {
l.lock().unwrap().push(*x + *y);
});
let func = consumer.into_fn();
func(&5, &3);
assert_eq!(*log.lock().unwrap(), vec![8]);
}
#[test]
fn test_name() {
let mut consumer = BoxBiConsumerOnce::<i32, i32>::noop();
assert_eq!(consumer.name(), None);
consumer.set_name("test_consumer");
assert_eq!(consumer.name(), Some("test_consumer"));
}
#[test]
fn test_moved_value() {
let data = [1, 2, 3];
let consumer = BoxBiConsumerOnce::new(move |_x: &i32, _y: &i32| {
println!("Data length: {}", data.len());
});
consumer.accept(&5, &3);
}
#[test]
fn test_new_with_name() {
let log = Arc::new(Mutex::new(Vec::new()));
let l = log.clone();
let consumer =
BoxBiConsumerOnce::new_with_name("test_consumer", move |x: &i32, y: &i32| {
l.lock().unwrap().push(*x + *y);
});
assert_eq!(consumer.name(), Some("test_consumer"));
consumer.accept(&5, &3);
assert_eq!(*log.lock().unwrap(), vec![8]);
}
#[test]
fn test_conditional_into_box() {
let log = Arc::new(Mutex::new(Vec::new()));
let l = log.clone();
let consumer = BoxBiConsumerOnce::new(move |x: &i32, y: &i32| {
l.lock().unwrap().push(*x + *y);
});
let conditional = consumer.when(|x: &i32, y: &i32| *x > 0 && *y > 0);
let boxed = conditional.into_box();
boxed.accept(&5, &3);
assert_eq!(*log.lock().unwrap(), vec![8]);
}
#[test]
fn test_conditional_into_fn() {
let log = Arc::new(Mutex::new(Vec::new()));
let l = log.clone();
let consumer = BoxBiConsumerOnce::new(move |x: &i32, y: &i32| {
l.lock().unwrap().push(*x + *y);
});
let conditional = consumer.when(|x: &i32, y: &i32| *x > 0 && *y > 0);
let func = conditional.into_fn();
func(&5, &3);
assert_eq!(*log.lock().unwrap(), vec![8]);
}
#[test]
fn test_conditional_into_box_false_branch() {
let log = Arc::new(Mutex::new(Vec::new()));
let l = log.clone();
let consumer = BoxBiConsumerOnce::new(move |x: &i32, y: &i32| {
l.lock().unwrap().push(*x + *y);
});
let conditional = consumer.when(|x: &i32, y: &i32| *x > 0 && *y > 0);
let boxed = conditional.into_box();
boxed.accept(&-5, &3);
assert_eq!(*log.lock().unwrap(), vec![]);
}
#[test]
fn test_conditional_into_fn_false_branch() {
let log = Arc::new(Mutex::new(Vec::new()));
let l = log.clone();
let consumer = BoxBiConsumerOnce::new(move |x: &i32, y: &i32| {
l.lock().unwrap().push(*x + *y);
});
let conditional = consumer.when(|x: &i32, y: &i32| *x > 0 && *y > 0);
let func = conditional.into_fn();
func(&-5, &3);
assert_eq!(*log.lock().unwrap(), vec![]);
}
#[test]
fn test_conditional_and_then() {
let log = Arc::new(Mutex::new(Vec::new()));
let l1 = log.clone();
let l2 = log.clone();
let consumer = BoxBiConsumerOnce::new(move |x: &i32, y: &i32| {
l1.lock().unwrap().push(*x + *y);
});
let conditional = consumer.when(|x: &i32, y: &i32| *x > 0 && *y > 0);
let chained = conditional.and_then(move |x: &i32, y: &i32| {
l2.lock().unwrap().push(*x * *y);
});
chained.accept(&5, &3);
assert_eq!(*log.lock().unwrap(), vec![8, 15]);
}
#[test]
fn test_box_consumer_once_into_box_identity() {
let log = Arc::new(Mutex::new(Vec::new()));
let l = log.clone();
let consumer = BoxBiConsumerOnce::new(move |x: &i32, y: &i32| {
l.lock().unwrap().push(*x + *y);
});
let boxed = consumer.into_box();
boxed.accept(&5, &3);
assert_eq!(*log.lock().unwrap(), vec![8]);
}
#[test]
fn test_box_consumer_once_into_fn_unwrap() {
let log = Arc::new(Mutex::new(Vec::new()));
let l = log.clone();
let consumer = BoxBiConsumerOnce::new(move |x: &i32, y: &i32| {
l.lock().unwrap().push(*x + *y);
});
let func = consumer.into_fn();
func(&5, &3);
assert_eq!(*log.lock().unwrap(), vec![8]);
}
}
#[cfg(test)]
mod closure_tests {
use super::*;
#[test]
fn test_closure_accept() {
let log = Arc::new(Mutex::new(Vec::new()));
let l = log.clone();
let closure = move |x: &i32, y: &i32| {
l.lock().unwrap().push(*x + *y);
};
closure.accept(&5, &3);
assert_eq!(*log.lock().unwrap(), vec![8]);
}
#[test]
fn test_closure_and_then() {
let log = Arc::new(Mutex::new(Vec::new()));
let l1 = log.clone();
let l2 = log.clone();
let chained = (move |x: &i32, y: &i32| {
l1.lock().unwrap().push(*x + *y);
})
.and_then(move |x: &i32, y: &i32| {
l2.lock().unwrap().push(*x * *y);
});
chained.accept(&5, &3);
assert_eq!(*log.lock().unwrap(), vec![8, 15]);
}
#[test]
fn test_closure_into_fn() {
let log = Arc::new(Mutex::new(Vec::new()));
let l = log.clone();
let closure = move |x: &i32, y: &i32| {
l.lock().unwrap().push(*x + *y);
};
let func = closure.into_fn();
func(&5, &3);
assert_eq!(*log.lock().unwrap(), vec![8]);
}
#[test]
fn test_closure_to_box() {
fn add_values(x: &i32, y: &i32) {
println!("Sum: {}", x + y);
}
let closure: fn(&i32, &i32) = add_values;
let box_consumer = closure.to_box();
box_consumer.accept(&5, &3);
let box_consumer2 = closure.to_box();
box_consumer2.accept(&10, &20);
}
#[test]
fn test_closure_to_fn() {
fn multiply_values(x: &i32, y: &i32) {
println!("Product: {}", x * y);
}
let closure: fn(&i32, &i32) = multiply_values;
let func = closure.to_fn();
func(&5, &3);
let func2 = closure.to_fn();
func2(&10, &20);
}
#[test]
fn test_closure_to_box_with_state() {
let log = Arc::new(Mutex::new(Vec::new()));
#[derive(Clone)]
struct LoggingConsumer {
log: Arc<Mutex<Vec<i32>>>,
}
impl LoggingConsumer {
fn consume(&self, x: &i32, y: &i32) {
self.log.lock().unwrap().push(*x + *y);
}
}
let consumer = LoggingConsumer { log: log.clone() };
let consumer_clone = consumer.clone();
let closure = move |x: &i32, y: &i32| consumer.consume(x, y);
let box_consumer = closure.to_box();
box_consumer.accept(&5, &3);
assert_eq!(*log.lock().unwrap(), vec![8]);
let closure2 = move |x: &i32, y: &i32| consumer_clone.consume(x, y);
let box_consumer2 = closure2.to_box();
box_consumer2.accept(&10, &20);
assert_eq!(*log.lock().unwrap(), vec![8, 30]);
}
#[test]
fn test_closure_to_fn_with_state() {
let log = Arc::new(Mutex::new(Vec::new()));
#[derive(Clone)]
struct LoggingConsumer {
log: Arc<Mutex<Vec<i32>>>,
}
impl LoggingConsumer {
fn consume(&self, x: &i32, y: &i32) {
self.log.lock().unwrap().push(*x * *y);
}
}
let consumer = LoggingConsumer { log: log.clone() };
let consumer_clone = consumer.clone();
let closure = move |x: &i32, y: &i32| consumer.consume(x, y);
let func = closure.to_fn();
func(&5, &3);
assert_eq!(*log.lock().unwrap(), vec![15]);
let closure2 = move |x: &i32, y: &i32| consumer_clone.consume(x, y);
let func2 = closure2.to_fn();
func2(&10, &20);
assert_eq!(*log.lock().unwrap(), vec![15, 200]);
}
}
#[cfg(test)]
mod debug_display_tests {
use super::*;
#[test]
fn test_debug() {
let consumer = BoxBiConsumerOnce::new(|_x: &i32, _y: &i32| {});
let debug_str = format!("{:?}", consumer);
assert!(debug_str.contains("BoxBiConsumerOnce"));
}
#[test]
fn test_debug_with_name() {
let mut consumer = BoxBiConsumerOnce::new(|_x: &i32, _y: &i32| {});
consumer.set_name("test_consumer");
let debug_str = format!("{:?}", consumer);
assert!(debug_str.contains("BoxBiConsumerOnce"));
assert!(debug_str.contains("test_consumer"));
}
#[test]
fn test_display() {
let consumer = BoxBiConsumerOnce::new(|_x: &i32, _y: &i32| {});
let display_str = format!("{}", consumer);
assert_eq!(display_str, "BoxBiConsumerOnce");
}
#[test]
fn test_display_with_name() {
let mut consumer = BoxBiConsumerOnce::new(|_x: &i32, _y: &i32| {});
consumer.set_name("my_consumer");
let display_str = format!("{}", consumer);
assert_eq!(display_str, "BoxBiConsumerOnce(my_consumer)");
}
#[test]
fn test_name_methods() {
let mut consumer = BoxBiConsumerOnce::new(|_x: &i32, _y: &i32| {});
assert_eq!(consumer.name(), None);
consumer.set_name("test");
assert_eq!(consumer.name(), Some("test"));
}
}
#[cfg(test)]
mod type_conversion_tests {
use super::*;
#[test]
fn test_box_into_box() {
let consumer = BoxBiConsumerOnce::new(|x: &i32, y: &i32| {
println!("x: {}, y: {}", x, y);
});
let boxed = consumer.into_box();
boxed.accept(&10, &20);
}
#[test]
fn test_box_into_fn() {
let consumer = BoxBiConsumerOnce::new(|x: &i32, y: &i32| {
println!("x: {}, y: {}", x, y);
});
let func = consumer.into_fn();
func(&10, &20);
}
#[test]
fn test_when_or_else_conversion() {
use std::sync::Arc;
use std::sync::Mutex;
let result = Arc::new(Mutex::new(0));
let result_clone1 = result.clone();
let result_clone2 = result.clone();
let consumer = BoxBiConsumerOnce::new(move |x: &i32, _y: &i32| {
*result_clone1.lock().unwrap() = *x;
})
.when(|x: &i32, y: &i32| x > y)
.or_else(move |_x: &i32, y: &i32| {
*result_clone2.lock().unwrap() = *y;
});
consumer.accept(&5, &3);
assert_eq!(*result.lock().unwrap(), 5);
}
}
#[cfg(test)]
mod default_implementation_tests {
use super::*;
struct CustomBiConsumerOnce {
log: Arc<Mutex<Vec<i32>>>,
multiplier: i32,
}
impl CustomBiConsumerOnce {
fn new(log: Arc<Mutex<Vec<i32>>>, multiplier: i32) -> Self {
Self { log, multiplier }
}
}
impl BiConsumerOnce<i32, i32> for CustomBiConsumerOnce {
fn accept(self, first: &i32, second: &i32) {
self.log
.lock()
.unwrap()
.push((*first + *second) * self.multiplier);
}
}
impl Clone for CustomBiConsumerOnce {
fn clone(&self) -> Self {
Self {
log: self.log.clone(),
multiplier: self.multiplier,
}
}
}
#[test]
fn test_custom_into_box() {
let log = Arc::new(Mutex::new(Vec::new()));
let consumer = CustomBiConsumerOnce::new(log.clone(), 2);
let boxed = consumer.into_box();
boxed.accept(&5, &3);
assert_eq!(*log.lock().unwrap(), vec![16]); }
#[test]
fn test_custom_into_fn() {
let log = Arc::new(Mutex::new(Vec::new()));
let consumer = CustomBiConsumerOnce::new(log.clone(), 3);
let func = consumer.into_fn();
func(&4, &2);
assert_eq!(*log.lock().unwrap(), vec![18]); }
#[test]
fn test_custom_to_box() {
let log = Arc::new(Mutex::new(Vec::new()));
let consumer = CustomBiConsumerOnce::new(log.clone(), 4);
let boxed = consumer.to_box();
boxed.accept(&3, &2);
assert_eq!(*log.lock().unwrap(), vec![20]);
consumer.accept(&1, &1);
assert_eq!(*log.lock().unwrap(), vec![20, 8]); }
#[test]
fn test_custom_to_fn() {
let log = Arc::new(Mutex::new(Vec::new()));
let consumer = CustomBiConsumerOnce::new(log.clone(), 5);
let func = consumer.to_fn();
func(&2, &3);
assert_eq!(*log.lock().unwrap(), vec![25]);
consumer.accept(&1, &0);
assert_eq!(*log.lock().unwrap(), vec![25, 5]); }
#[test]
fn test_custom_consumer_composition() {
let log = Arc::new(Mutex::new(Vec::new()));
let consumer1 = CustomBiConsumerOnce::new(log.clone(), 2);
let l2 = log.clone();
let chained = consumer1.into_box().and_then(move |x: &i32, y: &i32| {
l2.lock().unwrap().push(*x * *y);
});
chained.accept(&5, &3);
assert_eq!(*log.lock().unwrap(), vec![16, 15]); }
#[test]
fn test_custom_consumer_with_predicate() {
let log = Arc::new(Mutex::new(Vec::new()));
let consumer = CustomBiConsumerOnce::new(log.clone(), 10);
let conditional = consumer.into_box().when(|x: &i32, y: &i32| *x > *y);
conditional.accept(&5, &3);
assert_eq!(*log.lock().unwrap(), vec![80]);
let log2 = Arc::new(Mutex::new(Vec::new()));
let consumer2 = CustomBiConsumerOnce::new(log2.clone(), 10);
let conditional2 = consumer2.into_box().when(|x: &i32, y: &i32| *x > *y);
conditional2.accept(&3, &5);
assert_eq!(*log2.lock().unwrap(), vec![]); }
#[test]
fn test_custom_consumer_multiple_clones() {
let log = Arc::new(Mutex::new(Vec::new()));
let consumer = CustomBiConsumerOnce::new(log.clone(), 2);
let boxed1 = consumer.to_box();
let boxed2 = consumer.to_box();
let boxed3 = consumer.to_box();
boxed1.accept(&1, &1);
boxed2.accept(&2, &2);
boxed3.accept(&3, &3);
assert_eq!(*log.lock().unwrap(), vec![4, 8, 12]);
}
#[test]
fn test_custom_consumer_fn_multiple_uses() {
let log = Arc::new(Mutex::new(Vec::new()));
let consumer = CustomBiConsumerOnce::new(log.clone(), 3);
let fn1 = consumer.to_fn();
let fn2 = consumer.to_fn();
fn1(&2, &2);
fn2(&3, &3);
assert_eq!(*log.lock().unwrap(), vec![12, 18]);
}
}