]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
tests: add test to cover service exit status propagation
authorPeter Morrow <pemorrow@linux.microsoft.com>
Mon, 22 Nov 2021 16:21:43 +0000 (16:21 +0000)
committerPeter Morrow <pemorrow@linux.microsoft.com>
Mon, 13 Dec 2021 14:44:06 +0000 (14:44 +0000)
Various tests to cover MONITOR_METADATA setup for OnFailure= and
OnSuccess= dependencies.

test/TEST-68-PROPAGATE-EXIT-STATUS/Makefile [new symlink]
test/TEST-68-PROPAGATE-EXIT-STATUS/test.sh [new file with mode: 0755]
test/units/testsuite-68.service [new file with mode: 0644]
test/units/testsuite-68.sh [new file with mode: 0755]

diff --git a/test/TEST-68-PROPAGATE-EXIT-STATUS/Makefile b/test/TEST-68-PROPAGATE-EXIT-STATUS/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-68-PROPAGATE-EXIT-STATUS/test.sh b/test/TEST-68-PROPAGATE-EXIT-STATUS/test.sh
new file mode 100755 (executable)
index 0000000..eecd569
--- /dev/null
@@ -0,0 +1,11 @@
+#!/usr/bin/env bash
+# SPDX-License-Identifier: LGPL-2.1-or-later
+set -e
+
+TEST_DESCRIPTION="Test propagation of exit status to On{Failure,Success}= dependencies"
+TEST_NO_QEMU=1
+
+# shellcheck source=test/test-functions
+. "$TEST_BASE_DIR/test-functions"
+
+do_test "$@"
diff --git a/test/units/testsuite-68.service b/test/units/testsuite-68.service
new file mode 100644 (file)
index 0000000..2d86e1f
--- /dev/null
@@ -0,0 +1,7 @@
+# SPDX-License-Identifier: LGPL-2.1-or-later
+[Unit]
+Description=TEST-68-PROPAGATE-EXIT-STATUS
+
+[Service]
+Type=oneshot
+ExecStart=/usr/lib/systemd/tests/testdata/units/%N.sh
diff --git a/test/units/testsuite-68.sh b/test/units/testsuite-68.sh
new file mode 100755 (executable)
index 0000000..1ac244b
--- /dev/null
@@ -0,0 +1,230 @@
+#!/usr/bin/env bash
+# SPDX-License-Identifier: LGPL-2.1-or-later
+set -ex
+set -o pipefail
+
+# Wait for a service to enter a state within a timeout period, if it doesn't
+# enter the desired state within the timeout period then this function will
+# exit the test case with a non zero exit code.
+wait_on_state_or_fail () {
+    service=$1
+    expected_state=$2
+    timeout=$3
+
+    state=$(systemctl show "$service" --property=ActiveState --value)
+    while [ "$state" != "$expected_state" ]; do
+        if [ "$timeout" = "0" ]; then
+            systemd-analyze log-level info
+            exit 1
+        fi
+        timeout=$((timeout - 1))
+        sleep 1
+        state=$(systemctl show "$service" --property=ActiveState --value)
+    done
+}
+
+systemd-analyze log-level debug
+systemd-analyze log-target console
+
+# Trigger testservice-failure-exit-handler-68.service
+cat >/run/systemd/system/testservice-failure-68.service <<EOF
+[Unit]
+Description=TEST-68-PROPAGATE-EXIT-STATUS with OnFailure= trigger
+OnFailure=testservice-failure-exit-handler-68.service
+
+[Service]
+ExecStart=/bin/bash -c "exit 1"
+EOF
+
+# Another service which triggers testservice-failure-exit-handler-68.service
+cat >/run/systemd/system/testservice-failure-68-additional.service <<EOF
+[Unit]
+Description=TEST-68-PROPAGATE-EXIT-STATUS Additonal service with OnFailure= trigger
+OnFailure=testservice-failure-exit-handler-68.service
+
+[Service]
+ExecStart=/bin/bash -c "exit 1"
+EOF
+
+# Trigger testservice-success-exit-handler-68.service
+cat >/run/systemd/system/testservice-success-68.service <<EOF
+[Unit]
+Description=TEST-68-PROPAGATE-EXIT-STATUS with OnSuccess= trigger
+OnSuccess=testservice-success-exit-handler-68.service
+
+[Service]
+ExecStart=/bin/bash -c "exit 0"
+EOF
+
+# Trigger testservice-success-exit-handler-68.service
+cat >/run/systemd/system/testservice-success-68-additional.service <<EOF
+[Unit]
+Description=TEST-68-PROPAGATE-EXIT-STATUS Addition service with OnSuccess= trigger
+OnSuccess=testservice-success-exit-handler-68.service
+
+[Service]
+ExecStart=/bin/bash -c "exit 0"
+EOF
+
+# Script to check that when an OnSuccess= dependency fires, the correct
+# MONITOR* env variables are passed. This script handles the case where
+# multiple services triggered the unit that calls this script. In this
+# case we need to check the MONITOR_METADATA variable for >= 1 service
+# details since jobs may merge.
+cat >/tmp/check_on_success.sh <<EOF
+#!/usr/bin/env bash
+
+set -ex
+
+echo "MONITOR_METADATA=\$MONITOR_METADATA"
+
+IFS=';' read -ra ALL_SERVICE_MD <<< "\$MONITOR_METADATA"
+for SERVICE_MD in "\${ALL_SERVICE_MD[@]}"; do
+    IFS=',' read -ra METADATA <<< "\$SERVICE_MD"
+    IFS='=' read -ra SERVICE_RESULT <<< "\${METADATA[0]}"
+    SERVICE_RESULT=\${SERVICE_RESULT[1]}
+    IFS='=' read -ra EXIT_CODE <<< "\${METADATA[1]}"
+    EXIT_CODE=\${EXIT_CODE[1]}
+    IFS='=' read -ra EXIT_STATUS <<< "\${METADATA[2]}"
+    EXIT_STATUS=\${EXIT_STATUS[1]}
+    IFS='=' read -ra INVOCATION_ID <<< "\${METADATA[3]}"
+    INVOCATION_ID=\${INVOCATION_ID[1]}
+    IFS='=' read -ra UNIT <<< "\${METADATA[4]}"
+    UNIT=\${UNIT[1]}
+
+    if [ "\$SERVICE_RESULT" != "success" ]; then
+        echo 'SERVICE_RESULT was "\$SERVICE_RESULT", expected "success"';
+        exit 1;
+    fi
+
+    if [ "\$EXIT_CODE" != "exited" ]; then
+        echo 'EXIT_CODE was "\$EXIT_CODE", expected "exited"';
+        exit 1;
+    fi
+
+    if [ "\$EXIT_STATUS" != "0" ]; then
+        echo 'EXIT_STATUS was "\$EXIT_STATUS", expected "0"';
+        exit 1;
+    fi
+
+    if [ -z "\$INVOCATION_ID" ]; then
+        echo 'INVOCATION_ID unset';
+        exit 1;
+    fi
+
+    if [[ "\$UNIT" != "testservice-success-68.service" && "\$UNIT" != "testservice-success-68-additional.service" && "\$UNIT" != "testservice-transient-success-68.service" ]]; then
+        echo 'UNIT was "\$UNIT", expected "testservice-success-68{-additional,-transient}.service"';
+        exit 1;
+    fi
+done
+
+exit 0;
+EOF
+chmod +x /tmp/check_on_success.sh
+
+# Handle testservice-failure-exit-handler-68.service exiting with success.
+cat >/run/systemd/system/testservice-success-exit-handler-68.service <<EOF
+[Unit]
+Description=TEST-68-PROPAGATE-EXIT-STATUS handle service exiting in success
+
+[Service]
+ExecStartPre=/tmp/check_on_success.sh
+ExecStart=/tmp/check_on_success.sh
+EOF
+
+# Script to check that when an OnFailure= dependency fires, the correct
+# MONITOR* env variables are passed. This script handles the case where
+# multiple services triggered the unit that calls this script. In this
+# case we need to check the MONITOR_METADATA variable for >=1 service
+# details since jobs may merge.
+cat >/tmp/check_on_failure.sh <<EOF
+#!/usr/bin/env bash
+
+set -ex
+
+echo "MONITOR_METADATA=\$MONITOR_METADATA"
+
+IFS=';' read -ra ALL_SERVICE_MD <<< "\$MONITOR_METADATA"
+for SERVICE_MD in "\${ALL_SERVICE_MD[@]}"; do
+    IFS=',' read -ra METADATA <<< "\$SERVICE_MD"
+    IFS='=' read -ra SERVICE_RESULT <<< "\${METADATA[0]}"
+    SERVICE_RESULT=\${SERVICE_RESULT[1]}
+    IFS='=' read -ra EXIT_CODE <<< "\${METADATA[1]}"
+    EXIT_CODE=\${EXIT_CODE[1]}
+    IFS='=' read -ra EXIT_STATUS <<< "\${METADATA[2]}"
+    EXIT_STATUS=\${EXIT_STATUS[1]}
+    IFS='=' read -ra INVOCATION_ID <<< "\${METADATA[3]}"
+    INVOCATION_ID=\${INVOCATION_ID[1]}
+    IFS='=' read -ra UNIT <<< "\${METADATA[4]}"
+    UNIT=\${UNIT[1]}
+
+    if [ "\$SERVICE_RESULT" != "exit-code" ]; then
+        echo 'SERVICE_RESULT was "\$SERVICE_RESULT", expected "exit-code"';
+        exit 1;
+    fi
+
+    if [ "\$EXIT_CODE" != "exited" ]; then
+        echo 'EXIT_CODE was "\$EXIT_CODE", expected "exited"';
+        exit 1;
+    fi
+
+    if [ "\$EXIT_STATUS" != "1" ]; then
+        echo 'EXIT_STATUS was "\$EXIT_STATUS", expected "1"';
+        exit 1;
+    fi
+
+    if [ -z "\$INVOCATION_ID" ]; then
+        echo 'INVOCATION_ID unset';
+        exit 1;
+    fi
+
+    if [[ "\$UNIT" != "testservice-failure-68.service" && "\$UNIT" != "testservice-failure-68-additional.service" && "\$UNIT" != "testservice-transient-failure-68.service" ]]; then
+        echo 'UNIT was "\$UNIT", expected "testservice-failure-68{-additional,-transient}.service"';
+        exit 1;
+    fi
+done
+
+exit 0;
+EOF
+chmod +x /tmp/check_on_failure.sh
+
+
+# Handle testservice-failure-exit-handler-68.service exiting with failure.
+cat >/run/systemd/system/testservice-failure-exit-handler-68.service <<EOF
+[Unit]
+Description=TEST-68-PROPAGATE-EXIT-STATUS handle service exiting in failure
+
+[Service]
+ExecStartPre=/tmp/check_on_failure.sh
+ExecStart=/tmp/check_on_failure.sh
+EOF
+
+systemctl daemon-reload
+
+# The running of the OnFailure= and OnSuccess= jobs for all of these services
+# may result in jobs being merged.
+systemctl start testservice-failure-68.service
+wait_on_state_or_fail "testservice-failure-exit-handler-68.service" "inactive" "10"
+systemctl start testservice-failure-68-additional.service
+wait_on_state_or_fail "testservice-failure-exit-handler-68.service" "inactive" "10"
+systemctl start testservice-success-68.service
+wait_on_state_or_fail "testservice-success-exit-handler-68.service" "inactive" "10"
+systemctl start testservice-success-68-additional.service
+wait_on_state_or_fail "testservice-success-exit-handler-68.service" "inactive" "10"
+
+# Test some transient units since these exit very quickly.
+systemd-run --unit=testservice-transient-success-68 --property=OnSuccess=testservice-success-exit-handler-68.service /bin/bash -c "exit 0;"
+wait_on_state_or_fail "testservice-success-exit-handler-68.service" "inactive" "10"
+systemd-run --unit=testservice-transient-failure-68 --property=OnFailure=testservice-failure-exit-handler-68.service /bin/bash -c "exit 1;"
+wait_on_state_or_fail "testservice-failure-exit-handler-68.service" "inactive" "10"
+
+# These yield a higher chance of resulting in jobs merging.
+systemctl start testservice-failure-68.service testservice-failure-68-additional.service --no-block
+wait_on_state_or_fail "testservice-failure-exit-handler-68.service" "inactive" "10"
+systemctl start testservice-success-68.service testservice-success-68-additional.service --no-block
+wait_on_state_or_fail "testservice-success-exit-handler-68.service" "inactive" "10"
+
+systemd-analyze log-level info
+echo OK >/testok
+
+exit 0