From 8cfe1c2f7e09c537c4769e797ff37dad221e2e74 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Thu, 4 Jun 2026 08:37:54 +0900 Subject: [PATCH 1/6] test: skip test cases using userdbctl userdb support is optional, hence userdbctl may not be installed. --- test/units/TEST-07-PID1.nft.sh | 14 ++++++++------ test/units/TEST-74-AUX-UTILS.sysusers.sh | 10 ++++++---- test/units/TEST-74-AUX-UTILS.userdbctl.sh | 5 +++++ 3 files changed, 19 insertions(+), 10 deletions(-) diff --git a/test/units/TEST-07-PID1.nft.sh b/test/units/TEST-07-PID1.nft.sh index dbfefc281f..3713cd6c86 100755 --- a/test/units/TEST-07-PID1.nft.sh +++ b/test/units/TEST-07-PID1.nft.sh @@ -24,12 +24,14 @@ systemd-run --unit test-nft.service --service-type=exec -p DynamicUser=yes \ -p 'NFTSet=cgroup:inet:sd_test:c user:inet:sd_test:u group:inet:sd_test:g' sleep 10000 run nft list set inet sd_test c grep -qF "test-nft.service" "$RUN_OUT" -uid=$(userdbctl user --json=short test-nft | jq .uid) -run nft list set inet sd_test u -grep -qF "$uid" "$RUN_OUT" -gid=$(userdbctl user --json=short test-nft | jq .gid) -run nft list set inet sd_test g -grep -qF "$gid" "$RUN_OUT" +if command -v userdbctl >/dev/null; then + uid=$(userdbctl user --json=short test-nft | jq .uid) + run nft list set inet sd_test u + grep -qF "$uid" "$RUN_OUT" + gid=$(userdbctl user --json=short test-nft | jq .gid) + run nft list set inet sd_test g + grep -qF "$gid" "$RUN_OUT" +fi systemctl stop test-nft.service # scope diff --git a/test/units/TEST-74-AUX-UTILS.sysusers.sh b/test/units/TEST-74-AUX-UTILS.sysusers.sh index 2a06e85bfd..6e3fcac8c5 100755 --- a/test/units/TEST-74-AUX-UTILS.sysusers.sh +++ b/test/units/TEST-74-AUX-UTILS.sysusers.sh @@ -11,11 +11,13 @@ u unlockedtestuser - "An unlocked system user" / /bin/bash u! lockedtestuser - "A locked system user" / /bin/bash EOF -userdbctl -j user unlockedtestuser -userdbctl -j user lockedtestuser +if command -v userdbctl >/dev/null; then + userdbctl -j user unlockedtestuser + userdbctl -j user lockedtestuser -assert_eq "$(userdbctl -j user unlockedtestuser | jq .locked)" "null" -assert_eq "$(userdbctl -j user lockedtestuser | jq .locked)" "true" + assert_eq "$(userdbctl -j user unlockedtestuser | jq .locked)" "null" + assert_eq "$(userdbctl -j user lockedtestuser | jq .locked)" "true" +fi at_exit() { set +e diff --git a/test/units/TEST-74-AUX-UTILS.userdbctl.sh b/test/units/TEST-74-AUX-UTILS.userdbctl.sh index fdfff1a65c..dd57c6fee5 100755 --- a/test/units/TEST-74-AUX-UTILS.userdbctl.sh +++ b/test/units/TEST-74-AUX-UTILS.userdbctl.sh @@ -3,6 +3,11 @@ set -eux set -o pipefail +if ! command -v userdbctl >/dev/null; then + echo "userdbctl is not installed, skipping the test." + exit 0 +fi + # shellcheck source=test/units/util.sh . "$(dirname "$0")"/util.sh From 421429e7feb389e490d74cca6afa80cf304425df Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Thu, 4 Jun 2026 10:49:40 +0900 Subject: [PATCH 2/6] test: replace 'grep -q' with 'grep >/dev/null' After afa3eb821d4442d3b9d9e693be5322ffbdf594ad, we have introduced 'grep -q' at several places. Let's replace them. --- test/units/TEST-13-NSPAWN.pull-oci.sh | 6 +++--- test/units/TEST-50-DISSECT.dissect.sh | 2 +- test/units/TEST-50-DISSECT.mountfsd.sh | 4 ++-- test/units/TEST-58-REPART.sh | 2 +- test/units/TEST-74-AUX-UTILS.varlinkctl.sh | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/test/units/TEST-13-NSPAWN.pull-oci.sh b/test/units/TEST-13-NSPAWN.pull-oci.sh index e673b711f0..bd42aa0af5 100755 --- a/test/units/TEST-13-NSPAWN.pull-oci.sh +++ b/test/units/TEST-13-NSPAWN.pull-oci.sh @@ -126,13 +126,13 @@ systemd-mstack -U /tmp/ooo ls -alR /home/testuser/.local/state/machines/ocicombo.mstack -run0 -u testuser importctl list-images --user | grep -q ocicombo +run0 -u testuser importctl list-images --user | grep ocicombo >/dev/null ls -alR /home/testuser/.local/state/machines/ocicombo.mstack -run0 -u testuser systemd-nspawn -q --pipe -M ocicombo /sbin/init | grep -q luftikus +run0 -u testuser systemd-nspawn -q --pipe -M ocicombo /sbin/init | grep luftikus >/dev/null -run0 -u testuser --pipe systemd-run -q --unit=fimpel --user -p PrivateUsers=managed -p RootMStack=/home/testuser/.local/state/machines/ocicombo.mstack --pipe /sbin/init | grep -q luftikus +run0 -u testuser --pipe systemd-run -q --unit=fimpel --user -p PrivateUsers=managed -p RootMStack=/home/testuser/.local/state/machines/ocicombo.mstack --pipe /sbin/init | grep luftikus >/dev/null run0 -u testuser machinectl list-images -a --user diff --git a/test/units/TEST-50-DISSECT.dissect.sh b/test/units/TEST-50-DISSECT.dissect.sh index 65e684fa07..136444532d 100755 --- a/test/units/TEST-50-DISSECT.dissect.sh +++ b/test/units/TEST-50-DISSECT.dissect.sh @@ -411,7 +411,7 @@ ExecStart=bash -c ' \\ sleep 0.1; \\ done; \\ mount; \\ - mount | grep -F "on /tmp/img type squashfs" | grep -q -F "nosuid"; \\ + mount | grep -F "on /tmp/img type squashfs" | grep -F "nosuid" >/dev/null; \\ ' EOF systemctl start testservice-50d.service diff --git a/test/units/TEST-50-DISSECT.mountfsd.sh b/test/units/TEST-50-DISSECT.mountfsd.sh index 12a72f8257..d25743502d 100755 --- a/test/units/TEST-50-DISSECT.mountfsd.sh +++ b/test/units/TEST-50-DISSECT.mountfsd.sh @@ -175,13 +175,13 @@ EOF systemd-run -M testuser@ --user --pipe --wait \ --property RootImage="$MINIMAL_IMAGE.gpt" \ --property RootImageOptions="root:nosuid" \ - sh -c "test -e \"/dev/mapper/${MINIMAL_IMAGE_ROOTHASH}-verity\" && mount | grep -F squashfs | grep -q -F nosuid" + sh -c "test -e \"/dev/mapper/${MINIMAL_IMAGE_ROOTHASH}-verity\" && mount | grep -F squashfs | grep -F nosuid >/dev/null" systemd-run -M testuser@ --user --pipe --wait \ --property RootImage="$MINIMAL_IMAGE.raw" \ --property ExtensionImages=/tmp/app0.raw \ --property MountImages=/tmp/app0.raw:/var/tmp:nosuid \ - sh -c "test -e \"/dev/mapper/${MINIMAL_IMAGE_ROOTHASH}-verity\" && test -e \"/dev/mapper/$(/dev/null" rm -f /etc/polkit-1/rules.d/mountoptions.rules systemctl try-reload-or-restart polkit.service diff --git a/test/units/TEST-58-REPART.sh b/test/units/TEST-58-REPART.sh index 319b682298..de7bc3275b 100755 --- a/test/units/TEST-58-REPART.sh +++ b/test/units/TEST-58-REPART.sh @@ -1951,7 +1951,7 @@ EOF touch "$imgs/empty-password" # the expectation for hmac-sha256 is 'integrity: hmac(sha256)' - cryptsetup luksDump "${loop}p1" | grep -q "integrity: $(echo "$1" | sed -r 's/^hmac-(.*)$/hmac(\1)/')" + cryptsetup luksDump "${loop}p1" | grep "integrity: $(echo "$1" | sed -r 's/^hmac-(.*)$/hmac(\1)/')" >/dev/null cryptsetup open --type=luks2 --key-file="$imgs/empty-password" "${loop}p1" "$volume" dmsetup status > "$dmstatus" diff --git a/test/units/TEST-74-AUX-UTILS.varlinkctl.sh b/test/units/TEST-74-AUX-UTILS.varlinkctl.sh index ec71e2641e..0e95360000 100755 --- a/test/units/TEST-74-AUX-UTILS.varlinkctl.sh +++ b/test/units/TEST-74-AUX-UTILS.varlinkctl.sh @@ -207,7 +207,7 @@ varlinkctl call /run/systemd/io.systemd.Manager io.systemd.Manager.Reexecute '{} # Wait for the manager to finish re-exec before proceeding — the user manager # tests below use systemd-run which requires a functional PID 1. for _ in {1..10}; do - if systemctl is-system-running 2>/dev/null | grep -qE 'running|degraded'; then + if systemctl is-system-running 2>/dev/null | grep -E 'running|degraded' >/dev/null; then break fi sleep 1 From a576bc9a27a7f1b1d677718d8e2f31e3a2abd5aa Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Thu, 4 Jun 2026 13:53:47 +0900 Subject: [PATCH 3/6] TEST-13-NSPAWN: explicitly create usr/lib/systemd directory in the container image The main systemd package is not installed in the minimal image, hence the directory may not exist. --- test/units/TEST-13-NSPAWN.nspawn.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/test/units/TEST-13-NSPAWN.nspawn.sh b/test/units/TEST-13-NSPAWN.nspawn.sh index a6f5b32f62..5028270928 100755 --- a/test/units/TEST-13-NSPAWN.nspawn.sh +++ b/test/units/TEST-13-NSPAWN.nspawn.sh @@ -1586,6 +1586,7 @@ testcase_boot_param_split() { # Replace the init binary with a stub that records the argv and environment nspawn passes to it, # so we can verify that kernel-cmdline-style KEY=VALUE arguments are split between PID 1's # environment and argv the same way the kernel splits them. + mkdir -p "$root/usr/lib/systemd" cat >"$root/usr/lib/systemd/systemd" <<'EOF' #!/bin/bash set -e From a0a115835221ba9d2f485ef6d0608d9114b45675 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 5 Jun 2026 01:51:22 +0900 Subject: [PATCH 4/6] TEST-13-NSPAWN: /proc/kcore may not exist Similar to 45014d97dde3f1497ce8141f15f6a98cd46edef2. Follow-up for 83b8daa032cd0adb538cfd9467e6acf2c44aa661. --- test/units/TEST-13-NSPAWN.nspawn.sh | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/test/units/TEST-13-NSPAWN.nspawn.sh b/test/units/TEST-13-NSPAWN.nspawn.sh index 5028270928..4d38054d94 100755 --- a/test/units/TEST-13-NSPAWN.nspawn.sh +++ b/test/units/TEST-13-NSPAWN.nspawn.sh @@ -405,12 +405,18 @@ testcase_check_default_inaccessible_paths() { # Taken from src/nspawn/nspawn-mount.c:mount_all() inaccessible_paths=( "/proc/kallsyms" - "/proc/kcore" "/proc/keys" "/proc/sysrq-trigger" "/proc/timer_list" ) + # /proc/kcore may not exist on some kernels, e.g. Alpine/postmarketOS. + if [[ -e /proc/kcore ]]; then + inaccessible_paths+=( + "/proc/kcore" + ) + fi + root="$(mktemp -d /var/lib/machines/TEST-13-NSPAWN.default_inaccessible_paths.XXX)" container="$(basename "$root")" create_dummy_container "$root" From 76407b693990d0f8bf6792516f83799478f51bfb Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Thu, 4 Jun 2026 10:29:56 +0900 Subject: [PATCH 5/6] TEST-46-HOMED: postmarketos does not have homed Hence, the distro check in the test case is not necessary, at least now. --- test/units/TEST-46-HOMED.sh | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/test/units/TEST-46-HOMED.sh b/test/units/TEST-46-HOMED.sh index 0642eca280..660ccab18a 100755 --- a/test/units/TEST-46-HOMED.sh +++ b/test/units/TEST-46-HOMED.sh @@ -54,12 +54,6 @@ systemctl kill -sUSR1 systemd-homed testcase_basic() { local TMP_SKEL - . /etc/os-release - if [[ "${ID_LIKE:-}" == alpine ]] && ! systemd-detect-virt -cq; then - # luks seems to be broken on alpine/postmarketos. - return 0 - fi - TMP_SKEL=$(mktemp -d) echo hogehoge >"$TMP_SKEL"/hoge @@ -274,12 +268,6 @@ testcase_basic() { } testcase_blob() { - . /etc/os-release - if [[ "${ID_LIKE:-}" == alpine ]] && ! systemd-detect-virt -cq; then - # luks seems to be broken on alpine/postmarketos. - return 0 - fi - # blob directory tests # See docs/USER_RECORD_BLOB_DIRS.md checkblob() { From a54c100a1d1c9049297cf8ca23d5dfc135f4e0e1 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Thu, 4 Jun 2026 15:59:53 +0900 Subject: [PATCH 6/6] TEST-58-REPART: support libdevmapper built without UDEV_SYNC_SUPPORT When libdevmapper is built without UDEV_SYNC_SUPPORT (e.g. on Alpine/postmarketOS), it creates a device node under /dev/mapper/ instead of relying on udev to create a symlink. --- test/units/TEST-58-REPART.sh | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/test/units/TEST-58-REPART.sh b/test/units/TEST-58-REPART.sh index de7bc3275b..ba71fcb99d 100755 --- a/test/units/TEST-58-REPART.sh +++ b/test/units/TEST-58-REPART.sh @@ -2149,7 +2149,7 @@ testcase_block_device_replace() { local defs imgs btrfs_mntpoint_plain btrfs_mntpoint_encrypted local loop loop_btrfs_plain loop_btrfs_encrypted - local encrypted_device + local dm_btrfs_encrypted encrypted_device btrfs_mntpoint_plain="$(mktemp --directory "/tmp/test-repart.btrfs-mntpoint-plain.XXXXXXXXXX")" btrfs_mntpoint_encrypted="$(mktemp --directory "/tmp/test-repart.btrfs-mntpoint-encrypted.XXXXXXXXXX")" @@ -2216,7 +2216,13 @@ EOF "${loop}" assert_eq "$(findmnt "${btrfs_mntpoint_plain}" -o SOURCE -n)" "${loop}p1" - assert_eq "$(findmnt "${btrfs_mntpoint_encrypted}" -o SOURCE -n)" "/dev/mapper/btrfs-replace-encrypted" + dm_btrfs_encrypted="$(findmnt "${btrfs_mntpoint_encrypted}" -o SOURCE -n)" + if [[ "$dm_btrfs_encrypted" != "/dev/mapper/btrfs-replace-encrypted" ]]; then + # When libdevmapper is built without UDEV_SYNC_SUPPORT (e.g. on Alpine/postmarketOS), + # it creates a device node under /dev/mapper/ instead of relying on udev to create a symlink. + # In this case, verify that both device nodes refer to the same underlying device. + assert_eq "$(stat -c %Hr:%Lr "$dm_btrfs_encrypted")" "$(stat -c %Hr:%Lr /dev/mapper/btrfs-replace-encrypted)" + fi encrypted_device="/sys/dev/block/$(dmsetup table /dev/mapper/btrfs-replace-encrypted | cut -d" " -f7)" assert_eq "$(udevadm info --query=property --property=DEVNAME --value "${encrypted_device}")" "${loop}p2" grep -q tada "${btrfs_mntpoint_plain}/magic-plain"