systab/demo/test-tapes.sh
Matthias Johnson 6e2aaf99f6 Fix VHS quoting and make tape test runner Hide-aware
Sequential cleanup commands fixed the VHS parse error but exposed
a deeper issue: the test runner was blind to Hide/Show blocks,
so cleanup commands ran as tests and could delete jobs mid-sequence.

- test-tapes.sh now reads tapes line-by-line tracking Hide/Show state;
  only Type lines in visible (Show) blocks are executed as tests
- Pre-clean named jobs from each tape at start of run_tape to handle
  leftovers from previously failed runs (mirrors what the Hide cleanup
  does when VHS records the tape)
- 19 tape commands tested (cleanup commands correctly excluded)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-02 01:58:25 -07:00

135 lines
3.7 KiB
Bash
Executable file

#!/usr/bin/env bash
# test-tapes.sh — Verify all systab commands in VHS tape files run correctly.
# Reads each tape line-by-line, tracking Hide/Show blocks. Only runs
# Type "systab ..." and Type "EDITOR=..." lines that are in visible (Show) blocks.
#
# Run from the project root: ./demo/test-tapes.sh
set -uo pipefail
# Make ./systab callable as 'systab', matching how tapes reference it
PATH="$PWD:$PATH"
export PATH
TAPE_DIR="demo"
SYSTEMD_USER_DIR="${HOME}/.config/systemd/user"
passed=0
failed=0
total=0
tape_job_ids=()
if [[ -t 1 ]]; then
GREEN=$'\033[32m' RED=$'\033[31m' BOLD=$'\033[1m' RESET=$'\033[0m'
else
GREEN="" RED="" BOLD="" RESET=""
fi
pass() {
echo "${GREEN}[PASS]${RESET} $1"
passed=$((passed + 1))
total=$((total + 1))
}
fail() {
echo "${RED}[FAIL]${RESET} $1$2"
failed=$((failed + 1))
total=$((total + 1))
}
# Stop, disable, and remove all unit files created during tape tests
cleanup_tape_jobs() {
[[ ${#tape_job_ids[@]} -eq 0 ]] && return
for id in "${tape_job_ids[@]}"; do
[[ -z "$id" ]] && continue
for ext in service timer; do
local f="$SYSTEMD_USER_DIR/systab_${id}.${ext}"
[[ -f "$f" ]] || continue
systemctl --user stop "systab_${id}.${ext}" 2>/dev/null || true
systemctl --user disable "systab_${id}.${ext}" 2>/dev/null || true
rm -f "$f"
done
done
systemctl --user daemon-reload 2>/dev/null || true
tape_job_ids=()
}
trap cleanup_tape_jobs EXIT
# Collect any job IDs from command output into tape_job_ids
collect_ids() {
local id
while IFS= read -r id; do
[[ -n "$id" ]] && tape_job_ids+=("$id")
done < <(sed -n 's/^\(Job\|Service\) created: \([0-9a-f]\{6\}\).*$/\2/p' <<< "$1")
}
# Prepare a tape command for test execution:
# - EDITOR=nano → EDITOR=cat (non-interactive; cat exits 0, no file changes)
# - strip trailing " | less" (we capture stdout directly)
normalize() {
local cmd="$1"
cmd="${cmd//EDITOR=nano/EDITOR=cat}"
cmd="${cmd% | less}"
echo "$cmd"
}
# Run all systab commands from one tape file in order
run_tape() {
local tape="$1"
local tape_name
tape_name=$(basename "$tape" .tape)
echo ""
echo "${BOLD}=== $tape_name ===${RESET}"
cleanup_tape_jobs # clean up IDs from previous tape
# Pre-clean named jobs from this tape to handle leftovers from failed runs
local name
while IFS= read -r name; do
systab -X "$name" 2>/dev/null || true
done < <(grep -E '^Type "systab .*-n ' "$tape" | grep -oP '(?<=-n )\w+')
local line raw cmd output exit_code in_hide=false
while IFS= read -r line; do
# Track Hide/Show blocks — skip commands in hidden sections
[[ "$line" == "Hide" ]] && { in_hide=true; continue; }
[[ "$line" == "Show" ]] && { in_hide=false; continue; }
$in_hide && continue
# Only process visible Type lines with systab or EDITOR= commands
[[ "$line" == 'Type "systab '* ]] || [[ "$line" == 'Type "EDITOR='* ]] || continue
raw="${line#Type \"}"
raw="${raw%\"}"
cmd=$(normalize "$raw")
exit_code=0
# Pipe /dev/null for commands that read stdin interactively
if [[ "$cmd" == *"systab -C"* ]] || [[ "$cmd" == *"systab -e"* ]]; then
output=$(eval "$cmd" < /dev/null 2>&1) || exit_code=$?
else
output=$(eval "$cmd" 2>&1) || exit_code=$?
fi
collect_ids "$output"
if [[ $exit_code -eq 0 ]]; then
pass "$tape_name: $raw"
else
fail "$tape_name: $raw" "exit $exit_code: ${output:0:120}"
fi
done < "$tape"
}
echo "${BOLD}Testing systab commands from VHS tape files...${RESET}"
for tape in "$TAPE_DIR"/*.tape; do
run_tape "$tape"
done
echo ""
echo "---"
echo "${BOLD}${total} tape commands: ${GREEN}${passed} passed${RESET}, ${RED}${failed} failed${RESET}"
[[ $failed -eq 0 ]]