summaryrefslogtreecommitdiffstats
path: root/test/units/testsuite-55.sh
diff options
context:
space:
mode:
Diffstat (limited to 'test/units/testsuite-55.sh')
-rwxr-xr-xtest/units/testsuite-55.sh179
1 files changed, 179 insertions, 0 deletions
diff --git a/test/units/testsuite-55.sh b/test/units/testsuite-55.sh
new file mode 100755
index 0000000..838ba3a
--- /dev/null
+++ b/test/units/testsuite-55.sh
@@ -0,0 +1,179 @@
+#!/usr/bin/env bash
+# SPDX-License-Identifier: LGPL-2.1-or-later
+set -eux
+set -o pipefail
+
+systemd-analyze log-level debug
+
+# Ensure that the init.scope.d drop-in is applied on boot
+test "$(cat /sys/fs/cgroup/init.scope/memory.high)" != "max"
+
+# Loose checks to ensure the environment has the necessary features for systemd-oomd
+[[ -e /proc/pressure ]] || echo "no PSI" >>/skipped
+cgroup_type="$(stat -fc %T /sys/fs/cgroup/)"
+if [[ "$cgroup_type" != *"cgroup2"* ]] && [[ "$cgroup_type" != *"0x63677270"* ]]; then
+ echo "no cgroup2" >>/skipped
+fi
+if [ ! -f /usr/lib/systemd/systemd-oomd ] && [ ! -f /lib/systemd/systemd-oomd ]; then
+ echo "no oomd" >>/skipped
+fi
+
+if [[ -e /skipped ]]; then
+ exit 0
+fi
+
+rm -rf /run/systemd/system/testsuite-55-testbloat.service.d
+
+# Activate swap file if we are in a VM
+if systemd-detect-virt --vm --quiet; then
+ mkswap /swapfile
+ swapon /swapfile
+ swapon --show
+fi
+
+# Configure oomd explicitly to avoid conflicts with distro dropins
+mkdir -p /run/systemd/oomd.conf.d/
+cat >/run/systemd/oomd.conf.d/99-oomd-test.conf <<EOF
+[OOM]
+DefaultMemoryPressureDurationSec=2s
+EOF
+
+mkdir -p /run/systemd/system/-.slice.d/
+cat >/run/systemd/system/-.slice.d/99-oomd-test.conf <<EOF
+[Slice]
+ManagedOOMSwap=auto
+EOF
+
+mkdir -p /run/systemd/system/user@.service.d/
+cat >/run/systemd/system/user@.service.d/99-oomd-test.conf <<EOF
+[Service]
+ManagedOOMMemoryPressure=auto
+ManagedOOMMemoryPressureLimit=0%
+EOF
+
+mkdir -p /run/systemd/system/systemd-oomd.service.d/
+cat >/run/systemd/system/systemd-oomd.service.d/debug.conf <<EOF
+[Service]
+Environment=SYSTEMD_LOG_LEVEL=debug
+EOF
+
+systemctl daemon-reload
+
+# enable the service to ensure dbus-org.freedesktop.oom1.service exists
+# and D-Bus activation works
+systemctl enable systemd-oomd.service
+
+# if oomd is already running for some reasons, then restart it to make sure the above settings to be applied
+if systemctl is-active systemd-oomd.service; then
+ systemctl restart systemd-oomd.service
+fi
+
+systemctl start testsuite-55-testchill.service
+systemctl start testsuite-55-testbloat.service
+
+# Verify systemd-oomd is monitoring the expected units
+# Try to avoid racing the oomctl output check by checking in a loop with a timeout
+oomctl_output=$(oomctl)
+timeout="$(date -ud "1 minutes" +%s)"
+while [[ $(date -u +%s) -le $timeout ]]; do
+ if grep "/testsuite-55-workload.slice" <<< "$oomctl_output"; then
+ break
+ fi
+ oomctl_output=$(oomctl)
+ sleep 1
+done
+
+grep "/testsuite-55-workload.slice" <<< "$oomctl_output"
+grep "20.00%" <<< "$oomctl_output"
+grep "Default Memory Pressure Duration: 2s" <<< "$oomctl_output"
+
+systemctl status testsuite-55-testchill.service
+
+# systemd-oomd watches for elevated pressure for 2 seconds before acting.
+# It can take time to build up pressure so either wait 2 minutes or for the service to fail.
+timeout="$(date -ud "2 minutes" +%s)"
+while [[ $(date -u +%s) -le $timeout ]]; do
+ if ! systemctl status testsuite-55-testbloat.service; then
+ break
+ fi
+ oomctl
+ sleep 2
+done
+
+# testbloat should be killed and testchill should be fine
+if systemctl status testsuite-55-testbloat.service; then exit 42; fi
+if ! systemctl status testsuite-55-testchill.service; then exit 24; fi
+
+# Make sure we also work correctly on user units.
+
+systemctl start --machine "testuser@.host" --user testsuite-55-testchill.service
+systemctl start --machine "testuser@.host" --user testsuite-55-testbloat.service
+
+# Verify systemd-oomd is monitoring the expected units
+# Try to avoid racing the oomctl output check by checking in a loop with a timeout
+oomctl_output=$(oomctl)
+timeout="$(date -ud "1 minutes" +%s)"
+while [[ $(date -u +%s) -le $timeout ]]; do
+ if grep -E "/user.slice.*/testsuite-55-workload.slice" <<< "$oomctl_output"; then
+ break
+ fi
+ oomctl_output=$(oomctl)
+ sleep 1
+done
+
+grep -E "/user.slice.*/testsuite-55-workload.slice" <<< "$oomctl_output"
+grep "20.00%" <<< "$oomctl_output"
+grep "Default Memory Pressure Duration: 2s" <<< "$oomctl_output"
+
+systemctl --machine "testuser@.host" --user status testsuite-55-testchill.service
+
+# systemd-oomd watches for elevated pressure for 2 seconds before acting.
+# It can take time to build up pressure so either wait 2 minutes or for the service to fail.
+timeout="$(date -ud "2 minutes" +%s)"
+while [[ $(date -u +%s) -le $timeout ]]; do
+ if ! systemctl --machine "testuser@.host" --user status testsuite-55-testbloat.service; then
+ break
+ fi
+ oomctl
+ sleep 2
+done
+
+# testbloat should be killed and testchill should be fine
+if systemctl --machine "testuser@.host" --user status testsuite-55-testbloat.service; then exit 42; fi
+if ! systemctl --machine "testuser@.host" --user status testsuite-55-testchill.service; then exit 24; fi
+
+# only run this portion of the test if we can set xattrs
+if setfattr -n user.xattr_test -v 1 /sys/fs/cgroup/; then
+ sleep 120 # wait for systemd-oomd kill cool down and elevated memory pressure to come down
+
+ mkdir -p /run/systemd/system/testsuite-55-testbloat.service.d/
+ cat >/run/systemd/system/testsuite-55-testbloat.service.d/override.conf <<EOF
+[Service]
+ManagedOOMPreference=avoid
+EOF
+
+ systemctl daemon-reload
+ systemctl start testsuite-55-testchill.service
+ systemctl start testsuite-55-testmunch.service
+ systemctl start testsuite-55-testbloat.service
+
+ timeout="$(date -ud "2 minutes" +%s)"
+ while [[ "$(date -u +%s)" -le "$timeout" ]]; do
+ if ! systemctl status testsuite-55-testmunch.service; then
+ break
+ fi
+ oomctl
+ sleep 2
+ done
+
+ # testmunch should be killed since testbloat had the avoid xattr on it
+ if ! systemctl status testsuite-55-testbloat.service; then exit 25; fi
+ if systemctl status testsuite-55-testmunch.service; then exit 43; fi
+ if ! systemctl status testsuite-55-testchill.service; then exit 24; fi
+fi
+
+systemd-analyze log-level info
+
+echo OK >/testok
+
+exit 0