use std::path::PathBuf;
use std::process::Command;
const ORACLE_FILTER: &str = "elixir_oracle";
const EXPECTED_IGNORED_LANES: usize = 5;
const CI_WORKFLOW: &str = ".github/workflows/ci.yml";
const TEST_JOB: &str = "test";
const ORACLE_STEP: &str = "Run the Elixir escaping oracles";
fn repo_root() -> PathBuf {
PathBuf::from(env!("CARGO_MANIFEST_DIR"))
}
#[test]
fn ignored_elixir_oracle_lanes_are_selected_and_nonzero() {
let test_binary = std::env::current_exe().expect("the running test binary has a path");
let output = Command::new(&test_binary)
.args(["--ignored", "--list", ORACLE_FILTER])
.output()
.unwrap_or_else(|error| panic!("list tests via {}: {error}", test_binary.display()));
assert!(
output.status.success(),
"listing ignored tests failed ({}):\n{}",
output.status,
String::from_utf8_lossy(&output.stderr)
);
let listing = String::from_utf8_lossy(&output.stdout);
let selected: Vec<&str> = listing
.lines()
.filter(|line| line.ends_with(": test"))
.map(|line| line.trim_end_matches(": test"))
.collect();
assert!(
!selected.is_empty(),
"`--ignored --list {ORACLE_FILTER}` selected NO tests. Every Elixir oracle is #[ignore]d, \
so a selection that resolves to zero means the CI step runs nothing and still exits 0 -- \
the exact green-that-examined-nothing this gate exists to make impossible. Listing was:\n\
{listing}"
);
assert_eq!(
selected.len(),
EXPECTED_IGNORED_LANES,
"the oracle filter selects {} ignored lane(s), not the {EXPECTED_IGNORED_LANES} this \
module defines. Either a lane was added without updating EXPECTED_IGNORED_LANES, or one \
was deleted, renamed out of the `{ORACLE_FILTER}` filter, or had its #[ignore] removed. \
Selected: {selected:?}",
selected.len()
);
}
#[test]
fn ci_workflow_selects_the_ignored_elixir_oracle_lanes() {
let workflow_path = repo_root().join(CI_WORKFLOW);
let workflow = std::fs::read_to_string(&workflow_path)
.unwrap_or_else(|error| panic!("read {}: {error}", workflow_path.display()));
let block = workflow_job_block(&workflow, TEST_JOB).unwrap_or_else(|| {
panic!(
"{} has no `{TEST_JOB}` job, so nothing selects the #[ignore]d Elixir oracles at all",
workflow_path.display()
)
});
let run_command = step_run_command(&block, ORACLE_STEP).unwrap_or_else(|| {
panic!(
"the `{TEST_JOB}` job has no `{ORACLE_STEP}` step with a `run:` command. Every Elixir \
oracle is #[ignore]d; without that step none of them run anywhere."
)
});
assert!(
run_command.contains("--ignored"),
"`{ORACLE_STEP}` no longer passes --ignored, so it selects none of the lanes and still \
exits 0. Command was: {run_command}"
);
assert!(
run_command.contains(ORACLE_FILTER),
"`{ORACLE_STEP}` no longer names the `{ORACLE_FILTER}` filter, so it would select every \
#[ignore]d test in the crate rather than these lanes. Command was: {run_command}"
);
assert!(
block
.lines()
.filter(|line| !line.trim_start().starts_with('#'))
.any(|line| line.contains("setup-elixir")),
"the `{TEST_JOB}` job must install Elixir, or `{ORACLE_STEP}` fails for want of a \
toolchain rather than for a real regression"
);
}
fn workflow_job_block(workflow: &str, job: &str) -> Option<String> {
let header = format!(" {job}:");
let mut lines = workflow.lines().skip_while(|line| line.trim_end() != header);
let first = lines.next()?;
let mut block = String::from(first);
for line in lines {
let is_sibling_job = line.starts_with(" ") && !line.starts_with(" ") && line.trim_end().ends_with(':');
if is_sibling_job {
break;
}
block.push('\n');
block.push_str(line);
}
Some(block)
}
fn step_run_command<'a>(block: &'a str, step_name: &str) -> Option<&'a str> {
let header = format!("- name: {step_name}");
let mut lines = block
.lines()
.map(|line| line.trim_start())
.filter(|line| !line.starts_with('#'))
.skip_while(|line| line.trim_end() != header);
lines.next()?;
for line in lines {
if line.starts_with("- ") {
return None;
}
if let Some(command) = line.strip_prefix("run:") {
return Some(command.trim());
}
}
None
}
#[test]
fn the_workflow_readers_narrow_to_what_they_name() {
let workflow = concat!(
"jobs:\n",
" first:\n",
" steps:\n",
" # a comment mentioning --ignored and elixir_oracle\n",
" - name: Target\n",
" run: cargo test --lib something\n",
" - name: Other\n",
" run: cargo test --lib other -- --ignored\n",
" second:\n",
" steps:\n",
" - run: marker-in-second\n",
);
let block = workflow_job_block(workflow, "first").expect("first job block");
assert!(
!block.contains("marker-in-second"),
"the block leaked into the next job, so job-scoped assertions would prove nothing"
);
assert_eq!(
step_run_command(&block, "Target"),
Some("cargo test --lib something"),
"the reader must return the named step's own command"
);
assert!(
!step_run_command(&block, "Target")
.expect("target command")
.contains("--ignored"),
"the reader must not pick up the preceding comment's `--ignored`, nor the FOLLOWING \
step's -- matching either is how a wiring check keeps passing after the flag is deleted"
);
assert_eq!(
step_run_command(&block, "Absent"),
None,
"a step that does not exist must not resolve to a command"
);
}