summaryrefslogtreecommitdiff
path: root/scripts/test-wizard.sh
diff options
context:
space:
mode:
authorinfo@mode42.com <info@mode42.com>2026-08-07 18:23:28 +0000
committerinfo@mode42.com <info@mode42.com>2026-08-07 18:23:28 +0000
commitfa05a5f8238e9e1417235711656e5062ccc843a7 (patch)
tree46fbbd18de54492b59307c16efcc7f3152723238 /scripts/test-wizard.sh
Initial push
Diffstat (limited to 'scripts/test-wizard.sh')
-rwxr-xr-xscripts/test-wizard.sh113
1 files changed, 113 insertions, 0 deletions
diff --git a/scripts/test-wizard.sh b/scripts/test-wizard.sh
new file mode 100755
index 0000000..e75a401
--- /dev/null
+++ b/scripts/test-wizard.sh
@@ -0,0 +1,113 @@
+#!/usr/bin/env bash
+# test-wizard.sh — non-interactive smoke test for max25-lite-setup.sh.
+#
+# Drives the wizard through all three modem paths (serial, baycom, crdop)
+# using a mock `whiptail` on PATH that answers canned responses, then checks
+# the generated max25d.ini / crdop.ini / max25-bcpr.ini files are well formed.
+# No sudo, no hardware, no PTT — local ./local/ destination only.
+set -euo pipefail
+
+ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
+WIZARD="${ROOT}/scripts/max25-lite-setup.sh"
+WORKDIR="$(mktemp -d)"
+ERR=0
+
+ok() { echo "PASS: $*"; }
+fail() { echo "FAIL: $*" >&2; ERR=1; }
+
+cleanup() { rm -rf "$WORKDIR"; }
+trap cleanup EXIT
+
+mock_bin="${WORKDIR}/bin"
+mkdir -p "$mock_bin"
+
+# Mock whiptail: reads canned answers from $WHIPTAIL_ANSWERS (newline list, one
+# per --menu/--radiolist/--inputbox/--yesno call, in call order). --msgbox is a
+# no-op (informational only). Mirrors the 3>&1 1>&2 2>&3 capture convention:
+# the "answer" goes to this script's stderr; exit 0 means OK/Yes.
+cat >"${mock_bin}/whiptail" <<'MOCK'
+#!/usr/bin/env bash
+mode=""
+for a in "$@"; do
+ case "$a" in
+ --msgbox) mode=msgbox ;;
+ --yesno) mode=yesno ;;
+ --inputbox) mode=inputbox ;;
+ --menu) mode=menu ;;
+ --radiolist) mode=radiolist ;;
+ esac
+done
+[[ "$mode" == "msgbox" ]] && exit 0
+answers_file="${WHIPTAIL_ANSWERS:?WHIPTAIL_ANSWERS not set}"
+answer="$(head -n1 "$answers_file")"
+tail -n +2 "$answers_file" > "${answers_file}.next"
+mv "${answers_file}.next" "$answers_file"
+if [[ "$mode" == "yesno" ]]; then
+ [[ "$answer" == "yes" ]] && exit 0 || exit 1
+fi
+echo "$answer" >&2
+exit 0
+MOCK
+chmod +x "${mock_bin}/whiptail"
+
+# Mock arecord/aplay: force the "no ALSA cards" branch deterministically,
+# independent of the host's actual sound hardware, so the CRDOP path always
+# takes the same code path in this smoke test.
+for tool in arecord aplay; do
+ cat >"${mock_bin}/${tool}" <<'MOCK'
+#!/usr/bin/env bash
+exit 1
+MOCK
+ chmod +x "${mock_bin}/${tool}"
+done
+
+run_path() {
+ local label="$1" answers="$2" ini_glob="$3" want_grep="$4"
+ local answers_file="${WORKDIR}/answers-${label}"
+ printf '%s\n' "$answers" > "$answers_file"
+ rm -rf "${ROOT}/local/max25d.ini" "${ROOT}/local/crdop.ini" "${ROOT}/local/max25-bcpr.ini"
+ if PATH="${mock_bin}:${PATH}" WHIPTAIL_ANSWERS="$answers_file" \
+ bash "$WIZARD" </dev/null >"${WORKDIR}/out-${label}.log" 2>&1; then
+ if [[ -f "${ROOT}/local/max25d.ini" ]] && grep -q "$want_grep" "${ROOT}/local/max25d.ini"; then
+ ok "wizard ${label} path: max25d.ini written (${want_grep})"
+ else
+ fail "wizard ${label} path: max25d.ini missing or unexpected content"
+ cat "${WORKDIR}/out-${label}.log" >&2
+ fi
+ else
+ fail "wizard ${label} path: exited non-zero"
+ cat "${WORKDIR}/out-${label}.log" >&2
+ fi
+ rm -rf "${ROOT}/local/max25d.ini" "${ROOT}/local/crdop.ini" "${ROOT}/local/max25-bcpr.ini"
+}
+
+# serial: menu=serial, radiolist=/dev/ttyUSB0, callerid, callid, save-location=no (local)
+run_path "serial" "serial
+/dev/ttyUSB0
+CB-0
+QST
+no" "local/max25d.ini" "device = tnc2c"
+
+# baycom: menu=baycom, radiolist=/dev/ttyS0 (or whatever first port is), callerid, callid, no
+run_path "baycom" "baycom
+$(bash -c '
+ shopt -s nullglob
+ ports=(/dev/ttyUSB* /dev/ttyACM* /dev/ttyS*)
+ shopt -u nullglob
+ echo "${ports[0]:-/dev/ttyUSB0}"
+')
+CB-0
+QST
+no" "local/max25d.ini" "device = max25e0"
+
+# crdop: menu=crdop, [radiolist ALSA device only if arecord/aplay found any — assume
+# none in CI so wizard shows an informational msgbox and uses hw:0,0 defaults], callerid, callid, no
+run_path "crdop" "crdop
+CB-0
+QST
+no" "local/max25d.ini" "device = soft-crdop"
+
+if [[ "$ERR" -eq 0 ]]; then
+ echo "OK: wizard non-interactive smoke (serial / baycom / crdop)"
+fi
+exit "$ERR"
git clone -b <branch> https://cgit.mode42.com/<repo>.git
git clone -b <branch> git://cgit.mode42.com/<repo>.git

info@mode42.com