summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock1
-rw-r--r--tests/Cargo.toml1
-rw-r--r--tests/src/tests.rs131
3 files changed, 59 insertions, 74 deletions
diff --git a/Cargo.lock b/Cargo.lock
index c31425a1..86c4095a 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -2081,6 +2081,7 @@ dependencies = [
name = "typst-tests"
version = "0.2.0"
dependencies = [
+ "clap 4.2.4",
"comemo",
"elsa",
"iai",
diff --git a/tests/Cargo.toml b/tests/Cargo.toml
index ae4c3acb..788aade4 100644
--- a/tests/Cargo.toml
+++ b/tests/Cargo.toml
@@ -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"
diff --git a/tests/src/tests.rs b/tests/src/tests.rs
index da07c628..418f6704 100644
--- a/tests/src/tests.rs
+++ b/tests/src/tests.rs
@@ -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";
+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::new(env::args().skip(1));
+ 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 {