summaryrefslogtreecommitdiffstats
path: root/test/units/TEST-04-JOURNAL.bsod.sh
diff options
context:
space:
mode:
Diffstat (limited to 'test/units/TEST-04-JOURNAL.bsod.sh')
-rwxr-xr-xtest/units/TEST-04-JOURNAL.bsod.sh123
1 files changed, 123 insertions, 0 deletions
diff --git a/test/units/TEST-04-JOURNAL.bsod.sh b/test/units/TEST-04-JOURNAL.bsod.sh
new file mode 100755
index 0000000..83feb89
--- /dev/null
+++ b/test/units/TEST-04-JOURNAL.bsod.sh
@@ -0,0 +1,123 @@
+#!/usr/bin/env bash
+# SPDX-License-Identifier: LGPL-2.1-or-later
+set -eux
+set -o pipefail
+
+if systemd-detect-virt -cq; then
+ echo "This test requires a VM, skipping the test" | tee --append /skipped
+ exit 0
+fi
+
+if [[ ! -x /usr/lib/systemd/systemd-bsod ]]; then
+ echo "systemd-bsod is not installed, skipping the test" | tee --append /skipped
+ exit 0
+fi
+
+# shellcheck disable=SC2317
+at_exit() {
+ local EC=$?
+
+ if [[ $EC -ne 0 ]] && [[ -e /tmp/console.dump ]]; then
+ cat /tmp/console.dump
+ fi
+
+ if mountpoint -q /var/log/journal; then
+ # In order to preserve the journal from the just run test we need to do a little dance, as
+ # --relinquish-var is not a "true" opposite of --flush, meaning that it won't move the existing
+ # journal(s) from /var/log/ to /run/log/. To do that, let's rotate the journal first, so all
+ # important bits are in the archived journal(s)...
+ journalctl --rotate
+ # ...then instruct sd-journald to write further entries to the runtime journal...
+ journalctl --relinquish-var
+ # ...make sure there are no outstanding writes to the persistent journal that might block us from
+ # unmounting the tmpfs...
+ journalctl --sync
+ # ...move the archived journals to the runtime storage...
+ mv -v "/var/log/journal/$(</etc/machine-id)"/system@*.journal "/run/log/journal/$(</etc/machine-id)/"
+ # ...get rid of the tmpfs on /var/log/journal/...
+ umount /var/log/journal
+ # ...and finally flush everything to the "real" persistent journal, so we can collect it after the
+ # test finishes.
+ journalctl --flush
+ fi
+
+ return 0
+}
+
+vcs_dump_and_check() {
+ local expected_message="${1:?}"
+
+ # It might take a while before the systemd-bsod stuff appears on the VCS,
+ # so try it a couple of times
+ for _ in {0..9}; do
+ setterm --term linux --dump --file /tmp/console.dump
+ if grep -aq "Press any key to exit" /tmp/console.dump &&
+ grep -aq "$expected_message" /tmp/console.dump &&
+ grep -aq "The current boot has failed" /tmp/console.dump; then
+
+ return 0
+ fi
+
+ sleep .5
+ done
+
+ return 1
+}
+
+# Since systemd-bsod always fetches only the first emergency message from the
+# current boot, let's temporarily overmount /var/log/journal with a tmpfs,
+# as we're going to wipe it multiple times, but we need to keep the original
+# journal intact for the other tests to work correctly.
+trap at_exit EXIT
+mount -t tmpfs tmpfs /var/log/journal
+systemctl restart systemd-journald
+
+systemctl stop systemd-bsod
+
+# Since we just wiped the journal, there should be no emergency messages and
+# systemd-bsod should be just a no-op
+timeout 10s /usr/lib/systemd/systemd-bsod
+setterm --term linux --dump --file /tmp/console.dump
+(! grep "The current boot has failed" /tmp/console.dump)
+
+# systemd-bsod should pick up emergency messages only with UID=0, so let's check
+# that as well
+systemd-run --user --machine testuser@ --wait --pipe systemd-cat -p emerg echo "User emergency message"
+systemd-cat -p emerg echo "Root emergency message"
+journalctl --sync
+# Set $SYSTEMD_COLORS so systemd-bsod also prints out the QR code
+SYSTEMD_COLORS=256 /usr/lib/systemd/systemd-bsod &
+PID=$!
+vcs_dump_and_check "Root emergency message"
+grep -aq "Scan the QR code" /tmp/console.dump
+# TODO: check if systemd-bsod exits on a key press (didn't figure this one out yet)
+kill $PID
+timeout 10 bash -c "while kill -0 $PID; do sleep .5; done"
+
+# Wipe the journal
+journalctl --vacuum-size=1 --rotate
+(! journalctl -q -b -p emerg --grep .)
+
+# Check the systemd-bsod.service as well
+# Note: the systemd-bsod.service unit has ConditionVirtualization=no, so let's
+# temporarily override it just for the test
+mkdir /run/systemd/system/systemd-bsod.service.d
+printf '[Unit]\nConditionVirtualization=\n' >/run/systemd/system/systemd-bsod.service.d/99-override.conf
+systemctl daemon-reload
+systemctl start systemd-bsod
+systemd-cat -p emerg echo "Service emergency message"
+vcs_dump_and_check "Service emergency message"
+systemctl status systemd-bsod
+systemctl stop systemd-bsod
+
+# Wipe the journal
+journalctl --vacuum-size=1 --rotate
+(! journalctl -q -b -p emerg --grep .)
+
+# Same as above, but make sure the service responds to signals even when there are
+# no "emerg" messages, see systemd/systemd#30084
+(! systemctl is-active systemd-bsod)
+systemctl start systemd-bsod
+timeout 5s bash -xec 'until systemctl is-active systemd-bsod; do sleep .5; done'
+timeout 5s systemctl stop systemd-bsod
+timeout 5s bash -xec 'while systemctl is-active systemd-bsod; do sleep .5; done'