feat(station): Abschlussbild beim Herunterfahren und beim Neustart
E-Paper behaelt sein Bild dauerhaft, auch stromlos. Faehrt der Pi herunter, wird der Anzeigedienst mit abgeraeumt und das zuletzt gezeichnete Bild bleibt fuer immer stehen - bei der Abnahme stand dort die Rueckfrage des Tastermenues, und der ausgeschaltete Pi sah aus, als warte er noch auf eine Eingabe. Zwei neue Units, ninlight-poweroff.service (WantedBy=poweroff.target) und ninlight-reboot.service (WantedBy=reboot.target). Sie haengen am System, nicht am Tasterdienst: so greifen sie bei jedem Herunterfahren - Menue, "poweroff" per SSH, "reboot" - und nicht nur auf einem von drei Wegen. Zwei Units statt einer Fallunterscheidung, weil systemd einem ExecStart nicht sagt, wohin die Reise geht. Die Texte unterscheiden sich: "AUSGESCHALTET / Strom kann getrennt werden" gegen "NEUSTART / Strom NICHT trennen!" samt Hinweis auf die rund zwei Minuten, die der Zero W bis zum Anzeigedienst braucht. An diesem Pi hat ein Stromzug in genau dieser Wartezeit schon eine SD-Karte gekostet. Reihenfolge: die Units ordnen sich per After=ninlight-display.service hinter dessen Stop ein, und "ninlight-station display final <kind>" wartet zusaetzlich, bis systemctl is-active nicht mehr anschlaegt - dasselbe Muster wie display_handover(), nur ohne Wiederanfahren. Gibt der Dienst die Leitungen nicht frei, wird nicht gezeichnet (GPIO busy), sondern gewarnt: ein Anzeigefehler haelt das Herunterfahren nie auf. Nebenbei behoben: display_run() reichte nur "$1" an display.py weiter und haette "--final poweroff" halbiert.
This commit is contained in:
@@ -129,6 +129,21 @@ case "\$1" in
|
||||
unit="\${!#}"
|
||||
if [ "\$unit" = "ninlight-display" ]; then
|
||||
code="\${FAKE_DISPLAY_SERVICE_ACTIVE_EXIT:-0}"
|
||||
# Testschalter fuer den Abschlussbildschirm: der Anzeigedienst gilt fuer die
|
||||
# ersten N Abfragen als AKTIV und danach als gestoppt - so, wie es beim
|
||||
# Herunterfahren wirklich ablaeuft (systemd stoppt ihn, das dauert einen Moment).
|
||||
# Gezaehlt wird in einer Datei, weil jeder Stub-Aufruf ein eigener Prozess ist.
|
||||
if [ -n "\${FAKE_DISPLAY_ACTIVE_FOR:-}" ]; then
|
||||
n=\$(cat "$rundir/.display-active-count" 2>/dev/null || echo 0)
|
||||
n=\$((n + 1))
|
||||
echo "\$n" >"$rundir/.display-active-count"
|
||||
if [ "\$n" -le "\${FAKE_DISPLAY_ACTIVE_FOR}" ]; then
|
||||
echo active
|
||||
exit 0
|
||||
fi
|
||||
echo inactive
|
||||
exit 3
|
||||
fi
|
||||
else
|
||||
code="\${FAKE_SYSTEMCTL_ACTIVE_EXIT:-0}"
|
||||
fi
|
||||
@@ -1308,6 +1323,104 @@ ERR=$(run_cli "$SBX" migrate on --listen 2>&1 >/dev/null)
|
||||
set -e
|
||||
echo "$ERR" | grep -q "keine Migrationsimages" && pass "nach dem Umschalten warnt sie" || fail "keine Warnung, obwohl der gewaehlte Satz leer ist: $ERR"
|
||||
|
||||
echo
|
||||
echo "=== Abschluss A: 'display final' kennt zwei verschiedene Bilder ==="
|
||||
# E-Paper behaelt sein Bild dauerhaft. Beim Ausschalten darf man den Stecker ziehen, beim
|
||||
# Neustart gerade nicht - deshalb zwei Schalter, nicht einer.
|
||||
SBX="$TMPROOT/fin1"
|
||||
setup_sandbox "$SBX"
|
||||
export FAKE_DISPLAY_SERVICE_ACTIVE_EXIT=3 # Anzeigedienst laeuft nicht
|
||||
set +e
|
||||
OUT=$(run_cli "$SBX" display final poweroff 2>&1)
|
||||
RC=$?
|
||||
set -e
|
||||
[ "$RC" -eq 0 ] && pass "Exit-Code 0" || fail "Exit-Code $RC: $OUT"
|
||||
grep -q "STUB display.py --final poweroff" "$SBX/cmd.log" && pass "display.py wird mit '--final poweroff' aufgerufen" || fail "falscher Aufruf: $(cat "$SBX/cmd.log")"
|
||||
: >"$SBX/cmd.log"
|
||||
run_cli "$SBX" display final reboot >/dev/null 2>&1
|
||||
grep -q "STUB display.py --final reboot" "$SBX/cmd.log" && pass "und mit '--final reboot' fuer den Neustart" || fail "falscher Aufruf: $(cat "$SBX/cmd.log")"
|
||||
grep -q "poweroff" "$SBX/cmd.log" && fail "der Neustart ruft das Ausschaltbild auf" || pass "die beiden Wege werden nicht verwechselt"
|
||||
unset FAKE_DISPLAY_SERVICE_ACTIVE_EXIT
|
||||
|
||||
echo
|
||||
echo "=== Abschluss B: ohne 'poweroff'/'reboot' passiert nichts ==="
|
||||
SBX="$TMPROOT/fin2"
|
||||
setup_sandbox "$SBX"
|
||||
set +e
|
||||
ERR=$(run_cli "$SBX" display final 2>&1 >/dev/null)
|
||||
RC=$?
|
||||
set -e
|
||||
[ "$RC" -ne 0 ] && pass "Exit-Code != 0" || fail "Exit-Code 0 ohne Spielart"
|
||||
grep -q "STUB display.py" "$SBX/cmd.log" 2>/dev/null && fail "display.py wurde trotzdem aufgerufen" || pass "das Panel wurde nicht angefasst"
|
||||
set +e
|
||||
ERR=$(run_cli "$SBX" display final quatsch 2>&1 >/dev/null)
|
||||
RC=$?
|
||||
set -e
|
||||
[ "$RC" -ne 0 ] && pass "Exit-Code != 0 fuer eine unbekannte Spielart" || fail "Exit-Code 0 fuer 'quatsch'"
|
||||
grep -q "STUB display.py" "$SBX/cmd.log" 2>/dev/null && fail "display.py wurde fuer 'quatsch' aufgerufen" || pass "und auch dafuer nicht"
|
||||
|
||||
echo
|
||||
echo "=== Abschluss C: gezeichnet wird erst, NACHDEM der Anzeigedienst die Leitungen freigegeben hat ==="
|
||||
# Zwei Prozesse auf denselben GPIO-/SPI-Leitungen enden in "lgpio.error: 'GPIO busy'" -
|
||||
# in diesem Projekt schon zweimal passiert.
|
||||
SBX="$TMPROOT/fin3"
|
||||
setup_sandbox "$SBX"
|
||||
export FAKE_DISPLAY_ACTIVE_FOR=2 # erst beim dritten Blick ist er gestoppt
|
||||
set +e
|
||||
OUT=$(NINLIGHT_DISPLAY_RELEASE_WAIT_S=5 run_cli "$SBX" display final poweroff 2>&1)
|
||||
RC=$?
|
||||
set -e
|
||||
unset FAKE_DISPLAY_ACTIVE_FOR
|
||||
[ "$RC" -eq 0 ] && pass "Exit-Code 0" || fail "Exit-Code $RC: $OUT"
|
||||
grep -q "STUB display.py --final poweroff" "$SBX/cmd.log" && pass "das Abschlussbild wurde gezeichnet" || fail "gar nicht gezeichnet: $(cat "$SBX/cmd.log")"
|
||||
# Die Reihenfolge in der GEMEINSAMEN Logdatei ist der Beleg: jede is-active-Abfrage steht
|
||||
# vor dem display.py-Aufruf, keine danach.
|
||||
# "|| true" ueberall: ohne Treffer liefert grep 1, und unter "set -e" wuerde die SUITE an
|
||||
# dieser Stelle stillschweigend abbrechen, statt einen Fehler zu melden - eine Mutation,
|
||||
# die das Warten ganz entfernt, waere dann scheinbar gruen (genau so passiert).
|
||||
DRAW_LINE=$(grep -n "STUB display.py" "$SBX/cmd.log" 2>/dev/null | head -n1 | cut -d: -f1 || true)
|
||||
LAST_CHECK=$(grep -n "systemctl is-active --quiet ninlight-display" "$SBX/cmd.log" 2>/dev/null | tail -n1 | cut -d: -f1 || true)
|
||||
CHECKS=$(grep -c "systemctl is-active --quiet ninlight-display" "$SBX/cmd.log" 2>/dev/null || true)
|
||||
CHECKS=${CHECKS:-0}
|
||||
if [ -n "$DRAW_LINE" ] && [ -n "$LAST_CHECK" ] && [ "$LAST_CHECK" -lt "$DRAW_LINE" ]; then
|
||||
pass "alle Abfragen des Anzeigedienstes stehen VOR dem Zeichnen"
|
||||
else
|
||||
fail "gezeichnet wurde nicht nach der Freigabe (Zeichnen Zeile '$DRAW_LINE', letzte Abfrage Zeile '$LAST_CHECK')"
|
||||
fi
|
||||
[ "$CHECKS" -ge 3 ] && pass "es wurde wirklich gewartet ($CHECKS Abfragen)" || fail "nur $CHECKS Abfrage(n) - es wurde gar nicht auf die Freigabe gewartet"
|
||||
|
||||
echo
|
||||
echo "=== Abschluss D: ein Anzeigedienst, der nicht loslaesst, haelt das Herunterfahren nicht auf ==="
|
||||
# Lieber kein Abschlussbild als ein haengendes Herunterfahren - und auf keinen Fall ein
|
||||
# zweiter Prozess auf den belegten Leitungen.
|
||||
SBX="$TMPROOT/fin4"
|
||||
setup_sandbox "$SBX"
|
||||
export FAKE_DISPLAY_ACTIVE_FOR=9999
|
||||
set +e
|
||||
ERR=$(NINLIGHT_DISPLAY_RELEASE_WAIT_S=2 run_cli "$SBX" display final poweroff 2>&1 >/dev/null)
|
||||
RC=$?
|
||||
set -e
|
||||
unset FAKE_DISPLAY_ACTIVE_FOR
|
||||
[ "$RC" -eq 0 ] && pass "Exit-Code 0 (ein Anzeigefehler haelt das Herunterfahren nie auf)" || fail "Exit-Code $RC: $ERR"
|
||||
grep -q "STUB display.py" "$SBX/cmd.log" && fail "es wurde auf belegte Leitungen gezeichnet - 'GPIO busy'" || pass "nicht gezeichnet, solange der Dienst haelt"
|
||||
echo "$ERR" | grep -qi "warnung" && pass "Warnung auf stderr" || fail "keine Warnung: $ERR"
|
||||
# Und es wurde NICHT versucht, den Dienst von hier aus zu stoppen: das liefe mitten in
|
||||
# der Abschalt-Transaktion.
|
||||
grep -q "systemctl stop ninlight-display" "$SBX/cmd.log" && fail "'systemctl stop' mitten im Herunterfahren" || pass "kein 'systemctl stop' aus dem Abschaltschritt heraus"
|
||||
|
||||
echo
|
||||
echo "=== Abschluss E: ein scheiterndes display.py bleibt eine Warnung ==="
|
||||
SBX="$TMPROOT/fin5"
|
||||
setup_sandbox "$SBX"
|
||||
export FAKE_DISPLAY_SERVICE_ACTIVE_EXIT=3
|
||||
set +e
|
||||
ERR=$(FAKE_DISPLAY_EXIT=1 run_cli "$SBX" display final reboot 2>&1 >/dev/null)
|
||||
RC=$?
|
||||
set -e
|
||||
unset FAKE_DISPLAY_SERVICE_ACTIVE_EXIT
|
||||
[ "$RC" -eq 0 ] && pass "Exit-Code 0" || fail "Exit-Code $RC - ein Anzeigefehler wuerde das Herunterfahren rot machen: $ERR"
|
||||
echo "$ERR" | grep -qi "warnung" && pass "Warnung auf stderr" || fail "keine Warnung: $ERR"
|
||||
|
||||
echo
|
||||
if [ "$FAILED" -eq 0 ]; then
|
||||
echo "Alle Tests bestanden."
|
||||
|
||||
@@ -53,6 +53,8 @@ setup_sandbox() {
|
||||
echo "# dummy" >"$sandbox/tools/station/ninlight-station.service"
|
||||
echo "# dummy" >"$sandbox/tools/station/ninlight-display.service"
|
||||
echo "# dummy" >"$sandbox/tools/station/ninlight-button.service"
|
||||
echo "# dummy" >"$sandbox/tools/station/ninlight-poweroff.service"
|
||||
echo "# dummy" >"$sandbox/tools/station/ninlight-reboot.service"
|
||||
# display/ wird ECHT kopiert, nicht durch Attrappen ersetzt: die Zusage aus Task 6b
|
||||
# ist, dass die beiden uebernommenen Panel-Treiber UND der Herkunftsnachweis
|
||||
# HERKUNFT.md mit auf den Pi gehen. Mit selbst erfundenen Dateinamen im Sandbox-Repo
|
||||
@@ -185,6 +187,8 @@ run_deploy() {
|
||||
NINLIGHT_STATION_UNIT="$SANDBOX_STATE/etc/systemd/system/ninlight-station.service" \
|
||||
NINLIGHT_DISPLAY_UNIT="$SANDBOX_STATE/etc/systemd/system/ninlight-display.service" \
|
||||
NINLIGHT_BUTTON_UNIT="$SANDBOX_STATE/etc/systemd/system/ninlight-button.service" \
|
||||
NINLIGHT_POWEROFF_UNIT="$SANDBOX_STATE/etc/systemd/system/ninlight-poweroff.service" \
|
||||
NINLIGHT_REBOOT_UNIT="$SANDBOX_STATE/etc/systemd/system/ninlight-reboot.service" \
|
||||
NINLIGHT_SIGN_DIR="$sign_dir" \
|
||||
"$sandbox/tools/station/deploy.sh" "$@"
|
||||
}
|
||||
@@ -1240,6 +1244,33 @@ set -e
|
||||
&& pass "der Altbestand images/migrate wurde entfernt" \
|
||||
|| fail "images/migrate liegt noch da"
|
||||
|
||||
echo
|
||||
echo "=== Szenario 32: die beiden Abschlussbild-Units werden mit ausgeliefert ==="
|
||||
# Ohne sie bliebe auf dem E-Paper nach dem Herunterfahren fuer immer das letzte Bild
|
||||
# stehen - bei der Abnahme war das die Rueckfrage des Tastermenues.
|
||||
SANDBOX="$TMPROOT/s32"; STUBBIN="$TMPROOT/bin32"; LOG="$TMPROOT/s32.log"; SANDBOX_STATE="$TMPROOT/s32-state"
|
||||
setup_sandbox "$SANDBOX"
|
||||
setup_stubbin "$STUBBIN" "$LOG"
|
||||
mkdir -p "$SANDBOX/build/foo"
|
||||
echo "foo-image" >"$SANDBOX/build/foo/ninlight_foo_ota.img"
|
||||
: >"$LOG"
|
||||
set +e
|
||||
OUT=$(run_deploy "$SANDBOX" pi-test 2>&1)
|
||||
RC=$?
|
||||
set -e
|
||||
[ "$RC" -eq 0 ] && pass "Exit-Code 0" || fail "Exit-Code $RC: $OUT"
|
||||
for u in ninlight-poweroff ninlight-reboot; do
|
||||
[ -f "$SANDBOX_STATE/etc/systemd/system/$u.service" ] \
|
||||
&& pass "$u.service installiert" || fail "$u.service fehlt - sie waere toter Text im Repo"
|
||||
done
|
||||
# Ein Deploy darf keine Unit EINSCHALTEN, die vorher aus war - das macht setup_pi.sh.
|
||||
grep -Fq "systemctl enable ninlight-poweroff" "$LOG" \
|
||||
&& fail "der Deploy aktiviert die Abschlussbild-Unit" \
|
||||
|| pass "der Deploy aktiviert sie nicht (das ist setup_pi.sh's Aufgabe)"
|
||||
# Und die Ablage ist hinterher leer.
|
||||
[ ! -e /tmp/ninlight-poweroff.service ] && [ ! -e /tmp/ninlight-reboot.service ] \
|
||||
&& pass "die Ablage wurde aufgeraeumt" || fail "Unit-Dateien blieben unter /tmp liegen"
|
||||
|
||||
echo
|
||||
if [ "$FAILED" -eq 0 ]; then
|
||||
echo "Alle Tests bestanden."
|
||||
|
||||
@@ -1865,3 +1865,126 @@ def test_the_display_and_the_server_agree_on_the_set_names():
|
||||
spec.loader.exec_module(server)
|
||||
assert display.IMAGESET_DIRS == server.IMAGE_SET_DIRS
|
||||
assert display.IMAGESET_DEFAULT == server.DEFAULT_IMAGE_SET
|
||||
|
||||
|
||||
# --- Abschlussbildschirm beim Herunterfahren und beim Neustart -----------------------
|
||||
#
|
||||
# E-Paper ist bistabil: das zuletzt gezeichnete Bild bleibt fuer immer stehen, auch
|
||||
# stromlos. Ohne dieses Bild behauptet das Panel nach dem Ausschalten weiter den Zustand
|
||||
# von vorher - bei der Abnahme stand dort die Rueckfrage des Tastermenues, und der Pi sah
|
||||
# aus, als warte er noch auf eine Eingabe.
|
||||
|
||||
def _final_text(kind):
|
||||
return " ".join(render.lines({"mode": "final", "final": kind}))
|
||||
|
||||
|
||||
def test_the_shutdown_and_the_reboot_screen_differ():
|
||||
"""Der wichtigste Unterschied im ganzen Bild: beim Ausschalten DARF man den Stecker
|
||||
ziehen, beim Neustart NICHT (an diesem Pi hat ein Stromzug schon eine SD-Karte
|
||||
gekostet)."""
|
||||
off, reboot = _final_text("poweroff"), _final_text("reboot")
|
||||
assert off != reboot
|
||||
assert "AUSGESCHALTET" in off and "NEUSTART" in reboot
|
||||
# Ausschalten: erlaubt das Trennen ausdruecklich.
|
||||
assert "kann getrennt werden" in off
|
||||
# Neustart: verbietet es ebenso ausdruecklich - und sagt nirgends das Gegenteil.
|
||||
assert "NICHT trennen" in reboot
|
||||
assert "kann getrennt werden" not in reboot
|
||||
|
||||
|
||||
def test_the_reboot_screen_says_how_long_it_stays():
|
||||
"""Ein Zero W braucht gut anderthalb Minuten bis zum Anzeigedienst - ohne diesen Satz
|
||||
sieht das stehende Bild nach "haengt" aus, und genau dann greift jemand zum Stecker."""
|
||||
assert "min" in _final_text("reboot")
|
||||
|
||||
|
||||
def test_the_final_screen_carries_nothing_else():
|
||||
"""Kein Bildsatz, keine Fusszeile, kein Zaehler: die Station ist im Begriff zu
|
||||
verschwinden, und die einzige Auskunft, auf die es jetzt ankommt, ist "Stecker?"."""
|
||||
state = {"mode": "final", "final": "poweroff", "imageset": "mit-wlan",
|
||||
"imageset_ok": True, "served": 7}
|
||||
blocks = render.blocks(state)
|
||||
assert not any(role == render.ROLE_FOOTER for _, role in blocks)
|
||||
assert not any("Bildsatz" in text or "Ausgeliefert" in text for text, _ in blocks)
|
||||
|
||||
|
||||
def test_an_unknown_final_kind_claims_neither():
|
||||
"""Lieber gar nichts behaupten als "ausgeschaltet" zu sagen, wenn gleich wieder
|
||||
gebootet wird."""
|
||||
text = " ".join(render.lines({"mode": "final", "final": "was-auch-immer"}))
|
||||
assert "AUSGESCHALTET" not in text
|
||||
assert "getrennt" not in text
|
||||
|
||||
|
||||
def test_both_final_screens_are_actually_drawable():
|
||||
for kind in ("poweroff", "reboot"):
|
||||
image = render.compose({"mode": "final", "final": kind})
|
||||
assert image.size == (render.PANEL_WIDTH_PX, render.PANEL_HEIGHT_PX)
|
||||
assert _ink_box(image) is not None, kind
|
||||
|
||||
|
||||
def test_run_final_draws_fully_and_sleeps(monkeypatch):
|
||||
"""Ueber die ECHTE display.run_final(): Vollaufbau (kein Teilaufbau - dieses eine Bild
|
||||
ueberdauert alle anderen und darf keine Reste des vorigen tragen) und danach schlafen
|
||||
legen, damit das Panel nicht unter Bias in den Ruhezustand geht."""
|
||||
calls = []
|
||||
|
||||
class _Panel:
|
||||
def __init__(self, revision):
|
||||
calls.append(("init", revision))
|
||||
|
||||
def clear(self):
|
||||
calls.append(("clear", None))
|
||||
|
||||
def draw_full(self, image):
|
||||
calls.append(("full", image))
|
||||
|
||||
def draw_partial(self, image):
|
||||
calls.append(("partial", image))
|
||||
return False
|
||||
|
||||
def sleep(self):
|
||||
calls.append(("sleep", None))
|
||||
|
||||
monkeypatch.setattr(display, "Panel", _Panel)
|
||||
display.run_final("V3", "reboot")
|
||||
|
||||
kinds = [k for k, _ in calls]
|
||||
assert kinds == ["init", "clear", "full", "sleep"], kinds
|
||||
# ... und gezeichnet wurde wirklich das Neustart-Bild, nicht irgendeines.
|
||||
image = dict((k, v) for k, v in calls)["full"]
|
||||
expected = render.compose({"mode": "final", "final": "reboot"})
|
||||
assert list(image.getdata()) == list(expected.getdata())
|
||||
assert list(image.getdata()) != list(
|
||||
render.compose({"mode": "final", "final": "poweroff"}).getdata())
|
||||
|
||||
|
||||
def test_display_main_passes_the_final_kind_through(monkeypatch):
|
||||
"""Die Verdrahtung in display.main() selbst: "--final reboot" muss beim Neustartbild
|
||||
landen. Ohne diese Zusage liesse sich die Spielart in main() durch eine feste
|
||||
ersetzen, ohne dass ein Test rot wuerde - und auf dem Panel stuende beim Neustart
|
||||
"Strom kann getrennt werden"."""
|
||||
drawn = []
|
||||
|
||||
class _Panel:
|
||||
def __init__(self, revision):
|
||||
pass
|
||||
|
||||
def clear(self):
|
||||
pass
|
||||
|
||||
def draw_full(self, image):
|
||||
drawn.append(image)
|
||||
|
||||
def sleep(self):
|
||||
pass
|
||||
|
||||
monkeypatch.setattr(display, "Panel", _Panel)
|
||||
monkeypatch.setenv("EPD_REVISION", "V3")
|
||||
for kind in ("reboot", "poweroff"):
|
||||
drawn.clear()
|
||||
monkeypatch.setattr(sys, "argv", ["display.py", "--final", kind])
|
||||
display.main()
|
||||
assert len(drawn) == 1
|
||||
expected = render.compose({"mode": "final", "final": kind})
|
||||
assert list(drawn[0].getdata()) == list(expected.getdata()), kind
|
||||
|
||||
@@ -146,6 +146,13 @@ echo "STUB systemctl \$*" >>"$log"
|
||||
# ein Szenario NUR ihn scheitern lassen kann, ohne die Anzeige mitzureissen - sonst
|
||||
# liesse sich nicht zeigen, dass ein fehlgeschlagenes enable/start des Tasters fuer
|
||||
# sich genommen keinen Abbruch ausloest.
|
||||
# Gezielt EINE Unit scheitern lassen (Abschlussbild): FAKE_ENABLE_FAIL_SUBSTR nennt den
|
||||
# Teilstring des Unit-Namens, dessen "enable" fehlschlaegt.
|
||||
if [ -n "\${FAKE_ENABLE_FAIL_SUBSTR:-}" ] && [ "\$1" = "enable" ]; then
|
||||
case "\$*" in
|
||||
*"\$FAKE_ENABLE_FAIL_SUBSTR"*) exit 1 ;;
|
||||
esac
|
||||
fi
|
||||
case "\$*" in
|
||||
*ninlight-button*)
|
||||
case "\$1" in
|
||||
@@ -217,6 +224,8 @@ run_setup() {
|
||||
NINLIGHT_STATION_UNIT="$state/etc/systemd/system/ninlight-station.service" \
|
||||
NINLIGHT_DISPLAY_UNIT="$state/etc/systemd/system/ninlight-display.service" \
|
||||
NINLIGHT_BUTTON_UNIT="$state/etc/systemd/system/ninlight-button.service" \
|
||||
NINLIGHT_POWEROFF_UNIT="$state/etc/systemd/system/ninlight-poweroff.service" \
|
||||
NINLIGHT_REBOOT_UNIT="$state/etc/systemd/system/ninlight-reboot.service" \
|
||||
NINLIGHT_NM_DIR="$state/etc/NetworkManager/system-connections" \
|
||||
NINLIGHT_BOOT_CONFIG_NEW="$state/boot/firmware/config.txt" \
|
||||
NINLIGHT_BOOT_CONFIG_OLD="$state/boot/config.txt" \
|
||||
@@ -1080,6 +1089,50 @@ for d in migrate-wlan migrate-nocreds; do
|
||||
|| fail "images/$d wurde leer angelegt"
|
||||
done
|
||||
|
||||
echo
|
||||
echo "=== Szenario: der Abschlussbildschirm wird installiert UND aktiviert ==="
|
||||
# Der Abschlussbildschirm gehoert ins System, nicht in den Tasterdienst: so greift er bei
|
||||
# jedem Herunterfahren (Menue, "poweroff" per SSH, Neustart) und nicht nur auf einem von
|
||||
# drei Wegen. Zwei Units, weil sich die Texte unterscheiden muessen.
|
||||
STATE="$TMPROOT/sfin-state"; STUBBIN="$TMPROOT/binfin"; LOG="$TMPROOT/sfin.log"
|
||||
setup_state "$STATE"
|
||||
setup_stubbin "$STUBBIN" "$LOG"
|
||||
: >"$LOG"
|
||||
set +e
|
||||
OUT=$(run_setup "$STATE" "$STUBBIN" 2>&1)
|
||||
RC=$?
|
||||
set -e
|
||||
[ "$RC" -eq 0 ] && pass "Exit-Code 0" || fail "Exit-Code $RC, Ausgabe: $OUT"
|
||||
for u in ninlight-poweroff ninlight-reboot; do
|
||||
[ -f "$STATE/etc/systemd/system/$u.service" ] \
|
||||
&& pass "$u.service installiert" || fail "$u.service fehlt"
|
||||
grep -Fq "systemctl enable $u.service" "$LOG" \
|
||||
&& pass "$u.service aktiviert" || fail "kein 'systemctl enable $u' im Log"
|
||||
done
|
||||
# "enable", aber KEIN "start": diese Units tun beim Systemstart nichts, sie gehoeren zur
|
||||
# Abschalt-Transaktion. Ein "start" wuerde das Abschlussbild mitten im Betrieb zeichnen.
|
||||
grep -Fq "systemctl restart ninlight-poweroff" "$LOG" \
|
||||
&& fail "die Abschlussbild-Unit wird beim Einrichten gestartet - das Bild kaeme sofort" \
|
||||
|| pass "sie wird nicht gestartet, nur aktiviert"
|
||||
grep -Fq "systemctl start ninlight-poweroff" "$LOG" \
|
||||
&& fail "die Abschlussbild-Unit wird beim Einrichten gestartet" \
|
||||
|| pass "auch kein 'systemctl start'"
|
||||
|
||||
echo
|
||||
echo "=== Szenario: ein fehlgeschlagenes enable des Abschlussbilds warnt nur ==="
|
||||
# Eine Station, deren Panel nach dem Ausschalten das falsche Bild zeigt, ist aergerlich;
|
||||
# eine, die sich gar nicht einrichten laesst, ist unbrauchbar.
|
||||
STATE="$TMPROOT/sfin2-state"; STUBBIN="$TMPROOT/binfin2"; LOG="$TMPROOT/sfin2.log"
|
||||
setup_state "$STATE"
|
||||
setup_stubbin "$STUBBIN" "$LOG"
|
||||
: >"$LOG"
|
||||
set +e
|
||||
OUT=$(FAKE_ENABLE_FAIL_SUBSTR=ninlight-poweroff run_setup "$STATE" "$STUBBIN" 2>&1)
|
||||
RC=$?
|
||||
set -e
|
||||
[ "$RC" -eq 0 ] && pass "Exit-Code 0 trotz fehlgeschlagenem enable" || fail "Exit-Code $RC: $OUT"
|
||||
echo "$OUT" | grep -qi "warnung" && pass "Warnung in der Ausgabe" || fail "keine Warnung: $OUT"
|
||||
|
||||
echo
|
||||
if [ "$FAILED" -eq 0 ]; then
|
||||
echo "Alle Tests bestanden."
|
||||
|
||||
Reference in New Issue
Block a user