mirror of
https://github.com/typst/typst
synced 2025-06-28 00:03:17 +08:00
use clap for parsing tests. (#876)
This commit is contained in:
parent
851b154a6c
commit
4cea7007d0
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -2081,6 +2081,7 @@ dependencies = [
|
|||||||
name = "typst-tests"
|
name = "typst-tests"
|
||||||
version = "0.2.0"
|
version = "0.2.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"clap 4.2.4",
|
||||||
"comemo",
|
"comemo",
|
||||||
"elsa",
|
"elsa",
|
||||||
"iai",
|
"iai",
|
||||||
|
@ -17,6 +17,7 @@ tiny-skia = "0.6.2"
|
|||||||
ttf-parser = "0.17"
|
ttf-parser = "0.17"
|
||||||
unscanny = "0.1"
|
unscanny = "0.1"
|
||||||
walkdir = "2"
|
walkdir = "2"
|
||||||
|
clap = { version = "4.2.1", features = ["derive"] }
|
||||||
|
|
||||||
[[test]]
|
[[test]]
|
||||||
name = "tests"
|
name = "tests"
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
use std::cell::{RefCell, RefMut};
|
use std::cell::{RefCell, RefMut};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::env;
|
|
||||||
use std::ffi::OsStr;
|
use std::ffi::OsStr;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::ops::Range;
|
use std::ops::Range;
|
||||||
@ -33,10 +32,53 @@ const PDF_DIR: &str = "pdf";
|
|||||||
const FONT_DIR: &str = "../assets/fonts";
|
const FONT_DIR: &str = "../assets/fonts";
|
||||||
const FILE_DIR: &str = "../assets/files";
|
const FILE_DIR: &str = "../assets/files";
|
||||||
|
|
||||||
fn main() {
|
use clap::Parser;
|
||||||
let args = Args::new(env::args().skip(1));
|
|
||||||
let mut filtered = Vec::new();
|
|
||||||
|
|
||||||
|
#[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
|
// Since different tests can affect each other through the memoization
|
||||||
// cache, a deterministic order is important for reproducibility.
|
// cache, a deterministic order is important for reproducibility.
|
||||||
for entry in WalkDir::new("typ").sort_by_file_name() {
|
for entry in WalkDir::new("typ").sort_by_file_name() {
|
||||||
@ -78,14 +120,9 @@ fn main() {
|
|||||||
let pdf_path =
|
let pdf_path =
|
||||||
args.pdf.then(|| Path::new(PDF_DIR).join(path).with_extension("pdf"));
|
args.pdf.then(|| Path::new(PDF_DIR).join(path).with_extension("pdf"));
|
||||||
|
|
||||||
ok += test(
|
ok +=
|
||||||
&mut world,
|
test(&mut world, &src_path, &png_path, &ref_path, pdf_path.as_deref(), &args)
|
||||||
&src_path,
|
as usize;
|
||||||
&png_path,
|
|
||||||
&ref_path,
|
|
||||||
pdf_path.as_deref(),
|
|
||||||
args.update,
|
|
||||||
) as usize;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if len > 1 {
|
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 {
|
fn library() -> Library {
|
||||||
/// Display: Test
|
/// Display: Test
|
||||||
/// Category: test
|
/// Category: test
|
||||||
@ -357,7 +334,7 @@ fn test(
|
|||||||
png_path: &Path,
|
png_path: &Path,
|
||||||
ref_path: &Path,
|
ref_path: &Path,
|
||||||
pdf_path: Option<&Path>,
|
pdf_path: Option<&Path>,
|
||||||
update: bool,
|
args: &Args,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
let name = src_path.strip_prefix(TYP_DIR).unwrap_or(src_path);
|
let name = src_path.strip_prefix(TYP_DIR).unwrap_or(src_path);
|
||||||
println!("Testing {}", name.display());
|
println!("Testing {}", name.display());
|
||||||
@ -374,6 +351,12 @@ fn test(
|
|||||||
|
|
||||||
let parts: Vec<_> = text.split("\n---").collect();
|
let parts: Vec<_> = text.split("\n---").collect();
|
||||||
for (i, &part) in parts.iter().enumerate() {
|
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
|
let is_header = i == 0
|
||||||
&& parts.len() > 1
|
&& parts.len() > 1
|
||||||
&& part
|
&& part
|
||||||
@ -424,7 +407,7 @@ fn test(
|
|||||||
.zip(ref_pixmap.data())
|
.zip(ref_pixmap.data())
|
||||||
.any(|(&a, &b)| a.abs_diff(b) > 2)
|
.any(|(&a, &b)| a.abs_diff(b) > 2)
|
||||||
{
|
{
|
||||||
if update {
|
if args.update {
|
||||||
update_image(png_path, ref_path);
|
update_image(png_path, ref_path);
|
||||||
updated = true;
|
updated = true;
|
||||||
} else {
|
} else {
|
||||||
@ -433,7 +416,7 @@ fn test(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if !document.pages.is_empty() {
|
} else if !document.pages.is_empty() {
|
||||||
if update {
|
if args.update {
|
||||||
update_image(png_path, ref_path);
|
update_image(png_path, ref_path);
|
||||||
updated = true;
|
updated = true;
|
||||||
} else {
|
} else {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user