Adds tools/difftest: a Zig driver built against a copy of Ghostty 1.3.1's own src/terminal (Zig 0.15.2, set up under target/ by tools/difftest/setup.sh) and a Rust twin on ghostty-terminal, both printing a canonical dump of every scrollback/active row (cells, graphemes, styles, hyperlinks, row flags), cursor, modes, regions, tabstops and colors. A seeded generator produces escape-heavy streams (UTF-8/wide/combining/emoji, C0, CSI with edge params, SGR, modes, ESC, OSC, DCS, margins, insert/delete); `just difftest` runs it with Zig assertions on (ReleaseSafe vs debug Rust) and off (ReleaseFast vs production Rust), with minimizers and a triage script. Divergences found and fixed in Rust (each with a regression test): - ill-formed UTF-8 decoding follows the SIMD path a default Ghostty build uses (not Zig's scalar fallback) - PageList::erase_rows keeps Zig's row-flag behavior on regrow - grapheme move on wrap with left/right margins uses the original cell Upstream bugs found and deliberately NOT replicated (per the project rule): a stale cell pointer after page growth in Terminal.zig:482/539 that drops a grapheme, plus several Zig assertion failures/segfaults; documented with minimized repros in docs/rewrite/notes/difftest-DF.md. Final run: 390k cases across many geometries, 0 divergences (Zig-abort cases, ~0.1-0.5%, are not compared). Test Plan: - just difftest 20000 "1 2 3" - cargo test -p ghostty-terminal (regression tests)
40 lines
1.5 KiB
Bash
Executable File
40 lines
1.5 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Prepare the Zig side of the differential fuzzer (idempotent).
|
|
#
|
|
# 1. Zig 0.15.2 (Ghostty 1.3.1's required version) -> target/zig-0.15.2/
|
|
# 2. A COPY of the reference Ghostty source -> target/zig-src/
|
|
# (the reference tree itself is never modified)
|
|
# 3. The Zig driver, built twice:
|
|
# target/difftest-zig/bin/difftest_zig ReleaseSafe (assertions on)
|
|
# target/difftest-zig-fast/bin/difftest_zig ReleaseFast (assertions off)
|
|
#
|
|
# Everything lives under target/ (never /tmp, which is RAM-backed).
|
|
set -euo pipefail
|
|
ROOT="$(cd "$(dirname "$0")/../.." && pwd)"
|
|
REF="${GHOSTTY_ZIG_REF:-$ROOT/../ghostty}"
|
|
ZIGVER=0.15.2
|
|
ZIGDIR="$ROOT/target/zig-$ZIGVER"
|
|
ZIG="$ZIGDIR/zig-x86_64-linux-$ZIGVER/zig"
|
|
|
|
if [ ! -x "$ZIG" ]; then
|
|
mkdir -p "$ZIGDIR"
|
|
timeout 900 curl -sSfL -o "$ZIGDIR/zig.tar.xz" \
|
|
"https://ziglang.org/download/$ZIGVER/zig-x86_64-linux-$ZIGVER.tar.xz"
|
|
timeout 300 tar -C "$ZIGDIR" -xf "$ZIGDIR/zig.tar.xz"
|
|
rm -f "$ZIGDIR/zig.tar.xz"
|
|
fi
|
|
|
|
if [ ! -f "$ROOT/target/zig-src/build.zig" ]; then
|
|
mkdir -p "$ROOT/target/zig-src"
|
|
timeout 600 rsync -a --exclude .git --exclude .zig-cache --exclude zig-cache \
|
|
"$REF/" "$ROOT/target/zig-src/"
|
|
fi
|
|
|
|
cd "$ROOT/tools/difftest/zig"
|
|
for m in ReleaseSafe:difftest-zig ReleaseFast:difftest-zig-fast; do
|
|
timeout 1800 "$ZIG" build -Doptimize="${m%%:*}" \
|
|
--cache-dir "$ROOT/target/zig-cache/local" \
|
|
--global-cache-dir "$ROOT/target/zig-cache/global" \
|
|
--prefix "$ROOT/target/${m##*:}"
|
|
done
|