Verify wallpaper policy application

This commit is contained in:
Gabriel Brown
2026-08-18 15:00:18 -04:00
parent c8004e400a
commit 52818b7290
3 changed files with 404 additions and 80 deletions
+161
View File
@@ -0,0 +1,161 @@
#!/usr/bin/env bash
set -euo pipefail
repo_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
service="$repo_dir/config/dot/quickshell/services/Wallpaper.qml"
fixture="$(mktemp -d /tmp/panama-wallpaper-service.XXXXXX)"
config_home="$fixture/config"
state_home="$fixture/state"
config_path="$config_home/quickshell"
harness="$config_path/wallpaper-service-harness.qml"
test_bin="$fixture/bin"
command_log="$fixture/commands.log"
active_state="$fixture/active.json"
control="$fixture/control"
shell_log="$fixture/quickshell.log"
harness_pid=""
fail() {
printf 'wallpaper service contract: %s\n' "$1" >&2
[[ -s "$shell_log" ]] && sed -n '1,180p' "$shell_log" >&2
exit 1
}
for needle in 'property var activeByOutput' 'function applyPolicy' 'function setSingle'; do
rg -Fq "$needle" "$service" || fail "Wallpaper service is missing $needle"
done
instances_for_harness() {
qs list --all 2>/dev/null | awk -v expected="$harness" '
/^Instance / { pid = "" }
/^[[:space:]]*Process ID:/ { pid = $3 }
/^[[:space:]]*Config path:/ {
path = $0
sub(/^[[:space:]]*Config path: /, "", path)
if (path == expected && pid ~ /^[0-9]+$/) print pid
}
'
}
cleanup() {
if [[ "$harness_pid" =~ ^[0-9]+$ ]] && kill -0 "$harness_pid" 2>/dev/null; then
kill "$harness_pid" 2>/dev/null || true
fi
rm -rf "$fixture"
}
trap cleanup EXIT
mkdir -p "$config_home/panama" "$state_home" "$test_bin"
cp -a "$repo_dir/config/dot/quickshell" "$config_path"
printf '%s\n' '{}' >"$config_home/panama/settings.json"
printf '%s\n' '{}' >"$active_state"
: >"$command_log"
: >"$control"
cat >"$test_bin/hyprctl" <<'EOF'
#!/usr/bin/env bash
set -euo pipefail
printf '%s' 'hyprctl' >>"$PANAMA_WALLPAPER_COMMAND_LOG"
printf ' %s' "$@" >>"$PANAMA_WALLPAPER_COMMAND_LOG"
printf '\n' >>"$PANAMA_WALLPAPER_COMMAND_LOG"
if [[ "${1:-}" == "hyprpaper" && "${2:-}" == "wallpaper" ]]; then
request="${3:-}"
output="${request%%,*}"
path="${request#*,}"
if [[ "$(<"$PANAMA_WALLPAPER_CONTROL")" == fail-second && "$output" == HDMI-A-1 ]]; then
exit 7
fi
next="$(jq -c --arg output "$output" --arg path "$path" '. + {($output):$path}' \
"$PANAMA_WALLPAPER_ACTIVE_STATE")"
printf '%s\n' "$next" >"$PANAMA_WALLPAPER_ACTIVE_STATE"
exit 0
fi
if [[ "${1:-}" == "hyprpaper" && "${2:-}" == "listactive" ]]; then
if [[ "$(<"$PANAMA_WALLPAPER_CONTROL")" == wrong ]]; then
printf 'DP-2: /images/wrong.jpg\nHDMI-A-1: /images/b.jpg\n'
exit 0
fi
jq -r 'to_entries[] | "\(.key): \(.value)"' "$PANAMA_WALLPAPER_ACTIVE_STATE"
exit 0
fi
exit 91
EOF
chmod +x "$test_bin/hyprctl"
qs_for_harness() {
env_args=(
XDG_CONFIG_HOME="$config_home"
XDG_STATE_HOME="$state_home"
PATH="$test_bin:$PATH"
PANAMA_WALLPAPER_COMMAND_LOG="$command_log"
PANAMA_WALLPAPER_ACTIVE_STATE="$active_state"
PANAMA_WALLPAPER_CONTROL="$control"
)
if [[ "$harness_pid" =~ ^[0-9]+$ && "${1:-}" == "ipc" ]]; then
env "${env_args[@]}" qs -p "$harness" ipc --pid "$harness_pid" "${@:2}"
else
env "${env_args[@]}" qs -p "$harness" "$@"
fi
}
wait_idle() {
local status=""
for _ in $(seq 1 80); do
status="$(qs_for_harness ipc call wallpaper-service-test status)"
[[ "$(jq -r '.busy' <<<"$status")" == false ]] && { printf '%s' "$status"; return; }
sleep 0.1
done
fail "wallpaper transaction did not settle: $status"
}
qs_for_harness --daemonize >"$shell_log" 2>&1 || fail 'isolated service harness did not launch'
for _ in $(seq 1 60); do
harness_pid="$(instances_for_harness | head -1)"
if [[ "$harness_pid" =~ ^[0-9]+$ ]] \
&& qs_for_harness ipc show 2>/dev/null | rg -q '^target wallpaper-service-test$'; then
break
fi
sleep 0.1
done
[[ "$harness_pid" =~ ^[0-9]+$ ]] || fail 'isolated service harness process did not start'
wait_idle >/dev/null
: >"$command_log"
printf '%s\n' '{}' >"$active_state"
qs_for_harness ipc call wallpaper-service-test applyPerMonitor >/dev/null
success="$(wait_idle)"
expected_calls=$'hyprctl hyprpaper wallpaper DP-2,/images/a.jpg\nhyprctl hyprpaper wallpaper HDMI-A-1,/images/b.jpg\nhyprctl hyprpaper listactive'
[[ "$(<"$command_log")" == "$expected_calls" ]] || fail "transaction argv/order was wrong: $(<"$command_log")"
jq -e '.lastError == "" and .mode == "per-monitor" and .path == "/images/a.jpg"
and .assignments == {"HDMI-A-1":"/images/b.jpg"}
and .activeByOutput == {"DP-2":"/images/a.jpg","HDMI-A-1":"/images/b.jpg"}' \
<<<"$success" >/dev/null || fail "verified policy was not persisted: $success"
printf 'wrong\n' >"$control"
: >"$command_log"
qs_for_harness ipc call wallpaper-service-test applySingle /images/c.jpg >/dev/null
wrong="$(wait_idle)"
jq -e '.path == "/images/a.jpg" and .mode == "per-monitor"
and .lastError == "Hyprpaper did not confirm that background."' \
<<<"$wrong" >/dev/null || fail "wrong readback persisted an unverified policy: $wrong"
printf 'fail-second\n' >"$control"
: >"$command_log"
qs_for_harness ipc call wallpaper-service-test applyPerMonitor >/dev/null
failed="$(wait_idle)"
jq -e '.path == "/images/a.jpg" and .mode == "per-monitor"
and .lastError == "Hyprpaper did not apply that background."' \
<<<"$failed" >/dev/null || fail "partial output failure changed policy: $failed"
[[ "$(tail -1 "$command_log")" == 'hyprctl hyprpaper wallpaper HDMI-A-1,/images/b.jpg' ]] \
|| fail 'transaction continued after the failed output'
if rg -n 'ReferenceError|TypeError|Binding loop|Unable to assign|Cannot assign' "$shell_log"; then
fail 'service harness emitted a QML runtime warning'
fi
printf 'wallpaper service contract: PASS\n'