120 lines
3.1 KiB
Bash
120 lines
3.1 KiB
Bash
|
|
#!/usr/bin/env bash
|
||
|
|
# test-tapes.sh — Verify all systab commands in VHS tape files run correctly.
|
||
|
|
# Greps Type "systab ..." and Type "EDITOR=... systab ..." lines from *.tape
|
||
|
|
# files and runs them in order per tape, reporting pass/fail.
|
||
|
|
#
|
||
|
|
# 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 # each tape starts with a clean slate
|
||
|
|
|
||
|
|
local raw cmd output exit_code
|
||
|
|
while IFS= read -r raw; do
|
||
|
|
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 < <(grep -E '^Type "(systab |EDITOR=)' "$tape" | sed 's/^Type "//; s/"$//')
|
||
|
|
}
|
||
|
|
|
||
|
|
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 ]]
|