]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
test: introduce TEST-08-INITRD 28801/head
authorFrantisek Sumsal <frantisek@sumsal.cz>
Fri, 11 Aug 2023 14:46:53 +0000 (16:46 +0200)
committerFrantisek Sumsal <frantisek@sumsal.cz>
Sat, 12 Aug 2023 08:13:56 +0000 (10:13 +0200)
And move the initrd related tests from TEST-01-BASIC there.

Additionally, this should provide coverage for recemt shutdown initrd
related issues, see:
  - https://github.com/systemd/systemd/issues/28645
  - https://github.com/systemd/systemd/pull/28648
  - https://github.com/systemd/systemd/pull/28793

test/TEST-01-BASIC/test.sh
test/TEST-08-INITRD/Makefile [new symlink]
test/TEST-08-INITRD/test.sh [new file with mode: 0755]
test/units/testsuite-01.sh
test/units/testsuite-08.service [new file with mode: 0644]
test/units/testsuite-08.sh [new file with mode: 0755]

index c729e95f1dde606f5960af56a5b236d1a9e80321..93185cf896929d438306f91a29b7f63155860e7d 100755 (executable)
@@ -17,37 +17,13 @@ KERNEL_APPEND="foo -- -z bar --- baz $KERNEL_APPEND"
 . "${TEST_BASE_DIR:?}/test-functions"
 
 test_append_files() {
-    # install tests manually so the test is functional even when -Dinstall-tests=false
-    local dst="${1:?}/usr/lib/systemd/tests/testdata/units/"
+    local workspace="${1:?}"
+    local dst
+
+    # Install tests manually so the test is functional even when -Dinstall-tests=false
+    dst="$workspace/usr/lib/systemd/tests/testdata/units/"
     mkdir -p "$dst"
     cp -v "$TEST_UNITS_DIR"/{testsuite-01,end}.service "$TEST_UNITS_DIR/testsuite.target" "$dst"
 }
 
-# Setup a one shot service in initrd that creates a dummy bind mount under /run
-# to check if the mount persists though the initrd transition. The "check" part
-# is in the respective testsuite-01.sh script.
-#
-# See: https://github.com/systemd/systemd/issues/28452
-run_qemu_hook() {
-    local extra="$WORKDIR/initrd.extra"
-
-    mkdir -m 755 "$extra"
-    mkdir -m 755 "$extra/etc" "$extra/etc/systemd" "$extra/etc/systemd/system" "$extra/etc/systemd/system/initrd.target.wants"
-
-    cat >"$extra/etc/systemd/system/initrd-run-mount.service" <<EOF
-[Unit]
-Description=Create a mount in /run that should survive the transition from initrd
-
-[Service]
-Type=oneshot
-RemainAfterExit=yes
-ExecStart=sh -xec "mkdir /run/initrd-mount-source /run/initrd-mount-target; mount -v --bind /run/initrd-mount-source /run/initrd-mount-target"
-EOF
-    ln -svrf "$extra/etc/systemd/system/initrd-run-mount.service" "$extra/etc/systemd/system/initrd.target.wants/initrd-run-mount.service"
-
-    (cd "$extra" && find . | cpio -o -H newc -R root:root > "$extra.cpio")
-
-    INITRD_EXTRA="$extra.cpio"
-}
-
 do_test "$@"
diff --git a/test/TEST-08-INITRD/Makefile b/test/TEST-08-INITRD/Makefile
new file mode 120000 (symlink)
index 0000000..e9f93b1
--- /dev/null
@@ -0,0 +1 @@
+../TEST-01-BASIC/Makefile
\ No newline at end of file
diff --git a/test/TEST-08-INITRD/test.sh b/test/TEST-08-INITRD/test.sh
new file mode 100755 (executable)
index 0000000..29fd1f7
--- /dev/null
@@ -0,0 +1,101 @@
+#!/usr/bin/env bash
+# SPDX-License-Identifier: LGPL-2.1-or-later
+set -e
+
+TEST_DESCRIPTION="Test various scenarios involving transition from/to initrd"
+TEST_NO_NSPAWN=1
+
+# shellcheck source=test/test-functions
+. "${TEST_BASE_DIR:?}/test-functions"
+
+test_append_files() {
+    local workspace="${1:?}"
+    local sd_initrd file dir
+
+    # Create a shutdown initrd
+    #
+    # This should provide coverage for shutdown initrd related issues, see:
+    #   - https://github.com/systemd/systemd/issues/28645
+    #   - https://github.com/systemd/systemd/pull/28648
+    #   - https://github.com/systemd/systemd/pull/28793
+    #
+    # This is a bit messier than I originally anticipated, as installing our own libraries
+    # is handled implicitly by install_systemd() which I don't want to use here, since
+    # I need only the systemd-shutdown binary
+    sd_initrd="$workspace/shutdown-initrd"
+    mkdir -p "$sd_initrd/etc" "$sd_initrd/usr"
+    initdir="$sd_initrd" image_install bash /usr/lib/os-release
+    ln -srf "$sd_initrd/usr/lib/os-release" "$sd_initrd/etc/initrd-release"
+    initdir="$sd_initrd" inst_binary "$workspace/usr/lib/systemd/systemd-shutdown" "/usr/lib/systemd/systemd-shutdown"
+    initdir="$sd_initrd" inst_libs "$sd_initrd/usr/lib/systemd/systemd-shutdown"
+    # We need to deal with libsystemd stuff explicitly, as we don't call install_systemd() here
+    while read -r file; do
+        initdir="$sd_initrd" inst_library "$file" "${file##"$workspace"}"
+        initdir="$sd_initrd" inst_libs "$file"
+    done < <(find "$workspace/usr/" -name "libsystemd*.so*")
+    # Call systemd-shutdown indirectly, so we can show a message that we can check for
+    # later to make sure the shutdown initrd was actually executed
+    cat >"$sd_initrd/shutdown" <<\EOF
+#!/usr/bin/bash -eu
+echo "Hello from shutdown initrd"
+exec /usr/lib/systemd/systemd-shutdown "$@"
+EOF
+    chmod +x "$sd_initrd/shutdown"
+}
+
+check_result_qemu_hook() {
+    local console_log="${TESTDIR:?}/console.log"
+
+    if [[ ! -e "$console_log" ]]; then
+        dfatal "Missing console log - this shouldn't happen"
+        return 1
+    fi
+
+    # The console log should not contain messages like:
+    # [    6.245000] systemd-shutdown[1]: Failed to move /run/initramfs to /: Invalid argument
+    # [    6.245955] systemd-shutdown[1]: Failed to switch root to "/run/initramfs": Invalid argument
+    if grep -qE "systemd-shutdown.+: Failed to move /run/initramfs" "$console_log" ||
+       grep -qE "systemd-shutdown.+: Failed to switch root" "$console_log"; then
+        derror "sd-shutdown failed to switch root in shutdown initrd"
+        return 1
+    fi
+
+    # Check if the shutdown initrd was executed at all
+    if ! grep -qE "^Hello from shutdown initrd\s*$" "$console_log"; then
+        derror "Missing 'hello' message from shutdown initrd"
+        return 1
+    fi
+
+    return 0
+}
+
+# Setup a one shot service in initrd that creates a dummy bind mount under /run
+# to check if the mount persists though the initrd transition. The "check" part
+# is in the respective testsuite-08.sh script.
+#
+# See: https://github.com/systemd/systemd/issues/28452
+run_qemu_hook() {
+    local extra="${TESTDIR:?}/initrd.extra"
+
+    mkdir -m 755 "$extra"
+    mkdir -m 755 "$extra/etc" "$extra/etc/systemd" "$extra/etc/systemd/system" "$extra/etc/systemd/system/initrd.target.wants"
+
+    cat >"$extra/etc/systemd/system/initrd-run-mount.service" <<EOF
+[Unit]
+Description=Create a mount in /run that should survive the transition from initrd
+
+[Service]
+Type=oneshot
+RemainAfterExit=yes
+ExecStart=mkdir /run/initrd-mount-source /run/initrd-mount-target
+ExecStart=mount -v --bind /run/initrd-mount-source /run/initrd-mount-target
+ExecStart=cp -v /etc/initrd-release /run/initrd-mount-target/hello-world
+EOF
+    ln -svrf "$extra/etc/systemd/system/initrd-run-mount.service" "$extra/etc/systemd/system/initrd.target.wants/initrd-run-mount.service"
+
+    (cd "$extra" && find . | cpio -o -H newc -R root:root > "$extra.cpio")
+
+    INITRD_EXTRA="$extra.cpio"
+}
+
+do_test "$@"
index a1193ce6fbf4e06e44a8e604c4baf868723a650e..780f37ee128116028248e1c7be3d6f00aa018772 100755 (executable)
@@ -19,11 +19,6 @@ if systemd-detect-virt -q --container; then
     test ! -e /run/systemd/container
     cp -afv /tmp/container /run/systemd/container
 else
-    # We should've created a mount under /run in initrd (see the other half of the test)
-    # that should've survived the transition from initrd to the real system
-    test -d /run/initrd-mount-target
-    mountpoint /run/initrd-mount-target
-
     # We bring the loopback netdev up only during a full setup, so it should
     # not get brought back up during reexec if we disable it beforehand
     [[ "$(ip -o link show lo)" =~ LOOPBACK,UP ]]
diff --git a/test/units/testsuite-08.service b/test/units/testsuite-08.service
new file mode 100644 (file)
index 0000000..2db35cf
--- /dev/null
@@ -0,0 +1,9 @@
+# SPDX-License-Identifier: LGPL-2.1-or-later
+[Unit]
+Description=TEST-08-INITRD
+After=multi-user.target
+
+[Service]
+ExecStartPre=rm -f /failed /testok
+ExecStart=/usr/lib/systemd/tests/testdata/units/%N.sh
+Type=oneshot
diff --git a/test/units/testsuite-08.sh b/test/units/testsuite-08.sh
new file mode 100755 (executable)
index 0000000..9598c8e
--- /dev/null
@@ -0,0 +1,22 @@
+#!/usr/bin/env bash
+# SPDX-License-Identifier: LGPL-2.1-or-later
+set -eux
+set -o pipefail
+
+if systemd-detect-virt -qc; then
+    echo >&2 "This test can't run in a container"
+    exit 1
+fi
+
+# We should've created a mount under /run in initrd (see the other half of the test)
+# that should've survived the transition from initrd to the real system
+test -d /run/initrd-mount-target
+mountpoint /run/initrd-mount-target
+[[ -e /run/initrd-mount-target/hello-world ]]
+
+# Copy the prepared shutdown initrd to its intended location. Check the respective
+# test.sh file for details
+mkdir -p /run/initramfs
+cp -r /shutdown-initrd/* /run/initramfs/
+
+touch /testok