]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
test: Add integration test for btrfs compression in repart 39597/head
authorChris Down <chris@chrisdown.name>
Thu, 6 Nov 2025 15:36:19 +0000 (23:36 +0800)
committerChris Down <chris@chrisdown.name>
Sun, 9 Nov 2025 13:14:22 +0000 (21:14 +0800)
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")

test/units/TEST-58-REPART.sh

index b752af3f4dcc6f7de4b9bf7b79fe055efbd4866c..251c33742555d5472674327fe7f868581148e6cb 100755 (executable)
@@ -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"