Test: Isolate dock geometry fixtures
This commit is contained in:
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user