use qubit_function::{
BoxFunctionOnce,
FunctionOnce,
Predicate,
RcPredicate,
};
#[test]
fn test_function_once_trait_apply() {
let double = |x: &i32| x * 2;
assert_eq!(double.apply(&21), 42);
}
#[test]
fn test_function_once_trait_apply_with_move() {
let value = String::from("hello");
let append = move |s: &String| format!("{} {}", s, value);
assert_eq!(append.apply(&String::from("world")), "world hello");
}
#[test]
fn test_function_once_trait_into_box() {
let double = |x: &i32| x * 2;
let boxed = double.into_box();
assert_eq!(boxed.apply(&21), 42);
}
#[test]
fn test_function_once_trait_into_fn() {
let double = |x: &i32| x * 2;
let func = double.into_fn();
assert_eq!(func(&21), 42);
}
#[test]
fn test_function_once_trait_to_box() {
let double = |x: &i32| x * 2;
let boxed = double.to_box();
assert_eq!(boxed.apply(&21), 42);
assert_eq!(double.apply(&10), 20);
}
#[test]
fn test_function_once_trait_to_fn() {
let double = |x: &i32| x * 2;
let func = double.to_fn();
assert_eq!(func(&21), 42);
assert_eq!(double.apply(&10), 20);
}
#[test]
fn test_box_function_once_new() {
let double = BoxFunctionOnce::new(|x: &i32| x * 2);
assert_eq!(double.apply(&21), 42);
}
#[test]
fn test_box_function_once_new_allows_non_static_t() {
fn run<'a>(value: &'a str) -> usize {
let func: BoxFunctionOnce<&'a str, usize> = BoxFunctionOnce::new(|x: &&'a str| x.len());
func.apply(&value)
}
let text = String::from("hello");
assert_eq!(run(text.as_str()), 5);
}
#[test]
fn test_box_function_once_new_allows_non_static_r() {
fn run<'a>(value: &'a str) -> &'a str {
let func: BoxFunctionOnce<&'a str, &'a str> = BoxFunctionOnce::new(|x: &&'a str| *x);
func.apply(&value)
}
let text = String::from("qubit");
assert_eq!(run(text.as_str()), "qubit");
}
#[test]
fn test_box_function_once_new_with_move() {
let data = vec![1, 2, 3];
let extend = BoxFunctionOnce::new(move |v: &Vec<i32>| {
let mut result = v.clone();
result.extend(data);
result
});
let input = vec![0];
assert_eq!(extend.apply(&input), vec![0, 1, 2, 3]);
}
#[test]
fn test_box_function_once_identity() {
let identity = BoxFunctionOnce::<i32, i32>::identity();
assert_eq!(identity.apply(&42), 42);
}
#[test]
fn test_box_function_once_constant() {
let constant = BoxFunctionOnce::constant("hello");
assert_eq!(constant.apply(&123), "hello");
}
#[test]
fn test_box_function_once_apply() {
let add_one = BoxFunctionOnce::new(|x: &i32| x + 1);
assert_eq!(add_one.apply(&41), 42);
}
#[test]
fn test_box_function_once_and_then() {
let add_one = BoxFunctionOnce::new(|x: &i32| x + 1);
let double = BoxFunctionOnce::new(|x: &i32| x * 2);
let composed = add_one.and_then(double);
assert_eq!(composed.apply(&5), 12); }
#[test]
fn test_box_function_once_and_then_with_move() {
let data1 = vec![1, 2];
let data2 = vec![3, 4];
let extend1 = BoxFunctionOnce::new(move |v: &Vec<i32>| {
let mut result = v.clone();
result.extend(data1);
result
});
let extend2 = BoxFunctionOnce::new(move |v: &Vec<i32>| {
let mut result = v.clone();
result.extend(data2);
result
});
let composed = extend1.and_then(extend2);
let input = vec![0];
assert_eq!(composed.apply(&input), vec![0, 1, 2, 3, 4]);
}
#[test]
fn test_box_function_once_when_or_else() {
let double = BoxFunctionOnce::new(|x: &i32| x * 2);
let identity = BoxFunctionOnce::<i32, i32>::identity();
let conditional = double.when(|x: &i32| *x > 0).or_else(identity);
assert_eq!(conditional.apply(&5), 10);
}
#[test]
fn test_box_function_once_when_or_else_negative() {
let double = BoxFunctionOnce::new(|x: &i32| x * 2);
let identity = BoxFunctionOnce::<i32, i32>::identity();
let conditional = double.when(|x: &i32| *x > 0).or_else(identity);
assert_eq!(conditional.apply(&-5), -5);
}
#[test]
fn test_box_function_once_when_with_closure() {
let double = BoxFunctionOnce::new(|x: &i32| x * 2);
let conditional = double.when(|x: &i32| *x >= 10).or_else(|x: &i32| *x);
assert_eq!(conditional.apply(&15), 30);
}
#[test]
fn test_box_function_once_when_with_predicate() {
let double = BoxFunctionOnce::new(|x: &i32| x * 2);
let is_positive = RcPredicate::new(|x: &i32| *x > 0);
let conditional = double
.when(is_positive.clone())
.or_else(BoxFunctionOnce::<i32, i32>::identity());
assert_eq!(conditional.apply(&5), 10);
assert!(is_positive.test(&3));
}
#[test]
fn test_box_function_once_when_with_move() {
let multiplier = 3;
let double = BoxFunctionOnce::new(move |x: &i32| x * multiplier);
let negate = BoxFunctionOnce::new(|x: &i32| -(*x));
let conditional = double.when(|x: &i32| *x > 0).or_else(negate);
assert_eq!(conditional.apply(&5), 15);
}
#[test]
fn test_box_function_once_into_box() {
let double = BoxFunctionOnce::new(|x: &i32| x * 2);
let boxed = double.into_box();
assert_eq!(boxed.apply(&21), 42);
}
#[test]
fn test_box_function_once_into_fn() {
let double = BoxFunctionOnce::new(|x: &i32| x * 2);
let func = double.into_fn();
assert_eq!(func(&21), 42);
}
#[test]
fn test_box_function_once_to_box_unavailable() {
let func = BoxFunctionOnce::new(|x: &i32| x * 2);
let boxed = func.into_box();
assert_eq!(boxed.apply(&21), 42);
}
#[test]
fn test_function_once_with_zero() {
let double = BoxFunctionOnce::new(|x: &i32| x * 2);
assert_eq!(double.apply(&0), 0);
}
#[test]
fn test_function_once_with_negative() {
let double = BoxFunctionOnce::new(|x: &i32| x * 2);
assert_eq!(double.apply(&-42), -84);
}
#[test]
fn test_function_once_with_max_value() {
let identity = BoxFunctionOnce::<i32, i32>::identity();
assert_eq!(identity.apply(&i32::MAX), i32::MAX);
}
#[test]
fn test_function_once_with_min_value() {
let identity = BoxFunctionOnce::<i32, i32>::identity();
assert_eq!(identity.apply(&i32::MIN), i32::MIN);
}
#[test]
fn test_function_once_chain_multiple() {
let add_one = BoxFunctionOnce::new(|x: &i32| x + 1);
let double = BoxFunctionOnce::new(|x: &i32| x * 2);
let add_ten = BoxFunctionOnce::new(|x: &i32| x + 10);
let composed = add_one.and_then(double).and_then(add_ten);
assert_eq!(composed.apply(&5), 22); }
#[test]
fn test_function_once_with_string() {
let to_upper = BoxFunctionOnce::new(|s: &String| s.to_uppercase());
let input = String::from("hello");
assert_eq!(to_upper.apply(&input), "HELLO");
}
#[test]
fn test_function_once_with_vec() {
let get_len = BoxFunctionOnce::new(|v: &Vec<i32>| v.len());
let vec = vec![1, 2, 3, 4, 5];
assert_eq!(get_len.apply(&vec), 5);
}
#[test]
fn test_function_once_with_option() {
let unwrap_or_zero = BoxFunctionOnce::new(|opt: &Option<i32>| opt.unwrap_or(0));
assert_eq!(unwrap_or_zero.apply(&Some(42)), 42);
}
#[test]
fn test_function_once_with_option_none() {
let unwrap_or_zero = BoxFunctionOnce::new(|opt: &Option<i32>| opt.unwrap_or(0));
assert_eq!(unwrap_or_zero.apply(&None), 0);
}
#[test]
fn test_conditional_function_once_edge_cases() {
let double = BoxFunctionOnce::new(|x: &i32| x * 2);
let negate = BoxFunctionOnce::new(|x: &i32| -(*x));
let conditional = double.when(|x: &i32| *x >= 0).or_else(negate);
assert_eq!(conditional.apply(&0), 0);
}
#[test]
fn test_function_once_with_moved_vec() {
let data = vec![1, 2, 3];
let func = BoxFunctionOnce::new(move |x: &i32| {
let mut result = data.clone();
result.push(*x);
result
});
assert_eq!(func.apply(&4), vec![1, 2, 3, 4]);
}
#[test]
fn test_function_once_with_moved_string() {
let prefix = String::from("Hello, ");
let func = BoxFunctionOnce::new(move |s: &String| format!("{}{}", prefix, s));
assert_eq!(func.apply(&String::from("World")), "Hello, World");
}
#[test]
fn test_function_once_with_complex_closure() {
let threshold = 10;
let multiplier = 2;
let func = BoxFunctionOnce::new(
move |x: &i32| {
if *x > threshold {
x * multiplier
} else {
*x
}
},
);
assert_eq!(func.apply(&15), 30);
}
#[test]
fn test_function_once_with_complex_closure_below_threshold() {
let threshold = 10;
let multiplier = 2;
let func = BoxFunctionOnce::new(
move |x: &i32| {
if *x > threshold {
x * multiplier
} else {
*x
}
},
);
assert_eq!(func.apply(&5), 5);
}
#[test]
fn test_fn_function_once_ops_and_then() {
use qubit_function::FnFunctionOnceOps;
let parse = |s: &String| s.parse::<i32>().unwrap_or(0);
let double = |x: &i32| x * 2;
let composed = parse.and_then(double);
assert_eq!(composed.apply(&String::from("21")), 42);
}
#[test]
fn test_fn_function_once_ops_when() {
use qubit_function::FnFunctionOnceOps;
let double = |x: &i32| x * 2;
let conditional = double.when(|x: &i32| *x > 0).or_else(|x: &i32| -(*x));
assert_eq!(conditional.apply(&5), 10);
}
#[test]
fn test_fn_function_once_ops_when_negative() {
use qubit_function::FnFunctionOnceOps;
let double = |x: &i32| x * 2;
let conditional = double.when(|x: &i32| *x > 0).or_else(|x: &i32| -(*x));
assert_eq!(conditional.apply(&-5), 5);
}
#[test]
fn test_function_once_resource_transfer() {
let buffer = vec![1, 2, 3];
let transfer = BoxFunctionOnce::new(move |target: &Vec<i32>| {
let mut result = target.clone();
result.extend(buffer);
result
});
let target = vec![0];
let result = transfer.apply(&target);
assert_eq!(result, vec![0, 1, 2, 3]);
}
#[test]
fn test_function_once_with_box() {
let data = Box::new(42);
let func = BoxFunctionOnce::new(move |x: &i32| *data + *x);
assert_eq!(func.apply(&8), 50);
}
#[test]
fn test_function_once_with_rc() {
use std::rc::Rc;
let data = Rc::new(vec![1, 2, 3]);
let func = BoxFunctionOnce::new(move |x: &i32| data.len() + (*x as usize));
assert_eq!(func.apply(&2), 5);
}
#[cfg(test)]
mod function_once_default_impl_tests {
use qubit_function::{
BoxFunctionOnce,
FunctionOnce,
};
struct CustomFunctionOnce {
multiplier: i32,
}
impl FunctionOnce<i32, i32> for CustomFunctionOnce {
fn apply(self, input: &i32) -> i32 {
input * self.multiplier
}
}
#[derive(Clone)]
struct CloneableCustomFunctionOnce {
multiplier: i32,
}
impl FunctionOnce<i32, i32> for CloneableCustomFunctionOnce {
fn apply(self, input: &i32) -> i32 {
input * self.multiplier
}
}
#[test]
fn test_custom_into_box() {
let custom = CustomFunctionOnce { multiplier: 3 };
let boxed = custom.into_box();
assert_eq!(boxed.apply(&14), 42);
}
#[test]
fn test_custom_into_fn() {
let custom = CustomFunctionOnce { multiplier: 6 };
let func = custom.into_fn();
assert_eq!(func(&7), 42);
}
#[test]
fn test_cloneable_to_box() {
let custom = CloneableCustomFunctionOnce { multiplier: 3 };
let boxed = custom.to_box();
assert_eq!(boxed.apply(&14), 42);
assert_eq!(custom.apply(&10), 30);
}
#[test]
fn test_cloneable_to_fn() {
let custom = CloneableCustomFunctionOnce { multiplier: 6 };
let func = custom.to_fn();
assert_eq!(func(&7), 42);
assert_eq!(custom.apply(&5), 30);
}
#[test]
fn test_custom_chained_conversions() {
let custom = CustomFunctionOnce { multiplier: 2 };
let boxed: BoxFunctionOnce<i32, i32> = custom.into_box();
assert_eq!(boxed.apply(&21), 42);
}
#[test]
fn test_custom_composition() {
let custom1 = CloneableCustomFunctionOnce { multiplier: 2 };
let custom2 = CloneableCustomFunctionOnce { multiplier: 3 };
let composed = custom1.to_box().and_then(custom2.to_box());
assert_eq!(composed.apply(&7), 42); }
#[test]
fn test_custom_with_captured_value() {
let captured = [1, 2, 3];
let custom = CloneableCustomFunctionOnce { multiplier: 2 };
let func = BoxFunctionOnce::new(move |x: &i32| {
let base = custom.apply(x);
base + captured.len() as i32
});
assert_eq!(func.apply(&10), 23); }
}
#[test]
fn test_custom_cloneable_function_once_to_box() {
#[derive(Clone, Debug)]
struct MyCloneableFunction {
multiplier: i32,
offset: i32,
}
impl MyCloneableFunction {
fn new(multiplier: i32, offset: i32) -> Self {
Self { multiplier, offset }
}
}
impl FunctionOnce<i32, i32> for MyCloneableFunction {
fn apply(self, input: &i32) -> i32 {
input * self.multiplier + self.offset
}
}
let func = MyCloneableFunction::new(3, 10);
let boxed = func.to_box();
assert_eq!(boxed.apply(&5), 25);
let another_boxed = func.to_box();
assert_eq!(another_boxed.apply(&2), 16);
let func_closure = func.to_fn();
assert_eq!(func_closure(&4), 22);
let final_boxed = func.to_box();
assert_eq!(final_boxed.apply(&1), 13); }
#[test]
fn test_box_function_once_debug_display() {
let double = BoxFunctionOnce::new(|x: &i32| x * 2);
let debug_str = format!("{:?}", double);
assert!(debug_str.contains("BoxFunctionOnce"));
assert!(debug_str.contains("name"));
assert!(debug_str.contains("function"));
let display_str = format!("{}", double);
assert_eq!(display_str, "BoxFunctionOnce");
let named_double = BoxFunctionOnce::new_with_name("double", |x: &i32| x * 2);
let named_debug_str = format!("{:?}", named_double);
assert!(named_debug_str.contains("BoxFunctionOnce"));
assert!(named_debug_str.contains("name"));
assert!(named_debug_str.contains("function"));
let named_display_str = format!("{}", named_double);
assert_eq!(named_display_str, "BoxFunctionOnce(double)");
}
#[test]
fn test_box_function_once_name_methods() {
let mut double = BoxFunctionOnce::new_with_name("double_func_once", |x: &i32| x * 2);
assert_eq!(double.name(), Some("double_func_once"));
double.set_name("modified_double_once");
assert_eq!(double.name(), Some("modified_double_once"));
assert_eq!(double.apply(&5), 10);
}
#[test]
fn test_box_conditional_function_once_debug_display() {
let double = BoxFunctionOnce::new(|x: &i32| x * 2);
let conditional = double.when(|x: &i32| *x > 0);
let debug_str = format!("{:?}", conditional);
assert!(debug_str.contains("BoxConditionalFunctionOnce"));
assert!(debug_str.contains("name"));
assert!(debug_str.contains("function"));
assert!(debug_str.contains("predicate"));
let display_str = format!("{}", conditional);
assert!(display_str.starts_with("BoxConditionalFunctionOnce("));
assert!(display_str.contains("BoxFunctionOnce"));
assert!(display_str.contains("BoxPredicate"));
assert!(display_str.ends_with(")"));
let triple = BoxFunctionOnce::new_with_name("triple_func_once", |x: &i32| x * 3);
let named_conditional = triple.when(|x: &i32| *x % 2 == 0);
let named_debug_str = format!("{:?}", named_conditional);
assert!(named_debug_str.contains("BoxConditionalFunctionOnce"));
assert!(named_debug_str.contains("name"));
assert!(named_debug_str.contains("function"));
assert!(named_debug_str.contains("predicate"));
let named_display_str = format!("{}", named_conditional);
assert!(named_display_str.starts_with("BoxConditionalFunctionOnce("));
assert!(named_display_str.contains("BoxFunctionOnce(triple_func_once)"));
assert!(named_display_str.contains("BoxPredicate"));
assert!(named_display_str.ends_with(")"));
}