fix(station): stat-Reihenfolge, Phase nur im Migrationsmodus, eingerueckte Konfig-Werte, kein /tmp-Zugriff im Test
Fixrunde 2 zu Task 4:
- N1 (wichtig): file_mode() in test_cli.sh/test_setup_pi.sh probierte
"stat -f '%Lp'" vor "stat -c '%a'" - auf GNU-coreutils (dem Pi) deutet
"-f" dort "Dateisystemstatus" und liefert Muell statt der Rechte-Zahl,
faellt aber trotzdem in den "||"-Zweig durch, der zusaetzlich "644"
anhaengt. Reihenfolge umgedreht und mit einem per gstat erzwungenen
GNU-Testlauf zusaetzlich abgesichert.
- N2 (wichtig): status zeigte nach einem Wechsel zurueck in den
Rettungsmodus weiterhin die letzte Migrationsphase aus einer liegen
gebliebenen control.json (moeglich seit RuntimeDirectoryPreserve=
restart aus Fixrunde 1). Phase wird jetzt nur noch angezeigt, wenn
Modus tatsaechlich "migration" ist.
- N3 (klein): die Schluesselerkennung in setup_pi.sh war rein
zeilenverankert ("^KEY=") und haette einen eingerueckten Bestandswert
als fehlend gewertet - beim naechsten Sourcen der Konfiguration haette
die zusaetzlich angehaengte Vorlagenzeile das eigene Passwort
ueberschrieben. Muster auf fuehrenden Leerraum/export gehaertet.
- N4 (klein): test_setup_pi.sh liess setup_pi.sh ueber den scp-Stub echte
Dateien im /tmp des Entwicklungsrechners anlegen und wieder loeschen.
Neue Variable NINLIGHT_STAGE_DIR biegt das auf eine Sandbox um.
Alle vier Punkte mit Regressionstests, N2 und N3 zusaetzlich per
Mutationsprobe (Fix zurueckgenommen, Test wird rot) verifiziert.
This commit is contained in:
@@ -30,10 +30,37 @@ fail() { echo "FEHLER - $1" >&2; FAILED=1; }
|
||||
|
||||
file_mode() {
|
||||
# $1 = Pfad. BSD-stat (macOS) und GNU-stat (Linux/Pi) haben unterschiedliche
|
||||
# Flags - hier reicht "irgendeine funktioniert".
|
||||
stat -f '%Lp' "$1" 2>/dev/null || stat -c '%a' "$1" 2>/dev/null
|
||||
# Flags - hier reicht "irgendeine funktioniert". Reihenfolge ist wichtig
|
||||
# (Fixrunde 2, N1): "stat -f '%Lp' datei" auf GNU-coreutils deutet "-f" als
|
||||
# "Dateisystemstatus" und '%Lp' als ZWEITES Dateiargument - der Aufruf schreibt
|
||||
# mehrere Zeilen Dateisystem-Infos auf stdout und scheitert (kein passendes
|
||||
# zweites File), aber der "||"-Zweig haengt DANACH trotzdem noch "644" an, und
|
||||
# der Vergleich "= 644" schlaegt fehl, obwohl die Rechte stimmen - auf dem Pi
|
||||
# (echtes GNU-coreutils) also immer rot. BSD-"stat -c" dagegen bricht sofort
|
||||
# mit einer Fehlermeldung auf stderr ab, ganz ohne Ausgabe auf stdout - der
|
||||
# GNU-Aufruf muss deshalb ZUERST stehen.
|
||||
stat -c '%a' "$1" 2>/dev/null || stat -f '%Lp' "$1" 2>/dev/null
|
||||
}
|
||||
|
||||
# Erzwingt den GNU-Zweig von file_mode() (der auf dem Pi tatsaechlich laeuft),
|
||||
# indem "stat" im PATH auf GNU-coreutils' "gstat" umgebogen wird, falls
|
||||
# vorhanden (macOS mit "brew install coreutils"). Ohne diese Probe wuerde ein
|
||||
# falsch herum sortiertes file_mode() auf dieser Entwicklungsmaschine (BSD-stat
|
||||
# zuerst probiert und erfolgreich) unbemerkt bleiben, obwohl es auf dem Pi
|
||||
# (nur GNU-stat) rot waere - genau der Fehler aus Fixrunde 2, N1.
|
||||
if command -v gstat >/dev/null 2>&1; then
|
||||
GSTAT_CHECK_DIR="$TMPROOT/gstat-check"
|
||||
mkdir -p "$GSTAT_CHECK_DIR/bin"
|
||||
ln -sf "$(command -v gstat)" "$GSTAT_CHECK_DIR/bin/stat"
|
||||
GSTAT_CHECK_FILE="$TMPROOT/gstat-check/probe"
|
||||
: >"$GSTAT_CHECK_FILE"
|
||||
chmod 0644 "$GSTAT_CHECK_FILE"
|
||||
GSTAT_MODE=$(PATH="$GSTAT_CHECK_DIR/bin:$PATH" file_mode "$GSTAT_CHECK_FILE")
|
||||
[ "$GSTAT_MODE" = "644" ] && pass "file_mode() liefert unter erzwungenem GNU-stat korrekt '644'" || fail "file_mode() liefert unter GNU-stat '$GSTAT_MODE' statt '644' - siehe Fixrunde 2, N1"
|
||||
else
|
||||
echo "Hinweis: gstat nicht gefunden - GNU-Zweig von file_mode() wird nur auf dem Pi selbst geprueft" >&2
|
||||
fi
|
||||
|
||||
# --- Stub-Kommandos fuer nmcli/systemctl/sudo im PATH ---
|
||||
# $1 = bindir, $2 = logdatei, $3 = nmcli-Zustandsverzeichnis, $4 = RUN_DIR,
|
||||
# $5 = Pfad zur systemd-Unit, deren RuntimeDirectoryPreserve-Zeile ueber das
|
||||
@@ -489,6 +516,39 @@ echo "$ERR" | grep -q "unerwartet" && pass "Fehlermeldung nennt den Mismatch" ||
|
||||
ACTIVE_AFTER=$(cat "$SBX/nmstate/active")
|
||||
[ -z "$ACTIVE_AFTER" ] && pass "beide Stationsprofile wurden nach dem erkannten Mismatch heruntergefahren" || fail "mindestens ein Profil blieb aktiv: $ACTIVE_AFTER"
|
||||
|
||||
echo
|
||||
echo "=== Zusatzfall N2 (Fixrunde 2): 'status' zeigt keine veraltete Migrationsphase mehr, nachdem in den Rettungsmodus zurueckgeschaltet wurde ==="
|
||||
SBX="$TMPROOT/tN2"
|
||||
setup_sandbox "$SBX"
|
||||
echo "dummy" >"$SBX/images/migrate/gu10_rgb_prod.img"
|
||||
run_cli "$SBX" migrate on --listen >/dev/null 2>&1
|
||||
run_cli "$SBX" arm gu10_rgb >/dev/null 2>&1 # control.json bleibt mit phase=armed liegen
|
||||
run_cli "$SBX" on >/dev/null 2>&1 # zurueck in den Rettungsmodus - control.json wird bewusst NICHT aufgeraeumt
|
||||
[ "$(control_phase "$SBX/run/control.json")" = "armed" ] && pass "Vorbedingung: control.json ist tatsaechlich noch mit phase=armed liegen geblieben" || fail "Vorbedingung nicht erfuellt (control.json wurde schon vorher veraendert)"
|
||||
# status.json so, wie sie der Server nach dem Neustart im Rettungsmodus schreiben
|
||||
# wuerde (mode=recovery, keine last_seen/phase-Felder - siehe server.py write_state()).
|
||||
cat >"$SBX/run/status.json" <<'JSON'
|
||||
{"mode": "recovery"}
|
||||
JSON
|
||||
OUT=$(run_cli "$SBX" status 2>&1)
|
||||
echo "$OUT" | grep -qE "Modus[[:space:]]*: recovery" && pass "Modus zeigt korrekt 'recovery'" || fail "Modus falsch: $OUT"
|
||||
echo "$OUT" | grep -qi "armed" && fail "status zeigt weiterhin die veraltete Migrationsphase 'armed' im Rettungsmodus: $OUT" || pass "keine veraltete Migrationsphase 'armed' im Rettungsmodus"
|
||||
echo "$OUT" | grep -qE "Phase[[:space:]]*: -" && pass "Phase zeigt den neutralen Platzhalter '-' ausserhalb des Migrationsmodus" || fail "Phase zeigt keinen neutralen Platzhalter: $OUT"
|
||||
|
||||
echo
|
||||
echo "=== Zusatzfall N2b (Fixrunde 2): dieselbe veraltete Freigabe, aber ohne aktualisierte status.json (Modus '-') - genau das woertliche Repro aus dem Review ==="
|
||||
SBX="$TMPROOT/tN2b"
|
||||
setup_sandbox "$SBX"
|
||||
echo "dummy" >"$SBX/images/migrate/gu10_rgb_prod.img"
|
||||
run_cli "$SBX" migrate on --listen >/dev/null 2>&1
|
||||
run_cli "$SBX" arm gu10_rgb >/dev/null 2>&1
|
||||
run_cli "$SBX" on >/dev/null 2>&1
|
||||
rm -f "$SBX/run/status.json" # kein Serverprozess in diesem Test aktualisiert sie
|
||||
OUT=$(run_cli "$SBX" status 2>&1)
|
||||
echo "$OUT" | grep -qE "Modus[[:space:]]*: -" && pass "Modus zeigt '-' (keine status.json vorhanden)" || fail "Modus unerwartet: $OUT"
|
||||
echo "$OUT" | grep -qi "armed" && fail "status zeigt 'armed', obwohl der Modus gar nicht bekannt ist: $OUT" || pass "keine 'armed'-Phase bei unbekanntem Modus"
|
||||
echo "$OUT" | grep -qE "Phase[[:space:]]*: -" && pass "Phase zeigt '-' statt einer Vermutung" || fail "Phase zeigt keinen neutralen Platzhalter: $OUT"
|
||||
|
||||
echo
|
||||
if [ "$FAILED" -eq 0 ]; then
|
||||
echo "Alle Tests bestanden."
|
||||
|
||||
Reference in New Issue
Block a user