use qubit_function::{
BoxConsumerOnce,
ConsumerOnce,
FnConsumerOnceOps,
};
use std::sync::{
Arc,
Mutex,
};
#[test]
fn test_consumer_once_default_conversions_allow_relaxed_generic_types() {
#[derive(Debug)]
struct BorrowedRc<'a> {
value: &'a str,
}
#[derive(Clone, Debug)]
struct BorrowedRcConsumerOnce;
impl<'a> ConsumerOnce<BorrowedRc<'a>> for BorrowedRcConsumerOnce {
fn accept(self, value: &BorrowedRc<'a>) {
assert_eq!(value.value, "left");
}
}
let text = String::from("left");
let value = BorrowedRc {
value: text.as_str(),
};
let consumer = BorrowedRcConsumerOnce;
consumer.clone().into_box().accept(&value);
consumer.clone().into_fn()(&value);
consumer.to_box().accept(&value);
consumer.to_fn()(&value);
}
#[cfg(test)]
mod box_consumer_once_tests {
use super::*;
#[test]
fn test_new() {
let log = Arc::new(Mutex::new(Vec::new()));
let l = log.clone();
let consumer = BoxConsumerOnce::new(move |x: &i32| {
l.lock().unwrap().push(*x);
});
consumer.accept(&5);
assert_eq!(*log.lock().unwrap(), vec![5]);
}
#[test]
fn test_accept() {
let log = Arc::new(Mutex::new(Vec::new()));
let l = log.clone();
let consumer = BoxConsumerOnce::new(move |x: &i32| {
l.lock().unwrap().push(*x * 2);
});
consumer.accept(&5);
assert_eq!(*log.lock().unwrap(), vec![10]);
}
#[test]
fn test_and_then() {
let log = Arc::new(Mutex::new(Vec::new()));
let l1 = log.clone();
let l2 = log.clone();
let chained = BoxConsumerOnce::new(move |x: &i32| {
l1.lock().unwrap().push(*x * 2);
})
.and_then(move |x: &i32| {
l2.lock().unwrap().push(*x + 10);
});
chained.accept(&5);
assert_eq!(*log.lock().unwrap(), vec![10, 15]);
}
#[test]
fn test_and_then_multiple() {
let log = Arc::new(Mutex::new(Vec::new()));
let l1 = log.clone();
let l2 = log.clone();
let l3 = log.clone();
let chained = BoxConsumerOnce::new(move |x: &i32| {
l1.lock().unwrap().push(*x * 2);
})
.and_then(move |x: &i32| {
l2.lock().unwrap().push(*x + 10);
})
.and_then(move |x: &i32| {
l3.lock().unwrap().push(*x - 1);
});
chained.accept(&5);
assert_eq!(*log.lock().unwrap(), vec![10, 15, 4]);
}
#[test]
fn test_noop() {
let noop = BoxConsumerOnce::<i32>::noop();
noop.accept(&42);
}
#[test]
fn test_new_with_name() {
let log = Arc::new(Mutex::new(Vec::new()));
let l = log.clone();
let consumer = BoxConsumerOnce::new_with_name("test_consumer", move |x: &i32| {
l.lock().unwrap().push(*x);
});
assert_eq!(consumer.name(), Some("test_consumer"));
consumer.accept(&5);
assert_eq!(*log.lock().unwrap(), vec![5]);
}
#[test]
fn test_if_then_true() {
let log = Arc::new(Mutex::new(Vec::new()));
let l = log.clone();
let consumer = BoxConsumerOnce::new(move |x: &i32| {
l.lock().unwrap().push(*x + 1);
});
let conditional = consumer.when(|x: &i32| *x > 0);
conditional.accept(&5);
assert_eq!(*log.lock().unwrap(), vec![6]);
}
#[test]
fn test_if_then_false() {
let log = Arc::new(Mutex::new(Vec::new()));
let l = log.clone();
let consumer = BoxConsumerOnce::new(move |x: &i32| {
l.lock().unwrap().push(*x + 1);
});
let conditional = consumer.when(|x: &i32| *x > 0);
conditional.accept(&-5);
assert_eq!(*log.lock().unwrap(), Vec::<i32>::new());
}
#[test]
fn test_if_then_else_true() {
let log = Arc::new(Mutex::new(Vec::new()));
let l1 = log.clone();
let l2 = log.clone();
let consumer = BoxConsumerOnce::new(move |x: &i32| {
l1.lock().unwrap().push(*x + 1);
});
let conditional = consumer.when(|x: &i32| *x > 0).or_else(move |x: &i32| {
l2.lock().unwrap().push(*x - 1);
});
conditional.accept(&5);
assert_eq!(*log.lock().unwrap(), vec![6]);
}
#[test]
fn test_if_then_else_false() {
let log = Arc::new(Mutex::new(Vec::new()));
let l1 = log.clone();
let l2 = log.clone();
let consumer = BoxConsumerOnce::new(move |x: &i32| {
l1.lock().unwrap().push(*x + 1);
});
let conditional = consumer.when(|x: &i32| *x > 0).or_else(move |x: &i32| {
l2.lock().unwrap().push(*x - 1);
});
conditional.accept(&-5);
assert_eq!(*log.lock().unwrap(), vec![-6]);
}
#[test]
fn test_into_box() {
let log = Arc::new(Mutex::new(Vec::new()));
let l = log.clone();
let consumer = BoxConsumerOnce::new(move |x: &i32| {
l.lock().unwrap().push(*x);
});
let boxed = consumer.into_box();
boxed.accept(&5);
assert_eq!(*log.lock().unwrap(), vec![5]);
}
#[test]
fn test_into_fn() {
let log = Arc::new(Mutex::new(Vec::new()));
let l = log.clone();
let consumer = BoxConsumerOnce::new(move |x: &i32| {
l.lock().unwrap().push(*x * 2);
});
let func = consumer.into_fn();
func(&5);
assert_eq!(*log.lock().unwrap(), vec![10]);
}
#[test]
fn test_into_fn_consumes_once() {
let log = Arc::new(Mutex::new(Vec::new()));
let l = log.clone();
let consumer = BoxConsumerOnce::new(move |x: &i32| {
l.lock().unwrap().push(*x * 2);
});
let func = consumer.into_fn();
func(&5);
assert_eq!(*log.lock().unwrap(), vec![10]);
}
}
#[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| {
l.lock().unwrap().push(*x * 2);
};
closure.accept(&5);
assert_eq!(*log.lock().unwrap(), vec![10]);
}
#[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| {
l1.lock().unwrap().push(*x * 2);
})
.and_then(move |x: &i32| {
l2.lock().unwrap().push(*x + 10);
});
chained.accept(&5);
assert_eq!(*log.lock().unwrap(), vec![10, 15]);
}
#[test]
fn test_closure_into_box() {
let log = Arc::new(Mutex::new(Vec::new()));
let l = log.clone();
let closure = move |x: &i32| {
l.lock().unwrap().push(*x * 2);
};
let boxed = closure.into_box();
boxed.accept(&5);
assert_eq!(*log.lock().unwrap(), vec![10]);
}
#[test]
fn test_closure_into_fn() {
let log = Arc::new(Mutex::new(Vec::new()));
let l = log.clone();
let closure = move |x: &i32| {
l.lock().unwrap().push(*x * 2);
};
let func = closure.into_fn();
func(&5);
assert_eq!(*log.lock().unwrap(), vec![10]);
}
#[test]
fn test_closure_multi_step_chaining() {
let log = Arc::new(Mutex::new(Vec::new()));
let l1 = log.clone();
let l2 = log.clone();
let l3 = log.clone();
let chained = (move |x: &i32| {
l1.lock().unwrap().push(*x * 2);
})
.and_then(move |x: &i32| {
l2.lock().unwrap().push(*x + 10);
})
.and_then(move |x: &i32| {
l3.lock().unwrap().push(*x / 2);
});
chained.accept(&5);
assert_eq!(*log.lock().unwrap(), vec![10, 15, 2]);
}
}
#[cfg(test)]
mod debug_display_tests {
use super::*;
#[test]
fn test_debug() {
let consumer = BoxConsumerOnce::new(|_x: &i32| {});
let debug_str = format!("{:?}", consumer);
assert!(debug_str.contains("BoxConsumerOnce"));
}
#[test]
fn test_display() {
let consumer = BoxConsumerOnce::new(|_x: &i32| {});
let display_str = format!("{}", consumer);
assert_eq!(display_str, "BoxConsumerOnce");
}
#[test]
fn test_display_with_name() {
let mut consumer = BoxConsumerOnce::new(|_x: &i32| {});
consumer.set_name("my_consumer");
let display_str = format!("{}", consumer);
assert_eq!(display_str, "BoxConsumerOnce(my_consumer)");
}
#[test]
fn test_name() {
let mut consumer = BoxConsumerOnce::new(|_x: &i32| {});
assert_eq!(consumer.name(), None);
consumer.set_name("test");
assert_eq!(consumer.name(), Some("test"));
}
#[test]
fn test_conditional_into_box() {
let log = Arc::new(Mutex::new(Vec::new()));
let l = log.clone();
let consumer = BoxConsumerOnce::new(move |x: &i32| {
l.lock().unwrap().push(*x);
});
let conditional = consumer.when(|x: &i32| *x > 0);
let boxed = conditional.into_box();
boxed.accept(&5);
assert_eq!(*log.lock().unwrap(), vec![5]);
}
#[test]
fn test_conditional_into_fn() {
let log = Arc::new(Mutex::new(Vec::new()));
let l = log.clone();
let consumer = BoxConsumerOnce::new(move |x: &i32| {
l.lock().unwrap().push(*x);
});
let conditional = consumer.when(|x: &i32| *x > 0);
let func = conditional.into_fn();
func(&5);
assert_eq!(*log.lock().unwrap(), vec![5]);
}
#[test]
fn test_conditional_and_then() {
let log = Arc::new(Mutex::new(Vec::new()));
let l1 = log.clone();
let l2 = log.clone();
let consumer = BoxConsumerOnce::new(move |x: &i32| {
l1.lock().unwrap().push(*x);
});
let conditional = consumer.when(|x: &i32| *x > 0);
let chained = conditional.and_then(move |x: &i32| {
l2.lock().unwrap().push(*x * 2);
});
chained.accept(&5);
assert_eq!(*log.lock().unwrap(), vec![5, 10]);
}
}
#[cfg(test)]
mod custom_consumer_once_tests {
use super::*;
struct CustomConsumer {
log: Arc<Mutex<Vec<i32>>>,
multiplier: i32,
}
impl CustomConsumer {
fn new(log: Arc<Mutex<Vec<i32>>>, multiplier: i32) -> Self {
Self { log, multiplier }
}
}
impl ConsumerOnce<i32> for CustomConsumer {
fn accept(self, value: &i32) {
self.log.lock().unwrap().push(*value * self.multiplier);
}
}
#[test]
fn test_custom_consumer_accept() {
let log = Arc::new(Mutex::new(Vec::new()));
let consumer = CustomConsumer::new(log.clone(), 3);
consumer.accept(&5);
assert_eq!(*log.lock().unwrap(), vec![15]);
}
#[test]
fn test_custom_consumer_into_box() {
let log = Arc::new(Mutex::new(Vec::new()));
let consumer = CustomConsumer::new(log.clone(), 2);
let boxed = consumer.into_box();
boxed.accept(&7);
assert_eq!(*log.lock().unwrap(), vec![14]);
}
#[test]
fn test_custom_consumer_into_fn() {
let log = Arc::new(Mutex::new(Vec::new()));
let consumer = CustomConsumer::new(log.clone(), 4);
let func = consumer.into_fn();
func(&3);
assert_eq!(*log.lock().unwrap(), vec![12]);
}
#[test]
fn test_custom_consumer_into_box_chaining() {
let log = Arc::new(Mutex::new(Vec::new()));
let l1 = log.clone();
let l2 = log.clone();
let consumer = CustomConsumer::new(l1, 2);
let boxed = consumer.into_box();
let chained = boxed.and_then(move |x: &i32| {
l2.lock().unwrap().push(*x + 100);
});
chained.accept(&5);
assert_eq!(*log.lock().unwrap(), vec![10, 105]);
}
#[test]
fn test_custom_consumer_with_generic_function() {
let log = Arc::new(Mutex::new(Vec::new()));
fn process_with_consumer<C>(consumer: C, value: &i32)
where
C: ConsumerOnce<i32>,
{
consumer.accept(value);
}
let consumer = CustomConsumer::new(log.clone(), 5);
process_with_consumer(consumer, &6);
assert_eq!(*log.lock().unwrap(), vec![30]);
}
#[test]
fn test_custom_consumer_into_box_with_generic_function() {
let log = Arc::new(Mutex::new(Vec::new()));
fn process_with_box_consumer(consumer: BoxConsumerOnce<i32>, value: &i32) {
consumer.accept(value);
}
let consumer = CustomConsumer::new(log.clone(), 3);
let boxed = consumer.into_box();
process_with_box_consumer(boxed, &8);
assert_eq!(*log.lock().unwrap(), vec![24]);
}
#[test]
fn test_multiple_custom_consumers_chained() {
let log = Arc::new(Mutex::new(Vec::new()));
let l1 = log.clone();
let l2 = log.clone();
let consumer1 = CustomConsumer::new(l1, 2);
let consumer2 = CustomConsumer::new(l2, 3);
let chained = consumer1.into_box().and_then(consumer2.into_box());
chained.accept(&5);
assert_eq!(*log.lock().unwrap(), vec![10, 15]);
}
struct StringLogger {
log: Arc<Mutex<Vec<String>>>,
prefix: String,
}
impl StringLogger {
fn new(log: Arc<Mutex<Vec<String>>>, prefix: impl Into<String>) -> Self {
Self {
log,
prefix: prefix.into(),
}
}
}
impl ConsumerOnce<String> for StringLogger {
fn accept(self, value: &String) {
self.log
.lock()
.unwrap()
.push(format!("{}{}", self.prefix, value));
}
}
#[test]
fn test_custom_string_consumer_into_box() {
let log = Arc::new(Mutex::new(Vec::new()));
let consumer = StringLogger::new(log.clone(), "Log: ");
let boxed = consumer.into_box();
boxed.accept(&"Hello".to_string());
assert_eq!(*log.lock().unwrap(), vec!["Log: Hello".to_string()]);
}
#[test]
fn test_custom_string_consumer_into_fn() {
let log = Arc::new(Mutex::new(Vec::new()));
let consumer = StringLogger::new(log.clone(), "Info: ");
let func = consumer.into_fn();
func(&"World".to_string());
assert_eq!(*log.lock().unwrap(), vec!["Info: World".to_string()]);
}
struct CountingConsumer {
counter: Arc<Mutex<usize>>,
value_log: Arc<Mutex<Vec<i32>>>,
}
impl CountingConsumer {
fn new(counter: Arc<Mutex<usize>>, value_log: Arc<Mutex<Vec<i32>>>) -> Self {
Self { counter, value_log }
}
}
impl ConsumerOnce<i32> for CountingConsumer {
fn accept(self, value: &i32) {
*self.counter.lock().unwrap() += 1;
self.value_log.lock().unwrap().push(*value);
}
}
#[test]
fn test_counting_consumer_into_box() {
let counter = Arc::new(Mutex::new(0));
let log = Arc::new(Mutex::new(Vec::new()));
let consumer = CountingConsumer::new(counter.clone(), log.clone());
let boxed = consumer.into_box();
boxed.accept(&42);
assert_eq!(*counter.lock().unwrap(), 1);
assert_eq!(*log.lock().unwrap(), vec![42]);
}
#[test]
fn test_counting_consumer_into_fn() {
let counter = Arc::new(Mutex::new(0));
let log = Arc::new(Mutex::new(Vec::new()));
let consumer = CountingConsumer::new(counter.clone(), log.clone());
let func = consumer.into_fn();
func(&99);
assert_eq!(*counter.lock().unwrap(), 1);
assert_eq!(*log.lock().unwrap(), vec![99]);
}
}
#[cfg(test)]
mod box_conditional_consumer_once_tests {
use super::*;
#[test]
fn test_accept_predicate_false() {
let log = Arc::new(Mutex::new(Vec::new()));
let l = log.clone();
let consumer = BoxConsumerOnce::new(move |x: &i32| {
l.lock().unwrap().push(*x);
});
let conditional = consumer.when(|x: &i32| *x > 0);
conditional.accept(&-5);
assert_eq!(*log.lock().unwrap(), Vec::<i32>::new());
}
#[test]
fn test_accept_predicate_true() {
let log = Arc::new(Mutex::new(Vec::new()));
let l = log.clone();
let consumer = BoxConsumerOnce::new(move |x: &i32| {
l.lock().unwrap().push(*x);
});
let conditional = consumer.when(|x: &i32| *x > 0);
conditional.accept(&5);
assert_eq!(*log.lock().unwrap(), vec![5]);
}
#[test]
fn test_accept_predicate_boundary() {
let log = Arc::new(Mutex::new(Vec::new()));
let l = log.clone();
let consumer = BoxConsumerOnce::new(move |x: &i32| {
l.lock().unwrap().push(*x);
});
let conditional = consumer.when(|x: &i32| *x > 0);
conditional.accept(&0);
assert_eq!(*log.lock().unwrap(), Vec::<i32>::new());
}
#[test]
fn test_into_box_predicate_true() {
let log = Arc::new(Mutex::new(Vec::new()));
let l = log.clone();
let consumer = BoxConsumerOnce::new(move |x: &i32| {
l.lock().unwrap().push(*x);
});
let conditional = consumer.when(|x: &i32| *x > 0);
let boxed = conditional.into_box();
boxed.accept(&5);
assert_eq!(*log.lock().unwrap(), vec![5]);
}
#[test]
fn test_into_box_predicate_false() {
let log = Arc::new(Mutex::new(Vec::new()));
let l = log.clone();
let consumer = BoxConsumerOnce::new(move |x: &i32| {
l.lock().unwrap().push(*x);
});
let conditional = consumer.when(|x: &i32| *x > 0);
let boxed = conditional.into_box();
boxed.accept(&-5);
assert_eq!(*log.lock().unwrap(), Vec::<i32>::new());
}
#[test]
fn test_into_box_predicate_boundary() {
let log = Arc::new(Mutex::new(Vec::new()));
let l = log.clone();
let consumer = BoxConsumerOnce::new(move |x: &i32| {
l.lock().unwrap().push(*x);
});
let conditional = consumer.when(|x: &i32| *x > 0);
let boxed = conditional.into_box();
boxed.accept(&0);
assert_eq!(*log.lock().unwrap(), Vec::<i32>::new());
}
#[test]
fn test_into_fn_predicate_true() {
let log = Arc::new(Mutex::new(Vec::new()));
let l = log.clone();
let consumer = BoxConsumerOnce::new(move |x: &i32| {
l.lock().unwrap().push(*x);
});
let conditional = consumer.when(|x: &i32| *x > 0);
let func = conditional.into_fn();
func(&5);
assert_eq!(*log.lock().unwrap(), vec![5]);
}
#[test]
fn test_into_fn_predicate_false() {
let log = Arc::new(Mutex::new(Vec::new()));
let l = log.clone();
let consumer = BoxConsumerOnce::new(move |x: &i32| {
l.lock().unwrap().push(*x);
});
let conditional = consumer.when(|x: &i32| *x > 0);
let func = conditional.into_fn();
func(&-5);
assert_eq!(*log.lock().unwrap(), Vec::<i32>::new());
}
#[test]
fn test_into_fn_predicate_boundary() {
let log = Arc::new(Mutex::new(Vec::new()));
let l = log.clone();
let consumer = BoxConsumerOnce::new(move |x: &i32| {
l.lock().unwrap().push(*x);
});
let conditional = consumer.when(|x: &i32| *x > 0);
let func = conditional.into_fn();
func(&0);
assert_eq!(*log.lock().unwrap(), Vec::<i32>::new());
}
#[test]
fn test_into_box_complex_predicate() {
let log = Arc::new(Mutex::new(Vec::new()));
let l = log.clone();
let consumer = BoxConsumerOnce::new(move |x: &i32| {
l.lock().unwrap().push(*x * 2);
});
let conditional = consumer.when(|x: &i32| *x % 2 == 0);
let boxed = conditional.into_box();
boxed.accept(&4);
assert_eq!(*log.lock().unwrap(), vec![8]);
}
#[test]
fn test_into_box_complex_predicate_false() {
let log = Arc::new(Mutex::new(Vec::new()));
let l = log.clone();
let consumer = BoxConsumerOnce::new(move |x: &i32| {
l.lock().unwrap().push(*x * 2);
});
let conditional = consumer.when(|x: &i32| *x % 2 == 0);
let boxed = conditional.into_box();
boxed.accept(&3);
assert_eq!(*log.lock().unwrap(), Vec::<i32>::new());
}
#[test]
fn test_into_fn_complex_predicate() {
let log = Arc::new(Mutex::new(Vec::new()));
let l = log.clone();
let consumer = BoxConsumerOnce::new(move |x: &i32| {
l.lock().unwrap().push(*x * 2);
});
let conditional = consumer.when(|x: &i32| *x % 2 == 0);
let func = conditional.into_fn();
func(&4);
assert_eq!(*log.lock().unwrap(), vec![8]);
}
#[test]
fn test_into_fn_complex_predicate_false() {
let log = Arc::new(Mutex::new(Vec::new()));
let l = log.clone();
let consumer = BoxConsumerOnce::new(move |x: &i32| {
l.lock().unwrap().push(*x * 2);
});
let conditional = consumer.when(|x: &i32| *x % 2 == 0);
let func = conditional.into_fn();
func(&3);
assert_eq!(*log.lock().unwrap(), Vec::<i32>::new());
}
#[test]
fn test_accept_with_always_true_predicate() {
let log = Arc::new(Mutex::new(Vec::new()));
let l = log.clone();
let consumer = BoxConsumerOnce::new(move |x: &i32| {
l.lock().unwrap().push(*x);
});
let conditional = consumer.when(|_: &i32| true);
conditional.accept(&42);
assert_eq!(*log.lock().unwrap(), vec![42]);
}
#[test]
fn test_accept_with_always_false_predicate() {
let log = Arc::new(Mutex::new(Vec::new()));
let l = log.clone();
let consumer = BoxConsumerOnce::new(move |x: &i32| {
l.lock().unwrap().push(*x);
});
let conditional = consumer.when(|_: &i32| false);
conditional.accept(&42);
assert_eq!(*log.lock().unwrap(), Vec::<i32>::new());
}
#[test]
fn test_accept_with_complex_predicate_logic() {
let log = Arc::new(Mutex::new(Vec::new()));
let l = log.clone();
let consumer = BoxConsumerOnce::new(move |x: &i32| {
l.lock().unwrap().push(*x * 10);
});
let conditional = consumer.when(|x: &i32| *x > 0 && *x % 2 == 0);
conditional.accept(&4);
assert_eq!(*log.lock().unwrap(), vec![40]);
}
#[test]
fn test_accept_with_complex_predicate_logic_fails() {
let log = Arc::new(Mutex::new(Vec::new()));
let l = log.clone();
let consumer = BoxConsumerOnce::new(move |x: &i32| {
l.lock().unwrap().push(*x * 10);
});
let conditional = consumer.when(|x: &i32| *x > 0 && *x % 2 == 0);
conditional.accept(&3);
assert_eq!(*log.lock().unwrap(), Vec::<i32>::new());
}
#[test]
fn test_accept_with_complex_predicate_logic_fails_negative() {
let log = Arc::new(Mutex::new(Vec::new()));
let l = log.clone();
let consumer = BoxConsumerOnce::new(move |x: &i32| {
l.lock().unwrap().push(*x * 10);
});
let conditional = consumer.when(|x: &i32| *x > 0 && *x % 2 == 0);
conditional.accept(&-4);
assert_eq!(*log.lock().unwrap(), Vec::<i32>::new());
}
#[test]
fn test_and_then_predicate_true() {
let log = Arc::new(Mutex::new(Vec::new()));
let l1 = log.clone();
let l2 = log.clone();
let conditional = BoxConsumerOnce::new(move |x: &i32| {
l1.lock().unwrap().push(*x);
})
.when(|x: &i32| *x > 0);
let chained = conditional.and_then(move |x: &i32| {
l2.lock().unwrap().push(*x * 2);
});
chained.accept(&5);
assert_eq!(*log.lock().unwrap(), vec![5, 10]);
}
#[test]
fn test_and_then_predicate_false() {
let log = Arc::new(Mutex::new(Vec::new()));
let l1 = log.clone();
let l2 = log.clone();
let conditional = BoxConsumerOnce::new(move |x: &i32| {
l1.lock().unwrap().push(*x);
})
.when(|x: &i32| *x > 0);
let chained = conditional.and_then(move |x: &i32| {
l2.lock().unwrap().push(*x * 2);
});
chained.accept(&-5);
assert_eq!(*log.lock().unwrap(), vec![-10]);
}
#[test]
fn test_and_then_multiple_conditionals() {
let log = Arc::new(Mutex::new(Vec::new()));
let l1 = log.clone();
let l2 = log.clone();
let l3 = log.clone();
let conditional1 = BoxConsumerOnce::new(move |x: &i32| {
l1.lock().unwrap().push(*x);
})
.when(|x: &i32| *x > 0);
let conditional2 = BoxConsumerOnce::new(move |x: &i32| {
l2.lock().unwrap().push(*x * 2);
})
.when(|x: &i32| *x % 2 == 0);
let chained = conditional1
.and_then(conditional2)
.and_then(move |x: &i32| {
l3.lock().unwrap().push(*x + 100);
});
chained.accept(&6);
assert_eq!(*log.lock().unwrap(), vec![6, 12, 106]);
}
}
#[cfg(test)]
mod custom_consumer_to_methods_tests {
use super::*;
#[derive(Clone)]
struct CloneableConsumer {
log: Arc<Mutex<Vec<i32>>>,
multiplier: i32,
}
impl CloneableConsumer {
fn new(log: Arc<Mutex<Vec<i32>>>, multiplier: i32) -> Self {
Self { log, multiplier }
}
}
impl ConsumerOnce<i32> for CloneableConsumer {
fn accept(self, value: &i32) {
self.log.lock().unwrap().push(*value * self.multiplier);
}
}
#[test]
fn test_custom_consumer_to_box() {
let log = Arc::new(Mutex::new(Vec::new()));
let consumer = CloneableConsumer::new(log.clone(), 2);
let boxed = consumer.to_box();
boxed.accept(&7);
assert_eq!(*log.lock().unwrap(), vec![14]);
}
#[test]
fn test_custom_consumer_to_box_multiple_times() {
let log = Arc::new(Mutex::new(Vec::new()));
let consumer = CloneableConsumer::new(log.clone(), 3);
let boxed1 = consumer.to_box();
let boxed2 = consumer.to_box();
boxed1.accept(&5);
boxed2.accept(&6);
assert_eq!(*log.lock().unwrap(), vec![15, 18]);
}
#[test]
fn test_custom_consumer_to_box_original_still_usable() {
let log = Arc::new(Mutex::new(Vec::new()));
let consumer = CloneableConsumer::new(log.clone(), 2);
let boxed = consumer.to_box();
boxed.accept(&5);
consumer.accept(&10);
assert_eq!(*log.lock().unwrap(), vec![10, 20]);
}
#[test]
fn test_custom_consumer_to_fn() {
let log = Arc::new(Mutex::new(Vec::new()));
let consumer = CloneableConsumer::new(log.clone(), 4);
let func = consumer.to_fn();
func(&3);
assert_eq!(*log.lock().unwrap(), vec![12]);
}
#[test]
fn test_custom_consumer_to_fn_original_still_usable() {
let log = Arc::new(Mutex::new(Vec::new()));
let consumer = CloneableConsumer::new(log.clone(), 2);
let func = consumer.to_fn();
func(&5);
consumer.accept(&10);
assert_eq!(*log.lock().unwrap(), vec![10, 20]);
}
#[test]
fn test_custom_consumer_to_box_chaining() {
let log = Arc::new(Mutex::new(Vec::new()));
let l1 = log.clone();
let l2 = log.clone();
let consumer = CloneableConsumer::new(l1, 2);
let boxed = consumer.to_box();
let chained = boxed.and_then(move |x: &i32| {
l2.lock().unwrap().push(*x + 100);
});
chained.accept(&5);
assert_eq!(*log.lock().unwrap(), vec![10, 105]);
}
}
#[cfg(test)]
mod closure_to_methods_tests {
use super::*;
#[test]
fn test_closure_to_box_requires_clone() {
let log = Arc::new(Mutex::new(Vec::new()));
let _l = log.clone();
#[derive(Clone)]
struct ClonableClosure {
log: Arc<Mutex<Vec<i32>>>,
multiplier: i32,
}
impl ConsumerOnce<i32> for ClonableClosure {
fn accept(self, value: &i32) {
self.log.lock().unwrap().push(*value * self.multiplier);
}
}
let log_clone = log.clone();
let consumer = ClonableClosure {
log: log_clone,
multiplier: 2,
};
let boxed = consumer.to_box();
boxed.accept(&5);
assert_eq!(*log.lock().unwrap(), vec![10]);
}
#[test]
fn test_closure_into_box_works_without_clone() {
let log = Arc::new(Mutex::new(Vec::new()));
let l = log.clone();
let closure = move |x: &i32| {
l.lock().unwrap().push(*x * 2);
};
let boxed = closure.into_box();
boxed.accept(&5);
assert_eq!(*log.lock().unwrap(), vec![10]);
}
#[test]
fn test_closure_into_fn_works_without_clone() {
let log = Arc::new(Mutex::new(Vec::new()));
let l = log.clone();
let closure = move |x: &i32| {
l.lock().unwrap().push(*x * 2);
};
let func = closure.into_fn();
func(&5);
assert_eq!(*log.lock().unwrap(), vec![10]);
}
#[test]
fn test_closure_state_capture_in_to_box_wrapper() {
let log = Arc::new(Mutex::new(Vec::new()));
let l = log.clone();
#[derive(Clone)]
struct ClosureWrapper<F: Clone + Fn(&i32)> {
f: F,
log: Arc<Mutex<Vec<i32>>>,
}
impl<F: Clone + Fn(&i32)> ConsumerOnce<i32> for ClosureWrapper<F> {
fn accept(self, value: &i32) {
(self.f)(value);
self.log.lock().unwrap().push(*value);
}
}
let wrapper = ClosureWrapper {
f: |x: &i32| println!("Value: {}", x),
log: l,
};
let boxed = wrapper.to_box();
boxed.accept(&5);
assert_eq!(*log.lock().unwrap(), vec![5]);
}
#[test]
#[ignore] fn test_closure_to_box_does_not_compile() {
let log = Arc::new(Mutex::new(Vec::new()));
let l = log.clone();
let closure = move |x: &i32| {
l.lock().unwrap().push(*x * 2);
};
let boxed = closure.into_box();
boxed.accept(&5);
assert_eq!(*log.lock().unwrap(), vec![10]);
}
}
#[cfg(test)]
mod closure_to_xxx_methods_tests {
use super::*;
#[test]
fn test_closure_fnonce_into_box() {
let log = Arc::new(Mutex::new(Vec::new()));
let l = log.clone();
let closure = move |x: &i32| {
l.lock().unwrap().push(*x * 3);
};
let boxed = closure.into_box();
boxed.accept(&7);
assert_eq!(*log.lock().unwrap(), vec![21]);
}
#[test]
fn test_closure_fnonce_into_fn() {
let log = Arc::new(Mutex::new(Vec::new()));
let l = log.clone();
let closure = move |x: &i32| {
l.lock().unwrap().push(*x + 100);
};
let func = closure.into_fn();
func(&5);
assert_eq!(*log.lock().unwrap(), vec![105]);
}
#[test]
fn test_closure_fnonce_ops_and_then() {
let log = Arc::new(Mutex::new(Vec::new()));
let l1 = log.clone();
let l2 = log.clone();
let chained = (move |x: &i32| {
l1.lock().unwrap().push(*x * 2);
})
.and_then(move |x: &i32| {
l2.lock().unwrap().push(*x + 50);
});
chained.accept(&5);
assert_eq!(*log.lock().unwrap(), vec![10, 55]);
}
#[test]
fn test_closure_fnonce_ops_multiple_and_then() {
let log = Arc::new(Mutex::new(Vec::new()));
let l1 = log.clone();
let l2 = log.clone();
let l3 = log.clone();
let chained = (move |x: &i32| {
l1.lock().unwrap().push(*x * 2);
})
.and_then(move |x: &i32| {
l2.lock().unwrap().push(*x + 10);
})
.and_then(move |x: &i32| {
l3.lock().unwrap().push(*x * 3);
});
chained.accept(&5);
assert_eq!(*log.lock().unwrap(), vec![10, 15, 15]);
}
#[test]
fn test_closure_into_box_with_when() {
let log = Arc::new(Mutex::new(Vec::new()));
let l = log.clone();
let closure = move |x: &i32| {
l.lock().unwrap().push(*x);
};
let boxed = closure.into_box();
let conditional = boxed.when(|x: &i32| *x > 0);
conditional.accept(&5);
assert_eq!(*log.lock().unwrap(), vec![5]);
}
#[test]
fn test_closure_into_box_with_when_false() {
let log = Arc::new(Mutex::new(Vec::new()));
let l = log.clone();
let closure = move |x: &i32| {
l.lock().unwrap().push(*x);
};
let boxed = closure.into_box();
let conditional = boxed.when(|x: &i32| *x > 0);
conditional.accept(&-5);
assert_eq!(*log.lock().unwrap(), Vec::<i32>::new());
}
#[test]
fn test_closure_into_box_with_or_else() {
let log = Arc::new(Mutex::new(Vec::new()));
let l1 = log.clone();
let l2 = log.clone();
let closure = move |x: &i32| {
l1.lock().unwrap().push(*x);
};
let boxed = closure.into_box();
let conditional = boxed.when(|x: &i32| *x > 0).or_else(move |x: &i32| {
l2.lock().unwrap().push(-*x);
});
conditional.accept(&-5);
assert_eq!(*log.lock().unwrap(), vec![5]); }
#[test]
fn test_closure_chain_then_conditional() {
let log = Arc::new(Mutex::new(Vec::new()));
let l1 = log.clone();
let l2 = log.clone();
let chained = (move |x: &i32| {
l1.lock().unwrap().push(*x * 2);
})
.and_then(move |x: &i32| {
l2.lock().unwrap().push(*x + 10);
});
let boxed = chained;
let conditional = boxed.when(|x: &i32| *x < 15);
conditional.accept(&5);
assert_eq!(*log.lock().unwrap(), vec![10, 15]); }
#[test]
fn test_closure_vs_noop() {
let log = Arc::new(Mutex::new(Vec::new()));
let l = log.clone();
let closure = move |x: &i32| {
l.lock().unwrap().push(*x);
};
let boxed = closure.into_box();
boxed.accept(&5);
let noop = BoxConsumerOnce::<i32>::noop();
noop.accept(&10);
assert_eq!(*log.lock().unwrap(), vec![5]);
}
#[test]
fn test_closure_into_box_preserves_behavior() {
let log = Arc::new(Mutex::new(Vec::new()));
let l1 = log.clone();
let l2 = log.clone();
let closure1 = move |x: &i32| {
l1.lock().unwrap().push(*x);
};
let closure2 = move |x: &i32| {
l2.lock().unwrap().push(*x);
};
let boxed1 = closure1.into_box();
boxed1.accept(&5);
closure2.accept(&5);
assert_eq!(*log.lock().unwrap(), vec![5, 5]);
}
#[test]
fn test_closure_into_fn_is_fnonce() {
let log = Arc::new(Mutex::new(Vec::new()));
let l = log.clone();
let closure = move |x: &i32| {
l.lock().unwrap().push(*x * 2);
};
let func = closure.into_fn();
func(&5);
assert_eq!(*log.lock().unwrap(), vec![10]);
}
#[test]
fn test_complex_closure_capture() {
let log = Arc::new(Mutex::new(Vec::new()));
let multiplier = 5;
let addition = 10;
let l = log.clone();
let closure = move |x: &i32| {
l.lock().unwrap().push(*x * multiplier + addition);
};
let boxed = closure.into_box();
boxed.accept(&3);
assert_eq!(*log.lock().unwrap(), vec![25]); }
#[test]
fn test_closure_into_box_with_string() {
let log = Arc::new(Mutex::new(Vec::new()));
let l = log.clone();
let closure = move |s: &String| {
l.lock().unwrap().push(s.clone());
};
let boxed = closure.into_box();
boxed.accept(&"Hello".to_string());
assert_eq!(*log.lock().unwrap(), vec!["Hello".to_string()]);
}
#[test]
fn test_fn_pointer_to_box() {
use std::sync::atomic::{
AtomicUsize,
Ordering,
};
static COUNTER: AtomicUsize = AtomicUsize::new(0);
fn increment_counter(_x: &i32) {
COUNTER.fetch_add(1, Ordering::SeqCst);
}
let boxed = increment_counter.to_box();
boxed.accept(&1);
assert_eq!(COUNTER.load(Ordering::SeqCst), 1);
}
#[test]
fn test_fn_pointer_to_fn() {
use std::sync::atomic::{
AtomicUsize,
Ordering,
};
static COUNTER: AtomicUsize = AtomicUsize::new(0);
fn increment_counter(_x: &i32) {
COUNTER.fetch_add(1, Ordering::SeqCst);
}
let func = increment_counter.to_fn();
func(&1);
assert_eq!(COUNTER.load(Ordering::SeqCst), 1);
}
#[test]
fn test_fn_pointer_to_box_preserves_original() {
use std::sync::atomic::{
AtomicUsize,
Ordering,
};
static COUNTER2: AtomicUsize = AtomicUsize::new(0);
fn increment_counter2(_x: &i32) {
COUNTER2.fetch_add(1, Ordering::SeqCst);
}
let boxed = increment_counter2.to_box();
boxed.accept(&1);
increment_counter2.accept(&2);
assert_eq!(COUNTER2.load(Ordering::SeqCst), 2);
}
#[test]
fn test_fn_pointer_to_fn_preserves_original() {
use std::sync::atomic::{
AtomicUsize,
Ordering,
};
static COUNTER3: AtomicUsize = AtomicUsize::new(0);
fn increment_counter3(_x: &i32) {
COUNTER3.fetch_add(1, Ordering::SeqCst);
}
let func = increment_counter3.to_fn();
func(&1);
increment_counter3.accept(&2);
assert_eq!(COUNTER3.load(Ordering::SeqCst), 2);
}
#[test]
fn test_fn_pointer_to_box_multiple_times() {
use std::sync::atomic::{
AtomicUsize,
Ordering,
};
static COUNTER4: AtomicUsize = AtomicUsize::new(0);
fn increment_counter4(_x: &i32) {
COUNTER4.fetch_add(1, Ordering::SeqCst);
}
let boxed1 = increment_counter4.to_box();
let boxed2 = increment_counter4.to_box();
boxed1.accept(&1);
boxed2.accept(&2);
assert_eq!(COUNTER4.load(Ordering::SeqCst), 2);
}
#[test]
fn test_fn_pointer_to_fn_multiple_times() {
use std::sync::atomic::{
AtomicUsize,
Ordering,
};
static COUNTER5: AtomicUsize = AtomicUsize::new(0);
fn increment_counter5(_x: &i32) {
COUNTER5.fetch_add(1, Ordering::SeqCst);
}
let func1 = increment_counter5.to_fn();
let func2 = increment_counter5.to_fn();
func1(&1);
func2(&2);
assert_eq!(COUNTER5.load(Ordering::SeqCst), 2);
}
}
#[cfg(test)]
mod advanced_to_methods_tests {
use super::*;
#[derive(Clone)]
struct CountingCloneableConsumer {
log: Arc<Mutex<Vec<i32>>>,
}
impl CountingCloneableConsumer {
fn new(log: Arc<Mutex<Vec<i32>>>) -> Self {
Self { log }
}
}
impl ConsumerOnce<i32> for CountingCloneableConsumer {
fn accept(self, value: &i32) {
self.log.lock().unwrap().push(*value);
}
}
#[test]
fn test_to_box_then_chain_and_then() {
let log = Arc::new(Mutex::new(Vec::new()));
let l1 = log.clone();
let l2 = log.clone();
let consumer = CountingCloneableConsumer::new(l1);
let boxed = consumer.to_box();
let chained = boxed.and_then(move |x: &i32| {
l2.lock().unwrap().push(*x * 2);
});
chained.accept(&5);
assert_eq!(*log.lock().unwrap(), vec![5, 10]);
}
#[test]
fn test_to_fn_then_call() {
let log = Arc::new(Mutex::new(Vec::new()));
let consumer = CountingCloneableConsumer::new(log.clone());
let func = consumer.to_fn();
func(&7);
assert_eq!(*log.lock().unwrap(), vec![7]);
}
#[test]
fn test_to_box_preserves_original_for_reuse() {
let log = Arc::new(Mutex::new(Vec::new()));
let consumer = CountingCloneableConsumer::new(log.clone());
let boxed1 = consumer.to_box();
let boxed2 = consumer.to_box();
boxed1.accept(&1);
boxed2.accept(&2);
consumer.accept(&3);
assert_eq!(*log.lock().unwrap(), vec![1, 2, 3]);
}
#[test]
fn test_to_fn_preserves_original_for_reuse() {
let log = Arc::new(Mutex::new(Vec::new()));
let consumer = CountingCloneableConsumer::new(log.clone());
let func1 = consumer.to_fn();
let func2 = consumer.to_fn();
func1(&10);
func2(&20);
consumer.accept(&30);
assert_eq!(*log.lock().unwrap(), vec![10, 20, 30]);
}
#[test]
fn test_default_trait_implementation_via_to_box() {
let log = Arc::new(Mutex::new(Vec::new()));
#[derive(Clone)]
struct SimpleConsumer {
multiplier: i32,
log: Arc<Mutex<Vec<i32>>>,
}
impl ConsumerOnce<i32> for SimpleConsumer {
fn accept(self, value: &i32) {
self.log.lock().unwrap().push(*value * self.multiplier);
}
}
let consumer = SimpleConsumer {
multiplier: 5,
log: log.clone(),
};
let boxed = consumer.to_box();
boxed.accept(&4);
assert_eq!(*log.lock().unwrap(), vec![20]);
}
#[test]
fn test_default_trait_implementation_via_to_fn() {
let log = Arc::new(Mutex::new(Vec::new()));
#[derive(Clone)]
struct SimpleConsumer {
multiplier: i32,
log: Arc<Mutex<Vec<i32>>>,
}
impl ConsumerOnce<i32> for SimpleConsumer {
fn accept(self, value: &i32) {
self.log.lock().unwrap().push(*value * self.multiplier);
}
}
let consumer = SimpleConsumer {
multiplier: 3,
log: log.clone(),
};
let func = consumer.to_fn();
func(&6);
assert_eq!(*log.lock().unwrap(), vec![18]);
}
}