#![allow(dead_code)]
#![allow(clippy::field_reassign_with_default)]
use forjar::core::policy_coverage::{
compute_coverage, coverage_to_json, format_coverage, PolicyCoverage,
};
use forjar::core::types::{
ComplianceMapping, ForjarConfig, PolicyRule, PolicyRuleType, Resource, ResourceType,
};
use std::collections::HashMap;
fn make_config_with_resources(resources: &[(&str, ResourceType, Option<&str>)]) -> ForjarConfig {
let mut config = ForjarConfig::default();
for (name, rtype, owner) in resources {
let resource = Resource {
resource_type: rtype.clone(),
owner: owner.map(|o| o.to_string()),
..Default::default()
};
config.resources.insert(name.to_string(), resource);
}
config
}
fn require_policy(rtype: &str) -> PolicyRule {
PolicyRule {
id: Some(format!("P-{rtype}")),
rule_type: PolicyRuleType::Require,
message: "test require".into(),
resource_type: Some(rtype.into()),
tag: None,
field: Some("owner".into()),
condition_field: None,
condition_value: None,
max_count: None,
min_count: None,
severity: None,
remediation: None,
compliance: vec![],
}
}
#[test]
fn format_coverage_percentage() {
let mut config = make_config_with_resources(&[
("f1", ResourceType::File, None),
("p1", ResourceType::Package, None),
]);
config.policies = vec![require_policy("file")];
let cov = compute_coverage(&config);
let text = format_coverage(&cov);
assert!(text.contains("50.0%"));
assert!(text.contains("1/2"));
}
#[test]
fn format_coverage_uncovered_listed() {
let mut config = make_config_with_resources(&[
("f1", ResourceType::File, None),
("pkg-nginx", ResourceType::Package, None),
]);
config.policies = vec![require_policy("file")];
let cov = compute_coverage(&config);
let text = format_coverage(&cov);
assert!(text.contains("pkg-nginx"));
assert!(text.contains("Uncovered"));
}
#[test]
fn format_coverage_by_type() {
let mut config = make_config_with_resources(&[("f1", ResourceType::File, None)]);
config.policies = vec![require_policy("file")];
let cov = compute_coverage(&config);
let text = format_coverage(&cov);
assert!(text.contains("require:"));
}
#[test]
fn format_coverage_frameworks() {
let mut policy = require_policy("file");
policy.compliance = vec![ComplianceMapping {
framework: "NIST".into(),
control: "AC-3".into(),
}];
let mut config = make_config_with_resources(&[("f1", ResourceType::File, None)]);
config.policies = vec![policy];
let cov = compute_coverage(&config);
let text = format_coverage(&cov);
assert!(text.contains("NIST"));
}
#[test]
fn coverage_json_output() {
let mut config = make_config_with_resources(&[("f1", ResourceType::File, None)]);
config.policies = vec![require_policy("file")];
let cov = compute_coverage(&config);
let json = coverage_to_json(&cov);
assert_eq!(json["total_resources"], 1);
assert_eq!(json["covered_resources"], 1);
assert_eq!(json["fully_covered"], true);
}
#[test]
fn coverage_json_uncovered() {
let config = make_config_with_resources(&[("orphan", ResourceType::File, None)]);
let cov = compute_coverage(&config);
let json = coverage_to_json(&cov);
assert_eq!(json["fully_covered"], false);
let uncovered = json["uncovered"].as_array().unwrap();
assert_eq!(uncovered.len(), 1);
assert_eq!(uncovered[0], "orphan");
}
#[test]
fn coverage_percent_empty() {
let cov = PolicyCoverage {
total_resources: 0,
covered_resources: 0,
uncovered: vec![],
per_resource: HashMap::new(),
by_type: HashMap::new(),
frameworks: std::collections::HashSet::new(),
};
assert!((cov.coverage_percent() - 100.0).abs() < f64::EPSILON);
assert!(cov.fully_covered());
}
#[test]
fn coverage_percent_half() {
let cov = PolicyCoverage {
total_resources: 4,
covered_resources: 2,
uncovered: vec!["a".into(), "b".into()],
per_resource: HashMap::new(),
by_type: HashMap::new(),
frameworks: std::collections::HashSet::new(),
};
assert!((cov.coverage_percent() - 50.0).abs() < f64::EPSILON);
assert!(!cov.fully_covered());
}