From 8cc69ed45ce250a12fdaa45262cacf93649d76e2 Mon Sep 17 00:00:00 2001 From: aiongg <67543387+aiongg@users.noreply.github.com> Date: Fri, 23 Oct 2026 21:36:10 -0400 Subject: [PATCH] CI: one test binary per crate, nextest, line tables only (#3855) * CI: line tables only for workspace crates, no debug info for dependencies * CI: one integration-test binary per crate Each crate's tests/*.rs files become modules of tests/it/main.rs. Files that change process-wide state (Color Settings, the font database, installed plug-ins, the working directory), the fuzz sweeps and the test targets the Affinity corpus workflow names stay their own binaries. * Docs: name the integration tests' new paths * CI: xtask test with nextest and doctests, one wasm check, clippy --keep-going cargo xtask ci runs the tests with cargo nextest (cargo test when it is not installed), builds them with --lib --bins --tests, runs the doctests as their own step, and checks the wasm crates in one cargo check --keep-going call. --- Cargo.toml | 4 ++ apps/vectorcraft-cli/tests/{ => it}/cli.rs | 2 - apps/vectorcraft-cli/tests/{ => it}/fileio.rs | 2 - apps/vectorcraft-cli/tests/it/main.rs | 7 +++ .../vectorcraft-cli/tests/{ => it}/mcp_e2e.rs | 2 - .../tests/{ => it}/automation_args.rs | 3 - apps/vectorcraft/tests/{ => it}/help.rs | 3 - apps/vectorcraft/tests/it/main.rs | 6 ++ crates/affinity/README.md | 8 +-- crates/affinity/src/tests.rs | 2 +- .../affinity/tests/{ => it}/import_limits.rs | 8 +-- crates/affinity/tests/it/main.rs | 20 +++++++ .../affinity/tests/{ => it}/outline_limits.rs | 2 - crates/affinity/tests/{ => it}/raster.rs | 4 +- crates/affinity/tests/{ => it}/real_files.rs | 11 ++-- crates/affinity/tests/{ => it}/text.rs | 10 +--- .../tests/{ => it}/affinity_features.rs | 7 +-- .../engine/tests/{ => it}/affinity_local.rs | 1 - .../engine/tests/{ => it}/artboard_click.rs | 1 - .../engine/tests/{ => it}/clear_commands.rs | 1 - .../tests/{ => it}/compound_attributes.rs | 1 - crates/engine/tests/{ => it}/dimensions.rs | 1 - .../tests/{ => it}/eyedropper_sources.rs | 1 - .../tests/{ => it}/find_replace_paras.rs | 2 - crates/engine/tests/{ => it}/inline_text.rs | 2 - crates/engine/tests/{ => it}/known_bugs.rs | 2 - .../engine/tests/{ => it}/lossy_overwrite.rs | 2 - crates/engine/tests/it/main.rs | 29 +++++++++ crates/engine/tests/{ => it}/model_based.rs | 2 - crates/engine/tests/{ => it}/param_keys.rs | 1 - .../tests/{ => it}/pen_click_after_smooth.rs | 1 - .../tests/{ => it}/pen_endpoint_picking.rs | 1 - crates/engine/tests/{ => it}/ruler_origin.rs | 1 - .../tests/{ => it}/selection_commands.rs | 1 - .../tests/{ => it}/stroke_visibility.rs | 1 - .../tests/{ => it}/text_stroke_scale.rs | 1 - .../tests/{ => it}/three_d_light_color.rs | 1 - crates/format/tests/{ => it}/links.rs | 2 - crates/format/tests/it/main.rs | 9 +++ crates/format/tests/{ => it}/native_v3.rs | 2 - crates/format/tests/{ => it}/native_v4.rs | 2 - crates/format/tests/{ => it}/save_options.rs | 2 - crates/format/tests/{ => it}/streaming.rs | 2 - crates/pathops/tests/it/main.rs | 12 ++++ crates/pathops/tests/{ => it}/ops.rs | 2 - .../tests/{ => it}/pathfinder_pinned.rs | 1 - crates/pathops/tests/{ => it}/prop_pathops.rs | 4 +- crates/pathops/tests/{ => it}/props.rs | 4 +- crates/pathops/tests/{ => it}/regressions.rs | 0 crates/render/tests/{ => it}/dash_align.rs | 0 crates/render/tests/{ => it}/golden.rs | 2 - .../render/tests/{ => it}/gradient_alpha.rs | 0 crates/render/tests/{ => it}/gradient_text.rs | 2 - crates/render/tests/it/main.rs | 10 ++++ crates/render/tests/{ => it}/radial_focal.rs | 0 .../render/tests/{ => it}/stroke_geometry.rs | 2 - crates/svg/tests/{ => it}/blend_export.rs | 2 - crates/svg/tests/{ => it}/colour_glyphs.rs | 2 - crates/svg/tests/{ => it}/container_export.rs | 2 - crates/svg/tests/{ => it}/css_rules.rs | 2 - crates/svg/tests/{ => it}/dash_align.rs | 2 - crates/svg/tests/{ => it}/data_attributes.rs | 1 - crates/svg/tests/{ => it}/effects_export.rs | 2 - .../tests/{ => it}/encoding_profile_fonts.rs | 6 +- crates/svg/tests/{ => it}/focal.rs | 2 - crates/svg/tests/{ => it}/font_weights.rs | 2 - .../svg/tests/{ => it}/foreign_attributes.rs | 1 - crates/svg/tests/{ => it}/gradients.rs | 2 - crates/svg/tests/{ => it}/ids.rs | 2 - crates/svg/tests/{ => it}/import_details.rs | 2 - crates/svg/tests/{ => it}/import_live.rs | 2 - crates/svg/tests/{ => it}/import_text.rs | 2 - crates/svg/tests/{ => it}/import_units.rs | 2 - crates/svg/tests/{ => it}/interactivity.rs | 1 - crates/svg/tests/it/main.rs | 35 +++++++++++ crates/svg/tests/{ => it}/mask_options.rs | 2 - .../svg/tests/{ => it}/non_scaling_stroke.rs | 2 - crates/svg/tests/{ => it}/options.rs | 2 - crates/svg/tests/{ => it}/prop_svg.rs | 2 - crates/svg/tests/{ => it}/raster_paints.rs | 2 - crates/svg/tests/{ => it}/roundtrip.rs | 2 - crates/svg/tests/{ => it}/stroke_export.rs | 2 - crates/svg/tests/{ => it}/svg_glyphs.rs | 2 - crates/svg/tests/{ => it}/symbols_layers.rs | 2 - crates/svg/tests/{ => it}/text_layout.rs | 2 - crates/svg/tests/{ => it}/text_paint_order.rs | 2 - crates/svg/tests/{ => it}/text_stroke.rs | 2 - .../svg/tests/{ => it}/title_control_chars.rs | 2 - crates/testkit/src/strategies.rs | 4 +- docs/development.md | 30 +++++++++- docs/file-format-parity.md | 2 +- docs/target-app-parity.md | 24 ++++---- docs/type-parity.md | 2 +- xtask/src/main.rs | 60 ++++++++++++------- 94 files changed, 235 insertions(+), 197 deletions(-) rename apps/vectorcraft-cli/tests/{ => it}/cli.rs (99%) rename apps/vectorcraft-cli/tests/{ => it}/fileio.rs (97%) create mode 100644 apps/vectorcraft-cli/tests/it/main.rs rename apps/vectorcraft-cli/tests/{ => it}/mcp_e2e.rs (98%) rename apps/vectorcraft/tests/{ => it}/automation_args.rs (96%) rename apps/vectorcraft/tests/{ => it}/help.rs (92%) create mode 100644 apps/vectorcraft/tests/it/main.rs rename crates/affinity/tests/{ => it}/import_limits.rs (97%) create mode 100644 crates/affinity/tests/it/main.rs rename crates/affinity/tests/{ => it}/outline_limits.rs (98%) rename crates/affinity/tests/{ => it}/raster.rs (97%) rename crates/affinity/tests/{ => it}/real_files.rs (93%) rename crates/affinity/tests/{ => it}/text.rs (98%) rename crates/engine/tests/{ => it}/affinity_features.rs (99%) rename crates/engine/tests/{ => it}/affinity_local.rs (98%) rename crates/engine/tests/{ => it}/artboard_click.rs (99%) rename crates/engine/tests/{ => it}/clear_commands.rs (99%) rename crates/engine/tests/{ => it}/compound_attributes.rs (98%) rename crates/engine/tests/{ => it}/dimensions.rs (99%) rename crates/engine/tests/{ => it}/eyedropper_sources.rs (99%) rename crates/engine/tests/{ => it}/find_replace_paras.rs (90%) rename crates/engine/tests/{ => it}/inline_text.rs (97%) rename crates/engine/tests/{ => it}/known_bugs.rs (92%) rename crates/engine/tests/{ => it}/lossy_overwrite.rs (98%) create mode 100644 crates/engine/tests/it/main.rs rename crates/engine/tests/{ => it}/model_based.rs (98%) rename crates/engine/tests/{ => it}/param_keys.rs (99%) rename crates/engine/tests/{ => it}/pen_click_after_smooth.rs (96%) rename crates/engine/tests/{ => it}/pen_endpoint_picking.rs (99%) rename crates/engine/tests/{ => it}/ruler_origin.rs (99%) rename crates/engine/tests/{ => it}/selection_commands.rs (99%) rename crates/engine/tests/{ => it}/stroke_visibility.rs (99%) rename crates/engine/tests/{ => it}/text_stroke_scale.rs (97%) rename crates/engine/tests/{ => it}/three_d_light_color.rs (99%) rename crates/format/tests/{ => it}/links.rs (94%) create mode 100644 crates/format/tests/it/main.rs rename crates/format/tests/{ => it}/native_v3.rs (98%) rename crates/format/tests/{ => it}/native_v4.rs (95%) rename crates/format/tests/{ => it}/save_options.rs (97%) rename crates/format/tests/{ => it}/streaming.rs (97%) create mode 100644 crates/pathops/tests/it/main.rs rename crates/pathops/tests/{ => it}/ops.rs (99%) rename crates/pathops/tests/{ => it}/pathfinder_pinned.rs (98%) rename crates/pathops/tests/{ => it}/prop_pathops.rs (98%) rename crates/pathops/tests/{ => it}/props.rs (96%) rename crates/pathops/tests/{ => it}/regressions.rs (100%) rename crates/render/tests/{ => it}/dash_align.rs (100%) rename crates/render/tests/{ => it}/golden.rs (99%) rename crates/render/tests/{ => it}/gradient_alpha.rs (100%) rename crates/render/tests/{ => it}/gradient_text.rs (94%) create mode 100644 crates/render/tests/it/main.rs rename crates/render/tests/{ => it}/radial_focal.rs (100%) rename crates/render/tests/{ => it}/stroke_geometry.rs (98%) rename crates/svg/tests/{ => it}/blend_export.rs (97%) rename crates/svg/tests/{ => it}/colour_glyphs.rs (96%) rename crates/svg/tests/{ => it}/container_export.rs (96%) rename crates/svg/tests/{ => it}/css_rules.rs (98%) rename crates/svg/tests/{ => it}/dash_align.rs (91%) rename crates/svg/tests/{ => it}/data_attributes.rs (99%) rename crates/svg/tests/{ => it}/effects_export.rs (96%) rename crates/svg/tests/{ => it}/encoding_profile_fonts.rs (97%) rename crates/svg/tests/{ => it}/focal.rs (94%) rename crates/svg/tests/{ => it}/font_weights.rs (94%) rename crates/svg/tests/{ => it}/foreign_attributes.rs (99%) rename crates/svg/tests/{ => it}/gradients.rs (96%) rename crates/svg/tests/{ => it}/ids.rs (96%) rename crates/svg/tests/{ => it}/import_details.rs (99%) rename crates/svg/tests/{ => it}/import_live.rs (99%) rename crates/svg/tests/{ => it}/import_text.rs (99%) rename crates/svg/tests/{ => it}/import_units.rs (96%) rename crates/svg/tests/{ => it}/interactivity.rs (99%) create mode 100644 crates/svg/tests/it/main.rs rename crates/svg/tests/{ => it}/mask_options.rs (97%) rename crates/svg/tests/{ => it}/non_scaling_stroke.rs (95%) rename crates/svg/tests/{ => it}/options.rs (97%) rename crates/svg/tests/{ => it}/prop_svg.rs (96%) rename crates/svg/tests/{ => it}/raster_paints.rs (98%) rename crates/svg/tests/{ => it}/roundtrip.rs (99%) rename crates/svg/tests/{ => it}/stroke_export.rs (95%) rename crates/svg/tests/{ => it}/svg_glyphs.rs (98%) rename crates/svg/tests/{ => it}/symbols_layers.rs (99%) rename crates/svg/tests/{ => it}/text_layout.rs (99%) rename crates/svg/tests/{ => it}/text_paint_order.rs (95%) rename crates/svg/tests/{ => it}/text_stroke.rs (96%) rename crates/svg/tests/{ => it}/title_control_chars.rs (93%) diff --git a/Cargo.toml b/Cargo.toml index c6a4b4521..f45b0b047 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -124,11 +124,15 @@ todo = "deny" unimplemented = "deny" unreachable = "deny" +# Workspace crates keep line tables, so panics and backtraces name file and line; dependencies +# carry no debug info. Full debug info would make the dev target dir several times larger. [profile.dev.package."*"] opt-level = 2 +debug = false [profile.dev] opt-level = 1 +debug = "line-tables-only" [profile.release] lto = "thin" diff --git a/apps/vectorcraft-cli/tests/cli.rs b/apps/vectorcraft-cli/tests/it/cli.rs similarity index 99% rename from apps/vectorcraft-cli/tests/cli.rs rename to apps/vectorcraft-cli/tests/it/cli.rs index e0d035e87..e06444b39 100644 --- a/apps/vectorcraft-cli/tests/cli.rs +++ b/apps/vectorcraft-cli/tests/it/cli.rs @@ -1,5 +1,3 @@ -// Integration tests: unwrapping and panicking on failure is fine here, unlike in shipped code (AGENTS.md › Robustness). -#![allow(clippy::unwrap_used, clippy::expect_used, clippy::panic)] use std::io::Write; use std::process::{Command, Stdio}; diff --git a/apps/vectorcraft-cli/tests/fileio.rs b/apps/vectorcraft-cli/tests/it/fileio.rs similarity index 97% rename from apps/vectorcraft-cli/tests/fileio.rs rename to apps/vectorcraft-cli/tests/it/fileio.rs index 4de10d932..104aeb0fe 100644 --- a/apps/vectorcraft-cli/tests/fileio.rs +++ b/apps/vectorcraft-cli/tests/it/fileio.rs @@ -1,6 +1,4 @@ //! The CLI opens every readable format (PDF, .ai, images) through the engine's `document.open`. -// Integration tests: unwrapping and panicking on failure is fine here, unlike in shipped code (AGENTS.md › Robustness). -#![allow(clippy::unwrap_used, clippy::expect_used, clippy::panic)] use std::process::Command; diff --git a/apps/vectorcraft-cli/tests/it/main.rs b/apps/vectorcraft-cli/tests/it/main.rs new file mode 100644 index 000000000..6918ea19b --- /dev/null +++ b/apps/vectorcraft-cli/tests/it/main.rs @@ -0,0 +1,7 @@ +//! Integration tests: one test binary for the crate, one module per area. +// Unwrapping and panicking on failure is fine here, unlike in shipped code (AGENTS.md › Robustness). +#![allow(clippy::unwrap_used, clippy::expect_used, clippy::panic)] + +mod cli; +mod fileio; +mod mcp_e2e; diff --git a/apps/vectorcraft-cli/tests/mcp_e2e.rs b/apps/vectorcraft-cli/tests/it/mcp_e2e.rs similarity index 98% rename from apps/vectorcraft-cli/tests/mcp_e2e.rs rename to apps/vectorcraft-cli/tests/it/mcp_e2e.rs index e75ef0940..5a353070a 100644 --- a/apps/vectorcraft-cli/tests/mcp_e2e.rs +++ b/apps/vectorcraft-cli/tests/it/mcp_e2e.rs @@ -1,6 +1,4 @@ //! End-to-end MCP over stdio against the built `vectorcraft-cli mcp --headless` binary. -// Integration tests: unwrapping and panicking on failure is fine here, unlike in shipped code (AGENTS.md › Robustness). -#![allow(clippy::unwrap_used, clippy::expect_used, clippy::panic)] use std::io::{BufRead, BufReader, Write}; use std::process::{Child, ChildStdin, ChildStdout, Command, Stdio}; diff --git a/apps/vectorcraft/tests/automation_args.rs b/apps/vectorcraft/tests/it/automation_args.rs similarity index 96% rename from apps/vectorcraft/tests/automation_args.rs rename to apps/vectorcraft/tests/it/automation_args.rs index 8156ff678..93b33fa16 100644 --- a/apps/vectorcraft/tests/automation_args.rs +++ b/apps/vectorcraft/tests/it/automation_args.rs @@ -1,6 +1,3 @@ -// Integration tests: unwrapping and panicking on failure is fine here, unlike in shipped code (AGENTS.md › Robustness). -#![allow(clippy::unwrap_used, clippy::expect_used, clippy::panic)] - use std::process::{Command, Stdio}; use std::time::{Duration, Instant}; diff --git a/apps/vectorcraft/tests/help.rs b/apps/vectorcraft/tests/it/help.rs similarity index 92% rename from apps/vectorcraft/tests/help.rs rename to apps/vectorcraft/tests/it/help.rs index 5c77ecdbb..7c7624031 100644 --- a/apps/vectorcraft/tests/help.rs +++ b/apps/vectorcraft/tests/it/help.rs @@ -1,6 +1,3 @@ -// Integration tests: unwrapping and panicking on failure is fine here, unlike in shipped code (AGENTS.md › Robustness). -#![allow(clippy::unwrap_used, clippy::expect_used, clippy::panic)] - //! `vectorcraft --help` prints the usage and exits before the app starts (#2110): run from a //! terminal, SSH or an agent's shell it used to open the window (or hang without a display). diff --git a/apps/vectorcraft/tests/it/main.rs b/apps/vectorcraft/tests/it/main.rs new file mode 100644 index 000000000..d9dcf39cb --- /dev/null +++ b/apps/vectorcraft/tests/it/main.rs @@ -0,0 +1,6 @@ +//! Integration tests: one test binary for the crate, one module per area. +// Unwrapping and panicking on failure is fine here, unlike in shipped code (AGENTS.md › Robustness). +#![allow(clippy::unwrap_used, clippy::expect_used, clippy::panic)] + +mod automation_args; +mod help; diff --git a/crates/affinity/README.md b/crates/affinity/README.md index 8986dae57..62e2974d2 100644 --- a/crates/affinity/README.md +++ b/crates/affinity/README.md @@ -92,10 +92,10 @@ text-frame fixture. ## Validation -* `engine/tests/affinity_features.rs` covers pages, several artboards per canvas and per spread, +* `engine/tests/it/affinity_features.rs` covers pages, several artboards per canvas and per spread, master pages, tables, paragraph formats, text scale, layer effects, overlays and embedded documents (whose artboards don't become artboards) on synthetic documents, and mutates them. - `engine/tests/affinity_local.rs` compares every artboard of local documents with their thumbnail + `engine/tests/it/affinity_local.rs` compares every artboard of local documents with their thumbnail when `AFFINITY_SAMPLES` points at a folder (never in CI; nothing is committed). * Unit tests on synthetic containers built by the `synth` feature (stored, zlib and zstd entries, checksums, budgets, cycles, hostile streams, every truncation) and property tests of random @@ -106,7 +106,7 @@ text-frame fixture. feature probes plus one separately identified derived regression input from [SethRobinson/Patchy](https://github.com/SethRobinson/Patchy). Only document data and provenance notices were inspected, never that project's importer or authoring scripts. -* `tests/real_files.rs` parses every file and freezes the modeled features of all 33 current +* `tests/it/real_files.rs` parses every file and freezes the modeled features of all 33 current `.af` files. Native raster tests compare decoded pixels with independent embedded images; text tests assert Unicode run boundaries, fallback fonts and feature retention. * `engine/tests/affinity_corpus.rs` requires editable native import, exact `.vectorcraft` @@ -123,7 +123,7 @@ text-frame fixture. documents with layer effects, colour overlays (also over tables), line styles, paragraph and character formats, tables, master pages, CMYK pixel layers and embedded documents (the embedding and the embedded stream), and checks that whatever opens also renders and exports. - `tests/import_limits.rs` builds hostile documents against the limits below: grids of 16 million + `tests/it/import_limits.rs` builds hostile documents against the limits below: grids of 16 million cells, grids and stories shared by many layers, 200 000 paragraphs, a document embedded hundreds of times. `fuzz/` has `cargo-fuzz` targets for the whole reader (`container`) and the object stream (`stream`): diff --git a/crates/affinity/src/tests.rs b/crates/affinity/src/tests.rs index 817012fa7..eeb709d34 100644 --- a/crates/affinity/src/tests.rs +++ b/crates/affinity/src/tests.rs @@ -1,4 +1,4 @@ -//! Unit tests on synthetic inputs; `tests/real_files.rs` covers public Affinity documents. +//! Unit tests on synthetic inputs; `tests/it/real_files.rs` covers public Affinity documents. mod preview { use crate::container::header; diff --git a/crates/affinity/tests/import_limits.rs b/crates/affinity/tests/it/import_limits.rs similarity index 97% rename from crates/affinity/tests/import_limits.rs rename to crates/affinity/tests/it/import_limits.rs index 9a955116f..088c33912 100644 --- a/crates/affinity/tests/import_limits.rs +++ b/crates/affinity/tests/it/import_limits.rs @@ -2,14 +2,8 @@ //! stories, paragraphs and embedded documents stay within the whole read's budget, however often //! a file links or embeds the same content. Original synthetic documents in the reader's //! accepted schema; no Affinity software or files were used. -#![cfg(feature = "synth")] -#![allow(clippy::unwrap_used, clippy::expect_used, clippy::panic)] -mod support { - pub mod text_fixture; -} - -use support::text_fixture::*; +use crate::text_fixture::*; use vectorcraft_affinity::{ Document, Error, Limits, model::{Kind, Node}, diff --git a/crates/affinity/tests/it/main.rs b/crates/affinity/tests/it/main.rs new file mode 100644 index 000000000..84b343019 --- /dev/null +++ b/crates/affinity/tests/it/main.rs @@ -0,0 +1,20 @@ +//! Integration tests: one test binary for the crate, one module per area. +// Unwrapping and panicking on failure is fine here, unlike in shipped code (AGENTS.md › Robustness). +#![allow(clippy::unwrap_used, clippy::expect_used, clippy::panic)] + +#[path = "../support/corpus.rs"] +mod corpus; +#[path = "../support/features.rs"] +mod features; +#[cfg(feature = "synth")] +#[path = "../support/text_fixture.rs"] +mod text_fixture; + +#[cfg(feature = "synth")] +mod import_limits; +#[cfg(feature = "synth")] +mod outline_limits; +mod raster; +mod real_files; +#[cfg(feature = "synth")] +mod text; diff --git a/crates/affinity/tests/outline_limits.rs b/crates/affinity/tests/it/outline_limits.rs similarity index 98% rename from crates/affinity/tests/outline_limits.rs rename to crates/affinity/tests/it/outline_limits.rs index b48eb494b..74151c192 100644 --- a/crates/affinity/tests/outline_limits.rs +++ b/crates/affinity/tests/it/outline_limits.rs @@ -1,7 +1,5 @@ //! Original synthetic graph tests for bounded `.af` outline expansion. These model the reader's //! accepted schema, without using Affinity software, third-party parser code or external assets. -#![cfg(feature = "synth")] -#![allow(clippy::unwrap_used, clippy::expect_used, clippy::panic)] use vectorcraft_affinity::{ Document, Limits, diff --git a/crates/affinity/tests/raster.rs b/crates/affinity/tests/it/raster.rs similarity index 97% rename from crates/affinity/tests/raster.rs rename to crates/affinity/tests/it/raster.rs index 173bc9158..794b4c4f1 100644 --- a/crates/affinity/tests/raster.rs +++ b/crates/affinity/tests/it/raster.rs @@ -1,7 +1,6 @@ //! Pixel retention on current Affinity 3 documents published under MIT by Patchy. //! Assertions use this reader's archive/stream and the original embedded image bytes; //! no third-party Affinity parser, source code or application is used as an oracle. -#![allow(clippy::unwrap_used, clippy::expect_used, clippy::panic)] use vectorcraft_affinity::{ Archive, Limits, @@ -9,8 +8,7 @@ use vectorcraft_affinity::{ stream, }; -#[path = "support/corpus.rs"] -mod corpus; +use crate::corpus; fn images(nodes: &[Node], out: &mut Vec) { for node in nodes { diff --git a/crates/affinity/tests/real_files.rs b/crates/affinity/tests/it/real_files.rs similarity index 93% rename from crates/affinity/tests/real_files.rs rename to crates/affinity/tests/it/real_files.rs index 66beca842..a1d72bd01 100644 --- a/crates/affinity/tests/real_files.rs +++ b/crates/affinity/tests/it/real_files.rs @@ -2,16 +2,13 @@ //! `corpus/affinity`, or any folder of `.af`/`.afdesign`/`.afphoto`/`.afpub` files named by //! `AFFINITY_SAMPLES` (searched recursively). CI requires a complete, checksum-verified pinned //! corpus via `AFFINITY_CORPUS_REQUIRED=1`; ordinary local runs may skip an absent corpus. -#![allow(clippy::unwrap_used, clippy::expect_used, clippy::panic)] use std::path::{Path, PathBuf}; use vectorcraft_affinity::{Archive, Limits, stream}; -#[path = "support/corpus.rs"] -mod corpus; -#[path = "support/features.rs"] -mod features; +use crate::corpus; +use crate::features; fn files(dir: &Path, out: &mut Vec) { for e in std::fs::read_dir(dir).into_iter().flatten().flatten() { @@ -90,7 +87,7 @@ fn public_documents_map_to_the_model() { #[test] fn affinity3_feature_retention_matches_pinned_signatures() { let Some(dir) = corpus::pinned() else { return }; - let expected = include_str!("support/affinity3-signatures.txt"); + let expected = include_str!("../support/affinity3-signatures.txt"); let mut checked = std::collections::BTreeSet::new(); for line in expected.lines().filter(|l| !l.starts_with('#') && !l.is_empty()) { let (name, signature) = line.split_once('\t').expect("signature row must have a tab"); @@ -108,7 +105,7 @@ fn affinity3_feature_retention_matches_pinned_signatures() { doc.saved_by ); } - let manifest = include_str!("../../../xtask/affinity-corpus.sha256"); + let manifest = include_str!("../../../../xtask/affinity-corpus.sha256"); let af_names: std::collections::BTreeSet<_> = manifest.lines().filter_map(|l| l.split_once(" ")).map(|(_, n)| n).filter(|n| n.ends_with(".af")).collect(); assert_eq!(checked, af_names, "every pinned .af file needs a reviewed structural baseline"); diff --git a/crates/affinity/tests/text.rs b/crates/affinity/tests/it/text.rs similarity index 98% rename from crates/affinity/tests/text.rs rename to crates/affinity/tests/it/text.rs index db984652b..35a621f81 100644 --- a/crates/affinity/tests/text.rs +++ b/crates/affinity/tests/it/text.rs @@ -1,14 +1,8 @@ //! Synthetic `.af` version-12 text regression oracles; see support/text_fixture.rs for provenance. //! Unicode ranges below test the scalar-index contract corroborated by the pinned Affinity 3 //! mixed-run fixture. Broad complex typography still needs independent visual validation. -#![cfg(feature = "synth")] -#![allow(clippy::unwrap_used, clippy::expect_used, clippy::panic)] -mod support { - pub mod corpus; - pub mod text_fixture; -} -use support::text_fixture::*; +use crate::text_fixture::*; use vectorcraft_affinity::{ Document, Limits, model::{Align, Kind, Paragraph, Text}, @@ -179,7 +173,7 @@ fn stored_fallback_font_is_used_only_when_it_names_a_font() { #[test] fn real_affinity3_text_fixtures_confirm_unicode_and_caps_fields() { - let Some(corpus) = support::corpus::pinned() else { return }; + let Some(corpus) = crate::corpus::pinned() else { return }; // Files fetched at the commit and sha256 in xtask/affinity-corpus.sha256. No Patchy parser // source was read; assertions describe this crate's parsing of its published MIT documents. let load = |name: &str| vectorcraft_affinity::read(&std::fs::read(corpus.join(name)).unwrap(), Limits::default()).unwrap(); diff --git a/crates/engine/tests/affinity_features.rs b/crates/engine/tests/it/affinity_features.rs similarity index 99% rename from crates/engine/tests/affinity_features.rs rename to crates/engine/tests/it/affinity_features.rs index dbc10fcb8..cfabffc9a 100644 --- a/crates/engine/tests/affinity_features.rs +++ b/crates/engine/tests/it/affinity_features.rs @@ -2,12 +2,9 @@ //! layer effects and embedded documents, on original synthetic documents built with the reader's //! `synth` feature (no Affinity software or files were used). The fixtures follow DesignCraft's //! Affinity import tests, whose reader VectorCraft shares. -#![allow(clippy::unwrap_used, clippy::expect_used, clippy::panic)] -#[path = "support/affinity_docs.rs"] -mod affinity_docs; -#[path = "../../affinity/tests/support/text_fixture.rs"] -mod text_fixture; +use crate::affinity_docs; +use crate::text_fixture; use std::sync::Arc; diff --git a/crates/engine/tests/affinity_local.rs b/crates/engine/tests/it/affinity_local.rs similarity index 98% rename from crates/engine/tests/affinity_local.rs rename to crates/engine/tests/it/affinity_local.rs index d3589fabf..b9854c6ba 100644 --- a/crates/engine/tests/affinity_local.rs +++ b/crates/engine/tests/it/affinity_local.rs @@ -3,7 +3,6 @@ //! stored in the file. Reports the mean difference per artboard (0–255, both on white); with //! `AFFINITY_SAMPLES_OUT` set, writes each board's thumbnail crop and render side by side there. //! Skipped when `AFFINITY_SAMPLES` is unset (as in CI). -#![allow(clippy::unwrap_used, clippy::expect_used, clippy::panic)] use std::path::{Path, PathBuf}; diff --git a/crates/engine/tests/artboard_click.rs b/crates/engine/tests/it/artboard_click.rs similarity index 99% rename from crates/engine/tests/artboard_click.rs rename to crates/engine/tests/it/artboard_click.rs index ff0066154..c9a7df8d0 100644 --- a/crates/engine/tests/artboard_click.rs +++ b/crates/engine/tests/it/artboard_click.rs @@ -1,7 +1,6 @@ //! Artboard clicks fit the object without changing its art or selection, and are one undo step. //! The second click of a double-click on an object does not fit another artboard, and that //! double-click does not open Artboard Options. Empty artboard space still does. -#![allow(clippy::unwrap_used)] use serde_json::json; use vectorcraft_doc::NodeId; diff --git a/crates/engine/tests/clear_commands.rs b/crates/engine/tests/it/clear_commands.rs similarity index 99% rename from crates/engine/tests/clear_commands.rs rename to crates/engine/tests/it/clear_commands.rs index 1cb639e20..50a6fbd86 100644 --- a/crates/engine/tests/clear_commands.rs +++ b/crates/engine/tests/it/clear_commands.rs @@ -1,5 +1,4 @@ //! Clear deletes its exact targets, including compound members (#786). -#![allow(clippy::unwrap_used, clippy::expect_used, clippy::panic)] use serde_json::json; use vectorcraft_doc::NodeId; diff --git a/crates/engine/tests/compound_attributes.rs b/crates/engine/tests/it/compound_attributes.rs similarity index 98% rename from crates/engine/tests/compound_attributes.rs rename to crates/engine/tests/it/compound_attributes.rs index 3366fc9c7..0bec97554 100644 --- a/crates/engine/tests/compound_attributes.rs +++ b/crates/engine/tests/it/compound_attributes.rs @@ -1,5 +1,4 @@ //! Compound appearance and fill-rule edits from a directly selected member (#1197). -#![allow(clippy::unwrap_used, clippy::expect_used, clippy::panic)] use serde_json::{Value, json}; use vectorcraft_doc::{NodeId, NodeKind}; diff --git a/crates/engine/tests/dimensions.rs b/crates/engine/tests/it/dimensions.rs similarity index 99% rename from crates/engine/tests/dimensions.rs rename to crates/engine/tests/it/dimensions.rs index 8413aef71..7c4872d56 100644 --- a/crates/engine/tests/dimensions.rs +++ b/crates/engine/tests/it/dimensions.rs @@ -1,5 +1,4 @@ //! Linked measurements, history, portable artwork and hostile command input. -#![allow(clippy::unwrap_used, clippy::expect_used, clippy::panic)] use serde_json::{Value, json}; use vectorcraft_engine::{ Session, ViewInfo, diff --git a/crates/engine/tests/eyedropper_sources.rs b/crates/engine/tests/it/eyedropper_sources.rs similarity index 99% rename from crates/engine/tests/eyedropper_sources.rs rename to crates/engine/tests/it/eyedropper_sources.rs index 9dc0ebf25..9639f3b8e 100644 --- a/crates/engine/tests/eyedropper_sources.rs +++ b/crates/engine/tests/it/eyedropper_sources.rs @@ -1,5 +1,4 @@ //! Visible art is readable by the Eyedropper without making it editable (#1251). -#![allow(clippy::unwrap_used)] use serde_json::json; use vectorcraft_doc::NodeId; diff --git a/crates/engine/tests/find_replace_paras.rs b/crates/engine/tests/it/find_replace_paras.rs similarity index 90% rename from crates/engine/tests/find_replace_paras.rs rename to crates/engine/tests/it/find_replace_paras.rs index b511ddf08..05217dd49 100644 --- a/crates/engine/tests/find_replace_paras.rs +++ b/crates/engine/tests/it/find_replace_paras.rs @@ -1,7 +1,5 @@ //! `edit.findReplace` keeps per-paragraph styles lined up with the text when a find or replace //! string holds a line break, as `text.editRange` does. -// Integration tests: unwrapping and panicking on failure is fine here, unlike in shipped code (AGENTS.md › Robustness). -#![allow(clippy::unwrap_used, clippy::expect_used, clippy::panic)] use serde_json::json; use vectorcraft_doc::{Justify, NodeId, NodeKind}; diff --git a/crates/engine/tests/inline_text.rs b/crates/engine/tests/it/inline_text.rs similarity index 97% rename from crates/engine/tests/inline_text.rs rename to crates/engine/tests/it/inline_text.rs index 5b009ea61..a7c23c836 100644 --- a/crates/engine/tests/inline_text.rs +++ b/crates/engine/tests/it/inline_text.rs @@ -1,7 +1,5 @@ //! Inline graphics in text drawn on the canvas and written to SVG and PDF: a symbol (a red //! circle drawn in code) set inline in a line of type. -// Integration tests: unwrapping and panicking on failure is fine here, unlike in shipped code (AGENTS.md › Robustness). -#![allow(clippy::unwrap_used, clippy::expect_used, clippy::panic)] use serde_json::{Value, json}; use vectorcraft_doc::{Document, NodeId, NodeKind, TextObject}; diff --git a/crates/engine/tests/known_bugs.rs b/crates/engine/tests/it/known_bugs.rs similarity index 92% rename from crates/engine/tests/known_bugs.rs rename to crates/engine/tests/it/known_bugs.rs index 61f1bf6da..ea394663a 100644 --- a/crates/engine/tests/known_bugs.rs +++ b/crates/engine/tests/it/known_bugs.rs @@ -1,7 +1,5 @@ //! Minimal reproductions of engine bugs found by the property tests. Each is `#[ignore]`d with a //! `BUG:` reason until fixed; remove the attribute when the fix lands. -// Integration tests: unwrapping and panicking on failure is fine here, unlike in shipped code (AGENTS.md › Robustness). -#![allow(clippy::unwrap_used, clippy::expect_used, clippy::panic)] use serde_json::json; use vectorcraft_engine::Session; diff --git a/crates/engine/tests/lossy_overwrite.rs b/crates/engine/tests/it/lossy_overwrite.rs similarity index 98% rename from crates/engine/tests/lossy_overwrite.rs rename to crates/engine/tests/it/lossy_overwrite.rs index c4ee60b4d..559e45a33 100644 --- a/crates/engine/tests/lossy_overwrite.rs +++ b/crates/engine/tests/it/lossy_overwrite.rs @@ -1,8 +1,6 @@ //! A file whose import left something out isn't written over silently: its hidden text, art or //! layers would be gone for good. -#![allow(clippy::unwrap_used, clippy::expect_used, clippy::panic)] - use serde_json::json; use vectorcraft_engine::Session; diff --git a/crates/engine/tests/it/main.rs b/crates/engine/tests/it/main.rs new file mode 100644 index 000000000..b0409cffd --- /dev/null +++ b/crates/engine/tests/it/main.rs @@ -0,0 +1,29 @@ +//! Integration tests: one test binary for the crate, one module per area. +// Unwrapping and panicking on failure is fine here, unlike in shipped code (AGENTS.md › Robustness). +#![allow(clippy::unwrap_used, clippy::expect_used, clippy::panic)] + +#[path = "../support/affinity_docs.rs"] +mod affinity_docs; +#[path = "../../../affinity/tests/support/text_fixture.rs"] +mod text_fixture; + +mod affinity_features; +mod affinity_local; +mod artboard_click; +mod clear_commands; +mod compound_attributes; +mod dimensions; +mod eyedropper_sources; +mod find_replace_paras; +mod inline_text; +mod known_bugs; +mod lossy_overwrite; +mod model_based; +mod param_keys; +mod pen_click_after_smooth; +mod pen_endpoint_picking; +mod ruler_origin; +mod selection_commands; +mod stroke_visibility; +mod text_stroke_scale; +mod three_d_light_color; diff --git a/crates/engine/tests/model_based.rs b/crates/engine/tests/it/model_based.rs similarity index 98% rename from crates/engine/tests/model_based.rs rename to crates/engine/tests/it/model_based.rs index 13a210324..b11e3b059 100644 --- a/crates/engine/tests/model_based.rs +++ b/crates/engine/tests/it/model_based.rs @@ -1,7 +1,5 @@ //! Model-based / stateful property tests: random command sequences drawn from the registry, with //! structural invariants checked after every step and history/serialization invariants at the end. -// Integration tests: unwrapping and panicking on failure is fine here, unlike in shipped code (AGENTS.md › Robustness). -#![allow(clippy::unwrap_used, clippy::expect_used, clippy::panic)] use proptest::prelude::*; use serde_json::json; diff --git a/crates/engine/tests/param_keys.rs b/crates/engine/tests/it/param_keys.rs similarity index 99% rename from crates/engine/tests/param_keys.rs rename to crates/engine/tests/it/param_keys.rs index fbde80a7a..3da393ca8 100644 --- a/crates/engine/tests/param_keys.rs +++ b/crates/engine/tests/it/param_keys.rs @@ -1,6 +1,5 @@ //! A caller's params are checked against the command's description, but a journal replays as it //! was recorded (#1442). -#![allow(clippy::unwrap_used, clippy::expect_used, clippy::panic)] use serde_json::json; use vectorcraft_engine::{Session, check_params}; diff --git a/crates/engine/tests/pen_click_after_smooth.rs b/crates/engine/tests/it/pen_click_after_smooth.rs similarity index 96% rename from crates/engine/tests/pen_click_after_smooth.rs rename to crates/engine/tests/it/pen_click_after_smooth.rs index d36a701b6..21b53a860 100644 --- a/crates/engine/tests/pen_click_after_smooth.rs +++ b/crates/engine/tests/it/pen_click_after_smooth.rs @@ -1,5 +1,4 @@ //! A click after a smooth anchor: the new corner has no handles, so the segment curves from the previous anchor's side only. -#![allow(clippy::unwrap_used, clippy::expect_used, clippy::panic)] use serde_json::json; use vectorcraft_doc::NodeKind; diff --git a/crates/engine/tests/pen_endpoint_picking.rs b/crates/engine/tests/it/pen_endpoint_picking.rs similarity index 99% rename from crates/engine/tests/pen_endpoint_picking.rs rename to crates/engine/tests/it/pen_endpoint_picking.rs index cfba10538..b2e77e52e 100644 --- a/crates/engine/tests/pen_endpoint_picking.rs +++ b/crates/engine/tests/it/pen_endpoint_picking.rs @@ -1,5 +1,4 @@ //! Original tiny-geometry controls for Pen endpoint/Alt integration with continue-any-path. -#![allow(clippy::unwrap_used, clippy::expect_used, clippy::panic)] use serde_json::json; use vectorcraft_doc::{Node, NodeId, NodeKind}; diff --git a/crates/engine/tests/ruler_origin.rs b/crates/engine/tests/it/ruler_origin.rs similarity index 99% rename from crates/engine/tests/ruler_origin.rs rename to crates/engine/tests/it/ruler_origin.rs index 353f0ccab..4b5c06286 100644 --- a/crates/engine/tests/ruler_origin.rs +++ b/crates/engine/tests/it/ruler_origin.rs @@ -1,5 +1,4 @@ //! #1212: ruler coordinates are saved metadata, independent of the artwork's coordinates. -#![allow(clippy::unwrap_used, clippy::expect_used, clippy::panic)] use serde_json::{Value, json}; use vectorcraft_doc::RulerMode; diff --git a/crates/engine/tests/selection_commands.rs b/crates/engine/tests/it/selection_commands.rs similarity index 99% rename from crates/engine/tests/selection_commands.rs rename to crates/engine/tests/it/selection_commands.rs index 7d05e68ce..4e9b8e10b 100644 --- a/crates/engine/tests/selection_commands.rs +++ b/crates/engine/tests/it/selection_commands.rs @@ -1,5 +1,4 @@ //! Selection command results and validation for agent callers (#784). -#![allow(clippy::unwrap_used, clippy::expect_used, clippy::panic)] use serde_json::{Value, json}; use vectorcraft_doc::NodeId; diff --git a/crates/engine/tests/stroke_visibility.rs b/crates/engine/tests/it/stroke_visibility.rs similarity index 99% rename from crates/engine/tests/stroke_visibility.rs rename to crates/engine/tests/it/stroke_visibility.rs index f9c574ab7..8f9ecdff0 100644 --- a/crates/engine/tests/stroke_visibility.rs +++ b/crates/engine/tests/it/stroke_visibility.rs @@ -1,5 +1,4 @@ //! Painting a previously unpainted zero-width stroke restores the existing 1 pt default. -#![allow(clippy::unwrap_used)] use serde_json::json; use vectorcraft_doc::NodeId; diff --git a/crates/engine/tests/text_stroke_scale.rs b/crates/engine/tests/it/text_stroke_scale.rs similarity index 97% rename from crates/engine/tests/text_stroke_scale.rs rename to crates/engine/tests/it/text_stroke_scale.rs index 10ab2bf0a..bece66d47 100644 --- a/crates/engine/tests/text_stroke_scale.rs +++ b/crates/engine/tests/it/text_stroke_scale.rs @@ -1,6 +1,5 @@ //! A stroke weight set on type is a document-space weight, whether the type was enlarged by its //! font size or by a transform (issue #3241). -#![allow(clippy::unwrap_used, clippy::panic)] use serde_json::json; use vectorcraft_doc::{NodeId, NodeKind}; diff --git a/crates/engine/tests/three_d_light_color.rs b/crates/engine/tests/it/three_d_light_color.rs similarity index 99% rename from crates/engine/tests/three_d_light_color.rs rename to crates/engine/tests/it/three_d_light_color.rs index f9de119f1..cb04c5649 100644 --- a/crates/engine/tests/three_d_light_color.rs +++ b/crates/engine/tests/it/three_d_light_color.rs @@ -1,5 +1,4 @@ //! Colored 3D lighting remains a live command and survives native and vector output. -#![allow(clippy::unwrap_used, clippy::expect_used, clippy::panic)] use serde_json::{Value, json}; use vectorcraft_doc::{Document, Node, NodeId}; use vectorcraft_engine::Session; diff --git a/crates/format/tests/links.rs b/crates/format/tests/it/links.rs similarity index 94% rename from crates/format/tests/links.rs rename to crates/format/tests/it/links.rs index 81622f2bb..e5a789f0d 100644 --- a/crates/format/tests/links.rs +++ b/crates/format/tests/it/links.rs @@ -1,7 +1,5 @@ //! Linked images in `.vectorcraft` files: their link details round-trip, and an image only linked //! images show is saved as its preview. -// Integration tests: unwrapping and panicking on failure is fine here, unlike in shipped code (AGENTS.md › Robustness). -#![allow(clippy::unwrap_used, clippy::expect_used, clippy::panic)] use std::sync::Arc; diff --git a/crates/format/tests/it/main.rs b/crates/format/tests/it/main.rs new file mode 100644 index 000000000..a5f028c38 --- /dev/null +++ b/crates/format/tests/it/main.rs @@ -0,0 +1,9 @@ +//! Integration tests: one test binary for the crate, one module per area. +// Unwrapping and panicking on failure is fine here, unlike in shipped code (AGENTS.md › Robustness). +#![allow(clippy::unwrap_used, clippy::expect_used, clippy::panic)] + +mod links; +mod native_v3; +mod native_v4; +mod save_options; +mod streaming; diff --git a/crates/format/tests/native_v3.rs b/crates/format/tests/it/native_v3.rs similarity index 98% rename from crates/format/tests/native_v3.rs rename to crates/format/tests/it/native_v3.rs index c6fa5216f..33633de5c 100644 --- a/crates/format/tests/native_v3.rs +++ b/crates/format/tests/it/native_v3.rs @@ -1,7 +1,5 @@ //! `.vectorcraft` v3: compression, pruning unused images, keys from newer versions, colour //! profiles as a document field, saving for older versions and the embedded preview. -// Integration tests: unwrapping and panicking on failure is fine here, unlike in shipped code (AGENTS.md › Robustness). -#![allow(clippy::unwrap_used, clippy::expect_used, clippy::panic)] use std::io::Write as _; use std::sync::Arc; diff --git a/crates/format/tests/native_v4.rs b/crates/format/tests/it/native_v4.rs similarity index 95% rename from crates/format/tests/native_v4.rs rename to crates/format/tests/it/native_v4.rs index bd2017e58..c24231651 100644 --- a/crates/format/tests/native_v4.rs +++ b/crates/format/tests/it/native_v4.rs @@ -1,7 +1,5 @@ //! `.vectorcraft` v4: large data after the JSON (images, the PDF, profiles), small files still plain //! JSON, older versions inline, damaged offsets refused. -// Integration tests: unwrapping and panicking on failure is fine here, unlike in shipped code (AGENTS.md › Robustness). -#![allow(clippy::unwrap_used, clippy::expect_used, clippy::panic)] use std::sync::Arc; diff --git a/crates/format/tests/save_options.rs b/crates/format/tests/it/save_options.rs similarity index 97% rename from crates/format/tests/save_options.rs rename to crates/format/tests/it/save_options.rs index dbc712f5a..41b91a9c5 100644 --- a/crates/format/tests/save_options.rs +++ b/crates/format/tests/it/save_options.rs @@ -1,8 +1,6 @@ //! The native save options of the file itself: Include Linked Files, embedded ICC profiles and the //! PDF a PDF-compatible file carries, each round-tripping (and ignored by readers that don't //! need them). -// Integration tests: unwrapping and panicking on failure is fine here, unlike in shipped code (AGENTS.md › Robustness). -#![allow(clippy::unwrap_used, clippy::expect_used, clippy::panic)] use std::sync::Arc; diff --git a/crates/format/tests/streaming.rs b/crates/format/tests/it/streaming.rs similarity index 97% rename from crates/format/tests/streaming.rs rename to crates/format/tests/it/streaming.rs index 6775584c1..93a58f894 100644 --- a/crates/format/tests/streaming.rs +++ b/crates/format/tests/it/streaming.rs @@ -2,8 +2,6 @@ //! before (the same JSON and data after it, unpacked; the same gzip header), files written the old //! way still open, entries are read whatever their order, and the limits apply per part of the //! file. -// Integration tests: unwrapping and panicking on failure is fine here, unlike in shipped code (AGENTS.md › Robustness). -#![allow(clippy::unwrap_used, clippy::expect_used, clippy::panic)] use std::collections::BTreeMap; use std::io::{Read, Write}; diff --git a/crates/pathops/tests/it/main.rs b/crates/pathops/tests/it/main.rs new file mode 100644 index 000000000..3f565e040 --- /dev/null +++ b/crates/pathops/tests/it/main.rs @@ -0,0 +1,12 @@ +//! Integration tests: one test binary for the crate, one module per area. +// Unwrapping and panicking on failure is fine here, unlike in shipped code (AGENTS.md › Robustness). +#![allow(clippy::unwrap_used, clippy::expect_used, clippy::panic)] + +#[path = "../common/mod.rs"] +mod common; + +mod ops; +mod pathfinder_pinned; +mod prop_pathops; +mod props; +mod regressions; diff --git a/crates/pathops/tests/ops.rs b/crates/pathops/tests/it/ops.rs similarity index 99% rename from crates/pathops/tests/ops.rs rename to crates/pathops/tests/it/ops.rs index 0833e5b26..ff8e6aa76 100644 --- a/crates/pathops/tests/ops.rs +++ b/crates/pathops/tests/it/ops.rs @@ -1,5 +1,3 @@ -// Integration tests: unwrapping and panicking on failure is fine here, unlike in shipped code (AGENTS.md › Robustness). -#![allow(clippy::unwrap_used, clippy::expect_used, clippy::panic)] use std::f64::consts::PI; use kurbo::{ParamCurve, Point, Rect, Shape as _}; diff --git a/crates/pathops/tests/pathfinder_pinned.rs b/crates/pathops/tests/it/pathfinder_pinned.rs similarity index 98% rename from crates/pathops/tests/pathfinder_pinned.rs rename to crates/pathops/tests/it/pathfinder_pinned.rs index 5e9f27a3d..a6e987d27 100644 --- a/crates/pathops/tests/pathfinder_pinned.rs +++ b/crates/pathops/tests/it/pathfinder_pinned.rs @@ -1,7 +1,6 @@ //! The exact output of every Pathfinder operation, pinned so that work on the windings and the //! coverage tests can't change it: overlapping ellipses, rectangles and stars (even-odd and //! non-zero, repeated keys for Merge) at a few counts. -#![allow(clippy::unwrap_used, clippy::expect_used, clippy::panic)] use vectorcraft_geom::{FillRule, PathData, Point, Rect, SubPath, shapes}; use vectorcraft_pathops::{PathfinderOp, Shape, pathfinder}; diff --git a/crates/pathops/tests/prop_pathops.rs b/crates/pathops/tests/it/prop_pathops.rs similarity index 98% rename from crates/pathops/tests/prop_pathops.rs rename to crates/pathops/tests/it/prop_pathops.rs index 82feae9f9..995f86975 100644 --- a/crates/pathops/tests/prop_pathops.rs +++ b/crates/pathops/tests/it/prop_pathops.rs @@ -1,9 +1,7 @@ //! Path-operation properties on concave polygons, ellipses and random smooth curves (complements //! `props.rs`, which uses rectangles and circles). -// Integration tests: unwrapping and panicking on failure is fine here, unlike in shipped code (AGENTS.md › Robustness). -#![allow(clippy::unwrap_used, clippy::expect_used, clippy::panic)] -mod common; +use crate::common; use proptest::prelude::*; use vectorcraft_geom::{FillRule, PathData, Point, Rect}; diff --git a/crates/pathops/tests/props.rs b/crates/pathops/tests/it/props.rs similarity index 96% rename from crates/pathops/tests/props.rs rename to crates/pathops/tests/it/props.rs index f09e96f0f..b5adcb7cc 100644 --- a/crates/pathops/tests/props.rs +++ b/crates/pathops/tests/it/props.rs @@ -1,6 +1,4 @@ -// Integration tests: unwrapping and panicking on failure is fine here, unlike in shipped code (AGENTS.md › Robustness). -#![allow(clippy::unwrap_used, clippy::expect_used, clippy::panic)] -mod common; +use crate::common; use std::f64::consts::PI; diff --git a/crates/pathops/tests/regressions.rs b/crates/pathops/tests/it/regressions.rs similarity index 100% rename from crates/pathops/tests/regressions.rs rename to crates/pathops/tests/it/regressions.rs diff --git a/crates/render/tests/dash_align.rs b/crates/render/tests/it/dash_align.rs similarity index 100% rename from crates/render/tests/dash_align.rs rename to crates/render/tests/it/dash_align.rs diff --git a/crates/render/tests/golden.rs b/crates/render/tests/it/golden.rs similarity index 99% rename from crates/render/tests/golden.rs rename to crates/render/tests/it/golden.rs index f889b1721..4820cf8b6 100644 --- a/crates/render/tests/golden.rs +++ b/crates/render/tests/it/golden.rs @@ -1,7 +1,5 @@ //! Pixel-sample "golden" tests on small fixtures: gradients, blend modes, clip groups, stroke //! alignment/dashes/arrowheads, effects, text, and opacity folding vs layer compositing. -// Integration tests: unwrapping and panicking on failure is fine here, unlike in shipped code (AGENTS.md › Robustness). -#![allow(clippy::unwrap_used, clippy::expect_used, clippy::panic)] use serde_json::json; use vectorcraft_color::{BlendMode, Color, Gradient, GradientKind, GradientPaint, GradientStop, Paint}; diff --git a/crates/render/tests/gradient_alpha.rs b/crates/render/tests/it/gradient_alpha.rs similarity index 100% rename from crates/render/tests/gradient_alpha.rs rename to crates/render/tests/it/gradient_alpha.rs diff --git a/crates/render/tests/gradient_text.rs b/crates/render/tests/it/gradient_text.rs similarity index 94% rename from crates/render/tests/gradient_text.rs rename to crates/render/tests/it/gradient_text.rs index 6307a406a..2857058ce 100644 --- a/crates/render/tests/gradient_text.rs +++ b/crates/render/tests/it/gradient_text.rs @@ -1,6 +1,4 @@ //! Gradients on type: a vector across the text, and run strokes fitted like object strokes. -// Integration tests: unwrapping and panicking on failure is fine here, unlike in shipped code (AGENTS.md › Robustness). -#![allow(clippy::unwrap_used, clippy::expect_used, clippy::panic)] use serde_json::json; use vectorcraft_color::Paint; diff --git a/crates/render/tests/it/main.rs b/crates/render/tests/it/main.rs new file mode 100644 index 000000000..67afd6993 --- /dev/null +++ b/crates/render/tests/it/main.rs @@ -0,0 +1,10 @@ +//! Integration tests: one test binary for the crate, one module per area. +// Unwrapping and panicking on failure is fine here, unlike in shipped code (AGENTS.md › Robustness). +#![allow(clippy::unwrap_used, clippy::expect_used, clippy::panic)] + +mod dash_align; +mod golden; +mod gradient_alpha; +mod gradient_text; +mod radial_focal; +mod stroke_geometry; diff --git a/crates/render/tests/radial_focal.rs b/crates/render/tests/it/radial_focal.rs similarity index 100% rename from crates/render/tests/radial_focal.rs rename to crates/render/tests/it/radial_focal.rs diff --git a/crates/render/tests/stroke_geometry.rs b/crates/render/tests/it/stroke_geometry.rs similarity index 98% rename from crates/render/tests/stroke_geometry.rs rename to crates/render/tests/it/stroke_geometry.rs index b53ed21c3..a8813da23 100644 --- a/crates/render/tests/stroke_geometry.rs +++ b/crates/render/tests/it/stroke_geometry.rs @@ -1,7 +1,5 @@ //! Pixel tests for the shared stroke geometry (`vectorcraft_effects::stroke`) on the canvas: //! dotted lines (zero-length dashes) and arrowheads (hollow kinds, alignment, compositing). -// Integration tests: unwrapping and panicking on failure is fine here, unlike in shipped code (AGENTS.md › Robustness). -#![allow(clippy::unwrap_used, clippy::expect_used, clippy::panic)] use vectorcraft_color::{Color, Gradient, GradientKind, GradientPaint, GradientStop, Paint}; use vectorcraft_doc::{Appearance, AppearanceItem, ArrowAlign, Arrowhead, Dash, Document, LineCap, StrokeLayer}; diff --git a/crates/svg/tests/blend_export.rs b/crates/svg/tests/it/blend_export.rs similarity index 97% rename from crates/svg/tests/blend_export.rs rename to crates/svg/tests/it/blend_export.rs index ffe510524..65fb26799 100644 --- a/crates/svg/tests/blend_export.rs +++ b/crates/svg/tests/it/blend_export.rs @@ -1,7 +1,5 @@ //! Blend modes and opacity masks in SVG export look as on the canvas: every mode follows the //! reference formulas when resvg draws the file, and masks take luminance the canvas's way. -// Integration tests: unwrapping and panicking on failure is fine here, unlike in shipped code (AGENTS.md › Robustness). -#![allow(clippy::unwrap_used, clippy::expect_used, clippy::panic)] use vectorcraft_color::blend::blend_rgb; use vectorcraft_color::{BlendMode, Color, Paint}; diff --git a/crates/svg/tests/colour_glyphs.rs b/crates/svg/tests/it/colour_glyphs.rs similarity index 96% rename from crates/svg/tests/colour_glyphs.rs rename to crates/svg/tests/it/colour_glyphs.rs index 4120c9edc..03de592d8 100644 --- a/crates/svg/tests/colour_glyphs.rs +++ b/crates/svg/tests/it/colour_glyphs.rs @@ -1,7 +1,5 @@ //! Colour bitmap glyphs (emoji): outlined text writes their images; live text leaves them to the //! viewer, and embedded fonts don't carry them. -// Integration tests: unwrapping and panicking on failure is fine here, unlike in shipped code (AGENTS.md › Robustness). -#![allow(clippy::unwrap_used, clippy::expect_used, clippy::panic)] use skrifa::raw::TableProvider; use vectorcraft_doc::{CharStyle, Document, Node, NodeKind, TextObject}; diff --git a/crates/svg/tests/container_export.rs b/crates/svg/tests/it/container_export.rs similarity index 96% rename from crates/svg/tests/container_export.rs rename to crates/svg/tests/it/container_export.rs index 24d6bcd33..5f34b6cc3 100644 --- a/crates/svg/tests/container_export.rs +++ b/crates/svg/tests/it/container_export.rs @@ -1,8 +1,6 @@ //! The appearance of groups and layers in SVG export: their own fills and strokes are baked into //! paths painting the members (below or above them as the contents slot says), their geometry //! effects into the members, and their raster effects filter the whole group. -// Integration tests: unwrapping and panicking on failure is fine here, unlike in shipped code (AGENTS.md › Robustness). -#![allow(clippy::unwrap_used, clippy::expect_used, clippy::panic)] use std::sync::Arc; diff --git a/crates/svg/tests/css_rules.rs b/crates/svg/tests/it/css_rules.rs similarity index 98% rename from crates/svg/tests/css_rules.rs rename to crates/svg/tests/it/css_rules.rs index 48e0747ca..0a7633db4 100644 --- a/crates/svg/tests/css_rules.rs +++ b/crates/svg/tests/it/css_rules.rs @@ -1,8 +1,6 @@ //! CSS for objects (the CSS Properties panel): shapes give backgrounds, borders and corner radii, //! type its font, gradients `linear-gradient()`/`radial-gradient()`, and every property both write //! reads as SVG export writes it. -// Integration tests: unwrapping and panicking on failure is fine here, unlike in shipped code (AGENTS.md › Robustness). -#![allow(clippy::unwrap_used, clippy::expect_used, clippy::panic)] use vectorcraft_color::{BlendMode, Color, Gradient, GradientGeom, GradientKind, GradientPaint, Paint}; use vectorcraft_doc::{Appearance, CharStyle, Document, Effect, Justify, LiveShape, Node, NodeId, NodeKind, TextObject}; diff --git a/crates/svg/tests/dash_align.rs b/crates/svg/tests/it/dash_align.rs similarity index 91% rename from crates/svg/tests/dash_align.rs rename to crates/svg/tests/it/dash_align.rs index edb047b1b..2885d3744 100644 --- a/crates/svg/tests/dash_align.rs +++ b/crates/svg/tests/it/dash_align.rs @@ -1,7 +1,5 @@ //! Dashes fitted to corners export as the canvas's filled outlines (a dash array can't fit them); //! exact dashes stay a `stroke-dasharray`. Checked by rendering the exported SVG with resvg. -// Integration tests: unwrapping and panicking on failure is fine here, unlike in shipped code (AGENTS.md › Robustness). -#![allow(clippy::unwrap_used, clippy::expect_used, clippy::panic)] use vectorcraft_color::{Color, Paint}; use vectorcraft_doc::{Appearance, AppearanceItem, Dash, Document, Node, StrokeLayer}; diff --git a/crates/svg/tests/data_attributes.rs b/crates/svg/tests/it/data_attributes.rs similarity index 99% rename from crates/svg/tests/data_attributes.rs rename to crates/svg/tests/it/data_attributes.rs index 762404816..981662c7c 100644 --- a/crates/svg/tests/data_attributes.rs +++ b/crates/svg/tests/it/data_attributes.rs @@ -1,6 +1,5 @@ //! Synthetic XML 1.0/SVG round trips: https://www.w3.org/TR/xml/#AVNormalize //! https://www.w3.org/TR/xml/#NT-NameChar https://www.w3.org/TR/xml/#charsets -#![allow(clippy::unwrap_used, clippy::expect_used, clippy::panic)] use std::collections::HashSet; use usvg::roxmltree; use vectorcraft_doc::{Document, Node}; diff --git a/crates/svg/tests/effects_export.rs b/crates/svg/tests/it/effects_export.rs similarity index 96% rename from crates/svg/tests/effects_export.rs rename to crates/svg/tests/it/effects_export.rs index 800d00e1d..26154045a 100644 --- a/crates/svg/tests/effects_export.rs +++ b/crates/svg/tests/it/effects_export.rs @@ -1,7 +1,5 @@ //! Live effects in SVG export: a fill or stroke's own raster effects become filters on that item's //! element, and geometry effects on type are baked through its outlines. -// Integration tests: unwrapping and panicking on failure is fine here, unlike in shipped code (AGENTS.md › Robustness). -#![allow(clippy::unwrap_used, clippy::expect_used, clippy::panic)] use serde_json::json; use vectorcraft_color::{Color, Paint}; diff --git a/crates/svg/tests/encoding_profile_fonts.rs b/crates/svg/tests/it/encoding_profile_fonts.rs similarity index 97% rename from crates/svg/tests/encoding_profile_fonts.rs rename to crates/svg/tests/it/encoding_profile_fonts.rs index 722e90b30..0cbb61b48 100644 --- a/crates/svg/tests/encoding_profile_fonts.rs +++ b/crates/svg/tests/it/encoding_profile_fonts.rs @@ -1,8 +1,6 @@ //! SVG Options → Encoding, SVG Profile and embedded fonts: UTF-16 and ISO 8859-1 files read //! back, entity styling parses in usvg, SVG Tiny 1.2 has no filters, masks, symbols or style //! sheets, and embedded fonts hold only the glyphs used where their licence allows it. -// Integration tests: unwrapping and panicking on failure is fine here, unlike in shipped code (AGENTS.md › Robustness). -#![allow(clippy::unwrap_used, clippy::expect_used, clippy::panic)] use std::sync::Arc; @@ -287,7 +285,7 @@ fn variable_font_settings_are_written_embedded_and_read_back() { /// The bundled Source Sans 3 Regular renamed `family` (13 characters, as long as the original /// name) with OS/2 `fsType` set to `fs_type`. fn licensed_font(family: &str, fs_type: u16) -> Vec { - let mut data = include_bytes!("../../../assets/fonts/SourceSans3-Regular.ttf").to_vec(); + let mut data = include_bytes!("../../../../assets/fonts/SourceSans3-Regular.ttf").to_vec(); let table = |data: &[u8], tag: &[u8; 4]| { let f = skrifa::FontRef::new(data).unwrap(); let r = f.table_directory.table_records().iter().find(|r| r.tag().to_be_bytes() == *tag).unwrap(); @@ -320,7 +318,7 @@ fn font_licences_are_respected() { let fonts = embedded(&o.svg); assert_eq!(fonts.len(), 1, "{:?}", o.warnings); assert_eq!(fonts[0].0, "\"Wholed Sans 3\""); - let size = include_bytes!("../../../assets/fonts/SourceSans3-Regular.ttf").len(); + let size = include_bytes!("../../../../assets/fonts/SourceSans3-Regular.ttf").len(); assert!(fonts[0].2.len() + 64 >= size, "embedded whole: {} of {size} bytes", fonts[0].2.len()); assert!(o.warnings.iter().any(|w| w.contains("Sealed Sans 3") && w.contains("doesn't allow embedding")), "{:?}", o.warnings); assert!(o.warnings.iter().any(|w| w.contains("Wholed Sans 3") && w.contains("whole")), "{:?}", o.warnings); diff --git a/crates/svg/tests/focal.rs b/crates/svg/tests/it/focal.rs similarity index 94% rename from crates/svg/tests/focal.rs rename to crates/svg/tests/it/focal.rs index e61914458..4d76faf40 100644 --- a/crates/svg/tests/focal.rs +++ b/crates/svg/tests/it/focal.rs @@ -1,6 +1,4 @@ //! Radial gradients' focal points as `fx`/`fy`, out and back in. -// Integration tests: unwrapping and panicking on failure is fine here, unlike in shipped code (AGENTS.md › Robustness). -#![allow(clippy::unwrap_used, clippy::expect_used, clippy::panic)] use vectorcraft_color::{Gradient, GradientGeom, GradientKind, GradientPaint, Paint}; use vectorcraft_doc::{Appearance, Document, Node}; diff --git a/crates/svg/tests/font_weights.rs b/crates/svg/tests/it/font_weights.rs similarity index 94% rename from crates/svg/tests/font_weights.rs rename to crates/svg/tests/it/font_weights.rs index 31d358c61..0e1a41183 100644 --- a/crates/svg/tests/font_weights.rs +++ b/crates/svg/tests/it/font_weights.rs @@ -1,7 +1,5 @@ //! Font weights in SVG and CSS: every style is written with its numeric weight (Semibold 600, //! Light 300, Black 900…; Bold as `bold`), and SVG import reads the numbers back to the same face. -// Integration tests: unwrapping and panicking on failure is fine here, unlike in shipped code (AGENTS.md › Robustness). -#![allow(clippy::unwrap_used, clippy::expect_used, clippy::panic)] use vectorcraft_doc::{CharStyle, Document, Node, NodeKind, TextObject}; use vectorcraft_geom::Point; diff --git a/crates/svg/tests/foreign_attributes.rs b/crates/svg/tests/it/foreign_attributes.rs similarity index 99% rename from crates/svg/tests/foreign_attributes.rs rename to crates/svg/tests/it/foreign_attributes.rs index 9f734d0e7..da949e09a 100644 --- a/crates/svg/tests/foreign_attributes.rs +++ b/crates/svg/tests/it/foreign_attributes.rs @@ -1,7 +1,6 @@ //! Attributes in other applications' XML namespaces (https://www.w3.org/TR/xml-names/) survive a //! round trip through VectorCraft: kept on import, written back on export with their namespaces //! declared on the root. -#![allow(clippy::unwrap_used, clippy::expect_used, clippy::panic)] use usvg::roxmltree; use vectorcraft_doc::{Document, ForeignAttribute, Node, NodeKind}; use vectorcraft_svg::{ExportOptions, MAX_FOREIGN, MAX_FOREIGN_VALUE, export, export_full, import, import_with_report}; diff --git a/crates/svg/tests/gradients.rs b/crates/svg/tests/it/gradients.rs similarity index 96% rename from crates/svg/tests/gradients.rs rename to crates/svg/tests/it/gradients.rs index 9009316cd..efbbc30e6 100644 --- a/crates/svg/tests/gradients.rs +++ b/crates/svg/tests/it/gradients.rs @@ -1,7 +1,5 @@ //! Gradient defs: text gradients span the laid-out text, stroke gradients the stroked area, //! identical gradients share a def named after their swatch, and midpoints survive re-import. -// Integration tests: unwrapping and panicking on failure is fine here, unlike in shipped code (AGENTS.md › Robustness). -#![allow(clippy::unwrap_used, clippy::expect_used, clippy::panic)] use vectorcraft_color::{Color, Gradient, GradientKind, GradientPaint, GradientStop, Paint}; use vectorcraft_doc::{Appearance, CharStyle, Document, Node, NodeKind, TextObject}; diff --git a/crates/svg/tests/ids.rs b/crates/svg/tests/it/ids.rs similarity index 96% rename from crates/svg/tests/ids.rs rename to crates/svg/tests/it/ids.rs index affd496ef..cbd2e834d 100644 --- a/crates/svg/tests/ids.rs +++ b/crates/svg/tests/it/ids.rs @@ -1,7 +1,5 @@ //! Object IDs: names survive the round trip (Layer Names), Minimal writes only referenced ids, //! Unique ids never collide, and other apps' label attributes become object names. -// Integration tests: unwrapping and panicking on failure is fine here, unlike in shipped code (AGENTS.md › Robustness). -#![allow(clippy::unwrap_used, clippy::expect_used, clippy::panic)] use std::collections::HashSet; diff --git a/crates/svg/tests/import_details.rs b/crates/svg/tests/it/import_details.rs similarity index 99% rename from crates/svg/tests/import_details.rs rename to crates/svg/tests/it/import_details.rs index cd308d785..9db57336d 100644 --- a/crates/svg/tests/import_details.rs +++ b/crates/svg/tests/it/import_details.rs @@ -1,8 +1,6 @@ //! SVG import details: linked images read from the SVG's folder and kept linked (a placeholder //! and a warning when missing), SVG images as vector art, nested clips, undisplayed objects as //! hidden objects, and reflected or repeated gradients. -// Integration tests: unwrapping and panicking on failure is fine here, unlike in shipped code (AGENTS.md › Robustness). -#![allow(clippy::unwrap_used, clippy::expect_used, clippy::panic)] use std::path::{Path, PathBuf}; diff --git a/crates/svg/tests/import_live.rs b/crates/svg/tests/it/import_live.rs similarity index 99% rename from crates/svg/tests/import_live.rs rename to crates/svg/tests/it/import_live.rs index b327cbe5c..35b0c810d 100644 --- a/crates/svg/tests/import_live.rs +++ b/crates/svg/tests/it/import_live.rs @@ -1,8 +1,6 @@ //! SVG import keeps what the canvas edits live: `` becomes a pattern swatch, `` //! with `` a symbol and its instances, blurs and drop-shadow chains live effects; and //! export → import keeps them. -// Integration tests: unwrapping and panicking on failure is fine here, unlike in shipped code (AGENTS.md › Robustness). -#![allow(clippy::unwrap_used, clippy::expect_used, clippy::panic)] use std::sync::Arc; diff --git a/crates/svg/tests/import_text.rs b/crates/svg/tests/it/import_text.rs similarity index 99% rename from crates/svg/tests/import_text.rs rename to crates/svg/tests/it/import_text.rs index a65a33c69..78716ef6e 100644 --- a/crates/svg/tests/import_text.rs +++ b/crates/svg/tests/it/import_text.rs @@ -1,7 +1,5 @@ //! SVG `` import fidelity: placement in the tree, type on a path, per-character positions, //! paints and the style cascade. -// Integration tests: unwrapping and panicking on failure is fine here, unlike in shipped code (AGENTS.md › Robustness). -#![allow(clippy::unwrap_used, clippy::expect_used, clippy::panic)] use vectorcraft_color::{GradientKind, Paint}; use vectorcraft_doc::{CharStyle, Document, Justify, Node, NodeKind, TextKind, TextObject}; diff --git a/crates/svg/tests/import_units.rs b/crates/svg/tests/it/import_units.rs similarity index 96% rename from crates/svg/tests/import_units.rs rename to crates/svg/tests/it/import_units.rs index b6fc271cc..1ce01c7f0 100644 --- a/crates/svg/tests/import_units.rs +++ b/crates/svg/tests/it/import_units.rs @@ -1,7 +1,5 @@ //! SVG import units: physical lengths keep their printed size, pixels and user units map 1:1 to //! points, and the document's units follow the file's. -// Integration tests: unwrapping and panicking on failure is fine here, unlike in shipped code (AGENTS.md › Robustness). -#![allow(clippy::unwrap_used, clippy::expect_used, clippy::panic)] use vectorcraft_doc::{Document, Node, NodeKind, Unit}; use vectorcraft_geom::Rect; diff --git a/crates/svg/tests/interactivity.rs b/crates/svg/tests/it/interactivity.rs similarity index 99% rename from crates/svg/tests/interactivity.rs rename to crates/svg/tests/it/interactivity.rs index eb5cc3436..66b98959b 100644 --- a/crates/svg/tests/interactivity.rs +++ b/crates/svg/tests/it/interactivity.rs @@ -1,7 +1,6 @@ //! SVG Interactivity: event attributes (https://www.w3.org/TR/SVG11/script.html#EventAttributes) //! and `