Fix NetworkManager hotspot readiness

This commit is contained in:
v3d 2026-07-01 18:33:13 +02:00
parent 0f20889948
commit 3340108acd
5 changed files with 136 additions and 4 deletions

View file

@ -79,6 +79,12 @@ same_boot_mode_contract() {
grep -q 'wait_for_diagnostics onion' "$ROOT/usr/local/lib/pivilion/mode.sh"
}
networkmanager_startup_contract() {
grep -q 'pivilion_nm_prepare_interface "$IFACE"' "$ROOT/usr/local/lib/pivilion/mode.sh" &&
grep -q 'pivilion_nm_connection_up "$NM_HOTSPOT" "$IFACE"' "$ROOT/usr/local/lib/pivilion/mode.sh" &&
grep -q 'nmcli connection up "$connection" ifname "$iface"' "$ROOT/usr/local/lib/pivilion/networkmanager.sh"
}
shellcheck_scripts() {
command -v shellcheck >/dev/null 2>&1 || return 0
shellcheck "$ROOT/install.sh" "$ROOT"/usr/local/lib/pivilion/*.sh "$ROOT"/usr/local/bin/pivilion* "$ROOT/usr/local/bin/hotspot" "$ROOT/usr/local/bin/onion" "$ROOT/usr/local/bin/pikey"
@ -95,6 +101,8 @@ run "truthful runtime state contract" state_contract
run "agetty login-banner contract" tty_banner_contract
run "canonical boot configuration contract" boot_config_contract
run "same-boot hotspot and onion activation contract" same_boot_mode_contract
run "NetworkManager software-radio and delayed-device handling" "$ROOT/tests/test-networkmanager.sh"
run "NetworkManager hotspot startup contract" networkmanager_startup_contract
run "ShellCheck (when installed)" shellcheck_scripts
[ "$failures" -eq 0 ] || { echo "$failures test group(s) failed." >&2; exit 1; }

63
tests/test-networkmanager.sh Executable file
View file

@ -0,0 +1,63 @@
#!/bin/bash
set -euo pipefail
ROOT=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/.." && pwd)
TMP=$(mktemp -d)
trap 'rm -rf "$TMP"' EXIT
mkdir "$TMP/bin"
export MOCK_NM_LOG="$TMP/nmcli.log"
export MOCK_NM_STATE="$TMP/nm-state"
export MOCK_NM_READS="$TMP/nm-reads"
cat > "$TMP/bin/nmcli" <<'EOF'
#!/bin/bash
printf '%s\n' "$*" >> "$MOCK_NM_LOG"
case "$*" in
'radio wifi on') printf 'on\n' > "$MOCK_NM_STATE" ;;
'device set wlan0 managed yes') ;;
'-g GENERAL.STATE device show wlan0')
[ "$(cat "$MOCK_NM_STATE")" = on ] || { echo '20 (unavailable)'; exit 0; }
reads=$(cat "$MOCK_NM_READS" 2>/dev/null || echo 0)
reads=$((reads + 1)); printf '%s\n' "$reads" > "$MOCK_NM_READS"
if [ "$reads" -lt "${MOCK_NM_AVAILABLE_AFTER:-3}" ]; then echo '20 (unavailable)'; else echo '30 (disconnected)'; fi ;;
'radio') echo 'WIFI-HW WIFI'; echo 'enabled enabled' ;;
'device status') echo 'DEVICE TYPE STATE'; echo 'wlan0 wifi unavailable' ;;
'-f GENERAL.STATE,GENERAL.REASON device show wlan0') echo 'GENERAL.STATE: 20 (unavailable)'; echo 'GENERAL.REASON: 2 (unknown)' ;;
'connection up pivilion-hotspot ifname wlan0') ;;
esac
EOF
cat > "$TMP/bin/rfkill" <<'EOF'
#!/bin/sh
echo '0: phy0: Wireless LAN'
echo 'Soft blocked: no'
echo 'Hard blocked: no'
EOF
cat > "$TMP/bin/sleep" <<'EOF'
#!/bin/sh
exit 0
EOF
chmod +x "$TMP/bin/"*
PATH="$TMP/bin:$PATH"
export PATH
source "$ROOT/usr/local/lib/pivilion/networkmanager.sh"
# The mock starts software-disabled and becomes available after a delay.
PIVILION_NM_READY_TIMEOUT=5 pivilion_nm_prepare_interface wlan0
[ "$(cat "$MOCK_NM_STATE")" = on ]
[ "$(cat "$MOCK_NM_READS")" -eq 3 ]
sed -n '1p' "$MOCK_NM_LOG" | grep -Fqx 'radio wifi on'
sed -n '2p' "$MOCK_NM_LOG" | grep -Fqx 'device set wlan0 managed yes'
pivilion_nm_connection_up pivilion-hotspot wlan0
grep -Fqx 'connection up pivilion-hotspot ifname wlan0' "$MOCK_NM_LOG"
# A device that remains unavailable fails within the configured bound and logs
# the complete NetworkManager/rfkill snapshot.
: > "$MOCK_NM_LOG"
: > "$MOCK_NM_READS"
if MOCK_NM_AVAILABLE_AFTER=99 PIVILION_NM_READY_TIMEOUT=2 pivilion_nm_prepare_interface wlan0 >"$TMP/timeout.log" 2>&1; then exit 1; fi
grep -q 'Timed out after 2s' "$TMP/timeout.log"
grep -q '^-- nmcli radio --$' "$TMP/timeout.log"
grep -q '^-- nmcli device status --$' "$TMP/timeout.log"
grep -q '^-- wlan0 state and reason --$' "$TMP/timeout.log"
grep -q '^-- rfkill Wi-Fi state --$' "$TMP/timeout.log"