use qubit_function::{
BoxMutatingFunctionOnce,
MutatingFunctionOnce,
};
#[derive(Clone)]
struct TestMutatingFunctionOnce {
multiplier: i32,
}
impl TestMutatingFunctionOnce {
fn new(multiplier: i32) -> Self {
TestMutatingFunctionOnce { multiplier }
}
}
impl MutatingFunctionOnce<i32, i32> for TestMutatingFunctionOnce {
fn apply(self, input: &mut i32) -> i32 {
let old_value = *input;
*input *= self.multiplier;
old_value
}
}
#[cfg(test)]
mod test_box_mutating_function_once {
use super::{
BoxMutatingFunctionOnce,
MutatingFunctionOnce,
};
#[test]
fn test_new() {
let data = vec![1, 2, 3];
let func = BoxMutatingFunctionOnce::new(move |x: &mut Vec<i32>| {
let old_len = x.len();
x.extend(data);
old_len
});
let mut target = vec![0];
let old_len = func.apply(&mut target);
assert_eq!(old_len, 1);
assert_eq!(target, vec![0, 1, 2, 3]);
}
#[test]
fn test_new_allows_non_static_t() {
fn run<'a>(value: &'a str) -> usize {
let func: BoxMutatingFunctionOnce<&'a str, usize> =
BoxMutatingFunctionOnce::new(|x: &mut &'a str| x.len());
let mut input = value;
func.apply(&mut input)
}
let text = String::from("hello");
assert_eq!(run(text.as_str()), 5);
}
#[test]
fn test_new_allows_non_static_r() {
fn run<'a>(value: &'a str) -> &'a str {
let func: BoxMutatingFunctionOnce<&'a str, &'a str> =
BoxMutatingFunctionOnce::new(|x: &mut &'a str| *x);
let mut input = value;
func.apply(&mut input)
}
let text = String::from("qubit");
assert_eq!(run(text.as_str()), "qubit");
}
#[test]
fn test_with_string() {
let data = String::from(" world");
let func = BoxMutatingFunctionOnce::new(move |x: &mut String| {
let old_len = x.len();
x.push_str(&data);
old_len
});
let mut target = String::from("hello");
let old_len = func.apply(&mut target);
assert_eq!(old_len, 5);
assert_eq!(target, "hello world");
}
#[test]
fn test_and_then() {
let data1 = vec![1, 2];
let data2 = [3, 4];
let chained = BoxMutatingFunctionOnce::new(move |x: &mut Vec<i32>| {
x.extend(data1);
x.len()
})
.and_then(move |len: &usize| {
*len + data2.len()
});
let mut target = vec![0];
let final_len = chained.apply(&mut target);
assert_eq!(final_len, 5); assert_eq!(target, vec![0, 1, 2]);
}
#[test]
fn test_and_then_multiple_chains() {
let data1 = vec![1, 2];
let data2 = [3, 4];
let data3 = [5, 6];
let chained = BoxMutatingFunctionOnce::new(move |x: &mut Vec<i32>| {
x.extend(data1);
x.len()
})
.and_then(move |len: &usize| {
*len + data2.len()
})
.and_then(move |len: &usize| {
*len + data3.len()
});
let mut target = vec![0];
let final_len = chained.apply(&mut target);
assert_eq!(final_len, 7); assert_eq!(target, vec![0, 1, 2]);
}
#[test]
fn test_identity() {
let identity = BoxMutatingFunctionOnce::<i32, i32>::identity();
let mut value = 42;
let result = identity.apply(&mut value);
assert_eq!(result, 42);
assert_eq!(value, 42);
}
#[test]
fn test_map() {
let data = vec![1, 2, 3];
let func = BoxMutatingFunctionOnce::new(move |x: &mut Vec<i32>| {
let old_len = x.len();
x.extend(data);
old_len
});
let mapped = func.and_then::<String, _>(|old_len: &usize| {
format!("Old length: {}", *old_len)
});
let mut target = vec![0];
let result = mapped.apply(&mut target);
assert_eq!(result, "Old length: 1");
assert_eq!(target, vec![0, 1, 2, 3]);
}
#[test]
fn test_validation_pattern() {
struct Data {
value: i32,
}
let validator = BoxMutatingFunctionOnce::new(|data: &mut Data| {
if data.value < 0 {
data.value = 0;
Err("Fixed negative value")
} else {
Ok("Valid")
}
});
let mut data = Data { value: -5 };
let result = validator.apply(&mut data);
assert_eq!(data.value, 0);
assert!(result.is_err());
}
#[test]
fn test_resource_transfer() {
let resource = vec![1, 2, 3, 4, 5];
let func = BoxMutatingFunctionOnce::new(move |x: &mut Vec<i32>| {
let old_sum: i32 = x.iter().sum();
x.extend(resource);
old_sum
});
let mut target = vec![10, 20];
let old_sum = func.apply(&mut target);
assert_eq!(old_sum, 30);
assert_eq!(target, vec![10, 20, 1, 2, 3, 4, 5]);
}
}
#[cfg(test)]
mod test_closure {
use super::MutatingFunctionOnce;
#[test]
fn test_closure_implements_trait() {
let data = vec![1, 2, 3];
let closure = move |x: &mut Vec<i32>| {
let old_len = x.len();
x.extend(data);
old_len
};
let mut target = vec![0];
let old_len = closure.apply(&mut target);
assert_eq!(old_len, 1);
assert_eq!(target, vec![0, 1, 2, 3]);
}
#[test]
fn test_move_semantics() {
let data = vec![1, 2, 3];
let closure = move |x: &mut Vec<i32>| {
let old_len = x.len();
x.extend(data); old_len
};
let mut target = vec![0];
let old_len = closure.apply(&mut target);
assert_eq!(old_len, 1);
assert_eq!(target, vec![0, 1, 2, 3]);
}
}
#[test]
fn test_box_mutating_function_once_debug_display() {
let double = BoxMutatingFunctionOnce::new(|x: &mut i32| *x * 2);
let debug_str = format!("{:?}", double);
assert!(debug_str.contains("BoxMutatingFunctionOnce"));
assert!(debug_str.contains("name"));
assert!(debug_str.contains("function"));
let display_str = format!("{}", double);
assert_eq!(display_str, "BoxMutatingFunctionOnce");
let named_double = BoxMutatingFunctionOnce::new_with_name(
"mutating_once_double",
|x: &mut i32| *x * 2,
);
let named_debug_str = format!("{:?}", named_double);
assert!(named_debug_str.contains("BoxMutatingFunctionOnce"));
assert!(named_debug_str.contains("name"));
assert!(named_debug_str.contains("function"));
let named_display_str = format!("{}", named_double);
assert_eq!(
named_display_str,
"BoxMutatingFunctionOnce(mutating_once_double)"
);
}
#[test]
fn test_box_mutating_function_once_name_methods() {
let mut double = BoxMutatingFunctionOnce::new_with_name(
"box_mutating_once_func",
|x: &mut i32| {
*x *= 2;
*x
},
);
assert_eq!(double.name(), Some("box_mutating_once_func"));
double.set_name("modified_box_mutating_once");
assert_eq!(double.name(), Some("modified_box_mutating_once"));
let mut value = 5;
assert_eq!(double.apply(&mut value), 10);
assert_eq!(value, 10);
}
#[test]
fn test_box_conditional_mutating_function_once_debug_display() {
let double = BoxMutatingFunctionOnce::new(|x: &mut i32| *x * 2);
let conditional = double.when(|x: &i32| *x > 0);
let debug_str = format!("{:?}", conditional);
assert!(debug_str.contains("BoxConditionalMutatingFunctionOnce"));
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("BoxConditionalMutatingFunctionOnce("));
assert!(display_str.contains("BoxMutatingFunctionOnce"));
assert!(display_str.contains("BoxPredicate"));
assert!(display_str.ends_with(")"));
let triple = BoxMutatingFunctionOnce::new_with_name(
"triple_mutating_once_func",
|x: &mut 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("BoxConditionalMutatingFunctionOnce"));
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("BoxConditionalMutatingFunctionOnce(")
);
assert!(
named_display_str
.contains("BoxMutatingFunctionOnce(triple_mutating_once_func)")
);
assert!(named_display_str.contains("BoxPredicate"));
assert!(named_display_str.ends_with(")"));
}