test: add basic memory pressure extended test for oomd

Simple test to generate a lot of pressure in one unit and assert that
systemd-oomd kills the right one.
This commit is contained in:
Anita Zhang 2020-08-14 01:20:43 -07:00
parent 018b6f4548
commit e4ff80404a
6 changed files with 161 additions and 0 deletions

1
test/TEST-56-OOMD/Makefile Symbolic link
View File

@ -0,0 +1 @@
../TEST-01-BASIC/Makefile

48
test/TEST-56-OOMD/test.sh Executable file
View File

@ -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

View File

@ -65,6 +65,7 @@ BASICTOOLS=(
echo
env
false
getconf
getent
getfacl
grep

View File

@ -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

View File

@ -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

70
test/units/testsuite-56.sh Executable file
View File

@ -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