use do_memory_core::SelfLearningMemory;
use do_memory_mcp::mcp::tools::advanced_pattern_analysis::{
AdvancedPatternAnalysisInput, AdvancedPatternAnalysisTool, AnalysisConfig, AnalysisType,
};
use std::collections::HashMap;
use std::sync::Arc;
#[tokio::test]
async fn test_input_sanitization() {
let memory = Arc::new(SelfLearningMemory::new());
let tool = AdvancedPatternAnalysisTool::new(memory);
let mut malicious_data = HashMap::new();
malicious_data.insert(
"large".to_string(),
vec![f64::MAX, f64::MAX / 2.0, f64::MAX / 4.0],
);
malicious_data.insert(
"small".to_string(),
vec![
f64::MIN_POSITIVE,
f64::MIN_POSITIVE * 2.0,
f64::MIN_POSITIVE * 4.0,
],
);
malicious_data.insert(
"mixed".to_string(),
vec![0.0, f64::INFINITY, f64::NEG_INFINITY, f64::NAN],
);
let input = AdvancedPatternAnalysisInput {
analysis_type: AnalysisType::Statistical,
time_series_data: malicious_data,
config: None,
};
let result = tool.execute(input).await;
match result {
Ok(_) => {
}
Err(e) => {
assert!(!e.to_string().is_empty());
}
}
}
#[tokio::test]
async fn test_resource_limits() {
let memory = Arc::new(SelfLearningMemory::new());
let tool = AdvancedPatternAnalysisTool::new(memory);
let mut large_data = HashMap::new();
let max_series: Vec<f64> = (0..10_000).map(|x| x as f64).collect();
large_data.insert("max_size".to_string(), max_series);
let input = AdvancedPatternAnalysisInput {
analysis_type: AnalysisType::Statistical,
time_series_data: large_data,
config: Some(AnalysisConfig {
max_data_points: Some(10_000),
parallel_processing: Some(false),
..Default::default()
}),
};
let result = tool.execute(input).await;
match result {
Ok(output) => {
assert!(output.performance.memory_usage_bytes < 500 * 1024 * 1024); }
Err(e) => {
assert!(e.to_string().contains("data") || e.to_string().contains("size"));
}
}
}
#[tokio::test]
async fn test_numerical_stability_vulnerabilities() {
let memory = Arc::new(SelfLearningMemory::new());
let tool = AdvancedPatternAnalysisTool::new(memory);
let test_cases = vec![
("zeros", vec![0.0, 0.0, 0.0, 0.0, 0.0]),
("constants", vec![1.0, 1.0, 1.0, 1.0, 1.0]),
("near_zero", vec![1e-15, 2e-15, 3e-15, 4e-15, 5e-15]),
("large_variance", vec![1e-10, 1e10, 1e-10, 1e10, 1e-10]),
("division_triggers", vec![1.0, 2.0, 4.0, 8.0, 16.0]), ];
for (name, series) in test_cases {
let mut data = HashMap::new();
data.insert(name.to_string(), series);
let input = AdvancedPatternAnalysisInput {
analysis_type: AnalysisType::Comprehensive,
time_series_data: data,
config: None,
};
let result = tool.execute(input).await;
match result {
Ok(output) => {
assert!(output.performance.total_time_ms < 30_000); }
Err(e) => {
assert!(!e.to_string().is_empty());
}
}
}
}
#[tokio::test]
async fn test_error_information_leakage() {
let memory = Arc::new(SelfLearningMemory::new());
let tool = AdvancedPatternAnalysisTool::new(memory);
let error_cases = vec![
("empty_data", HashMap::new()),
("insufficient_data", {
let mut data = HashMap::new();
data.insert("small".to_string(), vec![1.0, 2.0]);
data
}),
("nan_data", {
let mut data = HashMap::new();
data.insert("nan".to_string(), vec![1.0, f64::NAN, 3.0]);
data
}),
];
for (case_name, data) in error_cases {
let input = AdvancedPatternAnalysisInput {
analysis_type: AnalysisType::Statistical,
time_series_data: data,
config: None,
};
let result = tool.execute(input).await;
assert!(result.is_err(), "Case {} should fail", case_name);
let error = result.unwrap_err();
let error_msg = error.to_string();
assert!(!error_msg.contains("panic"));
assert!(!error_msg.contains("unwrap"));
assert!(!error_msg.contains("internal"));
assert!(!error_msg.contains("debug"));
assert!(error_msg.len() > 10);
assert!(error_msg.len() < 500); }
}
#[tokio::test]
async fn test_input_data_immutability() {
let memory = Arc::new(SelfLearningMemory::new());
let tool = AdvancedPatternAnalysisTool::new(memory);
let original_data = vec![1.0, 2.0, 3.0, 4.0, 5.0];
let mut data = HashMap::new();
data.insert("test".to_string(), original_data.clone());
let input = AdvancedPatternAnalysisInput {
analysis_type: AnalysisType::Statistical,
time_series_data: data.clone(),
config: None,
};
let result = tool.execute(input).await;
assert!(result.is_ok());
assert_eq!(data.get("test").unwrap(), &original_data);
}
#[tokio::test]
async fn test_timeout_protection() {
let memory = Arc::new(SelfLearningMemory::new());
let tool = AdvancedPatternAnalysisTool::new(memory);
let mut data = HashMap::new();
let large_series: Vec<f64> = (0..1000).map(|x| x as f64).collect();
for i in 0..20 {
data.insert(format!("var_{}", i), large_series.clone());
}
let input = AdvancedPatternAnalysisInput {
analysis_type: AnalysisType::Comprehensive,
time_series_data: data,
config: Some(AnalysisConfig {
parallel_processing: Some(false), max_data_points: Some(100_000),
..Default::default()
}),
};
let result =
tokio::time::timeout(std::time::Duration::from_secs(30), tool.execute(input)).await;
match result {
Ok(analysis_result) => {
assert!(analysis_result.is_ok() || analysis_result.is_err());
}
Err(_) => {
}
}
}
#[tokio::test]
async fn test_output_sanitization() {
let memory = Arc::new(SelfLearningMemory::new());
let tool = AdvancedPatternAnalysisTool::new(memory);
let mut data = HashMap::new();
data.insert("normal".to_string(), vec![1.0, 2.0, 3.0, 4.0, 5.0]);
let input = AdvancedPatternAnalysisInput {
analysis_type: AnalysisType::Comprehensive,
time_series_data: data,
config: None,
};
let result = tool.execute(input).await;
assert!(result.is_ok());
let output = result.unwrap();
let json_result = serde_json::to_string(&output);
assert!(json_result.is_ok());
let json_str = json_result.unwrap();
assert!(json_str.len() > 100); assert!(json_str.len() < 1_000_000); }
#[tokio::test]
async fn test_malformed_configuration_resistance() {
let memory = Arc::new(SelfLearningMemory::new());
let tool = AdvancedPatternAnalysisTool::new(memory);
let mut data = HashMap::new();
data.insert("test".to_string(), vec![1.0, 2.0, 3.0, 4.0, 5.0]);
let extreme_configs = vec![
AnalysisConfig {
significance_level: Some(0.0), forecast_horizon: Some(1), anomaly_sensitivity: Some(0.0), enable_causal_inference: Some(true),
max_data_points: Some(1), parallel_processing: Some(false),
},
AnalysisConfig {
significance_level: Some(1.0), forecast_horizon: Some(100), anomaly_sensitivity: Some(1.0), enable_causal_inference: Some(false),
max_data_points: Some(1_000_000), parallel_processing: Some(true),
},
];
for config in extreme_configs {
let input = AdvancedPatternAnalysisInput {
analysis_type: AnalysisType::Comprehensive,
time_series_data: data.clone(),
config: Some(config),
};
let result = tool.execute(input).await;
match result {
Ok(_) => {
}
Err(e) => {
assert!(!e.to_string().contains("panic"));
}
}
}
}