use assert_cmd::Command;
use std::fs;
use std::path::Path;
type TestResult = Result<(), Box<dyn std::error::Error>>;
const BASE: &str = r#"
version = 1
canonical = "json-schema-2020-12"
authoring = "zod"
[gates]
"#;
const MACHINE_ROW: &str = r#"
[[floor.commands]]
name = "latency"
run = ["git", "--version"]
scope = "whole_repo"
inputs = "machine"
"#;
const TOOLCHAIN_ONLY: &str = r#"
[[floor.commands]]
name = "version"
run = ["git", "--version"]
scope = "whole_repo"
inputs = "toolchain"
"#;
const NETWORK_ROW: &str = r#"
[[floor.commands]]
name = "advisories"
run = ["git", "--version"]
scope = "whole_repo"
inputs = "network"
"#;
fn repo(floor: &str) -> Result<tempfile::TempDir, Box<dyn std::error::Error>> {
let dir = tempfile::tempdir()?;
fs::write(dir.path().join("pushkin.toml"), format!("{BASE}{floor}"))?;
Ok(dir)
}
struct Run {
code: i32,
out: String,
}
fn floor(dir: &Path) -> Result<Run, Box<dyn std::error::Error>> {
let output = Command::cargo_bin("pushkin")?
.current_dir(dir)
.arg("floor")
.output()?;
Ok(Run {
code: output.status.code().unwrap_or(-1),
out: format!(
"{}{}",
String::from_utf8_lossy(&output.stdout),
String::from_utf8_lossy(&output.stderr)
),
})
}
fn line_containing<'a>(out: &'a str, needle: &str) -> Option<&'a str> {
out.lines().find(|line| line.contains(needle))
}
#[test]
fn the_machine_class_parses_and_is_reported_per_command() -> TestResult {
let dir = repo(MACHINE_ROW)?;
let run = floor(dir.path())?;
assert_eq!(run.code, 0, "output:\n{}", run.out);
assert!(
run.out.contains("machine"),
"the per-command line must report the inputs class, got:\n{}",
run.out
);
Ok(())
}
#[test]
fn a_machine_inputs_command_prints_the_load_variance_disclosure() -> TestResult {
let dir = repo(MACHINE_ROW)?;
let run = floor(dir.path())?;
let disclosure = line_containing(&run.out, "quiet").unwrap_or_default();
assert!(
disclosure.contains("latency"),
"the disclosure must name the load-dependent command, got:\n{}",
run.out
);
assert!(
disclosure.to_lowercase().contains("machine"),
"the disclosure must say what the dependency IS, got:\n{}",
run.out
);
Ok(())
}
#[test]
fn a_floor_with_no_machine_command_prints_no_load_disclosure() -> TestResult {
let dir = repo(TOOLCHAIN_ONLY)?;
let run = floor(dir.path())?;
assert!(
line_containing(&run.out, "quiet").is_none(),
"no machine inputs means no load disclosure, got:\n{}",
run.out
);
Ok(())
}
#[test]
fn the_load_and_network_disclosures_are_separate_lines() -> TestResult {
let dir = repo(&format!("{MACHINE_ROW}{NETWORK_ROW}"))?;
let run = floor(dir.path())?;
let load = line_containing(&run.out, "quiet");
let network = line_containing(&run.out, "upstream data");
assert!(
load.is_some(),
"the load disclosure is missing:\n{}",
run.out
);
assert!(
network.is_some(),
"the network disclosure is missing:\n{}",
run.out
);
assert_ne!(
load, network,
"the two disclosures must be distinct lines, got:\n{}",
run.out
);
Ok(())
}
#[test]
fn the_repo_declares_bench_as_machine_dependent() -> TestResult {
let manifest = Path::new(env!("CARGO_MANIFEST_DIR")).join("../../pushkin.toml");
let text = fs::read_to_string(&manifest)?;
let bench = text
.split("[[floor.commands]]")
.find(|block| block.contains("name = \"bench\""))
.unwrap_or_default()
.to_owned();
assert!(
!bench.is_empty(),
"the repo manifest has no `bench` floor command"
);
assert!(
bench.contains("inputs = \"machine\""),
"bench measures wall-clock latency and must declare it, got:\n{bench}"
);
Ok(())
}