]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
tests: (fallocate) test the --collapse-range option
authorChristian Goeschel Ndjomouo <cgoesc2@wgu.edu>
Fri, 24 Apr 2026 00:19:55 +0000 (20:19 -0400)
committerChristian Goeschel Ndjomouo <cgoesc2@wgu.edu>
Wed, 29 Apr 2026 11:02:40 +0000 (07:02 -0400)
Signed-off-by: Christian Goeschel Ndjomouo <cgoesc2@wgu.edu>
tests/expected/fallocate/collapse-range [new file with mode: 0644]
tests/ts/fallocate/collapse-range [new file with mode: 0755]

diff --git a/tests/expected/fallocate/collapse-range b/tests/expected/fallocate/collapse-range
new file mode 100644 (file)
index 0000000..0283fa2
--- /dev/null
@@ -0,0 +1,5 @@
+aa aa aa aa aa aa aa aa  aa aa aa aa aa aa aa aa  |................|
+*
+55 55 55 55 55 55 55 55  55 55 55 55 55 55 55 55  |UUUUUUUUUUUUUUUU|
+*
+
diff --git a/tests/ts/fallocate/collapse-range b/tests/ts/fallocate/collapse-range
new file mode 100755 (executable)
index 0000000..d548910
--- /dev/null
@@ -0,0 +1,78 @@
+#!/usr/bin/env bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# Copyright (C) 2026 Christian Goeschel Ndjomouo <cgoesc2@wgu.edu>
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="collapse-range"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_CMD_FALLOCATE"
+ts_check_test_command "$TS_CMD_FINDMNT"
+ts_check_test_command "$TS_CMD_HEXDUMP"
+ts_check_prog "stat"
+
+# The --collapse-range option is only supported by ext4 and xfs
+fstype="$("$TS_CMD_FINDMNT" -o FSTYPE --noheadings --target "$TS_OUTDIR")"
+if [[ ! "$fstype" =~ (xfs|ext4) ]]; then
+    ts_skip "unsupported file system type $fstype"
+fi
+
+TEST_FILE="${TS_OUTDIR}/${TS_TESTNAME}.data"
+# We have to properly align the different data blocks
+# to the logical filesystem block size otherwise fallocate
+# will fail with EINVAL.
+BLKSIZE="$(stat --file-system --format=%s "$TS_OUTDIR")"
+
+# The three patterns are used to create distinct data blocks of size $BLKSIZE
+# and help test whether the kernel properly deleted the right block.
+#
+# Our test file's data block patterns will look something like this:
+#
+#   bs bytes   bs bytes     bs bytes
+# |aaaaaaaa...|ffffffff...|55555555...|
+# collapse this ----^
+# 
+# to obtain this
+#   bs bytes    bs bytes  
+# |aaaaaaaa...|55555555...|
+#
+{
+    printf '%*s' "$BLKSIZE" '' | tr ' ' '\252'
+    printf '%*s' "$BLKSIZE" '' | tr ' ' '\377'
+    printf '%*s' "$BLKSIZE" '' | tr ' ' '\125'
+} >"$TEST_FILE"
+
+# After this command the block with 'ff' should be removed
+# and the '55' block should follow 'aa' at offset $BLKSIZE.
+"$TS_CMD_FALLOCATE" --collapse-range --offset "$BLKSIZE" --length "$BLKSIZE" "$TEST_FILE" >>"$TS_OUTPUT" 2>>"$TS_ERRLOG"
+
+size_after="$(stat --format=%s "$TEST_FILE")"
+
+if (( size_after != (BLKSIZE * 2) )); then
+    rm -f "$TEST_FILE"
+    ts_failed "file not properly resized (size: $size_after, block size: $BLKSIZE)"
+fi
+
+# We look at the last 64 bytes of the first data block and the first 64 bytes
+# of the third data block that was transposed after the collapse.
+# we should see a seamless transition and no other data in between.
+"$TS_CMD_HEXDUMP" --canonical --skip $(( BLKSIZE - (4 * 16))) --length $(( 8 * 16 )) "$TEST_FILE" \
+                    | sed -e 's/^[[:alnum:]]*[[:space:]]*//g' >>"$TS_OUTPUT" 2>>"$TS_ERRLOG"
+
+rm -f "$TEST_FILE"
+
+ts_finalize