#![cfg_attr(coverage_nightly, coverage(off))]
use super::output::xml_escape;
use super::types::{OutputFormat, ValidateReadmeCmd};
#[allow(unused_imports)]
use crate::services::hallucination_detector::ValidationStatus;
use std::io::Write;
use std::path::PathBuf;
use std::process::ExitCode;
use tempfile::NamedTempFile;
#[test]
fn test_xml_escape_no_special_chars() {
assert_eq!(xml_escape("hello"), "hello");
assert_eq!(xml_escape("simple text"), "simple text");
assert_eq!(xml_escape("123abc"), "123abc");
}
#[test]
fn test_xml_escape_ampersand() {
assert_eq!(xml_escape("a & b"), "a & b");
assert_eq!(xml_escape("&&"), "&&");
assert_eq!(xml_escape("Tom & Jerry"), "Tom & Jerry");
}
#[test]
fn test_xml_escape_angle_brackets() {
assert_eq!(xml_escape("<tag>"), "<tag>");
assert_eq!(xml_escape("a < b > c"), "a < b > c");
assert_eq!(xml_escape("<>"), "<>");
}
#[test]
fn test_xml_escape_quotes() {
assert_eq!(xml_escape("\"quoted\""), ""quoted"");
assert_eq!(xml_escape("'single'"), "'single'");
assert_eq!(xml_escape("\"'mixed'\""), ""'mixed'"");
}
#[test]
fn test_xml_escape_all_special_chars() {
assert_eq!(
xml_escape("<tag attr=\"val\" data='x' & y>"),
"<tag attr="val" data='x' & y>"
);
}
#[test]
fn test_xml_escape_empty_string() {
assert_eq!(xml_escape(""), "");
}
#[test]
fn test_xml_escape_unicode() {
assert_eq!(xml_escape("hello"), "hello");
assert_eq!(xml_escape("<unicode>"), "<unicode>");
}
#[test]
fn test_output_format_debug() {
assert_eq!(format!("{:?}", OutputFormat::Text), "Text");
assert_eq!(format!("{:?}", OutputFormat::Json), "Json");
assert_eq!(format!("{:?}", OutputFormat::Junit), "Junit");
}
#[test]
fn test_output_format_clone() {
let format = OutputFormat::Json;
let cloned = format;
assert!(matches!(cloned, OutputFormat::Json));
}
#[test]
fn test_validate_readme_cmd_defaults() {
let cmd = ValidateReadmeCmd {
targets: vec![PathBuf::from("README.md")],
deep_context: PathBuf::from("deep_context.md"),
verified_threshold: 0.9,
contradiction_threshold: 0.3,
fail_on_contradiction: true,
fail_on_unverified: false,
output: OutputFormat::Text,
failures_only: false,
verbose: false,
};
assert_eq!(cmd.verified_threshold, 0.9);
assert_eq!(cmd.contradiction_threshold, 0.3);
assert!(cmd.fail_on_contradiction);
assert!(!cmd.fail_on_unverified);
assert!(!cmd.failures_only);
assert!(!cmd.verbose);
}
#[test]
fn test_validate_readme_cmd_with_multiple_targets() {
let cmd = ValidateReadmeCmd {
targets: vec![
PathBuf::from("README.md"),
PathBuf::from("CLAUDE.md"),
PathBuf::from("AGENT.md"),
],
deep_context: PathBuf::from("context.md"),
verified_threshold: 0.8,
contradiction_threshold: 0.4,
fail_on_contradiction: false,
fail_on_unverified: true,
output: OutputFormat::Json,
failures_only: true,
verbose: true,
};
assert_eq!(cmd.targets.len(), 3);
assert_eq!(cmd.verified_threshold, 0.8);
assert_eq!(cmd.contradiction_threshold, 0.4);
assert!(!cmd.fail_on_contradiction);
assert!(cmd.fail_on_unverified);
assert!(cmd.failures_only);
assert!(cmd.verbose);
}
#[test]
fn test_validate_readme_cmd_custom_thresholds() {
let cmd = ValidateReadmeCmd {
targets: vec![PathBuf::from("test.md")],
deep_context: PathBuf::from("dc.md"),
verified_threshold: 0.5,
contradiction_threshold: 0.1,
fail_on_contradiction: true,
fail_on_unverified: true,
output: OutputFormat::Junit,
failures_only: false,
verbose: false,
};
assert_eq!(cmd.verified_threshold, 0.5);
assert_eq!(cmd.contradiction_threshold, 0.1);
}
#[test]
fn test_execute_missing_deep_context_file() {
let cmd = ValidateReadmeCmd {
targets: vec![PathBuf::from("README.md")],
deep_context: PathBuf::from("/nonexistent/path/deep_context.md"),
verified_threshold: 0.9,
contradiction_threshold: 0.3,
fail_on_contradiction: true,
fail_on_unverified: false,
output: OutputFormat::Text,
failures_only: false,
verbose: false,
};
let result = cmd.execute();
assert!(result.is_err());
let err = result.unwrap_err();
assert!(err.to_string().contains("Failed to read deep context"));
}
#[test]
fn test_execute_missing_target_file() {
let mut deep_context_file = NamedTempFile::new().unwrap();
writeln!(
deep_context_file,
r#"
Functions:
- main()
Supported languages:
- Rust
"#
)
.unwrap();
let cmd = ValidateReadmeCmd {
targets: vec![PathBuf::from("/nonexistent/README.md")],
deep_context: deep_context_file.path().to_path_buf(),
verified_threshold: 0.9,
contradiction_threshold: 0.3,
fail_on_contradiction: true,
fail_on_unverified: false,
output: OutputFormat::Text,
failures_only: false,
verbose: false,
};
let result = cmd.execute();
assert!(result.is_err());
let err = result.unwrap_err();
assert!(err.to_string().contains("Failed to read target file"));
}
#[test]
fn test_execute_success_with_verified_claims() {
let mut deep_context_file = NamedTempFile::new().unwrap();
writeln!(
deep_context_file,
r#"
Functions:
- analyze_complexity()
Supported languages:
- Rust
- TypeScript
"#
)
.unwrap();
let mut readme_file = NamedTempFile::new().unwrap();
writeln!(readme_file, "PMAT can analyze Rust code complexity.").unwrap();
let cmd = ValidateReadmeCmd {
targets: vec![readme_file.path().to_path_buf()],
deep_context: deep_context_file.path().to_path_buf(),
verified_threshold: 0.9,
contradiction_threshold: 0.3,
fail_on_contradiction: true,
fail_on_unverified: false,
output: OutputFormat::Text,
failures_only: false,
verbose: false,
};
let result = cmd.execute();
assert!(result.is_ok());
assert_eq!(result.unwrap(), ExitCode::SUCCESS);
}
#[test]
fn test_execute_fails_on_contradiction() {
let mut deep_context_file = NamedTempFile::new().unwrap();
writeln!(
deep_context_file,
r#"
Functions:
- analyze()
Supported languages:
- Rust
"#
)
.unwrap();
let mut readme_file = NamedTempFile::new().unwrap();
writeln!(readme_file, "PMAT can compile Rust code.").unwrap();
let cmd = ValidateReadmeCmd {
targets: vec![readme_file.path().to_path_buf()],
deep_context: deep_context_file.path().to_path_buf(),
verified_threshold: 0.9,
contradiction_threshold: 0.3,
fail_on_contradiction: true,
fail_on_unverified: false,
output: OutputFormat::Text,
failures_only: false,
verbose: false,
};
let result = cmd.execute();
assert!(result.is_ok());
assert_eq!(result.unwrap(), ExitCode::FAILURE);
}
#[test]
fn test_execute_fails_on_unverified_when_enabled() {
let mut deep_context_file = NamedTempFile::new().unwrap();
writeln!(
deep_context_file,
r#"
Functions:
- analyze()
Supported languages:
- Rust
"#
)
.unwrap();
let mut readme_file = NamedTempFile::new().unwrap();
writeln!(readme_file, "PMAT can analyze COBOL code.").unwrap();
let cmd = ValidateReadmeCmd {
targets: vec![readme_file.path().to_path_buf()],
deep_context: deep_context_file.path().to_path_buf(),
verified_threshold: 0.9,
contradiction_threshold: 0.3,
fail_on_contradiction: false,
fail_on_unverified: true,
output: OutputFormat::Text,
failures_only: false,
verbose: false,
};
let result = cmd.execute();
assert!(result.is_ok());
}
#[test]
fn test_execute_with_verbose_output() {
let mut deep_context_file = NamedTempFile::new().unwrap();
writeln!(
deep_context_file,
r#"
Supported languages:
- Rust
"#
)
.unwrap();
let mut readme_file = NamedTempFile::new().unwrap();
writeln!(readme_file, "PMAT can analyze Rust code.").unwrap();
let cmd = ValidateReadmeCmd {
targets: vec![readme_file.path().to_path_buf()],
deep_context: deep_context_file.path().to_path_buf(),
verified_threshold: 0.9,
contradiction_threshold: 0.3,
fail_on_contradiction: true,
fail_on_unverified: false,
output: OutputFormat::Text,
failures_only: false,
verbose: true,
};
let result = cmd.execute();
assert!(result.is_ok());
}
#[test]
fn test_execute_with_json_output() {
let mut deep_context_file = NamedTempFile::new().unwrap();
writeln!(
deep_context_file,
r#"
Supported languages:
- Rust
"#
)
.unwrap();
let mut readme_file = NamedTempFile::new().unwrap();
writeln!(readme_file, "PMAT can analyze Rust code.").unwrap();
let cmd = ValidateReadmeCmd {
targets: vec![readme_file.path().to_path_buf()],
deep_context: deep_context_file.path().to_path_buf(),
verified_threshold: 0.9,
contradiction_threshold: 0.3,
fail_on_contradiction: true,
fail_on_unverified: false,
output: OutputFormat::Json,
failures_only: false,
verbose: false,
};
let result = cmd.execute();
assert!(result.is_ok());
}
#[test]
fn test_execute_with_junit_output() {
let mut deep_context_file = NamedTempFile::new().unwrap();
writeln!(
deep_context_file,
r#"
Supported languages:
- Rust
"#
)
.unwrap();
let mut readme_file = NamedTempFile::new().unwrap();
writeln!(readme_file, "PMAT can analyze Rust code.").unwrap();
let cmd = ValidateReadmeCmd {
targets: vec![readme_file.path().to_path_buf()],
deep_context: deep_context_file.path().to_path_buf(),
verified_threshold: 0.9,
contradiction_threshold: 0.3,
fail_on_contradiction: true,
fail_on_unverified: false,
output: OutputFormat::Junit,
failures_only: false,
verbose: false,
};
let result = cmd.execute();
assert!(result.is_ok());
}