use clap for parsing tests. (#876)

This commit is contained in:
astrale-sharp 2023-04-21 11:16:32 +02:00 committed by GitHub
parent 851b154a6c
commit 4cea7007d0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 60 additions and 75 deletions

1
Cargo.lock generated
View File

@ -2081,6 +2081,7 @@ dependencies = [
name = "typst-tests"
version = "0.2.0"
dependencies = [
"clap 4.2.4",
"comemo",
"elsa",
"iai",

View File

@ -17,6 +17,7 @@ tiny-skia = "0.6.2"
ttf-parser = "0.17"
unscanny = "0.1"
walkdir = "2"
clap = { version = "4.2.1", features = ["derive"] }
[[test]]
name = "tests"

View File

@ -2,7 +2,6 @@
use std::cell::{RefCell, RefMut};
use std::collections::HashMap;
use std::env;
use std::ffi::OsStr;
use std::fs;
use std::ops::Range;
@ -33,10 +32,53 @@ const PDF_DIR: &str = "pdf";
const FONT_DIR: &str = "../assets/fonts";
const FILE_DIR: &str = "../assets/files";
fn main() {
let args = Args::new(env::args().skip(1));
let mut filtered = Vec::new();
use clap::Parser;
#[derive(Debug, Clone, Parser)]
#[clap(name = "typst-test", author)]
struct Args {
filter: Vec<String>,
/// runs only the specified subtest
#[arg(short, long)]
subtest: Option<usize>,
#[arg(long)]
exact: bool,
#[arg(long)]
update: bool,
#[arg(long)]
pdf: bool,
#[command(flatten)]
print: PrintConfig,
#[arg(long)]
nocapture: bool, // simply ignores the argument
}
/// Which things to print out for debugging.
#[derive(Default, Debug, Copy, Clone, Eq, PartialEq, Parser)]
struct PrintConfig {
#[arg(long)]
syntax: bool,
#[arg(long)]
model: bool,
#[arg(long)]
frames: bool,
}
impl Args {
fn matches(&self, path: &Path) -> bool {
if self.exact {
let name = path.file_name().unwrap().to_string_lossy();
self.filter.iter().any(|v| v == &name)
} else {
let path = path.to_string_lossy();
self.filter.is_empty() || self.filter.iter().any(|v| path.contains(v))
}
}
}
fn main() {
let args = Args::parse();
let mut filtered = Vec::new();
// Since different tests can affect each other through the memoization
// cache, a deterministic order is important for reproducibility.
for entry in WalkDir::new("typ").sort_by_file_name() {
@ -78,14 +120,9 @@ fn main() {
let pdf_path =
args.pdf.then(|| Path::new(PDF_DIR).join(path).with_extension("pdf"));
ok += test(
&mut world,
&src_path,
&png_path,
&ref_path,
pdf_path.as_deref(),
args.update,
) as usize;
ok +=
test(&mut world, &src_path, &png_path, &ref_path, pdf_path.as_deref(), &args)
as usize;
}
if len > 1 {
@ -104,66 +141,6 @@ fn main() {
}
}
/// Parsed command line arguments.
struct Args {
filter: Vec<String>,
exact: bool,
pdf: bool,
update: bool,
print: PrintConfig,
}
/// Which things to print out for debugging.
#[derive(Default, Copy, Clone, Eq, PartialEq)]
struct PrintConfig {
syntax: bool,
model: bool,
frames: bool,
}
impl Args {
fn new(args: impl Iterator<Item = String>) -> Self {
let mut filter = Vec::new();
let mut exact = false;
let mut pdf = false;
let mut update = env::var_os("UPDATE_EXPECT").is_some();
let mut print = PrintConfig::default();
for arg in args {
match arg.as_str() {
// Ignore this, its for cargo.
"--nocapture" => {}
// Match only the exact filename.
"--exact" => exact = true,
// Generate PDFs.
"--pdf" => pdf = true,
// Update the reference images.
"--update" => update = true,
// Debug print the syntax trees.
"--syntax" => print.syntax = true,
// Debug print the model.
"--model" => print.model = true,
// Debug print the frames.
"--frames" => print.frames = true,
// Everything else is a file filter.
_ => filter.push(arg),
}
}
Self { filter, exact, pdf, update, print }
}
fn matches(&self, path: &Path) -> bool {
if self.exact {
let name = path.file_name().unwrap().to_string_lossy();
self.filter.iter().any(|v| v == &name)
} else {
let path = path.to_string_lossy();
self.filter.is_empty() || self.filter.iter().any(|v| path.contains(v))
}
}
}
fn library() -> Library {
/// Display: Test
/// Category: test
@ -357,7 +334,7 @@ fn test(
png_path: &Path,
ref_path: &Path,
pdf_path: Option<&Path>,
update: bool,
args: &Args,
) -> bool {
let name = src_path.strip_prefix(TYP_DIR).unwrap_or(src_path);
println!("Testing {}", name.display());
@ -374,6 +351,12 @@ fn test(
let parts: Vec<_> = text.split("\n---").collect();
for (i, &part) in parts.iter().enumerate() {
if let Some(x) = args.subtest {
if x != i {
println!("skipped subtest {i}");
continue;
}
}
let is_header = i == 0
&& parts.len() > 1
&& part
@ -424,7 +407,7 @@ fn test(
.zip(ref_pixmap.data())
.any(|(&a, &b)| a.abs_diff(b) > 2)
{
if update {
if args.update {
update_image(png_path, ref_path);
updated = true;
} else {
@ -433,7 +416,7 @@ fn test(
}
}
} else if !document.pages.is_empty() {
if update {
if args.update {
update_image(png_path, ref_path);
updated = true;
} else {