@@ -15,19 +15,13 @@ notrun=()
interrupt=true
diff="diff -u"
showme=false
-have_test_arg=false
-randomize=false
-exact_order=false
export here=`pwd`
-xfile=""
-subdir_xfile=""
brief_test_summary=false
do_report=false
DUMP_OUTPUT=false
iterations=1
istop=false
loop_on_fail=0
-exclude_tests=()
# This is a global variable used to pass test failure text to reporting gunk
_err_msg=""
@@ -49,8 +43,9 @@ timestamp=${TIMESTAMP:=false}
rm -f $tmp.list $tmp.tmp $tmp.grep $here/$iam.out $tmp.report.* $tmp.arglist
-SRC_GROUPS="generic"
-export SRC_DIR="tests"
+# We need to include the test list processing first as argument parsing
+# requires test list parsing and setup.
+. ./common/test_list
usage()
{
@@ -124,153 +119,12 @@ examples:
exit 1
}
-get_sub_group_list()
-{
- local d=$1
- local grp=$2
-
- test -s "$SRC_DIR/$d/group.list" || return 1
-
- local grpl=$(sed -n < $SRC_DIR/$d/group.list \
- -e 's/#.*//' \
- -e 's/$/ /' \
- -e "s;^\($VALID_TEST_NAME\).* $grp .*;$SRC_DIR/$d/\1;p")
- echo $grpl
-}
-
-get_group_list()
-{
- local grp=$1
- local grpl=""
- local sub=$(dirname $grp)
- local fsgroup="$FSTYP"
-
- if [ -n "$sub" -a "$sub" != "." -a -d "$SRC_DIR/$sub" ]; then
- # group is given as <subdir>/<group> (e.g. xfs/quick)
- grp=$(basename $grp)
- get_sub_group_list $sub $grp
- return
- fi
-
- if [ "$FSTYP" = ext2 -o "$FSTYP" = ext3 ]; then
- fsgroup=ext4
- fi
- for d in $SRC_GROUPS $fsgroup; do
- if ! test -d "$SRC_DIR/$d" ; then
- continue
- fi
- grpl="$grpl $(get_sub_group_list $d $grp)"
- done
- echo $grpl
-}
-
-# Find all tests, excluding files that are test metadata such as group files.
-# It matches test names against $VALID_TEST_NAME defined in common/rc
-get_all_tests()
-{
- touch $tmp.list
- for d in $SRC_GROUPS $FSTYP; do
- if ! test -d "$SRC_DIR/$d" ; then
- continue
- fi
- ls $SRC_DIR/$d/* | \
- grep -v "\..*" | \
- grep "^$SRC_DIR/$d/$VALID_TEST_NAME"| \
- grep -v "group\|Makefile" >> $tmp.list 2>/dev/null
- done
-}
-
-# takes the list of tests to run in $tmp.list, and removes the tests passed to
-# the function from that list.
-trim_test_list()
-{
- local test_list="$*"
-
- rm -f $tmp.grep
- local numsed=0
- for t in $test_list
- do
- if [ $numsed -gt 100 ]; then
- grep -v -f $tmp.grep <$tmp.list >$tmp.tmp
- mv $tmp.tmp $tmp.list
- numsed=0
- rm -f $tmp.grep
- fi
- echo "^$t\$" >>$tmp.grep
- numsed=`expr $numsed + 1`
- done
- grep -v -f $tmp.grep <$tmp.list >$tmp.tmp
- mv $tmp.tmp $tmp.list
- rm -f $tmp.grep
-}
-
_timestamp()
{
local now=`date "+%T"`
echo -n " [$now]"
}
-_prepare_test_list()
-{
- unset list
- # Tests specified on the command line
- if [ -s $tmp.arglist ]; then
- cat $tmp.arglist > $tmp.list
- else
- touch $tmp.list
- fi
-
- # Specified groups to include
- # Note that the CLI processing adds a leading space to the first group
- # parameter, so we have to catch that here checking for "all"
- if ! $have_test_arg && [ "$GROUP_LIST" == " all" ]; then
- # no test numbers, do everything
- get_all_tests
- else
- for group in $GROUP_LIST; do
- list=$(get_group_list $group)
- if [ -z "$list" ]; then
- echo "Group \"$group\" is empty or not defined?"
- exit 1
- fi
-
- for t in $list; do
- grep -s "^$t\$" $tmp.list >/dev/null || \
- echo "$t" >>$tmp.list
- done
- done
- fi
-
- # Specified groups to exclude
- for xgroup in $XGROUP_LIST; do
- list=$(get_group_list $xgroup)
- if [ -z "$list" ]; then
- echo "Group \"$xgroup\" is empty or not defined?"
- continue
- fi
-
- trim_test_list $list
- done
-
- # sort the list of tests into numeric order unless we're running tests
- # in the exact order specified
- if ! $exact_order; then
- if $randomize; then
- if type shuf >& /dev/null; then
- sorter="shuf"
- else
- sorter="awk -v seed=$RANDOM -f randomize.awk"
- fi
- else
- sorter="cat"
- fi
- list=`sort -n $tmp.list | uniq | $sorter`
- else
- list=`cat $tmp.list`
- fi
- rm -f $tmp.list
-}
-
# Process command arguments first.
while [ $# -gt 0 ]; do
case "$1" in
@@ -285,48 +139,20 @@ while [ $# -gt 0 ]; do
export OVERLAY=true
;;
- -g) group=$2 ; shift ;
- GROUP_LIST="$GROUP_LIST ${group//,/ }"
- ;;
+ -g) _tl_setup_group $2 ; shift ;;
+ -e) _tl_setup_exclude_tests $2 ; shift ;;
+ -E) _tl_setup_exclude_file $2 ; shift ;;
+ -x) _tl_setup_exclude_group $2; shift ;;
+ -X) _tl_setup_exclude_subdir $2; shift ;;
+ -r) _tl_setup_randomise ;;
+ --exact-order) _tl_setup_ordered ;;
- -x) xgroup=$2 ; shift ;
- XGROUP_LIST="$XGROUP_LIST ${xgroup//,/ }"
- ;;
-
- -X) subdir_xfile=$2; shift ;
- ;;
- -e)
- xfile=$2; shift ;
- readarray -t -O "${#exclude_tests[@]}" exclude_tests < \
- <(echo "$xfile" | tr ', ' '\n\n')
- ;;
-
- -E) xfile=$2; shift ;
- if [ -f $xfile ]; then
- readarray -t -O ${#exclude_tests[@]} exclude_tests < \
- <(sed "s/#.*$//" $xfile)
- fi
- ;;
-s) RUN_SECTION="$RUN_SECTION $2"; shift ;;
-S) EXCLUDE_SECTION="$EXCLUDE_SECTION $2"; shift ;;
-l) diff="diff" ;;
-udiff) diff="$diff -u" ;;
-n) showme=true ;;
- -r)
- if $exact_order; then
- echo "Cannot specify -r and --exact-order."
- exit 1
- fi
- randomize=true
- ;;
- --exact-order)
- if $randomize; then
- echo "Cannnot specify --exact-order and -r."
- exit 1
- fi
- exact_order=true
- ;;
-i) iterations=$2; shift ;;
-I) iterations=$2; istop=true; shift ;;
-T) timestamp=true ;;
@@ -344,13 +170,13 @@ while [ $# -gt 0 ]; do
-*) usage ;;
*) # not an argument, we've got tests now.
- have_test_arg=true ;;
+ _tl_setup_cli $*
esac
# if we've found a test specification, the break out of the processing
# loop before we shift the arguments so that this is the first argument
# that we process in the test arg loop below.
- if $have_test_arg; then
+ if $_tl_have_test_args; then
break;
fi
@@ -388,51 +214,6 @@ if [ -n "$FUZZ_REWRITE_DURATION" ]; then
fi
fi
-if [ -n "$subdir_xfile" ]; then
- for d in $SRC_GROUPS $FSTYP; do
- [ -f $SRC_DIR/$d/$subdir_xfile ] || continue
- for f in `sed "s/#.*$//" $SRC_DIR/$d/$subdir_xfile`; do
- exclude_tests+=($d/$f)
- done
- done
-fi
-
-# Process tests from command line now.
-if $have_test_arg; then
- while [ $# -gt 0 ]; do
- case "$1" in
- -*) echo "Arguments before tests, please!"
- status=1
- exit $status
- ;;
- *) # Expand test pattern (e.g. xfs/???, *fs/001)
- list=$(cd $SRC_DIR; echo $1)
- for t in $list; do
- t=${t#$SRC_DIR/}
- test_dir=${t%%/*}
- test_name=${t##*/}
- group_file=$SRC_DIR/$test_dir/group.list
-
- if grep -Eq "^$test_name" $group_file; then
- # in group file ... OK
- echo $SRC_DIR/$test_dir/$test_name \
- >>$tmp.arglist
- else
- # oops
- echo "$t - unknown test, ignored"
- fi
- done
- ;;
- esac
-
- shift
- done
-elif [ -z "$GROUP_LIST" ]; then
- # default group list is the auto group. If any other group or test is
- # specified, we use that instead.
- GROUP_LIST="auto"
-fi
-
if [ `id -u` -ne 0 ]
then
echo "check: QA must be run as root"
@@ -593,21 +374,6 @@ _check_filesystems()
return $ret
}
-_expunge_test()
-{
- local TEST_ID="$1"
-
- for f in "${exclude_tests[@]}"; do
- # $f may contain traling spaces and comments
- local id_regex="^${TEST_ID}\b"
- if [[ "$f" =~ ${id_regex} ]]; then
- echo " [expunged]"
- return 0
- fi
- done
- return 1
-}
-
# retain files which would be overwritten in subsequent reruns of the same test
_stash_fail_loop_files() {
local seq_prefix="${REPORT_DIR}/${1}"
@@ -714,7 +480,7 @@ _run_seq() {
}
_detect_kmemleak
-_prepare_test_list
+_tl_prepare_test_list
fstests_start_time="$(date +"%F %T")"
if $OPTIONS_HAVE_SECTIONS; then
@@ -794,7 +560,7 @@ function run_section()
# TEST_DEV could be changed, source common/rc again with
# correct FSTYP to get FSTYP specific configs, e.g. common/xfs
. common/rc
- _prepare_test_list
+ _tl_prepare_test_list
elif [ "$OLD_TEST_FS_MOUNT_OPTS" != "$TEST_FS_MOUNT_OPTS" ]; then
_test_unmount 2> /dev/null
if ! _test_mount
@@ -859,7 +625,7 @@ function run_section()
loop_status=() # track rerun-on-failure state
local tc_status ix
- local -a _list=( $list )
+ local -a _list=( $_tl_tests )
for ((ix = 0; ix < ${#_list[*]}; !${#loop_status[*]} && ix++)); do
seq="${_list[$ix]}"
@@ -880,7 +646,7 @@ function run_section()
# the filename for the test and the name output are different.
# we don't include the tests/ directory in the name output.
- export seqnum=${seq#$SRC_DIR/}
+ export seqnum=$(_tl_strip_src_dir $seq)
group=${seqnum%%/*}
if $OPTIONS_HAVE_SECTIONS; then
REPORT_DIR="$RESULT_BASE/$section"
@@ -902,7 +668,7 @@ function run_section()
echo -n "$seqnum"
if $showme; then
- if _expunge_test $seqnum; then
+ if _tl_expunge_test $seqnum; then
tc_status="expunge"
else
echo
@@ -928,7 +694,7 @@ function run_section()
rm -f $seqres.out.bad $seqres.hints
# check if we really should run it
- if _expunge_test $seqnum; then
+ if _tl_expunge_test $seqnum; then
tc_status="expunge"
_stash_test_status "$seqnum" "$tc_status"
continue
@@ -196,7 +196,7 @@ _xunit_make_testcase_report()
echo -e "\t\t<skipped/>" >> $report
;;
"fail")
- local out_src="${SRC_DIR}/${test_name}.out"
+ local out_src="${_tl_src_dir}/${test_name}.out"
local full_file="${REPORT_DIR}/${test_name}.full"
local dmesg_file="${REPORT_DIR}/${test_name}.dmesg"
local outbad_file="${REPORT_DIR}/${test_name}.out.bad"
new file mode 100644
@@ -0,0 +1,295 @@
+##/bin/bash
+# SPDX-License-Identifier: GPL-2.0+
+# Copyright (c) 2000-2002,2006 Silicon Graphics, Inc. All Rights Reserved.
+# Copyright (c) 2024 Red Hat, Inc. All Rights Reserved.
+#
+# Test list parsing and building functions
+#
+# Note: this file must stand alone and not be dependent on any other includes,
+# most especially common/rc and common/config. This is because we have to
+# include this file before option parsing, whilst the rc/config includes need to
+# be included -after- option parsing.
+#
+# Any function or variable that is public should have a "_tl_" prefix.
+
+export _tl_src_dir="tests"
+
+_SRC_GROUPS="generic"
+_GROUP_LIST=
+_XGROUP_LIST=
+_tl_exact_order=false
+_tl_randomise=false
+_tl_have_test_args=false
+_tl_file="$tmp.test_list"
+_tl_exclude_tests=()
+_tl_tests=
+
+_tl_strip_src_dir()
+{
+ local test="$1"
+
+ echo ${test#$_tl_src_dir/}
+}
+
+get_sub_group_list()
+{
+ local d=$1
+ local grp=$2
+
+ test -s "$_tl_src_dir/$d/group.list" || return 1
+
+ local grpl=$(sed -n < $_tl_src_dir/$d/group.list \
+ -e 's/#.*//' \
+ -e 's/$/ /' \
+ -e "s;^\($VALID_TEST_NAME\).* $grp .*;$_tl_src_dir/$d/\1;p")
+ echo $grpl
+}
+
+get_group_list()
+{
+ local grp=$1
+ local grpl=""
+ local sub=$(dirname $grp)
+ local fsgroup="$FSTYP"
+
+ if [ -n "$sub" -a "$sub" != "." -a -d "$_tl_src_dir/$sub" ]; then
+ # group is given as <subdir>/<group> (e.g. xfs/quick)
+ grp=$(basename $grp)
+ get_sub_group_list $sub $grp
+ return
+ fi
+
+ if [ "$FSTYP" = ext2 -o "$FSTYP" = ext3 ]; then
+ fsgroup=ext4
+ fi
+ for d in $_SRC_GROUPS $fsgroup; do
+ if ! test -d "$_tl_src_dir/$d" ; then
+ continue
+ fi
+ grpl="$grpl $(get_sub_group_list $d $grp)"
+ done
+ echo $grpl
+}
+
+# Find all tests, excluding files that are test metadata such as group files.
+# It matches test names against $VALID_TEST_NAME defined in common/rc
+get_all_tests()
+{
+ touch $tmp.list
+ for d in $_SRC_GROUPS $FSTYP; do
+ if ! test -d "$_tl_src_dir/$d" ; then
+ continue
+ fi
+ ls $_tl_src_dir/$d/* | \
+ grep -v "\..*" | \
+ grep "^$_tl_src_dir/$d/$VALID_TEST_NAME"| \
+ grep -v "group\|Makefile" >> $tmp.list 2>/dev/null
+ done
+}
+
+# takes the list of tests to run in $tmp.list, and removes the tests passed to
+# the function from that list.
+trim_test_list()
+{
+ local test_list="$*"
+
+ rm -f $tmp.grep
+ local numsed=0
+ for t in $test_list
+ do
+ if [ $numsed -gt 100 ]; then
+ grep -v -f $tmp.grep <$tmp.list >$tmp.tmp
+ mv $tmp.tmp $tmp.list
+ numsed=0
+ rm -f $tmp.grep
+ fi
+ echo "^$t\$" >>$tmp.grep
+ numsed=`expr $numsed + 1`
+ done
+ grep -v -f $tmp.grep <$tmp.list >$tmp.tmp
+ mv $tmp.tmp $tmp.list
+ rm -f $tmp.grep
+}
+
+_tl_prepare_test_list()
+{
+ unset _tl_tests
+ # Tests specified on the command line
+ if [ -s $_tl_file ]; then
+ cat $_tl_file > $tmp.list
+ else
+ touch $tmp.list
+ fi
+
+ # Specified groups to include
+ # Note that the CLI processing adds a leading space to the first group
+ # parameter, so we have to catch that here checking for "all"
+ if ! $_tl_have_test_args && [ "$_GROUP_LIST" == " all" ]; then
+ # no test numbers, do everything
+ get_all_tests
+ else
+ for group in $_GROUP_LIST; do
+ list=$(get_group_list $group)
+ if [ -z "$list" ]; then
+ echo "Group \"$group\" is empty or not defined?"
+ exit 1
+ fi
+
+ for t in $list; do
+ grep -s "^$t\$" $tmp.list >/dev/null || \
+ echo "$t" >>$tmp.list
+ done
+ done
+ fi
+
+ # Specified groups to exclude
+ for xgroup in $_XGROUP_LIST; do
+ list=$(get_group_list $xgroup)
+ if [ -z "$list" ]; then
+ echo "Group \"$xgroup\" is empty or not defined?"
+ continue
+ fi
+
+ trim_test_list $list
+ done
+
+ # sort the list of tests into numeric order unless we're running tests
+ # in the exact order specified
+ if ! $_tl_exact_order; then
+ if $_tl_randomise; then
+ if type shuf >& /dev/null; then
+ sorter="shuf"
+ else
+ sorter="awk -v seed=$RANDOM -f randomize.awk"
+ fi
+ else
+ sorter="cat"
+ fi
+ _tl_tests=`sort -n $tmp.list | uniq | $sorter`
+ else
+ _tl_tests=`cat $tmp.list`
+ fi
+ rm -f $tmp.list
+}
+
+_tl_expunge_test()
+{
+ local TEST_ID="$1"
+
+ for f in "${_tl_exclude_tests[@]}"; do
+ # $f may contain traling spaces and comments
+ local id_regex="^${TEST_ID}\b"
+ if [[ "$f" =~ ${id_regex} ]]; then
+ echo " [expunged]"
+ return 0
+ fi
+ done
+ return 1
+}
+
+_tl_setup_exclude_tests()
+{
+ local list="$1"
+
+ readarray -t -O "${#_tl_exclude_tests[@]}" _tl_exclude_tests < \
+ <(echo "$list" | tr ', ' '\n\n')
+}
+
+_tl_setup_exclude_file()
+{
+ local xfile="$1"
+
+ if [ -f $xfile ]; then
+ readarray -t -O ${#_tl_exclude_tests[@]} _tl_exclude_tests < \
+ <(sed "s/#.*$//" $xfile)
+ fi
+}
+
+_tl_setup_exclude_subdir()
+{
+ local xfile="$1"
+ local d
+ local f
+
+ [ -z "$xfile" ] && return
+
+ for d in $_SRC_GROUPS $FSTYP; do
+ [ -f $_tl_src_dir/$d/$xfile ] || continue
+ for f in `sed "s/#.*$//" $_tl_src_dir/$d/$xfile`; do
+ _tl_exclude_tests+=($d/$f)
+ done
+ done
+}
+
+_tl_setup_exclude_group()
+{
+ local xgroup="$1"
+
+ _XGROUP_LIST="$_XGROUP_LIST ${xgroup//,/ }"
+}
+
+_tl_setup_group()
+{
+ local group="$1"
+
+ _GROUP_LIST="$_GROUP_LIST ${group//,/ }"
+}
+
+_tl_setup_randomise()
+{
+ if $_tl_exact_order; then
+ echo "Cannot specify -r and --exact-order."
+ exit 1
+ fi
+ _tl_randomise=true
+}
+
+_tl_setup_ordered()
+{
+ if $_tl_randomise; then
+ echo "Cannnot specify --exact-order and -r."
+ exit 1
+ fi
+ _tl_exact_order=true
+}
+
+_tl_setup_cli()
+{
+ while [ $# -gt 0 ]; do
+ case "$1" in
+ -*) echo "Arguments before tests, please!"
+ status=1
+ exit $status
+ ;;
+ *) # Expand test pattern (e.g. xfs/???, *fs/001)
+ local list=$(cd $_tl_src_dir; echo $1)
+ local t
+
+ for t in $list; do
+ t=${t#$_tl_src_dir/}
+ local test_dir=${t%%/*}
+ local test_name=${t##*/}
+ local group_file=$_tl_src_dir/$test_dir/group.list
+
+ if grep -Eq "^$test_name" $group_file; then
+ # in group file ... OK
+ echo $_tl_src_dir/$test_dir/$test_name \
+ >> $_tl_file
+ _tl_have_test_args=true
+ else
+ # oops
+ echo "$t - unknown test, ignored"
+ fi
+ done
+ ;;
+ esac
+
+ shift
+ done
+
+ if ! $_tl_have_test_args && [ -z "$_GROUP_LIST" ]; then
+ # default group list is the auto group. If any other group or
+ # test is specified, we use that instead.
+ _GROUP_LIST="auto"
+ fi
+}