use crate::verdict::Severity;
pub fn short_sha(sha: &str) -> &str {
if sha.len() >= 7 { &sha[..7] } else { sha }
}
pub fn is_approver_independent(is_commit_author: bool, is_pr_author: bool) -> bool {
!is_commit_author && !is_pr_author
}
pub fn signature_severity(unsigned_count: usize) -> Severity {
if unsigned_count == 0 {
Severity::Pass
} else {
Severity::Error
}
}
pub fn build_provenance_severity(unverified_count: usize) -> Severity {
if unverified_count == 0 {
Severity::Pass
} else {
Severity::Error
}
}
pub fn required_status_checks_severity(fail_count: usize) -> Severity {
if fail_count == 0 {
Severity::Pass
} else {
Severity::Error
}
}
pub fn branch_history_severity(unprotected_count: usize) -> Severity {
if unprotected_count == 0 {
Severity::Pass
} else {
Severity::Error
}
}
pub fn branch_protection_enforcement_severity(non_enforced_count: usize) -> Severity {
if non_enforced_count == 0 {
Severity::Pass
} else {
Severity::Error
}
}
pub fn two_party_review_severity(independent_count: usize) -> Severity {
if independent_count >= 2 {
Severity::Pass
} else {
Severity::Error
}
}
pub fn hosted_build_severity(non_hosted_count: usize) -> Severity {
if non_hosted_count == 0 {
Severity::Pass
} else {
Severity::Error
}
}
pub fn provenance_authenticity_severity(unauthenticated_count: usize) -> Severity {
if unauthenticated_count == 0 {
Severity::Pass
} else {
Severity::Error
}
}
pub fn build_isolation_severity(non_isolated_count: usize) -> Severity {
if non_isolated_count == 0 {
Severity::Pass
} else {
Severity::Error
}
}
pub fn dependency_signature_severity(unsigned_count: usize) -> Severity {
if unsigned_count == 0 {
Severity::Pass
} else {
Severity::Error
}
}
pub fn container_signature_severity(all_signed: bool, count: u32) -> Severity {
if count == 0 {
Severity::Warning
} else if all_signed {
Severity::Pass
} else {
Severity::Error
}
}
pub fn container_provenance_severity(all_have_provenance: bool, count: u32) -> Severity {
if count == 0 {
Severity::Warning
} else if all_have_provenance {
Severity::Pass
} else {
Severity::Error
}
}
pub fn stale_review_severity(stale_count: usize) -> Severity {
if stale_count == 0 {
Severity::Pass
} else {
Severity::Error
}
}
pub fn description_quality_severity(body_length: usize, min_length: usize) -> Severity {
if body_length >= min_length {
Severity::Pass
} else {
Severity::Error
}
}
pub fn merge_commit_policy_severity(merge_count: usize) -> Severity {
if merge_count == 0 {
Severity::Pass
} else {
Severity::Error
}
}
pub fn conventional_title_severity(is_conventional: bool) -> Severity {
if is_conventional {
Severity::Pass
} else {
Severity::Error
}
}
pub fn security_file_change_severity(sensitive_count: usize) -> Severity {
if sensitive_count == 0 {
Severity::Pass
} else {
Severity::Error
}
}
pub fn release_traceability_severity(linked_cr_count: usize) -> Severity {
if linked_cr_count > 0 {
Severity::Pass
} else {
Severity::Error
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn is_approver_independent_exhaustive_equivalence() {
for &ca in &[false, true] {
for &pa in &[false, true] {
let result = is_approver_independent(ca, pa);
let spec = !ca && !pa;
assert_eq!(
result, spec,
"is_approver_independent({ca}, {pa}): got {result}, spec {spec}"
);
}
}
}
#[test]
fn signature_severity_equivalence() {
assert_eq!(signature_severity(0), Severity::Pass);
for count in 1..=100 {
assert_eq!(
signature_severity(count),
Severity::Error,
"signature_severity({count}) should be Error"
);
}
}
#[test]
fn build_provenance_severity_equivalence() {
assert_eq!(build_provenance_severity(0), Severity::Pass);
for count in 1..=100 {
assert_eq!(
build_provenance_severity(count),
Severity::Error,
"build_provenance_severity({count}) should be Error"
);
}
}
#[test]
fn classify_scope_exhaustive_equivalence() {
use crate::scope::classify_scope;
for files in 0..=20usize {
for comps in 0..=20usize {
let result = classify_scope(files, comps);
let spec = if files <= 1 {
Severity::Pass
} else if comps <= 1 {
Severity::Pass
} else if comps == 2 {
Severity::Warning
} else {
Severity::Error
};
assert_eq!(
result, spec,
"classify_scope({files}, {comps}): got {result:?}, spec {spec:?}"
);
}
}
}
#[test]
fn required_status_checks_severity_equivalence() {
assert_eq!(required_status_checks_severity(0), Severity::Pass);
for count in 1..=10 {
assert_eq!(
required_status_checks_severity(count),
Severity::Error,
"required_status_checks_severity({count}) should be Error"
);
}
}
#[test]
fn branch_history_severity_equivalence() {
assert_eq!(branch_history_severity(0), Severity::Pass);
for count in 1..=10 {
assert_eq!(
branch_history_severity(count),
Severity::Error,
"branch_history_severity({count}) should be Error"
);
}
}
#[test]
fn branch_protection_enforcement_severity_equivalence() {
assert_eq!(branch_protection_enforcement_severity(0), Severity::Pass);
for count in 1..=10 {
assert_eq!(
branch_protection_enforcement_severity(count),
Severity::Error,
"branch_protection_enforcement_severity({count}) should be Error"
);
}
}
#[test]
fn two_party_review_severity_equivalence() {
assert_eq!(two_party_review_severity(0), Severity::Error);
assert_eq!(two_party_review_severity(1), Severity::Error);
assert_eq!(two_party_review_severity(2), Severity::Pass);
for count in 3..=10 {
assert_eq!(
two_party_review_severity(count),
Severity::Pass,
"two_party_review_severity({count}) should be Pass"
);
}
}
#[test]
fn hosted_build_severity_equivalence() {
assert_eq!(hosted_build_severity(0), Severity::Pass);
for count in 1..=10 {
assert_eq!(
hosted_build_severity(count),
Severity::Error,
"hosted_build_severity({count}) should be Error"
);
}
}
#[test]
fn provenance_authenticity_severity_equivalence() {
assert_eq!(provenance_authenticity_severity(0), Severity::Pass);
for count in 1..=10 {
assert_eq!(
provenance_authenticity_severity(count),
Severity::Error,
"provenance_authenticity_severity({count}) should be Error"
);
}
}
#[test]
fn build_isolation_severity_equivalence() {
assert_eq!(build_isolation_severity(0), Severity::Pass);
for count in 1..=10 {
assert_eq!(
build_isolation_severity(count),
Severity::Error,
"build_isolation_severity({count}) should be Error"
);
}
}
#[test]
fn stale_review_severity_equivalence() {
assert_eq!(stale_review_severity(0), Severity::Pass);
for count in 1..=10 {
assert_eq!(
stale_review_severity(count),
Severity::Error,
"stale_review_severity({count}) should be Error"
);
}
}
#[test]
fn description_quality_severity_equivalence() {
let min = 10;
for len in 0..min {
assert_eq!(
description_quality_severity(len, min),
Severity::Error,
"description_quality_severity({len}, {min}) should be Error"
);
}
for len in min..=50 {
assert_eq!(
description_quality_severity(len, min),
Severity::Pass,
"description_quality_severity({len}, {min}) should be Pass"
);
}
}
#[test]
fn merge_commit_policy_severity_equivalence() {
assert_eq!(merge_commit_policy_severity(0), Severity::Pass);
for count in 1..=10 {
assert_eq!(
merge_commit_policy_severity(count),
Severity::Error,
"merge_commit_policy_severity({count}) should be Error"
);
}
}
#[test]
fn conventional_title_severity_equivalence() {
assert_eq!(conventional_title_severity(true), Severity::Pass);
assert_eq!(conventional_title_severity(false), Severity::Error);
}
#[test]
fn security_file_change_severity_equivalence() {
assert_eq!(security_file_change_severity(0), Severity::Pass);
for count in 1..=10 {
assert_eq!(
security_file_change_severity(count),
Severity::Error,
"security_file_change_severity({count}) should be Error"
);
}
}
#[test]
fn release_traceability_severity_equivalence() {
assert_eq!(release_traceability_severity(0), Severity::Error);
for count in 1..=10 {
assert_eq!(
release_traceability_severity(count),
Severity::Pass,
"release_traceability_severity({count}) should be Pass"
);
}
}
#[test]
fn dependency_signature_severity_equivalence() {
assert_eq!(dependency_signature_severity(0), Severity::Pass);
for count in 1..=100 {
assert_eq!(
dependency_signature_severity(count),
Severity::Error,
"dependency_signature_severity({count}) should be Error"
);
}
}
#[test]
fn container_signature_severity_equivalence() {
assert_eq!(container_signature_severity(true, 0), Severity::Warning);
assert_eq!(container_signature_severity(false, 0), Severity::Warning);
assert_eq!(container_signature_severity(true, 1), Severity::Pass);
assert_eq!(container_signature_severity(true, 5), Severity::Pass);
assert_eq!(container_signature_severity(false, 1), Severity::Error);
assert_eq!(container_signature_severity(false, 10), Severity::Error);
}
#[test]
fn container_provenance_severity_equivalence() {
assert_eq!(container_provenance_severity(true, 0), Severity::Warning);
assert_eq!(container_provenance_severity(false, 0), Severity::Warning);
assert_eq!(container_provenance_severity(true, 1), Severity::Pass);
assert_eq!(container_provenance_severity(true, 5), Severity::Pass);
assert_eq!(container_provenance_severity(false, 1), Severity::Error);
assert_eq!(container_provenance_severity(false, 10), Severity::Error);
}
}