test: Add integration test for btrfs compression in repart

Add testcase_btrfs_compression() to verify that btrfs partitions with
Compression= and CopyFiles= directives work correctly.

The test verifies the fix for issue #39584, where mkfs.btrfs would fail
with "ERROR: --compression must be used with --rootdir" when repart
tried to create compressed btrfs filesystems.

The test creates a partition definition with Format=btrfs,
Compression=zstd, and CopyFiles=, then validates:

1. systemd-repart output shows "Rootdir from:" and "Compress:",
   confirming that the --rootdir code path is used
2. mkfs.btrfs is invoked with both --compress and --rootdir options
3. The file is successfully copied to the filesystem
4. Compression is actually applied (verified via compsize output
   containing "zstd")
This commit is contained in:
Chris Down
2025-11-06 23:36:19 +08:00
parent f30a29245d
commit 2091caddb8

View File

@@ -1685,6 +1685,76 @@ EOF
grep -q 'UUID=[0-9a-f-]* /home btrfs discard,rw,nodev,suid,exec,subvol=@home,zstd:1,noatime,lazytime 0 1' "$root"/etc/fstab
}
testcase_btrfs_compression() {
local defs imgs loop output
if ! systemd-analyze compare-versions "$(btrfs --version | head -n 1 | awk '{ print $2 }')" ge v6.13; then
echo "btrfs-progs is not installed or older than v6.13, skipping test."
return 0
fi
defs="$(mktemp -d)"
imgs="$(mktemp -d)"
# shellcheck disable=SC2064
trap "rm -rf '$defs' '$imgs'" RETURN
chmod 0755 "$defs"
echo "*** testcase for btrfs compression with CopyFiles (OFFLINE=$OFFLINE) ***"
# Must not be in tmpfs due to exclusions. It also must be large and
# compressible so that the compression check succeeds later.
src=/etc/test-source-file
dd if=/dev/zero of="$src" bs=1M count=1 2>/dev/null
tee "$defs/btrfs-compressed.conf" <<EOF
[Partition]
Type=linux-generic
Format=btrfs
Compression=zstd
CopyFiles=$src:/test-file
SizeMinBytes=100M
SizeMaxBytes=100M
EOF
systemd-repart --offline="$OFFLINE" \
--definitions="$defs" \
--empty=create \
--size=auto \
--dry-run=no \
--seed="$seed" \
"$imgs/btrfs-compressed.img" 2>&1 | tee "$imgs/repart-output.txt"
rm "$src"
output=$(cat "$imgs/repart-output.txt")
assert_in "Rootdir from:" "$output"
assert_in "Compress:" "$output"
if [[ "$OFFLINE" == "yes" ]] || systemd-detect-virt --quiet --container; then
echo "Skipping mount verification (requires loop devices)"
return 0
fi
loop="$(losetup -P --show --find "$imgs/btrfs-compressed.img")"
# shellcheck disable=SC2064
trap "umount '$imgs/mount' 2>/dev/null || true; losetup -d '$loop' 2>/dev/null || true; rm -rf '$defs' '$imgs'" RETURN
echo "Loop device: $loop"
udevadm wait --timeout=60 --settle "${loop:?}p1"
mkdir -p "$imgs/mount"
mount -t btrfs "${loop:?}p1" "$imgs/mount"
[[ -f "$imgs/mount/test-file" ]]
[[ "$(stat -c%s "$imgs/mount/test-file")" == "1048576" ]]
if command -v compsize &>/dev/null; then
output=$(compsize "$imgs/mount/test-file" 2>&1)
assert_in "zstd" "$output"
fi
umount "$imgs/mount"
losetup -d "$loop"
}
testcase_varlink_list_devices() {
REPART="$(which systemd-repart)"
varlinkctl introspect "$REPART"