Test: Isolate dock geometry fixtures

This commit is contained in:
Gabriel Brown
2026-08-26 23:12:14 -04:00
parent 71f4f0d24b
commit 37688f702a
+100 -17
View File
@@ -27,8 +27,7 @@
# slot from a real icon rather than assuming one -- a DockItem is taller
# than it is wide, so a constant is wrong on one of the two orientations.
#
# The geometry checks launch isolated shells against a temporary config. The
# real settings are read to build them and never written.
# The geometry checks launch isolated shells against a temporary config.
set -uo pipefail
@@ -47,8 +46,69 @@ for path in "$dock" "$body" "$strip"; do
[[ -r "$path" ]] || fail "missing $path"
done
# Keep this contract honest: it must never add a probe to the linked source
# tree, and every exit path must leave that tree byte-for-byte as it began.
source_probe="$shell_dir/dock-position-probe.qml"
source_probe_existed=0
source_probe_checksum=""
if [[ -e "$source_probe" ]]; then
source_probe_existed=1
source_probe_checksum="$(sha256sum -- "$source_probe")"
fi
source_tree_checksum() {
find "$shell_dir" -type f -print0 \
| LC_ALL=C sort -z \
| xargs -0 sha256sum -- \
| sha256sum
}
source_tree_initial_checksum="$(source_tree_checksum)"
assert_source_tree_unchanged() {
[[ "$(source_tree_checksum)" == "$source_tree_initial_checksum" ]] \
|| { printf 'dock position contract: the Quickshell source tree changed\n' >&2; return 1; }
if (( source_probe_existed )); then
[[ -e "$source_probe" && "$(sha256sum -- "$source_probe")" == "$source_probe_checksum" ]] \
|| { printf 'dock position contract: the source probe changed\n' >&2; return 1; }
else
[[ ! -e "$source_probe" ]] \
|| { printf 'dock position contract: the contract created a source probe\n' >&2; return 1; }
fi
}
work="$(mktemp -d)"
trap 'rm -rf "$work" "$shell_dir/dock-position-probe.qml"' EXIT
fixture_shell="$work/quickshell"
cp -a "$shell_dir/." "$fixture_shell/" \
|| fail 'could not copy the Quickshell fixture'
fixture_pid=""
stop_fixture() {
[[ -n "$fixture_pid" ]] || return 0
if kill -0 "$fixture_pid" 2>/dev/null; then
kill -TERM "$fixture_pid" 2>/dev/null || true
wait "$fixture_pid" 2>/dev/null || true
fi
fixture_pid=""
}
cleanup() {
local status=$?
trap - EXIT HUP INT TERM
stop_fixture
rm -rf "$work"
assert_source_tree_unchanged || status=1
exit "$status"
}
trap cleanup EXIT HUP INT TERM
# These checks are deliberately against this harness. A live settings read or
# source-tree probe means the contract itself is unsafe before it maps a panel.
probe_name='dock-position-probe.qml'
source_write_marker="$(printf 'cat >\"$shell_dir/%s\"' "$probe_name")"
home_marker="$(printf '\044')HOME"
unsafe_harness=()
grep -Fq "$source_write_marker" "$0" && unsafe_harness+=('writes its probe in the Quickshell source tree')
grep -Fq "$home_marker" "$0" && unsafe_harness+=('reads the user configuration directory')
(( ${#unsafe_harness[@]} == 0 )) \
|| fail "unsafe harness: ${unsafe_harness[*]}"
# ── 3, 4, 6. What can be read ───────────────────────────────────────────────
@@ -111,7 +171,8 @@ PY
# ── 1, 2, 7. Geometry, measured ────────────────────────────────────────────────
cat >"$shell_dir/dock-position-probe.qml" <<'QML'
probe="$fixture_shell/$probe_name"
cat >"$probe" <<'QML'
import Quickshell
import QtQuick
import qs.modules.dock
@@ -164,28 +225,50 @@ ShellRoot {
}
QML
settings_source="${XDG_CONFIG_HOME:-$HOME/.config}/panama/settings.json"
[[ -r "$settings_source" ]] || fail 'no settings to build a probe configuration from'
measure() {
local position="$1"
python3 - "$settings_source" "$work/panama/settings.json" "$position" <<'PY'
python3 - "$work/config/panama/settings.json" "$position" <<'PY'
import json, pathlib, sys
data = json.loads(pathlib.Path(sys.argv[1]).read_text())
data["dockPosition"] = sys.argv[3]
out = pathlib.Path(sys.argv[2])
out = pathlib.Path(sys.argv[1])
data = {
"schemaVersion": 1,
"dockAutohide": True,
"dockPosition": sys.argv[2],
"dockScreens": [],
"dockIconSize": 48,
"dockRevealDelayMs": 0,
"dockHideDelayMs": 250,
"dockPinned": [],
}
out.parent.mkdir(parents=True, exist_ok=True)
out.write_text(json.dumps(data))
out.write_text(json.dumps(data) + "\n")
PY
( cd "$shell_dir" && XDG_CONFIG_HOME="$work" timeout 40 qs -p ./dock-position-probe.qml 2>&1 ) \
| grep -oE '(DOCKGEOM|MASKGEOM) .*'
local output="$work/$position.output"
(
cd "$fixture_shell" \
&& XDG_CONFIG_HOME="$work/config" XDG_STATE_HOME="$work/state" \
exec timeout --foreground --kill-after=5s 40s qs -p "./$probe_name"
) >"$output" 2>&1 &
fixture_pid=$!
if ! wait "$fixture_pid"; then
fixture_pid=""
cat "$output" >&2
fail "the $position fixture did not exit cleanly"
fi
fixture_pid=""
geometry="$(grep -oE '(DOCKGEOM|MASKGEOM) .*' "$output")" \
|| fail "the $position fixture produced no geometry"
}
bottom="$(measure bottom)"
geometry=""
measure bottom
bottom="$geometry"
[[ -n "$bottom" ]] || fail 'the bottom dock produced no geometry at all'
left="$(measure left)"
measure left
left="$geometry"
[[ -n "$left" ]] || fail 'the left dock produced no geometry at all'
right="$(measure right)"
measure right
right="$geometry"
[[ -n "$right" ]] || fail 'the right dock produced no geometry at all'
# The span checks read the window; the region checks read every line.