Testing strategy
Pull-request gates
Section titled “Pull-request gates”- Rust format, strict all-target/all-feature Clippy, and locked all-target tests.
- License, provenance, and advisory policy.
- Starlight type checking and static build.
- Criterion and libFuzzer target compilation.
- Real Worker and packaging-policy smoke tests.
- Windows ZIP, tar.gz, and 7z bidirectional interoperability.
- Official 7-Zip codec, filter, solid-mode, and AES interoperability with JSON evidence.
- Pinned RAR 1.3/1.5/3/5/7, PPMd, filter, encrypted-header and unsafe-link corpus cross-checked against 7-Zip with JSON evidence.
Layers
Section titled “Layers”Unit and property tests cover detection, paths, limits, conflict policy, randomized trees, and boundaries. Security corpora cover traversal, bombs, links, collisions, corruption, and truncation. Interoperability compares ZiFile in both directions with Windows reference tools. Performance tracks throughput, ratio, peak memory, startup, and large lists. Smoke tests cover CLI, desktop, Worker IPC/cancellation, packaging, installation, associations, and uninstall as their environments become available.
A permanent negative matrix constructs minimally signed or extension-hinted truncated/corrupt inputs for all 15 supported format classes. Both List and integrity testing must reject each input as an ordinary error without panicking. This complements rather than replaces continuous libFuzzer campaigns, the historical 7z crash fixtures, and real third-party corpora.
The Worker smoke streams a real list request and requires a complete final progress snapshot before metadata, a Unicode entry, and exactly one terminal event. It then cancels a 32 MiB random 7z creation and requires timely exit with no target or temporary residue. Queue unit tests cover strict FIFO, 32-item capacity, stale completion IDs, clearing, and immediate sensitive-payload release.
Listing and integrity testing use backward-compatible ListOptions and TestOptions to provide common progress and cooperative cancellation for ZIP, 7z, RAR, CAB, TAR compositions, and all six compression streams. Listing advances as entries are scanned; single streams also report actually decoded bytes. Both UIs use explicit scanning copy while a total is unknowable, then receive a consistent final total. The Worker emits bounded updates every 100 ms and a final snapshot after the operation returns, so small archives do not expose only an initial 0% value. A pre-cancel regression requires Cancelled before parsing begins, and every format round trip checks the final progress invariants.
CLI password tests cover explicit opt-in, CRLF/LF removal, preservation of surrounding spaces, and rejection of missing or empty input. The foundation smoke requires help to expose only --password-stdin, then creates, tests, and extracts a real AES 7z through standard input without printing the fixed test password.
Compression-level contract tests cover every encoder’s valid range, core boundary clamping, and fixed-level formats. CLI tests require zifile formats to expose each format’s range, fixed, or none, and reject both format-specific out-of-range values and explicit levels for fixed formats before creation so command-line input is neither silently clamped nor ignored. The foundation smoke also launches the real zifile.exe, checks key matrix rows, rejects ZIP level 10 and an explicit TAR level, then proves TAR creation succeeds when the level is omitted. A 7z integration regression creates level-0 and level-9 archives, reads the public LZMA2 coder properties, and requires them to differ. This proves from archive metadata that the UI/CLI setting affects the encoder instead of merely traversing the Worker protocol.
tests/performance/operation-queue-foreground.ps1 creates a 100,000-entry archive, submits three integrity tests through the real window, and verifies cancellation of the active operation, start of the next operation, clearing the waiting queue, and Worker reclamation. A separate bounded three-second activation retry first requires the ZiFile native handle to be the actual Windows foreground window; if the session cannot grant foreground ownership, the test refuses to run rather than recording background UI Automation as foreground evidence. Text timeouts include at most 500 characters of the last visible Document text, while finally still closes the process and removes the temporary fixture.
tests/smoke/packaging-policy.ps1 dynamically parses the current twenty-seven release, corpus, and repository-policy PowerShell scripts. It rejects missing/partial Partner Center identity, malformed Name/X.500 Publisher, missing cloud inputs, unsupported providers, development identities, unsigned OID publishers, invalid signed artifacts, and incomplete 1.0 readiness; it accepts valid input and fully evidenced 11/11 fixtures. It also requires post-signing audit, signed-only publishing, least privilege, signing timeout/concurrency, the rotation/emergency-stop/revocation runbook, and version, release-note, contributor, security, and readiness gates in CI. Every CI, documentation deployment, SBOM, and GitHub Release publication job has a workload-sized hard timeout, with job-scoped checks preventing an unrelated limit elsewhere in the same YAML from satisfying the gate. The dual-architecture reproducibility build is separately protected by a 120-minute hard timeout, stale-run cancellation, independent matrix conclusions, and retained failure evidence; real foreground ownership and bounded diagnostics in the queue smoke are also regression-checked. Policy smoke cannot replace a real account, cloud-HSM signature, or x64/ARM64 package-content audit.
The official 7-Zip corpus gate uses 7z.exe on the GitHub Windows Runner. Reference-created cases cover Copy, LZMA, LZMA2+BCJ, Deflate, BZip2, PPMd, and LZMA2+AES with encrypted headers. In the reverse direction, 7-Zip must test and extract both ordinary and AES archives created by ZiFile. Every case compares the complete relative file set and SHA-256 content hashes; the uploaded JSON evidence contains no password. CI 32836336921 passed all nine cases with 7-Zip 26.02; the evidence JSON SHA-256 is 06278BB8B96AB683A3C117BA5E30F1B4AB1CF89F1BBF01E72BAC0CC26B49DB14.
The RAR gate downloads six fixtures from the pinned rars source commit 7d8f9386ef777a2415da34fe1db193d8471ff7d0, verifies hard-coded SHA-256 values before use, and compares extraction trees byte for byte. It covers RAR 1.3, 1.54 multi-file, RAR 3 PPMd, RAR 5 compression and E8E9 filtering, plus a WinRAR 7.21 encrypted-header/Quick Open archive. Three pinned link/redirection archives must be rejected without output. CI 32853686537 passed all six valid and three rejection cases; the evidence JSON SHA-256 is 4C52D0240B911609C7DDB0CACB2E484F56C8F886E216347603B228261C4EE8EF. Because current 7-Zip no longer reads RAR 1.3, that case is compared with the known-good extracted tree from the same pinned upstream commit; the other five valid archives remain cross-checked against 7-Zip 26.02.
The CAB interoperability gate uses Windows makecab.exe to create MSZIP and LZX cabinets, then requires ZiFile signature detection, listing, testing, and extraction to match the SHA-256 output from system expand.exe. Rust integration fixtures cover uncompressed CAB content. Quantum compression and multi-cabinet sets remain explicitly unsupported. CI uploads structured evidence containing no user data.
A CAB decode-stage negative regression preserves valid metadata while flipping the first compressed CFDATA byte. Listing must still expose the one entry, then integrity testing and selective extraction must fail with an empty destination. This proves corrupt payloads cannot cross the temporary-file commit boundary instead of treating malformed-header coverage as decoder coverage.
Modification-time tests set deterministic source times, create ZIP/7z/TAR-family archives, and require both listed metadata and extracted files/directories to retain the expected values. Separately authored RAR 5 and CAB fixtures cover read-only providers. Protocol tests deserialize a legacy archive_entry event without the optional field, while both desktop binaries share formatting tests that distinguish UTC from timestamp fields whose archive format stores no time zone.
Every CI compiles fuzz targets. Weekly bounded campaigns exercise path policy, format detection, and every supported parser, including CAB, for 180 seconds each. Two historical malformed 7z artifacts (292 and 173 bytes) are replayed at every parser campaign start. Their discoveries led to Rust 1.93.0 and bounded-metadata sevenz-rust2 0.22.0; targeted run 32813469578 replayed both, executed another 498,937 inputs in 181 seconds, peaked at 370 MiB RSS, and found no new crash.
The RAR verification benchmark uses a deterministic 8 MiB RAR 5 method-3 archive with low-frequency pseudorandom noise, retaining compression work without exceeding the default 1000:1 expansion guard. The initial local Windows x64 baseline measured 58.12–64.49 ms, or 124.06–137.65 MiB/s. This is a same-machine regression baseline, not a universal performance claim. The original highly periodic fixture was correctly rejected as exceeding the safety ratio and was not used to bypass that guard.
The 100,000-entry UI model constructs at most 500 visible rows. A real deterministic ZIP baseline validates Worker listing, search, paging, 50% scrolling, tree-wide memory sampling, and cancellation with Worker reclamation. Five cancellation runs completed at 930.78 ms median and 1088.73 ms p95 with zero Workers remaining. These are same-machine regression baselines, not universal performance promises.
tests/performance/operation-queue-foreground.ps1 uses a 100,000-entry ZIP in a real foreground session to verify FIFO submission, active cancellation, next-operation progress, clearing pending work, and Worker reclamation. It supports both the default Iced desktop and the accessible Dioxus candidate, with bilingual UI text matching. tests/performance/extraction-cancellation-foreground.ps1 starts the real --extract-here flow with a deterministic multi-entry ZIP, cancels extraction, waits for Worker reclamation, and verifies that every committed file has a complete entry size with zero partial output files. Both scripts require an available interactive desktop; missing semantic Document UIA or an unrun foreground session remains incomplete evidence.
The core test active_cancellation_does_not_commit_a_partial_zip_output cancels ZIP extraction after the first progress data chunk and requires Cancelled with no committed atomic target file. It passed five repeated local runs. This strengthens core-layer evidence but does not replace the real desktop queue acceptance run.
Sorting regressions cover folder-first order, ascending/descending direction, missing modified times last, first-page reset, and the 500-row cap. The Criterion suite also sorts all 100,000 entries by name descending before collecting one page; the initial Windows x64 measurement was 13.96–15.32 ms (6.53–7.17 million entries/s). Header helper tests require the visible arrow and Dioxus aria-sort value to agree.
Folder-browser regressions cover explicit and implicit directories, direct children at root and nested levels, navigable breadcrumbs, archive-wide search, and resetting search/page state when entering a folder. The 100,000-entry fixture synthesizes one root folder and still collects at most 500 rows after entering it in either sort direction. On the initial local Windows x64 baseline, scanning 100,000 paths and synthesizing the root took 18.60–19.44 ms; entering the folder, sorting by name descending, and collecting 500 rows took 38.04–38.74 ms.
Folder-selection regressions cover one-pass all/partial/none counts for each direct child folder, adding or removing only the target descendants, disabled empty-folder semantics, and directory-row precedence when a file conflicts with an implicit directory. Dioxus source gates require the mixed state, bilingual selected/total labels, and deterministic row keys containing the page-local index. On the local Windows x64 baseline, one root aggregation across 100,000 entries with half selected took 30.97–32.75 ms.
tests/smoke/store-listing.ps1 verifies that the Simplified Chinese and English Store JSON satisfies Partner Center limits for descriptions, short descriptions, features, keywords, system requirements, licensing, and HTTPS URLs. It also requires each readable listing page to contain every authoritative JSON description paragraph and feature verbatim. Negative fixtures prove that an oversized feature, excess keywords, and a URL inside the description are rejected. This gate covers copy, not screenshots, age ratings, official identity, or certification.
The same smoke test exercises atomic screenshot import: it generates eight valid PNGs, requires complete capture metadata, imports from an independent directory, and reruns the formal manifest validator. Missing metadata, undersized images, duplicate content, and attempts to overwrite existing assets all fail. Temporary images are removed and never enter the formal asset directory.
tests/helpers/msix-repair is a C# test-only console helper; the product remains Rust-first. CI compiles it against a locked Windows App SDK 1.8 dependency, then a PowerShell supervisor that does not load the App SDK launches the non-mutating --probe. Even if App SDK initialization blocks before the helper entry point, the supervisor terminates the process directly after 15 seconds; the workflow adds a two-minute outer bound. A Runner that does not return records an incomplete/unsupported probe instead of hanging or claiming Repair passed, and a one-second blocking fixture continuously proves this hard-timeout path. When Repair is supported, the trusted lifecycle writes a random package LocalState sentinel, requires RepairPackageAsync to preserve it, then requires Reset-AppxPackage to remove it. Unsupported systems record unsupported explicitly.
tests/smoke/wack-readiness.ps1 uses an unsigned development-package fixture to prove readiness reports a missing WACK tool, invalid signatures, mismatched Partner Center Identity/Publisher/Publisher Display Name values, an unsigned publisher, wrong minimum OS, and package/audit hash mismatch. It also proves -RequireReady persists structured failure evidence. This smoke does not run WACK or replace a formal signed-candidate certification report.
Foreground keyboard automation checks internal WebView2 focus, bilingual forward/reverse navigation, disabled-control skipping, 7z selection, level adjustment, password clearing, and source buttons. Its default flow also creates a two-entry ZIP and checks archive listing, integrity testing, scoped Ctrl+A in the archive password field, Reload, committed search and scoped Ctrl+A, archive select-all/clear, conflict policy, disabled single-page pagination, and extract-button state; -SkipArchiveWorkflow is only an isolation mode for the legacy create-form regression. It verifies the exact ZiFile foreground window before every key and never records the password. An independent Windows x64 foreground UIA run now passes this workflow; the raw JSON is archived with the project records. This evidence does not replace Narrator, IME, high-contrast, DPI, or formal assistive-technology certification.
The accessible candidate exposes every handled shortcut—Ctrl+O, Ctrl+N, F1, Escape, and archive-scoped Ctrl+A—on the corresponding semantic control. A source regression keeps handler behavior and aria-keyshortcuts metadata aligned; this wiring evidence does not replace a real screen-reader announcement check.
The root keyboard handler prevents the default Escape action only when an active cancellation token exists. While idle it leaves Escape unhandled so native controls retain their close or exit behavior; the cancellation function also remains a no-op instead of publishing a false cancelling status when no token exists.
Shortcut matching ignores lock states such as Caps Lock and Num Lock but requires every other modifier to match the published contract exactly. Consequently, Ctrl+Shift+N, Alt+F1, and Ctrl+Shift+A are not downgraded to Ctrl+N, F1, or Ctrl+A. Regression coverage includes positive combinations, lock-state compatibility, and Shift/Alt negative cases.
The default Iced desktop follows the same exact functional-modifier rule for Ctrl+O, Ctrl+N, archive-scoped Ctrl+A, F1, and Escape. Its modifier type contains only Shift, Control, Alt, and Logo, so unmodified commands require NONE and Control commands require exactly CTRL; a pure event-mapping regression covers positive and extra-modifier cases.
When the accessible candidate changes between Home, Archive, Create, and About, it moves focus to the stable main region and labels that region with the active page heading. The effect is guarded by the page identity, so progress polling, queue updates, filtering, selection, and other same-page renders do not steal focus. Source and unit regressions lock the page-to-heading mapping and focus trigger; real Narrator and foreground keyboard validation remain required.
The accessible candidate uses a two-tone focus ring in its normal dark and light themes: the outer tone follows the theme while an opposing inner tone keeps focus distinguishable on both content surfaces and cyan active controls. Windows forced-colors mode uses Highlight and Canvas. A Rust source regression locks all three branches and the two-layer wiring; a real foreground keyboard and high-contrast pass is still required for visual evidence.
Reproducibility separately performs clean x64/ARM64 double builds. Schema-v2 evidence traced the former 4/5 result to build-a/build-b target paths embedded by generated glutin_wgl_sys code in the default Iced executable. The script remaps both isolated roots to one virtual path; run 32826187552 then proved 5/5 and reproducible=true on both architectures.