Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions chapel/smoke/two_repo_smoke.chpl
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,29 @@ proc main(): int {
ok &&= assertContains(blob, "\"total_weak_points\": 5", "aggregate total_weak_points (alpha only; beta errored)");
ok &&= assertContains(blob, "\"total_critical\": 1", "aggregate total_critical (alpha only)");

// --findingsOnly keeps exactly the results hasFindings() accepts. A clean
// scan whose adjudication was incomplete, or failed, must not vanish.
proc verdictOnly(v: string): RepoResult {
var r = makeRepoResult("repo-v", "/tmp/smoke/repo-v", 0, 0, 0, 10, "00");
r.verdict = v;
return r;
}
proc expectFindings(r: RepoResult, want: bool, tag: string): bool {
if hasFindings(r) != want {
writeln("smoke: FAIL [", tag, "] — hasFindings is ", hasFindings(r));
return false;
}
if verbose then writeln("smoke: ok [", tag, "]");
return true;
}
ok &&= expectFindings(verdictOnly(""), false, "clean scan, no adjudication: dropped");
ok &&= expectFindings(verdictOnly("pass"), false, "clean scan, verdict pass: dropped");
ok &&= expectFindings(verdictOnly("error"), true, "incomplete adjudication (error): kept");
ok &&= expectFindings(verdictOnly("fail"), true, "verdict fail with no weak points: kept");
ok &&= expectFindings(verdictOnly("warn"), true, "verdict warn with no weak points: kept");
ok &&= expectFindings(results[0], true, "weak points: kept");
ok &&= expectFindings(results[1], true, "scan error: kept");

try { remove(outputPath); } catch { }

if ok {
Expand Down
2 changes: 1 addition & 1 deletion chapel/src/MassPanic.chpl
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ module MassPanic {
// Always build via list to avoid Chapel array-shape mismatch on assignment.
var filteredList: list(RepoResult);
for r in resultsArr {
if !findingsOnly || r.weakPointCount > 0 || r.error != "" then
if !findingsOnly || hasFindings(r) then
filteredList.pushBack(r);
}
var filteredResults = filteredList.toArray();
Expand Down
10 changes: 10 additions & 0 deletions chapel/src/Protocol.chpl
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,16 @@ module Protocol {
var categories: list(CategoryCount);
}

// True when a result has anything to report: weak points, a scan error,
// or an adjudication verdict other than pass. `--findingsOnly` keeps
// exactly these results, so an incomplete adjudication (verdict "error")
// or a fail/warn verdict with no weak points is never silently dropped.
proc hasFindings(r: RepoResult): bool {
return r.weakPointCount > 0
|| r.error != ""
|| (r.verdict != "" && r.verdict != "pass");
}

record CategoryCount {
var name: string;
var count: int;
Expand Down
35 changes: 34 additions & 1 deletion src/assemblyline.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,14 @@ pub struct RepoResult {
pub report: Option<AssailReport>,
}

/// True when a result has anything to report: weak points or a scan error.
/// `--findings-only` keeps exactly these, so a repository whose scan failed is
/// never silently dropped from the report. Mirrors `hasFindings` in
/// `chapel/src/Protocol.chpl` (which also keeps non-pass adjudication verdicts).
pub fn has_findings(r: &RepoResult) -> bool {
r.weak_point_count > 0 || r.error.is_some()
}

/// Complete assemblyline report
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AssemblylineReport {
Expand Down Expand Up @@ -451,7 +459,7 @@ pub fn run_with_cache(

// Apply filters
if config.findings_only {
results.retain(|r| r.weak_point_count > 0);
results.retain(has_findings);
}
if config.min_findings > 0 {
results.retain(|r| r.weak_point_count >= config.min_findings);
Expand Down Expand Up @@ -543,6 +551,31 @@ pub fn write_report(report: &AssemblylineReport, path: &Path) -> Result<()> {
mod tests {
use super::*;

fn result(weak_points: usize, error: Option<&str>) -> RepoResult {
RepoResult {
repo_path: PathBuf::from("/tmp/r"),
repo_name: "r".into(),
weak_point_count: weak_points,
critical_count: 0,
high_count: 0,
total_files: 0,
total_lines: 0,
error: error.map(str::to_string),
fingerprint: None,
report: None,
}
}

#[test]
fn findings_only_keeps_failed_scans_and_drops_clean_ones() {
assert!(!has_findings(&result(0, None)), "a clean scan is dropped");
assert!(has_findings(&result(3, None)), "weak points are kept");
assert!(
has_findings(&result(0, Some("assail failed"))),
"a failed scan must never vanish from a findings-only report"
);
}

#[test]
fn test_is_source_file() {
assert!(is_source_file(Path::new("main.rs")));
Expand Down
Loading