use crate::domain::finding::Finding;
use crate::domain::rule_id::RuleId;
use crate::gates::paths::ki_records;
use crate::gates::{GateCtx, GateResult, Violation, read_text};
pub const CITES: &[RuleId] = &[RuleId::RecordWalksTheMechanism];
pub fn run(ctx: &GateCtx, args: &[String]) -> GateResult {
let mut bad = String::new();
for record in ki_records(ctx, args)? {
if !read_text(ctx, &record)?
.lines()
.any(|line| line == "## How it works")
{
bad.push(' ');
bad.push_str(record.as_str());
}
}
if bad.is_empty() {
Ok(vec![])
} else {
Ok(vec![Violation::Finding(Finding::global(
RuleId::RecordWalksTheMechanism,
bad.trim_start().to_string(),
))])
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::gates::tests_support::ki_fixture_body;
#[test]
fn accepts_the_anchored_heading() {
let dir = ki_fixture_body("# Vendor issue\n## How it works\nRun.\n");
let ctx = GateCtx::new(dir.path().to_str().unwrap());
assert!(run(&ctx, &[]).unwrap().is_empty());
}
#[test]
fn rejects_a_record_without_the_walkthrough() {
let dir = ki_fixture_body("# Vendor issue\n## Mechanism\nRun.\n");
let ctx = GateCtx::new(dir.path().to_str().unwrap());
let out: Vec<String> = run(&ctx, &[])
.unwrap()
.iter()
.map(ToString::to_string)
.collect();
assert_eq!(out.len(), 1);
assert!(out[0].starts_with("FAIL known-issues:a-record-walks-the-mechanism: "));
}
}