From ba6eb282294dab76d1015c6f90ff3e3849256e49 Mon Sep 17 00:00:00 2001 From: Aleksa Sarai Date: Mon, 11 May 2020 15:32:01 +1000 Subject: [PATCH] tests: add integration test for paused-and-updated containers Such containers should remain paused after the update. This has historically been true, but this helps ensure that the systemd cgroup changes (freezing the container during SetUnitProperties) don't break this behaviour. Signed-off-by: Aleksa Sarai --- tests/integration/helpers.bash | 53 ++++++++++++++++++++++------------ tests/integration/pause.bats | 16 +++++++--- tests/integration/update.bats | 24 +++++++++++++++ 3 files changed, 71 insertions(+), 22 deletions(-) diff --git a/tests/integration/helpers.bash b/tests/integration/helpers.bash index 8a8d6257..edbe8fb0 100644 --- a/tests/integration/helpers.bash +++ b/tests/integration/helpers.bash @@ -126,12 +126,19 @@ function init_cgroup_paths() { if stat -f -c %t /sys/fs/cgroup | grep -qFw 63677270; then CGROUP_UNIFIED=yes # "pseudo" controllers do not appear in /sys/fs/cgroup/cgroup.controllers. - # - devices (since kernel 4.15) - # - freezer (since kernel 5.2) - # Assume these are always available, as it is hard to detect - CGROUP_SUBSYSTEMS=$(cat /sys/fs/cgroup/cgroup.controllers; echo devices freezer) + # - devices (since kernel 4.15) we must assume to be supported because + # it's quite hard to test. + # - freezer (since kernel 5.2) we can auto-detect by looking for the + # "cgroup.freeze" file a *non-root* cgroup. + CGROUP_SUBSYSTEMS=$(cat /sys/fs/cgroup/cgroup.controllers; echo devices) CGROUP_BASE_PATH=/sys/fs/cgroup CGROUP_PATH=${CGROUP_BASE_PATH}${REL_CGROUPS_PATH} + + # Find any cgroup.freeze files... + if [ -n "$(find "$CGROUP_BASE_PATH" -type f -name "cgroup.freeze" -print -quit)" ] + then + CGROUP_SUBSYSTEMS+=" freezer" + fi else CGROUP_UNIFIED=no CGROUP_SUBSYSTEMS=$(awk '!/^#/ {print $1}' /proc/cgroups) @@ -174,7 +181,7 @@ function check_systemd_value() { unitname=$1 source=$2 expected=$3 - + if [ $(id -u) = "0" ]; then current=$(systemctl show $unitname | grep $source) else @@ -200,75 +207,85 @@ function fail() { # support it, the test is skipped with a message. function requires() { for var in "$@"; do + local skip_me case $var in criu) if [ ! -e "$CRIU" ]; then - skip "test requires ${var}" + skip_me=1 fi ;; root) if [ "$ROOTLESS" -ne 0 ]; then - skip "test requires ${var}" + skip_me=1 fi ;; rootless) if [ "$ROOTLESS" -eq 0 ]; then - skip "test requires ${var}" + skip_me=1 fi ;; rootless_idmap) if [[ "$ROOTLESS_FEATURES" != *"idmap"* ]]; then - skip "test requires ${var}" + skip_me=1 fi ;; rootless_cgroup) if [[ "$ROOTLESS_FEATURES" != *"cgroup"* ]]; then - skip "test requires ${var}" + skip_me=1 fi ;; rootless_no_cgroup) if [[ "$ROOTLESS_FEATURES" == *"cgroup"* ]]; then - skip "test requires ${var}" + skip_me=1 + fi + ;; + cgroups_freezer) + init_cgroup_paths + if [[ "$CGROUP_SUBSYSTEMS" != *"freezer"* ]]; then + skip_me=1 fi ;; cgroups_kmem) init_cgroup_paths if [ ! -e "${CGROUP_MEMORY_BASE_PATH}/memory.kmem.limit_in_bytes" ]; then - skip "Test requires ${var}" + skip_me=1 fi ;; cgroups_rt) init_cgroup_paths if [ ! -e "${CGROUP_CPU_BASE_PATH}/cpu.rt_period_us" ]; then - skip "Test requires ${var}" + skip_me=1 fi ;; cgroups_v1) init_cgroup_paths if [ "$CGROUP_UNIFIED" != "no" ]; then - skip "Test requires cgroups v1" + skip_me=1 fi ;; cgroups_v2) init_cgroup_paths if [ "$CGROUP_UNIFIED" != "yes" ]; then - skip "Test requires cgroups v2 (unified)" + skip_me=1 fi ;; systemd) if [ -z "${RUNC_USE_SYSTEMD}" ]; then - skip "Test requires systemd" + skip_me=1 fi ;; no_systemd) if [ -n "${RUNC_USE_SYSTEMD}" ]; then - skip "Test requires no systemd" + skip_me=1 fi ;; *) - fail "BUG: Invalid requires ${var}." + fail "BUG: Invalid requires $var." ;; esac + if [ -n "$skip_me" ]; then + skip "test requires $var" + fi done } diff --git a/tests/integration/pause.bats b/tests/integration/pause.bats index 4e25e59a..f2576f34 100644 --- a/tests/integration/pause.bats +++ b/tests/integration/pause.bats @@ -12,8 +12,12 @@ function teardown() { } @test "runc pause and resume" { - # XXX: currently cgroups require root containers. - requires root + if [[ "$ROOTLESS" -ne 0 ]] + then + requires rootless_cgroup + set_cgroups_path "$BUSYBOX_BUNDLE" + fi + requires cgroups_freezer # run busybox detached runc run -d --console-socket $CONSOLE_SOCKET test_busybox @@ -37,8 +41,12 @@ function teardown() { } @test "runc pause and resume with nonexist container" { - # XXX: currently cgroups require root containers. - requires root + if [[ "$ROOTLESS" -ne 0 ]] + then + requires rootless_cgroup + set_cgroups_path "$BUSYBOX_BUNDLE" + fi + requires cgroups_freezer # run test_busybox detached runc run -d --console-socket $CONSOLE_SOCKET test_busybox diff --git a/tests/integration/update.bats b/tests/integration/update.bats index 3063b2f8..0bb6597e 100644 --- a/tests/integration/update.bats +++ b/tests/integration/update.bats @@ -355,3 +355,27 @@ EOF cat "$CONTAINER_OUTPUT" [ -z "$(<"$CONTAINER_OUTPUT")" ] } + +@test "update paused container" { + [[ "$ROOTLESS" -ne 0 ]] && requires rootless_cgroup + requires cgroups_freezer + + # Run the container in the background. + runc run -d --console-socket "$CONSOLE_SOCKET" test_update + [ "$status" -eq 0 ] + + # Pause the container. + runc pause test_update + [ "$status" -eq 0 ] + + # Trigger an unrelated update. + runc update --pids-limit 30 test_update + [ "$status" -eq 0 ] + + # The container should still be paused. + testcontainer test_update paused + + # Resume the container. + runc resume test_update + [ "$status" -eq 0 ] +}