Merge pull request #23 from Nilstrieb/cross-platform-non-cursed-tests

Cross platform non cursed tests
This commit is contained in:
nora 2023-04-11 12:36:50 +02:00 committed by GitHub
commit 5b9441d3b4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 60 additions and 113 deletions

View file

@ -2,14 +2,6 @@ use anyhow::{ensure, Result};
use std::process::Command; use std::process::Command;
#[test] #[test]
#[ignore = "FIXME: Make this not cursed."]
#[cfg(not(unix))]
fn full_tests() -> Result<()> {
todo!()
}
#[test]
#[cfg(unix)]
fn full_tests() -> Result<()> { fn full_tests() -> Result<()> {
let status = Command::new("cargo").arg("runtest").spawn()?.wait()?; let status = Command::new("cargo").arg("runtest").spawn()?.wait()?;
ensure!(status.success(), "runtest failed"); ensure!(status.success(), "runtest failed");

View file

@ -1,9 +1,18 @@
fn main() -> anyhow::Result<()> { fn main() -> anyhow::Result<()> {
if std::env::var("MINIMIZE_LINTS").as_deref() == Ok("1") {
std::process::Command::new("cargo")
.arg("check")
.spawn()
.unwrap()
.wait()
.unwrap();
}
let root_var = let root_var =
std::env::var("MINIMIZE_RUNTEST_ROOTS").expect("MINIMIZE_RUNTEST_ROOTS env var not found"); std::env::var("MINIMIZE_RUNTEST_ROOTS").expect("MINIMIZE_RUNTEST_ROOTS env var not found");
let roots = root_var.split(",").collect::<Vec<_>>(); let roots = root_var.split(",").collect::<Vec<_>>();
let proj_dir = std::env::current_dir().expect("current dir not found"); let proj_dir = std::env::current_dir().expect("current dir not found");
testsuite::ensure_correct_minimization(&proj_dir, roots) testsuite::ensure_roots_kept(&proj_dir, roots)
} }

View file

@ -1,6 +1,3 @@
#[cfg(not(unix))]
compile_error!("FIXME: This does not support windows yet. I am so sorry.");
fn main() -> anyhow::Result<()> { fn main() -> anyhow::Result<()> {
testsuite::full_tests() testsuite::full_tests()
} }

View file

@ -4,10 +4,7 @@ use rayon::prelude::{IntoParallelIterator, ParallelIterator};
use regex::Regex; use regex::Regex;
use std::collections::hash_map::RandomState; use std::collections::hash_map::RandomState;
use std::collections::HashSet; use std::collections::HashSet;
use std::fs::Permissions; use std::ffi::OsString;
use std::io::BufWriter;
#[cfg(unix)]
use std::os::unix::prelude::PermissionsExt;
use std::path::PathBuf; use std::path::PathBuf;
use std::process::Command; use std::process::Command;
use std::{ use std::{
@ -18,17 +15,10 @@ use std::{
use tempfile::TempDir; use tempfile::TempDir;
/// This is called by the regression_checked binary during minimization and by the test runner at the end. /// This is called by the regression_checked binary during minimization and by the test runner at the end.
pub fn ensure_correct_minimization( pub fn ensure_roots_kept(
proj_dir: &Path, proj_dir: &Path,
start_roots: impl IntoIterator<Item = impl AsRef<str>>, start_roots: impl IntoIterator<Item = impl AsRef<str>>,
) -> Result<()> { ) -> Result<()> {
let required_deleted = get_required_deleted(&proj_dir).context("get REQUIRED-DELETED")?;
ensure!(
required_deleted.is_empty(),
"Some REQUIRE-DELETED have not been deleted: {required_deleted:?}"
);
let end_roots = HashSet::<_, RandomState>::from_iter( let end_roots = HashSet::<_, RandomState>::from_iter(
get_roots(proj_dir).context("getting final MINIMIZE-ROOTs")?, get_roots(proj_dir).context("getting final MINIMIZE-ROOTs")?,
); );
@ -54,12 +44,6 @@ fn run_build(command: &mut Command) -> Result<()> {
Ok(()) Ok(())
} }
#[cfg(not(unix))]
pub fn full_tests() -> Result<()> {
todo!("FIXME: Make this not cursed.")
}
#[cfg(unix)]
pub fn full_tests() -> Result<()> { pub fn full_tests() -> Result<()> {
run_build(Command::new("cargo").args([ run_build(Command::new("cargo").args([
"build", "build",
@ -69,20 +53,36 @@ pub fn full_tests() -> Result<()> {
"testsuite", "testsuite",
"--bin", "--bin",
"regression_checker", "regression_checker",
"--bin",
"cargo-minimize",
])) ]))
.context("running cargo build")?; .context("running cargo build")?;
let path = Path::new(file!()) let this_file = Path::new(file!())
.canonicalize()? .canonicalize()
.parent() .with_context(|| format!("failed to find current file: {}", file!()))?;
.unwrap()
.parent()
.unwrap()
.parent()
.unwrap()
.join("full-tests");
let children = fs::read_dir(&path).with_context(|| format!("reading {}", path.display()))?; let root_dir = this_file
.parent()
.unwrap()
.parent()
.unwrap()
.parent()
.unwrap();
let full_tests_path = root_dir.join("full-tests");
let mut regression_checker_path = root_dir
.join("target")
.join("debug")
.join("regression_checker");
if cfg!(windows) {
regression_checker_path.set_extension("exe");
}
let children = fs::read_dir(&full_tests_path)
.with_context(|| format!("reading {}", full_tests_path.display()))?;
let children = children let children = children
.map(|e| e.map_err(Into::into)) .map(|e| e.map_err(Into::into))
@ -94,14 +94,16 @@ pub fn full_tests() -> Result<()> {
.map(|child| { .map(|child| {
let path = child.path(); let path = child.path();
build(&path).with_context(|| format!("building {:?}", path.file_name().unwrap())) build(&path, &regression_checker_path)
.with_context(|| format!("building {:?}", path.file_name().unwrap()))
}) })
.collect::<Result<Vec<_>>>()?; .collect::<Result<Vec<_>>>()?;
} else { } else {
for child in children { for child in children {
let path = child.path(); let path = child.path();
build(&path).with_context(|| format!("building {:?}", path.file_name().unwrap()))?; build(&path, &regression_checker_path)
.with_context(|| format!("building {:?}", path.file_name().unwrap()))?;
} }
} }
@ -141,72 +143,7 @@ fn setup_dir(path: &Path) -> Result<(TempDir, PathBuf)> {
Ok((tempdir, proj_dir)) Ok((tempdir, proj_dir))
} }
fn setup_scripts(start_roots: &[String], proj_dir: &Path) -> Result<()> { fn build(path: &Path, regression_checker_path: &Path) -> Result<()> {
// FIXME: Do this in a good way.
// What the fuck is this.
{
let file = fs::File::create(proj_dir.join("check.sh"))?;
let expected_roots = start_roots
.iter()
.map(|root| format!("'{}'", root))
.collect::<Vec<_>>()
.join(", ");
write!(
BufWriter::new(&file),
r#"#!/usr/bin/env bash
if ! cargo check ; then
>&2 echo "Cargo check failed"
exit 1
fi
OUT=$(grep -ro "~MINIMIZE-ROOT [a-zA-Z_\-]*" --no-filename src)
python3 -c "
# Get the data from bash by just substituting it in. It works!
out = '''$OUT'''
lines = out.split('\n')
found = set()
for line in lines:
name = line.removeprefix('~MINIMIZE-ROOT').strip()
found.add(name)
# Pass in the data _from Rust directly_. Beautiful.
expected_roots = {{{expected_roots}}}
for root in expected_roots:
if root in found:
print(f'Found {{root}} in output')
else:
print(f'Did not find {{root}} in output!')
exit(1)
"
"#
)?;
file.set_permissions(Permissions::from_mode(0o777))?;
}
{
let file = fs::File::create(proj_dir.join("lint.sh"))?;
write!(
BufWriter::new(&file),
r#"#!/usr/bin/env bash
cargo check
"#
)?;
#[cfg(unix)]
file.set_permissions(Permissions::from_mode(0o777))?;
}
Ok(())
}
fn build(path: &Path) -> Result<()> {
let (_tempdir, proj_dir) = setup_dir(path).context("setting up tempdir")?; let (_tempdir, proj_dir) = setup_dir(path).context("setting up tempdir")?;
let mut cargo_minimize_path = PathBuf::from("target/debug/cargo-minimize"); let mut cargo_minimize_path = PathBuf::from("target/debug/cargo-minimize");
if cfg!(windows) { if cfg!(windows) {
@ -218,14 +155,19 @@ fn build(path: &Path) -> Result<()> {
let start_roots = get_roots(&proj_dir).context("getting initial MINIMIZE-ROOTs")?; let start_roots = get_roots(&proj_dir).context("getting initial MINIMIZE-ROOTs")?;
setup_scripts(&start_roots, &proj_dir).context("setting up scripts")?;
let mut cmd = Command::new(cargo_minimize); let mut cmd = Command::new(cargo_minimize);
cmd.current_dir(&proj_dir); cmd.current_dir(&proj_dir);
cmd.arg("minimize"); cmd.arg("minimize");
cmd.arg("--script-path=./check.sh"); cmd.arg({
cmd.arg("--script-path-lints=./lint.sh"); let mut flag = OsString::from("--script-path=");
flag.push(regression_checker_path);
flag
});
let minimize_roots = start_roots.join(",");
cmd.env("MINIMIZE_RUNTEST_ROOTS", &minimize_roots);
let out = cmd.output().context("spawning cargo-minimize")?; let out = cmd.output().context("spawning cargo-minimize")?;
let stderr = String::from_utf8(out.stderr).unwrap(); let stderr = String::from_utf8(out.stderr).unwrap();
@ -236,7 +178,14 @@ fn build(path: &Path) -> Result<()> {
"Command failed:\n--- stderr:\n{stderr}\n--- stdout:\n{stdout}" "Command failed:\n--- stderr:\n{stderr}\n--- stdout:\n{stdout}"
); );
ensure_correct_minimization(&proj_dir, &start_roots)?; let required_deleted = get_required_deleted(&proj_dir).context("get REQUIRED-DELETED")?;
ensure!(
required_deleted.is_empty(),
"Some REQUIRE-DELETED have not been deleted: {required_deleted:?}"
);
ensure_roots_kept(&proj_dir, &start_roots)?;
Ok(()) Ok(())
} }