mirror of
https://github.com/storytold/designcraft.git
synced 2026-10-29 04:36:47 -06:00
Merge pull request #1642 from aiongg/ci-speed
CI: one test binary per crate, nextest, line tables only
This commit is contained in:
@@ -45,10 +45,10 @@ jobs:
|
||||
persist-credentials: false
|
||||
|
||||
- name: Install Linux build dependencies
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y --no-install-recommends \
|
||||
pkg-config libxkbcommon-dev libwayland-dev libx11-dev libxcb1-dev libxcursor-dev \
|
||||
uses: storytold/craft-common-actions/actions/install-apt-packages@main
|
||||
with:
|
||||
packages: >-
|
||||
pkg-config libxkbcommon-dev libwayland-dev libx11-dev libxcb1-dev libxcursor-dev
|
||||
libxrandr-dev libxi-dev libfontconfig1-dev libfreetype-dev mesa-vulkan-drivers
|
||||
|
||||
- name: Install Rust (stable + clippy, rustfmt, wasm32)
|
||||
@@ -57,6 +57,10 @@ jobs:
|
||||
--target wasm32-unknown-unknown
|
||||
rustup default stable
|
||||
|
||||
- uses: taiki-e/install-action@f7e5d7c961414b23f5b25b2da9294395d08513ad # v2.87.26
|
||||
with:
|
||||
tool: cargo-nextest@0.9.145
|
||||
|
||||
- uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2.9.2
|
||||
with:
|
||||
save-if: ${{ github.ref == 'refs/heads/main' }}
|
||||
|
||||
@@ -40,12 +40,12 @@ Generated-in-code art is original and has no file to list: the UI icon set (`cra
|
||||
| `docs/images/page-4.png` | DesignCraft contributors | screenshot/render of DesignCraft itself (sample document generated in code) | MIT OR Apache-2.0 | Original; no Adobe UI |
|
||||
| `docs/images/page-cover.png` | DesignCraft contributors | screenshot/render of DesignCraft itself (sample document generated in code) | MIT OR Apache-2.0 | Original; no Adobe UI |
|
||||
| `docs/images/ui-spread.png` | DesignCraft contributors | screenshot/render of DesignCraft itself (sample document generated in code) | MIT OR Apache-2.0 | Original; no Adobe UI |
|
||||
| `crates/render/tests/golden/drop-shadow-spread.png` | DesignCraft contributors (generated) | rendered by DesignCraft's own renderer (`crates/render/tests/effects.rs`, synthetic shapes and bundled fonts) | MIT OR Apache-2.0 | Golden test image for soft effects |
|
||||
| `crates/render/tests/golden/drop-shadow-text.png` | DesignCraft contributors (generated) | rendered by DesignCraft's own renderer (`crates/render/tests/effects.rs`, synthetic shapes and bundled fonts) | MIT OR Apache-2.0 | Golden test image for soft effects |
|
||||
| `crates/render/tests/golden/drop-shadow.png` | DesignCraft contributors (generated) | rendered by DesignCraft's own renderer (`crates/render/tests/effects.rs`, synthetic shapes and bundled fonts) | MIT OR Apache-2.0 | Golden test image for soft effects |
|
||||
| `crates/render/tests/golden/feather.png` | DesignCraft contributors (generated) | rendered by DesignCraft's own renderer (`crates/render/tests/effects.rs`, synthetic shapes and bundled fonts) | MIT OR Apache-2.0 | Golden test image for soft effects |
|
||||
| `crates/render/tests/golden/inner-shadow.png` | DesignCraft contributors (generated) | rendered by DesignCraft's own renderer (`crates/render/tests/effects.rs`, synthetic shapes and bundled fonts) | MIT OR Apache-2.0 | Golden test image for soft effects |
|
||||
| `crates/render/tests/golden/outer-glow.png` | DesignCraft contributors (generated) | rendered by DesignCraft's own renderer (`crates/render/tests/effects.rs`, synthetic shapes and bundled fonts) | MIT OR Apache-2.0 | Golden test image for soft effects |
|
||||
| `crates/render/tests/golden/drop-shadow-spread.png` | DesignCraft contributors (generated) | rendered by DesignCraft's own renderer (`crates/render/tests/it/effects.rs`, synthetic shapes and bundled fonts) | MIT OR Apache-2.0 | Golden test image for soft effects |
|
||||
| `crates/render/tests/golden/drop-shadow-text.png` | DesignCraft contributors (generated) | rendered by DesignCraft's own renderer (`crates/render/tests/it/effects.rs`, synthetic shapes and bundled fonts) | MIT OR Apache-2.0 | Golden test image for soft effects |
|
||||
| `crates/render/tests/golden/drop-shadow.png` | DesignCraft contributors (generated) | rendered by DesignCraft's own renderer (`crates/render/tests/it/effects.rs`, synthetic shapes and bundled fonts) | MIT OR Apache-2.0 | Golden test image for soft effects |
|
||||
| `crates/render/tests/golden/feather.png` | DesignCraft contributors (generated) | rendered by DesignCraft's own renderer (`crates/render/tests/it/effects.rs`, synthetic shapes and bundled fonts) | MIT OR Apache-2.0 | Golden test image for soft effects |
|
||||
| `crates/render/tests/golden/inner-shadow.png` | DesignCraft contributors (generated) | rendered by DesignCraft's own renderer (`crates/render/tests/it/effects.rs`, synthetic shapes and bundled fonts) | MIT OR Apache-2.0 | Golden test image for soft effects |
|
||||
| `crates/render/tests/golden/outer-glow.png` | DesignCraft contributors (generated) | rendered by DesignCraft's own renderer (`crates/render/tests/it/effects.rs`, synthetic shapes and bundled fonts) | MIT OR Apache-2.0 | Golden test image for soft effects |
|
||||
| `assets/app-icon/LICENSE.txt` | (licence text) | this project | — | Licence for the app icon |
|
||||
| `assets/app-icon/designcraft-1024.png` | DesignCraft project owner (drawn in ArtCraft) | rendered from `assets/app-icon/designcraft.svg` by `packaging/icons.sh` | MIT OR Apache-2.0 (`assets/app-icon/LICENSE.txt`) | App icon: calico cat in a polka-dot scarf (see `assets/app-icon/README.md`) |
|
||||
| `assets/app-icon/designcraft-macos-512.png` | DesignCraft project owner (drawn in ArtCraft) | rendered from `assets/app-icon/designcraft.svg` by `packaging/icons.sh` | MIT OR Apache-2.0 (`assets/app-icon/LICENSE.txt`) | App icon: calico cat in a polka-dot scarf (see `assets/app-icon/README.md`) |
|
||||
|
||||
@@ -103,11 +103,16 @@ todo = "warn"
|
||||
too_many_arguments = "allow"
|
||||
type_complexity = "allow"
|
||||
|
||||
# Line tables keep file and line in panics and backtraces; full debug info
|
||||
# for every test binary and dependency would multiply the target dir size.
|
||||
# The test profile inherits both settings.
|
||||
[profile.dev.package."*"]
|
||||
opt-level = 2
|
||||
debug = false
|
||||
|
||||
[profile.dev]
|
||||
opt-level = 1
|
||||
debug = "line-tables-only"
|
||||
|
||||
[profile.release]
|
||||
opt-level = 3
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
mod cli;
|
||||
@@ -1,5 +1,3 @@
|
||||
#![cfg(not(target_arch = "wasm32"))]
|
||||
|
||||
use designcraft_engine::Session;
|
||||
use serde_json::json;
|
||||
use std::path::Path;
|
||||
@@ -1,5 +1,4 @@
|
||||
//! Browser Print must reject native spooler operations without trapping the editor.
|
||||
#![cfg(target_arch = "wasm32")]
|
||||
|
||||
use designcraft_engine::Session;
|
||||
use serde_json::json;
|
||||
-2
@@ -1,5 +1,3 @@
|
||||
#![cfg(not(target_arch = "wasm32"))]
|
||||
|
||||
use designcraft_engine::Session;
|
||||
use serde_json::json;
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
mod book_safety;
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
mod browser_print;
|
||||
mod character_style_from_selection;
|
||||
mod close_retention;
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
mod collection_state_atomicity;
|
||||
mod combined_close_glyph;
|
||||
mod distribute_locks;
|
||||
mod export_page_input;
|
||||
mod insert_pages_bounds;
|
||||
mod param_keys;
|
||||
mod pdf_backend;
|
||||
mod preflight_resolution;
|
||||
mod primary_frame_columns;
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
mod save_state_atomicity;
|
||||
mod stroke_tint_range;
|
||||
mod text_decorations;
|
||||
mod text_insert_memory;
|
||||
mod text_thread_regressions;
|
||||
mod thread_color_safety;
|
||||
-2
@@ -1,5 +1,3 @@
|
||||
#![cfg(not(target_arch = "wasm32"))]
|
||||
|
||||
use std::path::Path;
|
||||
use std::sync::Arc;
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
mod export_tag_styles;
|
||||
mod grouped_reading_order;
|
||||
@@ -0,0 +1,4 @@
|
||||
// Integration tests: unwrapping and panicking on failure is fine here, unlike in shipped code.
|
||||
#![allow(clippy::unwrap_used, clippy::expect_used, clippy::panic)]
|
||||
|
||||
mod system_fonts;
|
||||
@@ -1,7 +1,5 @@
|
||||
//! A new session finds the installed system fonts by family name (#22). One test in its own
|
||||
//! process, so the process-wide database starts fresh, as it does when the app starts.
|
||||
// Integration tests: unwrapping and panicking on failure is fine here, unlike in shipped code.
|
||||
#![allow(clippy::unwrap_used, clippy::expect_used, clippy::panic)]
|
||||
|
||||
use designcraft_fonts::{FontDb, system_font_dirs};
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
mod rgba_conversion_contract;
|
||||
@@ -3,8 +3,6 @@
|
||||
//! goes inside the write root. Paths that leave a root (`..`, another folder, a sibling with the
|
||||
//! same prefix, a link) are refused, nothing from a refused file reaches the document, and nothing
|
||||
//! is written outside.
|
||||
// Integration tests: unwrapping and panicking on failure is fine here, unlike in shipped code (AGENTS.md).
|
||||
#![allow(clippy::unwrap_used, clippy::expect_used, clippy::panic)]
|
||||
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
// Integration tests: unwrapping and panicking on failure is fine here, unlike in shipped code (AGENTS.md).
|
||||
#![allow(clippy::unwrap_used, clippy::expect_used, clippy::panic)]
|
||||
|
||||
mod automation_roots;
|
||||
@@ -1,5 +0,0 @@
|
||||
//! Run public contracts with the production content-cache hasher.
|
||||
#[path = "support/image_content_cache_contract.rs"]
|
||||
mod contracts;
|
||||
#[path = "support/image_fixtures.rs"]
|
||||
mod image_fixtures;
|
||||
+1
-1
@@ -42,7 +42,7 @@ fn mixed_gradient_export_survives_in_subprocess() {
|
||||
const CHILD: &str = "DESIGNCRAFT_TEST_MIXED_GRADIENT_CHILD";
|
||||
if std::env::var_os(CHILD).is_none() {
|
||||
let out = std::process::Command::new(std::env::current_exe().unwrap())
|
||||
.args(["--exact", "mixed_gradient_export_survives_in_subprocess", "--nocapture"])
|
||||
.args(["--exact", "gradient_color_spaces::mixed_gradient_export_survives_in_subprocess", "--nocapture"])
|
||||
.env(CHILD, "1")
|
||||
.output()
|
||||
.unwrap();
|
||||
@@ -0,0 +1,3 @@
|
||||
//! Run public contracts with the production content-cache hasher.
|
||||
#[path = "../support/image_content_cache_contract.rs"]
|
||||
mod contracts;
|
||||
@@ -0,0 +1,6 @@
|
||||
#[path = "../support/image_fixtures.rs"]
|
||||
mod image_fixtures;
|
||||
|
||||
mod gradient_color_spaces;
|
||||
mod image_content_cache;
|
||||
mod page_entry_search_contract;
|
||||
@@ -3,7 +3,7 @@
|
||||
//!
|
||||
//! Goldens live in `tests/golden/*.png` and are compared with a tolerance (antialiasing and blur
|
||||
//! rounding may differ by a few levels between SIMD levels). Regenerate them after an intended
|
||||
//! change with `DESIGNCRAFT_BLESS=1 cargo test -p designcraft-render --test effects`.
|
||||
//! change with `DESIGNCRAFT_BLESS=1 cargo test -p designcraft-render --test it effects::`.
|
||||
|
||||
use designcraft_compose::Cache;
|
||||
use designcraft_doc::build::NewDocument;
|
||||
@@ -0,0 +1,12 @@
|
||||
mod blend_over_paper;
|
||||
mod colorize;
|
||||
mod effects;
|
||||
mod glyph_retention;
|
||||
mod gradient_inks;
|
||||
mod gradients;
|
||||
mod pdf_geometry;
|
||||
mod perf;
|
||||
mod placed_pdf;
|
||||
mod stroke_alignment;
|
||||
mod text_frame_bottom;
|
||||
mod text_stroke_behind;
|
||||
@@ -1,6 +1,6 @@
|
||||
//! Renderer caching/culling behaviour, and a render-time regression test (`#[ignore]`: wall-clock
|
||||
//! timings are only meaningful on an idle machine — run with
|
||||
//! `cargo test --release -p designcraft-render --test perf -- --ignored`).
|
||||
//! `cargo test --release -p designcraft-render --test it perf:: -- --ignored`).
|
||||
|
||||
use std::time::Instant;
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
mod native_job_lifetime_control;
|
||||
-1
@@ -1,5 +1,4 @@
|
||||
//! Own a real native Job across last close. This does not run the asynchronous worker.
|
||||
#![cfg(not(target_arch = "wasm32"))]
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
+49
-22
@@ -12,7 +12,7 @@ mod stats;
|
||||
mod version;
|
||||
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::process::{Command, ExitCode};
|
||||
use std::process::{Command, ExitCode, Stdio};
|
||||
|
||||
const USAGE: &str = "\
|
||||
usage: cargo xtask <command>
|
||||
@@ -21,8 +21,10 @@ commands:
|
||||
assets check that every icon/image/font/asset is attributed in ASSETS.md
|
||||
layers enforce the crate dependency layering (plan/architecture.md §3)
|
||||
pdf-deps verify the pinned PDF backend, including Krilla dependencies
|
||||
wasm cargo check --target wasm32-unknown-unknown for the wasm-safe crates
|
||||
ci fmt --check, clippy -D warnings, test, assets, layers, wasm (stops at first failure)
|
||||
wasm cargo check --target wasm32-unknown-unknown for the wasm-safe crates (one call)
|
||||
test workspace tests (cargo nextest when installed, else cargo test), then doctests
|
||||
ci fmt --check, pdf-deps, clippy -D warnings, test, doctest, assets, layers, wasm
|
||||
(stops at first failure)
|
||||
corpus [--download]
|
||||
show where test corpora live; --download fetches PngSuite into corpus/pngsuite
|
||||
stats [--exact] count tests and lines per crate (--exact: ask the test harness via `-- --list`)
|
||||
@@ -39,6 +41,7 @@ fn main() -> ExitCode {
|
||||
Some("layers") => cmd_layers(),
|
||||
Some("pdf-deps") => pdf_deps::run(&root()),
|
||||
Some("wasm") => cmd_wasm(),
|
||||
Some("test") => cmd_test().and_then(|()| cmd_doctest()),
|
||||
Some("ci") => cmd_ci(),
|
||||
Some("corpus") => cmd_corpus(rest.contains(&"--download")),
|
||||
Some("stats") => stats::run(&root(), rest.contains(&"--exact")),
|
||||
@@ -134,21 +137,51 @@ fn wasm_set() -> Result<Vec<String>, String> {
|
||||
.collect())
|
||||
}
|
||||
|
||||
/// One `cargo check` for the whole set: each crate is checked once, and
|
||||
/// `--keep-going` still reports every failing crate. Features unify across the
|
||||
/// set, so each crate is checked with the union of the features the set enables.
|
||||
fn cmd_wasm() -> Result<(), String> {
|
||||
let set = wasm_set()?;
|
||||
let mut results = Vec::new();
|
||||
if set.is_empty() {
|
||||
return Err("no wasm-safe crates found in the workspace metadata".into());
|
||||
}
|
||||
let mut c = cargo();
|
||||
c.args(["check", "--target", "wasm32-unknown-unknown", "--keep-going"]);
|
||||
for pkg in &set {
|
||||
let mut c = cargo();
|
||||
c.args(["check", "--target", "wasm32-unknown-unknown", "-p", pkg]);
|
||||
let ok = run(c, &format!("cargo check --target wasm32-unknown-unknown -p {pkg}")).is_ok();
|
||||
results.push((pkg.clone(), ok));
|
||||
c.args(["-p", pkg]);
|
||||
}
|
||||
println!("\nwasm32-unknown-unknown check:");
|
||||
for (p, ok) in &results {
|
||||
println!(" {:<6} {p}", if *ok { "ok" } else { "FAIL" });
|
||||
}
|
||||
let failed = results.iter().filter(|r| !r.1).count();
|
||||
if failed == 0 { Ok(()) } else { Err(format!("{failed} crate(s) failed the wasm check")) }
|
||||
run(c, &format!("cargo check --target wasm32-unknown-unknown --keep-going -p {}", set.join(" -p ")))?;
|
||||
println!("\nwasm32-unknown-unknown check: ok ({} crates: {})", set.len(), set.join(", "));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Test targets for the test build. Examples are left out so they aren't
|
||||
/// linked; clippy `--all-targets` still compiles them.
|
||||
const TEST_TARGETS: [&str; 4] = ["--workspace", "--lib", "--bins", "--tests"];
|
||||
|
||||
fn nextest_available() -> bool {
|
||||
cargo().args(["nextest", "--version"]).stdout(Stdio::null()).stderr(Stdio::null()).status().is_ok_and(|s| s.success())
|
||||
}
|
||||
|
||||
fn cmd_test() -> Result<(), String> {
|
||||
let mut c = cargo();
|
||||
let tool = if nextest_available() {
|
||||
c.args(["nextest", "run"]);
|
||||
"nextest run"
|
||||
} else {
|
||||
eprintln!("note: cargo-nextest is not installed, running cargo test (cargo install cargo-nextest --locked)");
|
||||
c.arg("test");
|
||||
"test"
|
||||
};
|
||||
c.args(TEST_TARGETS);
|
||||
run(c, &format!("cargo {tool} {}", TEST_TARGETS.join(" ")))
|
||||
}
|
||||
|
||||
/// nextest does not run doctests.
|
||||
fn cmd_doctest() -> Result<(), String> {
|
||||
let mut c = cargo();
|
||||
c.args(["test", "--workspace", "--doc"]);
|
||||
run(c, "cargo test --workspace --doc")
|
||||
}
|
||||
|
||||
fn cmd_ci() -> Result<(), String> {
|
||||
@@ -171,14 +204,8 @@ fn cmd_ci() -> Result<(), String> {
|
||||
run(c, "cargo clippy --workspace --all-targets -- -D warnings")
|
||||
}),
|
||||
),
|
||||
(
|
||||
"test",
|
||||
Box::new(|| {
|
||||
let mut c = cargo();
|
||||
c.args(["test", "--workspace"]);
|
||||
run(c, "cargo test --workspace")
|
||||
}),
|
||||
),
|
||||
("test", Box::new(cmd_test)),
|
||||
("doctest", Box::new(cmd_doctest)),
|
||||
("assets", Box::new(|| assets::run(&root()))),
|
||||
("layers", Box::new(cmd_layers)),
|
||||
("wasm", Box::new(cmd_wasm)),
|
||||
|
||||
Reference in New Issue
Block a user