use pmat::services::deep_context::*;
use std::fs;
use std::path::PathBuf;
use tempfile::tempdir;
#[test]
fn test_deep_context_config_default() {
let config = DeepContextConfig::default();
assert!(config.period_days > 0);
assert!(config.parallel > 0);
assert!(!config.include_analyses.is_empty());
}
#[test]
fn test_deep_context_config_with_auto_scaling() {
let config = DeepContextConfig::with_auto_scaling();
assert!(config.max_depth.is_some());
assert!(config.parallel > 0);
}
#[test]
fn test_deep_context_config_custom() {
let config = DeepContextConfig {
max_depth: Some(5),
period_days: 30,
include_analyses: vec![AnalysisType::Ast, AnalysisType::Complexity],
parallel: 4,
..DeepContextConfig::default()
};
assert_eq!(config.max_depth, Some(5));
assert_eq!(config.period_days, 30);
assert_eq!(config.include_analyses.len(), 2);
assert_eq!(config.parallel, 4);
}
#[test]
fn test_analysis_type_enum_variants() {
use AnalysisType::*;
let types = vec![
Ast,
Complexity,
Churn,
Dag,
DeadCode,
DuplicateCode,
Satd,
Provability,
TechnicalDebtGradient,
BigO,
];
assert_eq!(types.len(), 10);
}
#[test]
fn test_complexity_thresholds_construction() {
let thresholds = ComplexityThresholds {
max_cyclomatic: 10,
max_cognitive: 15,
};
assert_eq!(thresholds.max_cyclomatic, 10);
assert_eq!(thresholds.max_cognitive, 15);
}
#[test]
fn test_cache_strategy_variants() {
use CacheStrategy::*;
let strategies = [Normal, ForceRefresh, Offline];
assert_eq!(strategies.len(), 3);
}
#[test]
fn test_deep_context_analyzer_creation_default_config() {
let config = DeepContextConfig::default();
let analyzer = DeepContextAnalyzer::new(config);
drop(analyzer);
}
#[test]
fn test_deep_context_analyzer_creation_custom_config() {
let config = DeepContextConfig {
max_depth: Some(10),
include_analyses: vec![AnalysisType::Complexity, AnalysisType::Churn],
period_days: 60,
parallel: 8,
..DeepContextConfig::default()
};
let analyzer = DeepContextAnalyzer::new(config);
drop(analyzer);
}
#[test]
fn test_deep_context_analyzer_creation_minimal_config() {
let config = DeepContextConfig {
max_depth: Some(1),
include_analyses: vec![], period_days: 1,
parallel: 1,
..DeepContextConfig::default()
};
let analyzer = DeepContextAnalyzer::new(config);
drop(analyzer);
}
#[tokio::test]
async fn test_analyze_project_nonexistent_path() {
let config = DeepContextConfig::default();
let analyzer = DeepContextAnalyzer::new(config);
let nonexistent = PathBuf::from("/nonexistent/path/to/project");
let result = analyzer.analyze_project(&nonexistent).await;
assert!(result.is_err());
}
#[tokio::test]
async fn test_analyze_project_empty_directory() {
let temp_dir = tempdir().unwrap();
let config = DeepContextConfig::default();
let analyzer = DeepContextAnalyzer::new(config);
let result = analyzer
.analyze_project(&temp_dir.path().to_path_buf())
.await;
match result {
Ok(_) | Err(_) => {}
}
}
#[tokio::test]
async fn test_analyze_project_with_single_file() {
let temp_dir = tempdir().unwrap();
let rust_file = temp_dir.path().join("main.rs");
fs::write(
&rust_file,
r#"
fn main() {
println!("Hello, world!");
}
"#,
)
.unwrap();
let config = DeepContextConfig::default();
let analyzer = DeepContextAnalyzer::new(config);
let result = analyzer
.analyze_project(&temp_dir.path().to_path_buf())
.await;
if let Ok(_) = result {}
}
#[tokio::test]
async fn test_analyze_single_file_nonexistent() {
let nonexistent = PathBuf::from("/nonexistent/file.rs");
let result = analyze_single_file(&nonexistent).await;
assert!(result.is_err());
}
#[tokio::test]
async fn test_analyze_single_file_rust() {
let temp_dir = tempdir().unwrap();
let rust_file = temp_dir.path().join("test.rs");
fs::write(
&rust_file,
r#"
pub fn add(a: i32, b: i32) -> i32 {
a + b
}
"#,
)
.unwrap();
let result = analyze_single_file(&rust_file).await;
if let Ok(context) = result {
assert!(context.path.ends_with("test.rs"));
}
}
#[tokio::test]
async fn test_analyze_single_file_empty_file() {
let temp_dir = tempdir().unwrap();
let empty_file = temp_dir.path().join("empty.rs");
fs::write(&empty_file, "").unwrap();
let result = analyze_single_file(&empty_file).await;
match result {
Ok(_) | Err(_) => {}
}
}
#[tokio::test]
async fn test_analyze_rust_language() {
let temp_dir = tempdir().unwrap();
let rust_file = temp_dir.path().join("lib.rs");
fs::write(
&rust_file,
r#"
pub struct Calculator {
value: i32,
}
impl Calculator {
pub fn new() -> Self {
Self { value: 0 }
}
pub fn add(&mut self, n: i32) {
self.value += n;
}
}
"#,
)
.unwrap();
let result = analyze_rust_language(&rust_file).await;
if let Ok(items) = result {
assert!(!items.is_empty());
}
}
#[tokio::test]
#[ignore = "RED phase test - Python analysis incomplete"]
async fn test_analyze_python_language() {
let temp_dir = tempdir().unwrap();
let py_file = temp_dir.path().join("test.py");
fs::write(
&py_file,
r#"
class Calculator:
def __init__(self):
self.value = 0
def add(self, n):
self.value += n
return self.value
"#,
)
.unwrap();
let result = analyze_python_language(&py_file).await;
if let Ok(items) = result {
assert!(!items.is_empty());
}
}
#[tokio::test]
async fn test_analyze_typescript_language() {
let temp_dir = tempdir().unwrap();
let ts_file = temp_dir.path().join("test.ts");
fs::write(
&ts_file,
r#"
interface Calculator {
value: number;
add(n: number): number;
}
class SimpleCalculator implements Calculator {
value: number = 0;
add(n: number): number {
this.value += n;
return this.value;
}
}
"#,
)
.unwrap();
let result = analyze_typescript_language(&ts_file).await;
if let Ok(items) = result {
assert!(!items.is_empty());
}
}
#[tokio::test]
async fn test_analyze_file_by_language_rust() {
let temp_dir = tempdir().unwrap();
let rust_file = temp_dir.path().join("test.rs");
fs::write(&rust_file, "fn test() {}").unwrap();
let result = analyze_file_by_language(&rust_file, "rust").await;
match result {
Ok(_) | Err(_) => {}
}
}
#[tokio::test]
async fn test_analyze_file_by_language_unknown() {
let temp_dir = tempdir().unwrap();
let unknown_file = temp_dir.path().join("test.xyz");
fs::write(&unknown_file, "some content").unwrap();
let result = analyze_file_by_language(&unknown_file, "unknown-lang").await;
match result {
Ok(_) | Err(_) => {}
}
}
#[tokio::test]
async fn test_analyze_churn_nonexistent_path() {
let nonexistent = PathBuf::from("/nonexistent/path");
let result = analyze_churn(&nonexistent, 30).await;
assert!(result.is_err());
}
#[tokio::test]
async fn test_analyze_churn_non_git_repo() {
let temp_dir = tempdir().unwrap();
let result = analyze_churn(temp_dir.path(), 30).await;
match result {
Ok(_) | Err(_) => {}
}
}
#[tokio::test]
async fn test_analyze_churn_zero_days() {
let temp_dir = tempdir().unwrap();
let result = analyze_churn(temp_dir.path(), 0).await;
match result {
Ok(_) | Err(_) => {}
}
}
#[tokio::test]
async fn test_analyze_churn_very_large_days() {
let temp_dir = tempdir().unwrap();
let result = analyze_churn(temp_dir.path(), u32::MAX).await;
match result {
Ok(_) | Err(_) => {}
}
}
#[tokio::test]
async fn test_format_as_json_empty_context() {
let config = DeepContextConfig::default();
let analyzer = DeepContextAnalyzer::new(config);
let empty_context = DeepContext::default();
let result = analyzer.format_as_json(&empty_context);
if let Ok(json) = result {
assert!(!json.is_empty());
assert!(json.contains("{")); }
}
#[tokio::test]
async fn test_format_as_sarif_empty_context() {
let config = DeepContextConfig::default();
let analyzer = DeepContextAnalyzer::new(config);
let empty_context = DeepContext::default();
let result = analyzer.format_as_sarif(&empty_context);
if let Ok(sarif) = result {
assert!(!sarif.is_empty());
assert!(sarif.contains("sarif") || sarif.contains("version"));
}
}
#[tokio::test]
async fn test_format_as_comprehensive_markdown() {
let config = DeepContextConfig::default();
let analyzer = DeepContextAnalyzer::new(config);
let empty_context = DeepContext::default();
let result = analyzer.format_as_comprehensive_markdown_legacy(&empty_context);
if let Ok(markdown) = result {
assert!(!markdown.is_empty());
assert!(markdown.contains("#") || markdown.contains("##"));
}
}
#[test]
fn test_confidence_level_variants() {
use ConfidenceLevel::*;
let levels = [High, Medium, Low];
assert_eq!(levels.len(), 3);
}
#[test]
fn test_priority_enum_variants() {
use Priority::*;
let priorities = [Critical, High, Medium, Low];
assert_eq!(priorities.len(), 4);
}
#[test]
fn test_impact_enum_variants() {
use Impact::*;
let impacts = [High, Medium, Low];
assert_eq!(impacts.len(), 3);
}
#[test]
fn test_node_type_enum_variants() {
use NodeType::*;
let types = [File, Directory];
assert_eq!(types.len(), 2);
}
#[tokio::test]
async fn test_analyze_project_max_depth_zero() {
let temp_dir = tempdir().unwrap();
let config = DeepContextConfig {
max_depth: Some(0),
..DeepContextConfig::default()
};
let analyzer = DeepContextAnalyzer::new(config);
let result = analyzer
.analyze_project(&temp_dir.path().to_path_buf())
.await;
match result {
Ok(_) | Err(_) => {}
}
}
#[tokio::test]
async fn test_analyze_single_file_very_large_file() {
let temp_dir = tempdir().unwrap();
let large_file = temp_dir.path().join("large.rs");
let content = (0..1000)
.map(|i| format!("fn func_{}() {{}}\n", i))
.collect::<String>();
fs::write(&large_file, content).unwrap();
let result = analyze_single_file(&large_file).await;
match result {
Ok(_) | Err(_) => {}
}
}