use anyhow::anyhow;
use debtmap::core::{
lazy::TransformationPipeline,
metrics::combine_metrics,
monadic::{lift_result, traverse_results, Applicative, OptionExt, ResultExt},
ComplexityMetrics, FileMetrics, FunctionMetrics, Language,
};
use std::path::PathBuf;
fn create_test_metrics_simple() -> FileMetrics {
FileMetrics {
path: PathBuf::from("test.rs"),
language: Language::Rust,
complexity: ComplexityMetrics {
functions: vec![FunctionMetrics {
name: "test_func".to_string(),
file: PathBuf::from("test.rs"),
line: 1,
cyclomatic: 2,
cognitive: 3,
nesting: 1,
length: 15,
is_test: false,
visibility: None,
is_trait_method: false,
in_test_module: false,
entropy_score: None,
is_pure: None,
purity_confidence: None,
detected_patterns: None,
upstream_callers: None,
downstream_callees: None,
mapping_pattern_result: None,
adjusted_complexity: None,
composition_metrics: None,
language_specific: None,
purity_reason: None,
call_dependencies: None,
purity_level: None,
error_swallowing_count: None,
error_swallowing_patterns: None,
entropy_analysis: None,
}],
cyclomatic_complexity: 2,
cognitive_complexity: 3,
},
debt_items: vec![],
dependencies: vec![],
duplications: vec![],
total_lines: 0,
module_scope: None,
classes: None,
}
}
fn create_test_metrics_complex() -> FileMetrics {
FileMetrics {
path: PathBuf::from("complex.rs"),
language: Language::Rust,
complexity: ComplexityMetrics {
functions: vec![
FunctionMetrics {
name: "complex_func1".to_string(),
file: PathBuf::from("complex.rs"),
line: 10,
cyclomatic: 5,
cognitive: 8,
nesting: 2,
length: 30,
is_test: false,
visibility: None,
is_trait_method: false,
in_test_module: false,
entropy_score: None,
is_pure: None,
purity_confidence: None,
detected_patterns: None,
upstream_callers: None,
downstream_callees: None,
mapping_pattern_result: None,
adjusted_complexity: None,
composition_metrics: None,
language_specific: None,
purity_reason: None,
call_dependencies: None,
purity_level: None,
error_swallowing_count: None,
error_swallowing_patterns: None,
entropy_analysis: None,
},
FunctionMetrics {
name: "complex_func2".to_string(),
file: PathBuf::from("complex.rs"),
line: 50,
cyclomatic: 3,
cognitive: 4,
nesting: 1,
length: 20,
is_test: false,
visibility: None,
is_trait_method: false,
in_test_module: false,
entropy_score: None,
is_pure: None,
purity_confidence: None,
detected_patterns: None,
upstream_callers: None,
downstream_callees: None,
mapping_pattern_result: None,
adjusted_complexity: None,
composition_metrics: None,
language_specific: None,
purity_reason: None,
call_dependencies: None,
purity_level: None,
error_swallowing_count: None,
error_swallowing_patterns: None,
entropy_analysis: None,
},
],
cyclomatic_complexity: 8,
cognitive_complexity: 12,
},
debt_items: vec![],
dependencies: vec![],
duplications: vec![],
total_lines: 0,
module_scope: None,
classes: None,
}
}
mod test_apply_result {
use super::*;
#[test]
fn test_apply_result_all_success() {
let app = Applicative::new(vec![1, 2, 3]);
let result = app.apply_result(|x| Ok(x * 2));
assert!(result.is_ok());
let values = result.unwrap().unwrap();
assert_eq!(values, vec![2, 4, 6]);
}
#[test]
fn test_apply_result_with_failure() {
let app = Applicative::new(vec![1, 2, 3]);
let result = app.apply_result(|x| {
if x == 2 {
Err(anyhow!("Error on 2"))
} else {
Ok(x * 2)
}
});
assert!(result.is_err());
}
#[test]
fn test_apply_result_empty_input() {
let app: Applicative<i32> = Applicative::new(vec![]);
let result = app.apply_result(|x| Ok(x * 2));
assert!(result.is_ok());
let values = result.unwrap().unwrap();
assert!(values.is_empty());
}
#[test]
fn test_apply_result_complex_transformation() {
let app = Applicative::new(vec!["hello", "world", "test"]);
let result = app.apply_result(|s| {
if s.len() > 4 {
Ok(s.to_uppercase())
} else {
Ok(s.to_string())
}
});
assert!(result.is_ok());
let values = result.unwrap().unwrap();
assert_eq!(values, vec!["HELLO", "WORLD", "test"]);
}
#[test]
fn test_apply_result_with_chaining() {
let app = Applicative::new(vec![1, 2, 3]);
let result = app.apply_result(|x| Ok(x * x));
assert!(result.is_ok());
let values = result.unwrap().unwrap();
assert_eq!(values, vec![1, 4, 9]);
}
}
mod test_combine_metrics {
use super::*;
#[test]
fn test_combine_metrics_empty() {
let metrics1 = ComplexityMetrics {
functions: vec![],
cyclomatic_complexity: 0,
cognitive_complexity: 0,
};
let metrics2 = ComplexityMetrics {
functions: vec![],
cyclomatic_complexity: 0,
cognitive_complexity: 0,
};
let combined = combine_metrics(metrics1, metrics2);
assert!(combined.functions.is_empty());
assert_eq!(combined.cyclomatic_complexity, 0);
assert_eq!(combined.cognitive_complexity, 0);
}
#[test]
fn test_combine_metrics_single_function_each() {
let func1 = FunctionMetrics {
name: "func1".to_string(),
file: PathBuf::from("file1.rs"),
line: 10,
cyclomatic: 3,
cognitive: 4,
nesting: 1,
length: 20,
is_test: false,
visibility: None,
is_trait_method: false,
in_test_module: false,
entropy_score: None,
is_pure: None,
purity_confidence: None,
detected_patterns: None,
upstream_callers: None,
downstream_callees: None,
mapping_pattern_result: None,
adjusted_complexity: None,
composition_metrics: None,
language_specific: None,
purity_reason: None,
call_dependencies: None,
purity_level: None,
error_swallowing_count: None,
error_swallowing_patterns: None,
entropy_analysis: None,
};
let func2 = FunctionMetrics {
name: "func2".to_string(),
file: PathBuf::from("file2.rs"),
line: 20,
cyclomatic: 5,
cognitive: 6,
nesting: 2,
length: 30,
is_test: false,
visibility: None,
is_trait_method: false,
in_test_module: false,
entropy_score: None,
is_pure: None,
purity_confidence: None,
detected_patterns: None,
upstream_callers: None,
downstream_callees: None,
mapping_pattern_result: None,
adjusted_complexity: None,
composition_metrics: None,
language_specific: None,
purity_reason: None,
call_dependencies: None,
purity_level: None,
error_swallowing_count: None,
error_swallowing_patterns: None,
entropy_analysis: None,
};
let metrics1 = ComplexityMetrics {
functions: vec![func1.clone()],
cyclomatic_complexity: 3,
cognitive_complexity: 4,
};
let metrics2 = ComplexityMetrics {
functions: vec![func2.clone()],
cyclomatic_complexity: 5,
cognitive_complexity: 6,
};
let combined = combine_metrics(metrics1, metrics2);
assert_eq!(combined.functions.len(), 2);
assert_eq!(combined.cyclomatic_complexity, 8);
assert_eq!(combined.cognitive_complexity, 10);
}
#[test]
fn test_combine_metrics_multiple_functions() {
let metrics1 = create_test_metrics_simple().complexity;
let metrics2 = create_test_metrics_complex().complexity;
let combined = combine_metrics(metrics1, metrics2);
assert_eq!(combined.functions.len(), 3);
assert_eq!(combined.cyclomatic_complexity, 10); assert_eq!(combined.cognitive_complexity, 15); }
#[test]
fn test_combine_metrics_preserves_function_details() {
let func1 = FunctionMetrics {
name: "detailed_func".to_string(),
file: PathBuf::from("detail.rs"),
line: 42,
cyclomatic: 7,
cognitive: 12,
nesting: 3,
length: 100,
is_test: false,
visibility: None,
is_trait_method: false,
in_test_module: false,
entropy_score: None,
is_pure: None,
purity_confidence: None,
detected_patterns: None,
upstream_callers: None,
downstream_callees: None,
mapping_pattern_result: None,
adjusted_complexity: None,
composition_metrics: None,
language_specific: None,
purity_reason: None,
call_dependencies: None,
purity_level: None,
error_swallowing_count: None,
error_swallowing_patterns: None,
entropy_analysis: None,
};
let metrics1 = ComplexityMetrics {
functions: vec![func1.clone()],
cyclomatic_complexity: 7,
cognitive_complexity: 12,
};
let metrics2 = ComplexityMetrics {
functions: vec![],
cyclomatic_complexity: 0,
cognitive_complexity: 0,
};
let combined = combine_metrics(metrics1, metrics2);
assert_eq!(combined.functions.len(), 1);
assert_eq!(combined.functions[0].name, "detailed_func");
assert_eq!(combined.functions[0].line, 42);
assert_eq!(combined.functions[0].nesting, 3);
assert_eq!(combined.functions[0].length, 100);
}
#[test]
fn test_combine_metrics_order_preservation() {
let func1 = FunctionMetrics::new("first".to_string(), PathBuf::from("a.rs"), 1);
let func2 = FunctionMetrics::new("second".to_string(), PathBuf::from("b.rs"), 2);
let func3 = FunctionMetrics::new("third".to_string(), PathBuf::from("c.rs"), 3);
let metrics1 = ComplexityMetrics {
functions: vec![func1, func2],
cyclomatic_complexity: 0,
cognitive_complexity: 0,
};
let metrics2 = ComplexityMetrics {
functions: vec![func3],
cyclomatic_complexity: 0,
cognitive_complexity: 0,
};
let combined = combine_metrics(metrics1, metrics2);
assert_eq!(combined.functions[0].name, "first");
assert_eq!(combined.functions[1].name, "second");
assert_eq!(combined.functions[2].name, "third");
}
}
mod test_applicative_apply {
use super::*;
#[test]
fn test_apply_simple_transformation() {
let app = Applicative::new(vec![1, 2, 3, 4, 5]);
let result = app.apply(|x| x * 2);
let values = result.unwrap();
assert_eq!(values, vec![2, 4, 6, 8, 10]);
}
#[test]
fn test_apply_empty_values() {
let app: Applicative<i32> = Applicative::new(vec![]);
let result = app.apply(|x| x + 1);
let values = result.unwrap();
assert!(values.is_empty());
}
#[test]
fn test_apply_string_transformation() {
let app = Applicative::new(vec!["hello", "world", "rust"]);
let result = app.apply(|s| s.to_uppercase());
let values = result.unwrap();
assert_eq!(values, vec!["HELLO", "WORLD", "RUST"]);
}
#[test]
fn test_apply_complex_type_transformation() {
#[derive(Debug, PartialEq)]
struct Person {
name: String,
age: u32,
}
let app = Applicative::new(vec![
Person {
name: "Alice".to_string(),
age: 30,
},
Person {
name: "Bob".to_string(),
age: 25,
},
]);
let result = app.apply(|p| p.age + 5);
let values = result.unwrap();
assert_eq!(values, vec![35, 30]);
}
#[test]
fn test_apply_chain_transformations() {
let app = Applicative::new(vec![1, 2, 3]);
let intermediate = app.apply(|x| x * x);
let result = intermediate.apply(|x| x + 1);
let values = result.unwrap();
assert_eq!(values, vec![2, 5, 10]);
}
#[test]
fn test_apply_closure_with_captures() {
let multiplier = 3;
let offset = 10;
let app = Applicative::new(vec![1, 2, 3, 4]);
let result = app.apply(|x| x * multiplier + offset);
let values = result.unwrap();
assert_eq!(values, vec![13, 16, 19, 22]);
}
#[test]
fn test_apply_preserves_order() {
let app = Applicative::new(vec![5, 3, 8, 1, 9]);
let result = app.apply(|x| x * 10);
let values = result.unwrap();
assert_eq!(values, vec![50, 30, 80, 10, 90]);
}
#[test]
fn test_apply_with_option_transformation() {
let app = Applicative::new(vec![Some(1), None, Some(3), None, Some(5)]);
let result = app.apply(|opt| opt.map(|x| x * 2));
let values = result.unwrap();
assert_eq!(values, vec![Some(2), None, Some(6), None, Some(10)]);
}
}
mod test_apply {
use super::*;
#[test]
fn test_apply_no_transformations() {
let pipeline = TransformationPipeline::new();
let value = 42;
let result = pipeline.apply(value);
assert_eq!(result, 42);
}
#[test]
fn test_apply_single_transformation() {
let pipeline = TransformationPipeline::new().add_transformation(|x| x * 2);
let result = pipeline.apply(10);
assert_eq!(result, 20);
}
#[test]
fn test_apply_multiple_transformations() {
let pipeline = TransformationPipeline::new()
.add_transformation(|x| x + 1)
.add_transformation(|x| x * 2)
.add_transformation(|x| x - 3);
let result = pipeline.apply(5);
assert_eq!(result, 9);
}
#[test]
fn test_apply_string_transformations() {
fn add_exclamation(s: String) -> String {
format!("{s}!")
}
fn uppercase(s: String) -> String {
s.to_uppercase()
}
let pipeline = TransformationPipeline::new()
.add_transformation(uppercase)
.add_transformation(add_exclamation);
let result = pipeline.apply("hello".to_string());
assert_eq!(result, "HELLO!");
}
#[test]
fn test_apply_all_multiple_values() {
let pipeline = TransformationPipeline::new()
.add_transformation(|x| x * 2)
.add_transformation(|x| x + 10);
let values = vec![1, 2, 3, 4, 5];
let results = pipeline.apply_all(values);
assert_eq!(results, vec![12, 14, 16, 18, 20]);
}
}
mod test_traverse_results {
use super::*;
#[test]
fn test_traverse_results_all_ok() {
let values = vec![1, 2, 3, 4, 5];
let result = traverse_results(values, |x| Ok(x * 2));
assert!(result.is_ok());
assert_eq!(result.unwrap(), vec![2, 4, 6, 8, 10]);
}
#[test]
fn test_traverse_results_with_error() {
let values = vec![1, 2, 3, 4, 5];
let result = traverse_results(values, |x| {
if x == 3 {
Err(anyhow!("Error at 3"))
} else {
Ok(x * 2)
}
});
assert!(result.is_err());
assert!(result.unwrap_err().to_string().contains("Error at 3"));
}
#[test]
fn test_traverse_results_empty_input() {
let values: Vec<i32> = vec![];
let result = traverse_results(values, |x| Ok(x * 2));
assert!(result.is_ok());
assert!(result.unwrap().is_empty());
}
#[test]
fn test_traverse_results_string_conversion() {
let values = vec!["1", "2", "3"];
let result = traverse_results(values, |s| {
s.parse::<i32>()
.map(|n| n * 10)
.map_err(|e| anyhow!("Parse error: {}", e))
});
assert!(result.is_ok());
assert_eq!(result.unwrap(), vec![10, 20, 30]);
}
#[test]
fn test_traverse_results_invalid_string_conversion() {
let values = vec!["1", "not_a_number", "3"];
let result = traverse_results(values, |s| {
s.parse::<i32>()
.map(|n| n * 10)
.map_err(|e| anyhow!("Parse error: {}", e))
});
assert!(result.is_err());
assert!(result.unwrap_err().to_string().contains("Parse error"));
}
#[test]
fn test_traverse_results_complex_transformation() {
#[derive(Debug, PartialEq)]
struct User {
id: u32,
name: String,
}
let ids = vec![1, 2, 3];
let result = traverse_results(ids, |id| {
if id > 0 && id <= 3 {
Ok(User {
id,
name: format!("User{id}"),
})
} else {
Err(anyhow!("User not found"))
}
});
assert!(result.is_ok());
let users = result.unwrap();
assert_eq!(users.len(), 3);
assert_eq!(users[0].name, "User1");
assert_eq!(users[1].name, "User2");
assert_eq!(users[2].name, "User3");
}
}
mod test_or_else_with {
use super::*;
use anyhow::Result;
#[test]
fn test_or_else_with_ok_value() {
let result: Result<i32> = Ok(42);
let fallback = result.or_else_with(|| Ok(100));
assert!(fallback.is_ok());
assert_eq!(fallback.unwrap(), 42); }
#[test]
fn test_or_else_with_error_fallback_success() {
let result: Result<i32> = Err(anyhow!("Initial error"));
let fallback = result.or_else_with(|| Ok(100));
assert!(fallback.is_ok());
assert_eq!(fallback.unwrap(), 100); }
#[test]
fn test_or_else_with_error_fallback_error() {
let result: Result<i32> = Err(anyhow!("Initial error"));
let fallback = result.or_else_with(|| Err(anyhow!("Fallback error")));
assert!(fallback.is_err());
assert!(fallback.unwrap_err().to_string().contains("Fallback error"));
}
#[test]
fn test_or_else_with_complex_type() {
#[derive(Debug, PartialEq)]
struct Data {
value: String,
count: u32,
}
let result: Result<Data> = Err(anyhow!("Failed to load"));
let fallback = result.or_else_with(|| {
Ok(Data {
value: "default".to_string(),
count: 0,
})
});
assert!(fallback.is_ok());
let data = fallback.unwrap();
assert_eq!(data.value, "default");
assert_eq!(data.count, 0);
}
#[test]
fn test_or_else_with_chain() {
let result: Result<i32> = Err(anyhow!("Error 1"));
let fallback = result
.or_else_with(|| Err(anyhow!("Error 2")))
.or_else_with(|| Ok(42));
assert!(fallback.is_ok());
assert_eq!(fallback.unwrap(), 42);
}
#[test]
fn test_or_else_with_side_effects() {
let mut counter = 0;
let result: Result<i32> = Err(anyhow!("Error"));
let fallback = result.or_else_with(|| {
counter += 1;
Ok(counter * 10)
});
assert!(fallback.is_ok());
assert_eq!(fallback.unwrap(), 10);
assert_eq!(counter, 1);
}
#[test]
fn test_or_else_with_no_execution_on_ok() {
let mut counter = 0;
let result: Result<i32> = Ok(42);
let fallback = result.or_else_with(|| {
counter += 1; Ok(100)
});
assert!(fallback.is_ok());
assert_eq!(fallback.unwrap(), 42);
assert_eq!(counter, 0); }
#[test]
fn test_or_else_with_async_like_pattern() {
fn fetch_primary() -> Result<String> {
Err(anyhow!("Primary failed"))
}
fn fetch_backup() -> Result<String> {
Ok("backup data".to_string())
}
let result = fetch_primary().or_else_with(fetch_backup);
assert!(result.is_ok());
assert_eq!(result.unwrap(), "backup data");
}
}
mod test_or_else_some {
use super::*;
#[test]
fn test_or_else_some_with_some_value() {
let value: Option<i32> = Some(42);
let fallback = value.or_else_some(|| Some(100));
assert!(fallback.is_some());
assert_eq!(fallback.unwrap(), 42); }
#[test]
fn test_or_else_some_with_none_fallback_some() {
let value: Option<i32> = None;
let fallback = value.or_else_some(|| Some(100));
assert!(fallback.is_some());
assert_eq!(fallback.unwrap(), 100); }
#[test]
fn test_or_else_some_with_none_fallback_none() {
let value: Option<i32> = None;
let fallback = value.or_else_some(|| None);
assert!(fallback.is_none());
}
#[test]
fn test_or_else_some_with_complex_type() {
#[derive(Debug, PartialEq)]
struct Config {
setting: String,
enabled: bool,
}
let value: Option<Config> = None;
let fallback = value.or_else_some(|| {
Some(Config {
setting: "default".to_string(),
enabled: true,
})
});
assert!(fallback.is_some());
let config = fallback.unwrap();
assert_eq!(config.setting, "default");
assert!(config.enabled);
}
#[test]
fn test_or_else_some_chain() {
let value: Option<i32> = None;
let result = value.or_else_some(|| None).or_else_some(|| Some(42));
assert!(result.is_some());
assert_eq!(result.unwrap(), 42);
}
#[test]
fn test_or_else_some_lazy_evaluation() {
let mut counter = 0;
let value: Option<i32> = None;
let fallback = value.or_else_some(|| {
counter += 1;
Some(counter * 10)
});
assert!(fallback.is_some());
assert_eq!(fallback.unwrap(), 10);
assert_eq!(counter, 1);
}
#[test]
fn test_or_else_some_no_execution_on_some() {
let mut counter = 0;
let value: Option<i32> = Some(42);
let fallback = value.or_else_some(|| {
counter += 1; Some(100)
});
assert!(fallback.is_some());
assert_eq!(fallback.unwrap(), 42);
assert_eq!(counter, 0); }
#[test]
fn test_or_else_some_practical_use_case() {
fn get_env_var() -> Option<String> {
None }
fn get_default_config() -> Option<String> {
Some("default_value".to_string())
}
let config = get_env_var().or_else_some(get_default_config);
assert!(config.is_some());
assert_eq!(config.unwrap(), "default_value");
}
#[test]
fn test_or_else_some_with_filter() {
let value: Option<i32> = None;
let result = value.or_else_some(|| Some(10)).filter_some(|&x| x > 5);
assert!(result.is_some());
assert_eq!(result.unwrap(), 10);
}
#[test]
fn test_or_else_some_edge_case_nested_options() {
let value: Option<Option<i32>> = None;
let fallback = value.or_else_some(|| Some(Some(42)));
assert!(fallback.is_some());
assert_eq!(fallback.unwrap().unwrap(), 42);
}
}
mod test_lift_result {
use super::*;
use anyhow::Result;
#[test]
fn test_lift_result_basic() {
let add_one = |x: i32| x + 1;
let lifted = lift_result(add_one);
let result = lifted(41);
assert!(result.is_ok());
assert_eq!(result.unwrap(), 42);
}
#[test]
fn test_lift_result_string_transformation() {
let uppercase = |s: String| s.to_uppercase();
let lifted = lift_result(uppercase);
let result = lifted("hello".to_string());
assert!(result.is_ok());
assert_eq!(result.unwrap(), "HELLO");
}
#[test]
fn test_lift_result_complex_type() {
#[derive(Debug, PartialEq)]
struct Point {
x: i32,
y: i32,
}
let double_point = |p: Point| Point {
x: p.x * 2,
y: p.y * 2,
};
let lifted = lift_result(double_point);
let result = lifted(Point { x: 3, y: 4 });
assert!(result.is_ok());
let doubled = result.unwrap();
assert_eq!(doubled.x, 6);
assert_eq!(doubled.y, 8);
}
#[test]
fn test_lift_result_composition() {
let add_one = |x: i32| x + 1;
let double = |x: i32| x * 2;
let lifted_add = lift_result(add_one);
let lifted_double = lift_result(double);
let result = lifted_add(5).and_then(lifted_double);
assert!(result.is_ok());
assert_eq!(result.unwrap(), 12); }
#[test]
fn test_lift_result_with_chain() {
let square = |x: i32| x * x;
let lifted = lift_result(square);
let result: Result<i32> = Ok(3).and_then(lifted).and_then(lift_result(|x| x + 1));
assert!(result.is_ok());
assert_eq!(result.unwrap(), 10); }
#[test]
fn test_lift_result_pure_function_guarantee() {
let pure_fn = |x: i32| x * 2;
let lifted = lift_result(pure_fn);
let result1 = lifted(21);
let result2 = lifted(21);
assert!(result1.is_ok());
assert!(result2.is_ok());
assert_eq!(result1.unwrap(), 42);
assert_eq!(result2.unwrap(), 42);
}
#[test]
fn test_lift_result_with_vec_map() {
let double = |x: i32| x * 2;
let lifted = lift_result(double);
let values = vec![1, 2, 3];
let results: Result<Vec<i32>> = values.into_iter().map(lifted).collect();
assert!(results.is_ok());
assert_eq!(results.unwrap(), vec![2, 4, 6]);
}
#[test]
fn test_lift_result_practical_parsing() {
fn parse_and_double(s: &str) -> Result<i32> {
let parsed: Result<i32> = s.parse().map_err(|e| anyhow!("{}", e));
parsed.and_then(lift_result(|x| x * 2))
}
let result = parse_and_double("21");
assert!(result.is_ok());
assert_eq!(result.unwrap(), 42);
}
#[test]
fn test_lift_result_tuple_transformation() {
let swap = |(a, b): (i32, String)| (b, a);
let lifted = lift_result(swap);
let result = lifted((42, "answer".to_string()));
assert!(result.is_ok());
let swapped = result.unwrap();
assert_eq!(swapped.0, "answer");
assert_eq!(swapped.1, 42);
}
#[test]
fn test_lift_result_closure_capture() {
let multiplier = 10;
let multiply = |x: i32| x * multiplier;
let lifted = lift_result(multiply);
let result = lifted(5);
assert!(result.is_ok());
assert_eq!(result.unwrap(), 50);
}
}
mod test_transformation_pipeline_default {
use super::*;
#[test]
fn test_default_creates_empty_pipeline() {
let pipeline: TransformationPipeline<i32> = Default::default();
let result = pipeline.apply(42);
assert_eq!(result, 42);
}
#[test]
fn test_default_apply_all_empty() {
let pipeline: TransformationPipeline<i32> = Default::default();
let values = vec![1, 2, 3, 4, 5];
let results = pipeline.apply_all(values.clone());
assert_eq!(results, values); }
#[test]
fn test_default_then_add_transformations() {
let pipeline: TransformationPipeline<i32> = Default::default();
let pipeline = pipeline
.add_transformation(|x| x + 1)
.add_transformation(|x| x * 2);
let result = pipeline.apply(10);
assert_eq!(result, 22); }
#[test]
fn test_default_type_inference() {
let pipeline = TransformationPipeline::default();
let pipeline = pipeline.add_transformation(|x: String| x.to_uppercase());
let result = pipeline.apply("hello".to_string());
assert_eq!(result, "HELLO");
}
#[test]
fn test_default_multiple_instances() {
let pipeline1: TransformationPipeline<i32> = Default::default();
let pipeline2: TransformationPipeline<i32> = Default::default();
assert_eq!(pipeline1.apply(100), pipeline2.apply(100));
}
#[test]
fn test_default_with_complex_type() {
#[derive(Debug, PartialEq, Clone)]
struct Data {
value: i32,
}
let pipeline: TransformationPipeline<Data> = Default::default();
let data = Data { value: 42 };
let result = pipeline.apply(data.clone());
assert_eq!(result, data);
}
#[test]
fn test_default_chain_behavior() {
let base_pipeline: TransformationPipeline<i32> = Default::default();
let pipeline1 = base_pipeline.add_transformation(|x| x + 10);
let pipeline2 = TransformationPipeline::default().add_transformation(|x| x * 2);
assert_eq!(pipeline1.apply(5), 15);
assert_eq!(pipeline2.apply(5), 10);
}
#[test]
fn test_default_practical_use_case() {
fn create_processing_pipeline(needs_normalization: bool) -> TransformationPipeline<f64> {
let mut pipeline = TransformationPipeline::default();
if needs_normalization {
pipeline = pipeline.add_transformation(|x| x / 100.0);
}
pipeline.add_transformation(|x| x * 2.0)
}
let pipeline_with_norm = create_processing_pipeline(true);
let pipeline_without_norm = create_processing_pipeline(false);
assert_eq!(pipeline_with_norm.apply(100.0), 2.0); assert_eq!(pipeline_without_norm.apply(100.0), 200.0); }
}