Files
Kir Kolyshkin 07cd18c9c9 tests/int: use assert for substring and regexp comparisons
The point of the assert helpers is that a failed test says what it
wanted and what it got, so leaving most comparisons as bare [[ ]]
defeats it.

Convert the rest of the checks on $output and $lines. Those using a glob
to look for a substring become --partial, the rest become --regexp (the
patterns are translated to extended regular expressions, and anchored
where the glob was).

The few remaining [[ ]] are not assertions: one is an if condition, and
another one is the left hand side of ||, offering an alternative to the
assert that follows it.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2026-10-02 14:47:43 -07:00

181 lines
6.4 KiB
Bash

#!/usr/bin/env bats
# Exec CPU affinity tests. For more details, see:
# - https://github.com/opencontainers/runtime-spec/pull/1253
load helpers
INITIAL_CPU_MASK="$(grep -F Cpus_allowed_list: /proc/self/status | awk '{ print $2 }')"
function setup() {
requires smp cgroups_cpuset
setup_busybox
echo "Initial CPU mask: $INITIAL_CPU_MASK" >&2
echo "---" >&2
}
function teardown() {
teardown_bundle
}
function first_cpu() {
sed 's/[-,].*//g' </sys/devices/system/cpu/online
}
# Convert list of cpus ("0,1" or "0-1") to mask as printed by nsexec.
# NOTE the range conversion is not proper, merely sufficient for tests here.
function cpus_to_mask() {
local cpus=$* mask=0
cpus=${cpus//,/-} # 1. "," --> "-".
cpus=${cpus//-/ } # 2. "-" --> " ".
for c in $cpus; do
mask=$((mask | 1 << c))
done
printf "0x%x" $mask
}
@test "runc exec [CPU affinity, only initial set from process.json]" {
first="$(first_cpu)"
second=$((first + 1)) # Hacky; might not work in all environments.
run -0 runc run -d --console-socket "$CONSOLE_SOCKET" ct1
for cpus in "$second" "$first-$second" "$first,$second" "$first"; do
proc='
{
"terminal": false,
"execCPUAffinity": {
"initial": "'$cpus'"
},
"args": [ "/bin/true" ],
"cwd": "/"
}'
mask=$(cpus_to_mask "$cpus")
echo "CPUS: $cpus, mask: $mask"
run -0 runc --debug exec --process <(echo "$proc") ct1
assert_output --regexp "nsexec.*: affinity: $mask"
done
}
@test "runc exec [CPU affinity, initial and final set from process.json]" {
first="$(first_cpu)"
second=$((first + 1)) # Hacky; might not work in all environments.
run -0 runc run -d --console-socket "$CONSOLE_SOCKET" ct1
for cpus in "$second" "$first-$second" "$first,$second" "$first"; do
proc='
{
"terminal": false,
"execCPUAffinity": {
"initial": "'$cpus'",
"final": "'$cpus'"
},
"args": [ "/bin/grep", "-F", "Cpus_allowed_list:", "/proc/self/status" ],
"cwd": "/"
}'
mask=$(cpus_to_mask "$cpus")
exp=${cpus//,/-} # "," --> "-".
echo "CPUS: $cpus, mask: $mask, final: $exp"
run -0 runc --debug exec --process <(echo "$proc") ct1
assert_output --regexp "nsexec.*: affinity: $mask"
assert_output --partial "Cpus_allowed_list: $exp" # Mind the literal tab.
done
}
@test "runc exec [CPU affinity, initial and final set from config.json]" {
initial="$(first_cpu)"
final=$((initial + 1)) # Hacky; might not work in all environments.
update_config " .process.execCPUAffinity.initial = \"$initial\"
| .process.execCPUAffinity.final = \"$final\""
run -0 runc run -d --console-socket "$CONSOLE_SOCKET" ct1
run -0 runc --debug exec ct1 grep "Cpus_allowed_list:" /proc/self/status
mask=$(cpus_to_mask "$initial")
assert_output --regexp "nsexec.*: affinity: $mask"
assert_output --partial "Cpus_allowed_list: $final" # Mind the literal tab.
}
@test "runc run [CPU affinity should reset]" {
first="$(first_cpu)"
# Running without cpuset should result in an affinity for all CPUs.
update_config '.process.args = [ "/bin/grep", "-F", "Cpus_allowed_list:", "/proc/self/status" ]'
update_config 'del(.linux.resources.cpu)'
run -0 taskset -c "$first" runc run ctr
refute_output $'Cpus_allowed_list:\t'"$first"
assert_output $'Cpus_allowed_list:\t'"$INITIAL_CPU_MASK"
}
@test "runc run [CPU affinity should reset to cgroup cpuset]" {
[ $EUID -ne 0 ] && requires rootless_cgroup
set_cgroups_path
first="$(first_cpu)"
second="$((first + 1))" # Hacky; might not work in all environments.
# Running with a cpuset should result in an affinity that matches.
update_config '.process.args = [ "/bin/grep", "-F", "Cpus_allowed_list:", "/proc/self/status" ]'
update_config '.linux.resources.cpu = {"mems": "0", "cpus": "'"$first-$second"'"}'
run -0 taskset -c "$first" runc run ctr
refute_output $'Cpus_allowed_list:\t'"$first"
# XXX: For some reason, systemd-cgroup leads to us using the all-set
# cpumask rather than the cpuset we configured?
[ -v RUNC_USE_SYSTEMD ] || [[ "$output" == $'Cpus_allowed_list:\t'"$first-$second" ]]
# Ditto for a cpuset that has no overlap with the original cpumask.
update_config '.linux.resources.cpu = {"mems": "0", "cpus": "'"$second"'"}'
run -0 taskset -c "$first" runc run ctr
refute_output $'Cpus_allowed_list:\t'"$first"
# XXX: For some reason, systemd-cgroup leads to us using the all-set
# cpumask rather than the cpuset we configured?
[ -v RUNC_USE_SYSTEMD ] || [[ "$output" == $'Cpus_allowed_list:\t'"$second" ]]
}
@test "runc exec [default CPU affinity should reset]" {
first="$(first_cpu)"
# Running without cpuset should result in an affinity for all CPUs.
update_config '.process.args = [ "/bin/sleep", "infinity" ]'
update_config 'del(.linux.resources.cpu)'
run -0 taskset -c "$first" runc run -d --console-socket "$CONSOLE_SOCKET" ctr3
run -0 taskset -c "$first" runc exec ctr3 grep -F Cpus_allowed_list: /proc/self/status
refute_output $'Cpus_allowed_list:\t'"$first"
assert_output $'Cpus_allowed_list:\t'"$INITIAL_CPU_MASK"
}
@test "runc exec [default CPU affinity should reset to cgroup cpuset]" {
[ $EUID -ne 0 ] && requires rootless_cgroup
set_cgroups_path
first="$(first_cpu)"
second="$((first + 1))" # Hacky; might not work in all environments.
# Running with a cpuset should result in an affinity that matches.
update_config '.process.args = [ "/bin/sleep", "infinity" ]'
update_config '.linux.resources.cpu = {"mems": "0", "cpus": "'"$first-$second"'"}'
run -0 taskset -c "$first" runc run -d --console-socket "$CONSOLE_SOCKET" ctr
run -0 taskset -c "$first" runc exec ctr grep -F Cpus_allowed_list: /proc/self/status
refute_output $'Cpus_allowed_list:\t'"$first"
# XXX: For some reason, systemd-cgroup leads to us using the all-set
# cpumask rather than the cpuset we configured?
[ -v RUNC_USE_SYSTEMD ] || [[ "$output" == $'Cpus_allowed_list:\t'"$first-$second" ]]
# Stop the container so we can reconfigure it.
run -0 runc delete -f ctr
# Ditto for a cpuset that has no overlap with the original cpumask.
update_config '.linux.resources.cpu = {"mems": "0", "cpus": "'"$second"'"}'
run -0 taskset -c "$first" runc run -d --console-socket "$CONSOLE_SOCKET" ctr
run -0 taskset -c "$first" runc exec ctr grep -F Cpus_allowed_list: /proc/self/status
refute_output $'Cpus_allowed_list:\t'"$first"
# XXX: For some reason, systemd-cgroup leads to us using the all-set
# cpumask rather than the cpuset we configured?
[ -v RUNC_USE_SYSTEMD ] || [[ "$output" == $'Cpus_allowed_list:\t'"$second" ]]
}