]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
test: add basic memory pressure extended test for oomd
authorAnita Zhang <the.anitazha@gmail.com>
Fri, 14 Aug 2020 08:20:43 +0000 (01:20 -0700)
committerAnita Zhang <the.anitazha@gmail.com>
Fri, 23 Oct 2020 00:04:22 +0000 (17:04 -0700)
Simple test to generate a lot of pressure in one unit and assert that
systemd-oomd kills the right one.

test/TEST-56-OOMD/Makefile [new symlink]
test/TEST-56-OOMD/test.sh [new file with mode: 0755]
test/test-functions
test/units/testsuite-56-slowgrowth.sh [new file with mode: 0755]
test/units/testsuite-56.service [new file with mode: 0644]
test/units/testsuite-56.sh [new file with mode: 0755]

diff --git a/test/TEST-56-OOMD/Makefile b/test/TEST-56-OOMD/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-56-OOMD/test.sh b/test/TEST-56-OOMD/test.sh
new file mode 100755 (executable)
index 0000000..55b0d1d
--- /dev/null
@@ -0,0 +1,48 @@
+#!/usr/bin/env bash
+set -e
+TEST_DESCRIPTION="systemd-oomd Memory Pressure Test"
+
+. $TEST_BASE_DIR/test-functions
+
+check_result_nspawn() {
+    local ret=1
+    local journald_report=""
+    local pids=""
+    [[ -e $1/testok ]] && ret=0
+    if [[ -e $1/skipped ]]; then
+        echo "TEST-56-OOMD was skipped:"
+        cat $1/skipped
+        ret=0
+    fi
+    [[ -f $1/failed ]] && cp -a $1/failed $TESTDIR
+    save_journal $1/var/log/journal
+    [[ -f $TESTDIR/failed ]] && cat $TESTDIR/failed
+    echo $JOURNAL_LIST
+    test -s $TESTDIR/failed && ret=$(($ret+1))
+    [ -n "$TIMED_OUT" ] && ret=$(($ret+1))
+    check_asan_reports "$1" || ret=$(($ret+1))
+    _umount_dir $initdir
+    return $ret
+}
+
+check_result_qemu() {
+    local ret=1
+    mount_initdir
+    [[ -e $initdir/testok ]] && ret=0
+    if [[ -e $initdir/skipped ]]; then
+        echo "TEST-56-OOMD was skipped:"
+        cat $initdir/skipped
+        ret=0
+    fi
+    [[ -f $initdir/failed ]] && cp -a $initdir/failed $TESTDIR
+    save_journal $initdir/var/log/journal
+    check_asan_reports "$initdir" || ret=$(($ret+1))
+    _umount_dir $initdir
+    [[ -f $TESTDIR/failed ]] && cat $TESTDIR/failed
+    echo $JOURNAL_LIST
+    test -s $TESTDIR/failed && ret=$(($ret+1))
+    [ -n "$TIMED_OUT" ] && ret=$(($ret+1))
+    return $ret
+}
+
+do_test "$@" 56
index 9893864bcd197f0e4b031ddd51dfd0dd93123525..a2cb28c3808ee28e2a80bfcc7189e73b9647a035 100644 (file)
@@ -65,6 +65,7 @@ BASICTOOLS=(
     echo
     env
     false
+    getconf
     getent
     getfacl
     grep
diff --git a/test/units/testsuite-56-slowgrowth.sh b/test/units/testsuite-56-slowgrowth.sh
new file mode 100755 (executable)
index 0000000..ff5a747
--- /dev/null
@@ -0,0 +1,34 @@
+#!/usr/bin/env bash
+set -eu -o pipefail
+
+PAGE_SIZE=$(getconf PAGE_SIZE)
+BLOAT_ITERATION_TARGET=$(( 100 << 20 )) # 100 MB
+BLOAT_HOLDER=()
+PID="$$"
+
+function bloat {
+        local set_size=$(cat "/proc/$PID/statm" | cut -d " " -f2)
+        local mem_usage=$(( "$set_size" * "$PAGE_SIZE" ))
+        local target_mem_size=$(( "$mem_usage" + "$1" ))
+
+        BLOAT_HOLDER=()
+        while [[ "$mem_usage" -lt "$target_mem_size" ]]; do
+                echo "target $target_mem_size"
+                echo "mem usage $mem_usage"
+                BLOAT_HOLDER+=( $(printf "%0.sg" {1..1000000}) )
+                set_size=$(cat "/proc/$PID/statm" | cut -d " " -f2)
+                mem_usage=$(( "$set_size" * "$PAGE_SIZE" ))
+        done
+}
+
+function run {
+        local arr=()
+
+        while [[ true ]]; do
+                bloat "$BLOAT_ITERATION_TARGET"
+                arr+=( "$BLOAT_HOLDER" )
+                sleep 1
+        done
+}
+
+run
diff --git a/test/units/testsuite-56.service b/test/units/testsuite-56.service
new file mode 100644 (file)
index 0000000..b53b090
--- /dev/null
@@ -0,0 +1,7 @@
+[Unit]
+Description=TESTSUITE-56-OOMD
+
+[Service]
+ExecStartPre=rm -f /failed /skipped /testok
+ExecStart=/usr/lib/systemd/tests/testdata/units/%N.sh
+Type=oneshot
diff --git a/test/units/testsuite-56.sh b/test/units/testsuite-56.sh
new file mode 100755 (executable)
index 0000000..5be6658
--- /dev/null
@@ -0,0 +1,70 @@
+#!/usr/bin/env bash
+set -ex
+set -o pipefail
+
+systemd-analyze log-level debug
+systemd-analyze log-target console
+
+# Loose checks to ensure the environment has the necessary features for systemd-oomd
+[[ "$( awk '/SwapTotal/ { print $2 }' /proc/meminfo )" != "0" ]] || echo "no swap" >> /skipped
+[[ -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
+[[ -e /skipped ]] && exit 0 || true
+
+cat > /etc/systemd/system/testworkload.slice <<EOF
+[Slice]
+CPUAccounting=true
+MemoryAccounting=true
+IOAccounting=true
+TasksAccounting=true
+ManagedOOMMemoryPressure=kill
+ManagedOOMMemoryPressureLimitPercent=50%
+EOF
+
+# Create a lot of memory pressure by setting memory.high to a very small value
+cat > /etc/systemd/system/testbloat.service <<EOF
+[Service]
+MemoryHigh=2M
+Slice=testworkload.slice
+ExecStart=/usr/lib/systemd/tests/testdata/units/testsuite-56-slowgrowth.sh
+EOF
+
+# This generates no memory pressure
+cat > /etc/systemd/system/testchill.service <<EOF
+[Service]
+MemoryHigh=2M
+Slice=testworkload.slice
+ExecStart=sleep infinity
+EOF
+
+systemctl daemon-reload
+
+systemctl start testbloat.service
+systemctl start testchill.service
+
+# Verify systemd-oomd is monitoring the expected units
+oomctl | grep "/testworkload.slice"
+oomctl | grep "50%"
+
+# systemd-oomd watches for elevated pressure for 30 seconds before acting.
+# It can take time to build up pressure so either wait 5 minutes or for the service to fail.
+timeout=$(date -ud "5 minutes" +%s)
+while [[ $(date -u +%s) -le $timeout ]]; do
+    if ! systemctl status testbloat.service; then
+        break
+    fi
+    sleep 15
+done
+
+# testbloat should be killed and testchill should be fine
+if systemctl status testbloat.service; then exit 42; fi
+if ! systemctl status testchill.service; then exit 24; fi
+
+systemd-analyze log-level info
+
+echo OK > /testok
+
+exit 0