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
|
# 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.
|
# 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
|
# The geometry checks launch isolated shells against a temporary config.
|
||||||
# real settings are read to build them and never written.
|
|
||||||
|
|
||||||
set -uo pipefail
|
set -uo pipefail
|
||||||
|
|
||||||
@@ -47,8 +46,69 @@ for path in "$dock" "$body" "$strip"; do
|
|||||||
[[ -r "$path" ]] || fail "missing $path"
|
[[ -r "$path" ]] || fail "missing $path"
|
||||||
done
|
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)"
|
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 ───────────────────────────────────────────────
|
# ── 3, 4, 6. What can be read ───────────────────────────────────────────────
|
||||||
|
|
||||||
@@ -111,7 +171,8 @@ PY
|
|||||||
|
|
||||||
# ── 1, 2, 7. Geometry, measured ────────────────────────────────────────────────
|
# ── 1, 2, 7. Geometry, measured ────────────────────────────────────────────────
|
||||||
|
|
||||||
cat >"$shell_dir/dock-position-probe.qml" <<'QML'
|
probe="$fixture_shell/$probe_name"
|
||||||
|
cat >"$probe" <<'QML'
|
||||||
import Quickshell
|
import Quickshell
|
||||||
import QtQuick
|
import QtQuick
|
||||||
import qs.modules.dock
|
import qs.modules.dock
|
||||||
@@ -164,28 +225,50 @@ ShellRoot {
|
|||||||
}
|
}
|
||||||
QML
|
QML
|
||||||
|
|
||||||
settings_source="${XDG_CONFIG_HOME:-$HOME/.config}/panama/settings.json"
|
|
||||||
[[ -r "$settings_source" ]] || fail 'no settings to build a probe configuration from'
|
|
||||||
|
|
||||||
measure() {
|
measure() {
|
||||||
local position="$1"
|
local position="$1"
|
||||||
python3 - "$settings_source" "$work/panama/settings.json" "$position" <<'PY'
|
python3 - "$work/config/panama/settings.json" "$position" <<'PY'
|
||||||
import json, pathlib, sys
|
import json, pathlib, sys
|
||||||
data = json.loads(pathlib.Path(sys.argv[1]).read_text())
|
out = pathlib.Path(sys.argv[1])
|
||||||
data["dockPosition"] = sys.argv[3]
|
data = {
|
||||||
out = pathlib.Path(sys.argv[2])
|
"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.parent.mkdir(parents=True, exist_ok=True)
|
||||||
out.write_text(json.dumps(data))
|
out.write_text(json.dumps(data) + "\n")
|
||||||
PY
|
PY
|
||||||
( cd "$shell_dir" && XDG_CONFIG_HOME="$work" timeout 40 qs -p ./dock-position-probe.qml 2>&1 ) \
|
local output="$work/$position.output"
|
||||||
| grep -oE '(DOCKGEOM|MASKGEOM) .*'
|
(
|
||||||
|
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'
|
[[ -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'
|
[[ -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'
|
[[ -n "$right" ]] || fail 'the right dock produced no geometry at all'
|
||||||
|
|
||||||
# The span checks read the window; the region checks read every line.
|
# The span checks read the window; the region checks read every line.
|
||||||
|
|||||||
Reference in New Issue
Block a user