#!/usr/bin/env bash # Functional test of json_escape + restore guard (DC-122 verification) set -euo pipefail # Updater script path: $1 overrides; default = adjacent to this test file # (numbered worktree prefixes included), falling back to installed location. SCRIPT="${1:-}" if [[ -z "$SCRIPT" ]]; then local_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" for cand in "$local_dir/dashcaddy-update.sh" \ "$local_dir"/*dashcaddy-update.sh \ /opt/dashcaddy/scripts/dashcaddy-update.sh; do [[ -f "$cand" ]] && SCRIPT="$cand" && break done fi [[ -f "$SCRIPT" ]] || { echo "updater script not found"; exit 1; } # Exactly ONE validated, trap-covered workspace for ALL temp artifacts. WORK=$(mktemp -d) || { echo "mktemp failed"; exit 1; } trap 'rm -rf "$WORK"' EXIT source <(sed -n '/^json_escape()/,/^}/p' "$SCRIPT") # Test 1: quotes + backslash + newline + tab round-trip through python json r=$(json_escape 'a"b\c d e') python3 - "$r" <<'PY' import json, sys v = json.loads('"' + sys.argv[1] + '"') assert v == 'a"b\\c\nd\te', f"round-trip mismatch: {v!r}" print("TEST1 OK: quotes/backslash/newline/tab round-trip valid JSON") PY # Test 2: control chars (backspace, form feed, x01) become \uXXXX short forms r2=$(json_escape "$(printf 'x\by\fz\001w')") python3 - "$r2" <<'PY' import json, sys v = json.loads('"' + sys.argv[1] + '"') assert v == "x\by\fz\x01w", f"control round-trip mismatch: {v!r}" print("TEST2 OK: control bytes escaped and parse back") PY # Test 3: restore_frontend_dir must REFUSE an invalid recorded target — # invoke it for real and assert (a) nonzero return, (b) zero mutations. sed -n '/^validate_frontend_target()/,/^}/p' "$SCRIPT" > "$WORK/rfd-parts.sh" sed -n '/^restore_frontend_dir()/,/^}/p' "$SCRIPT" >> "$WORK/rfd-parts.sh" log() { echo "[t] $*"; } source "$WORK/rfd-parts.sh" WORK2="$WORK/fixtures" mkdir -p "$WORK2/victim/dist" "$WORK2/backup/frontend" echo keep > "$WORK2/victim/dist/keep.js" cat > "$WORK2/backup/frontend.meta" < "$WORK2/backup/frontend.manifest" # Full-tree fingerprint BEFORE any restore attempt: prove ZERO mutations # anywhere in the victim tree across the refused restore. fp_before=$(find "$WORK2/victim" -type f -exec sha256sum {} + | sort) rc=0 restore_frontend_dir "$WORK2/backup" 2>/dev/null || rc=$? fp_after=$(find "$WORK2/victim" -type f -exec sha256sum {} + | sort) if [[ $rc -ne 0 ]]; then echo "TEST3a OK: restore returned nonzero ($rc) for invalid target"; else echo "TEST3 FAIL: restore returned 0"; exit 1; fi if [[ "$fp_before" == "$fp_after" ]]; then echo "TEST3b OK: victim untouched (fingerprint identical across refused restore)" else echo "TEST3 FAIL: victim modified"; exit 1 fi echo "ALL JSON/GUARD TESTS DONE"