--- /dev/null
+#!/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