]> www.infradead.org Git - users/sagi/blktests.git/commitdiff
Simplify test groups and overhaul test running
authorOmar Sandoval <osandov@fb.com>
Thu, 11 May 2017 07:12:54 +0000 (00:12 -0700)
committerOmar Sandoval <osandov@fb.com>
Thu, 11 May 2017 18:32:08 +0000 (11:32 -0700)
This gets rid of the concept of test groups as used by xfstests and
renames categories into groups. If it turns out we want it back, we can
reintroduce test tags later.

This rework also has a few other effects:

- The config file is now entirely optional, as is TEST_DEVS
- prepare() and prepare_device() are renamed to {group_,}requires() and
  {group_,}device_requires()
- QUICK and TIMED are now test flags instead of groups
- Running test groups is now just `./check block`

Signed-off-by: Omar Sandoval <osandov@fb.com>
27 files changed:
Documentation/running-tests.md
check
common/rc
new
tests/block/001
tests/block/002
tests/block/003
tests/block/004
tests/block/005
tests/block/006
tests/block/007
tests/block/group [moved from tests/block/category with 92% similarity]
tests/loop/001
tests/loop/group [moved from tests/loop/category with 92% similarity]
tests/meta/001
tests/meta/002
tests/meta/003
tests/meta/004
tests/meta/005
tests/meta/006
tests/meta/007
tests/meta/008
tests/meta/009
tests/meta/010
tests/meta/011
tests/meta/012
tests/meta/group [moved from tests/meta/category with 92% similarity]

index c0bd9006fec36b179b068eb8ae5e760e95bac250..c5035ccca4841e5852b37a66a97c3922122a7ccd 100644 (file)
@@ -1,28 +1,21 @@
 # Running Tests
 
-The `./check` script executes tests. Without any arguments, it executes the
-default set of tests. `./check` exits with a zero exit status if all tests
-passed and non-zero otherwise.
+The `./check` script executes tests. `./check` exits with a zero exit status if
+all tests passed and non-zero otherwise.
 
 ## Test Organization
 
-Tests are split up into various categories, which are the subdirectories of the
+Tests are split up into various groups, which are the subdirectories of the
 `tests` directory. For example, `tests/loop` contains tests for loop devices,
 and `tests/block` contains generic block layer tests.
 
-Tests also belong to one or more groups. Each test category is also a group.
-Additionally, there is a group for common functionality like "discard".
-Finally, there are a couple of basic groups:
+`./check` can execute individual tests or test groups. For example,
 
-- The `auto` group is the default set of tests. These tests are expected to
-  pass reliably.
-- The `quick` group is a subset of `auto` comprising tests that complete
-  "quickly" (i.e., in ~30 seconds or less on reasonable hardware).
-- The `timed` group comprises tests that honor the configured test timeout (see
-  below)
+```sh
+./check loop block/002
+```
 
-`./check` can execute individual tests or test groups, as well as exclude tests
-or test groups. See `./check -h`.
+will run all tests in the `loop` group and the `block/002` test.
 
 ## Configuration
 
@@ -48,4 +41,4 @@ can limit the runtime of each test to a specific length (in seconds).
 TIMEOUT=30
 ```
 
-Note that only tests in the `timed` group honor the timeout.
+Note that not all tests honor this timeout.
diff --git a/check b/check
index bac32e5d9f1cd1c001bc12ff2099bf574f7a2ca1..baa31dd78fc24f555a22d6dd5c355af09e73808d 100755 (executable)
--- a/check
+++ b/check
 
 . common/rc
 
+_found_test() {
+       local test_name="$1"
+
+       unset DESCRIPTION requires device_requires test test_device
+
+       if ! . "tests/${test_name}"; then
+               return 1
+       fi
+
+       if [[ -z $DESCRIPTION ]]; then
+               _warning "${test_name} does not define DESCRIPTION"
+               return 1
+       fi
+
+       if declare -fF test >/dev/null && declare -fF test_device >/dev/null; then
+               _warning "${test_name} defines both test() and test_device()"
+               return 1
+       fi
+
+       if ! declare -fF test >/dev/null && ! declare -fF test_device >/dev/null; then
+               _warning "${test_name} does not define test() or test_device()"
+               return 1
+       fi
+
+       if declare -fF device_requires >/dev/null && ! declare -fF test_device >/dev/null; then
+               _warning "${test_name} defines device_requires() but not test_device()"
+               return 1
+       fi
+
+       printf '%s\0' "$test_name"
+}
+
+_found_group() {
+       local group="$1"
+
+       local test_path
+       while IFS= read -r -d '' test_path; do
+               _found_test "${test_path#tests/}"
+       done < <(find "tests/$group" -type f -name '[0-9][0-9][0-9]' -print0)
+}
+
+_find_tests() {
+       if [[ $# -eq 0 ]]; then
+               # No filters given, run all tests except for the meta group.
+               local group_path
+               while IFS= read -r -d '' group_path; do
+                       if [[ $group_path != tests/meta ]]; then
+                               _found_group "${group_path#tests/}"
+                       fi
+               done < <(find tests -mindepth 2 -type f -name group -printf '%h\0')
+       else
+               local filter
+               for filter in "$@"; do
+                       # A filter is bad if it:
+                       #     - Is an absolute path
+                       #     - Is a relative path containing ".."
+                       if [[ $filter =~ ^/|(^|/)\.\.(/|$) ]]; then
+                               _warning "bad filter ${filter}"
+                               continue
+                       fi
+                       # Remove leading and internal "." components.
+                       filter="${filter##+(./)}"
+                       filter="${filter//\/+(.\/)/\/}"
+                       # Remove leading "tests/"
+                       filter="${filter#tests/}"
+
+                       if [[ -d tests/$filter ]]; then
+                               _found_group "$filter"
+                       elif [[ -f tests/$filter ]]; then
+                               _found_test "$filter"
+                       else
+                               _warning "no group or test named ${filter}"
+                       fi
+               done
+       fi
+}
+
 _check_dmesg() {
        local dmesg_marker="$1"
        local seqres="${RESULTS_DIR}/${TEST_NAME}"
@@ -80,7 +157,11 @@ _output_status() {
        local test="$1"
        local status="$2"
 
-       printf '%-60s' "$test ($DESCRIPTION)"
+       if [[ -v DESCRIPTION ]]; then
+               printf '%-60s' "$test ($DESCRIPTION)"
+       else
+               printf '%-60s' "$test"
+       fi
        if [[ -z $status ]]; then
                echo
                return
@@ -107,6 +188,11 @@ _output_status() {
        echo "]"
 }
 
+_output_notrun() {
+       _output_status "$1" "not run"
+       echo "    $SKIP_REASON"
+}
+
 _output_last_test_run() {
        if [[ -v TEST_DEV ]]; then
                _output_status "$TEST_NAME => $(basename "$TEST_DEV")" ""
@@ -188,7 +274,7 @@ _call_test() {
        fi
 
        trap _cleanup EXIT
-       TMPDIR="$(mktemp --tmpdir -d "blktests.${category}.${seq}.XXX")"
+       TMPDIR="$(mktemp --tmpdir -d "blktests.${TEST_NAME//\//.}.XXX")"
        if [[ $? -ne 0 ]]; then
                return
        fi
@@ -254,90 +340,39 @@ _call_test() {
        fi
 }
 
-_should_run_test() {
-       local test
-       local group
-       local include_group
-       local exclude_group
-
-       if [[ -n ${TESTS[$TEST_NAME]} ]]; then
-               return 0
-       fi
-
-       local ret=1
-       for group in "${TEST_GROUPS[@]}"; do
-               if [[ -n ${INCLUDE_GROUPS[$group]} ]]; then
-                       ret=0
-               fi
-               if [[ -n ${EXCLUDE_GROUPS[$group]} ]]; then
-                       return 1
-               fi
-       done
-
-       return $ret
-}
-
-_output_notrun() {
-       _output_status "$1" "not run"
-       echo "    $SKIP_REASON"
-}
-
 _run_test() {
        TEST_NAME="$1"
        CHECK_DMESG=1
        DMESG_FILTER=cat
 
-       if ! . "tests/${TEST_NAME}"; then
-               return
-       fi
-
-       if [[ ! -v TEST_GROUPS ]]; then
-               _warning "${TEST_NAME} does not define TEST_GROUPS"
-               return
-       fi
-
-       if [[ -z $DESCRIPTION ]]; then
-               _warning "${TEST_NAME} does not define DESCRIPTION"
-               return
-       fi
-
-       if declare -fF test >/dev/null && declare -fF test_device >/dev/null; then
-               _warning "${TEST_NAME} defines both test() and test_device()"
-               return
-       fi
-
-       if ! declare -fF test >/dev/null && ! declare -fF test_device >/dev/null; then
-               _warning "${TEST_NAME} does not define test() or test_device()"
-               return
-       fi
-
-       if ! _should_run_test; then
-               return
-       fi
+       . "tests/${TEST_NAME}"
 
        if declare -fF test >/dev/null; then
-               if declare -fF prepare >/dev/null && ! prepare; then
+               if declare -fF requires >/dev/null && ! requires; then
                        _output_notrun "$TEST_NAME"
-                       return
+                       return 0
                fi
 
                RESULTS_DIR="results/nodev"
                _call_test test
        else
-               if declare -fF prepare >/dev/null && ! prepare; then
-                       _output_notrun "$TEST_NAME => *"
-                       return
+               if [[ ${#TEST_DEVS[@]} -eq 0 ]]; then
+                       return 0
+               fi
+
+               if declare -fF requires >/dev/null && ! requires; then
+                       _output_notrun "$TEST_NAME"
+                       return 0
                fi
 
                local ret=0
-               for TEST_DEV in "${CATEGORY_TEST_DEVS[@]}"; do
+               for TEST_DEV in "${TEST_DEVS[@]}"; do
                        TEST_DEV_SYSFS="${TEST_DEV_SYSFS_DIRS["$TEST_DEV"]}"
-                       local test_dev="$(basename "$TEST_DEV")"
-                       if declare -fF prepare_device >/dev/null && ! prepare_device; then
-                               _output_notrun "$TEST_NAME => $test_dev"
-                               continue
+                       if declare -fF device_requires >/dev/null && ! device_requires; then
+                               _output_notrun "$TEST_NAME => $(basename "$TEST_DEV")"
+                               return 0
                        fi
-                       RESULTS_DIR="results/${test_dev}"
+                       RESULTS_DIR="results/$(basename "$TEST_DEV")"
                        if ! _call_test test_device; then
                                ret=1
                        fi
@@ -346,57 +381,43 @@ _run_test() {
        fi
 }
 
-_run_category() {
-       local category="$1"
+_run_group() {
+       local tests=("$@")
 
-       # Most of this script is written defensively against whitespace in the
-       # test name, but we can't handle it in the test logs.
-       if [[ $category =~ [[:space:]] ]]; then
-               _error "category name \"${category}\" contains whitespace"
-               return
+       if [[ ${#tests} -eq 0 ]]; then
+               return 0
        fi
 
-       if ! . "tests/${category}/category"; then
-               return
-       fi
+       local group="${tests[0]%/*}"
 
-       if ! declare -fF prepare >/dev/null; then
-               _warning "${category} does not define prepare()"
-               return
-       fi
+       . "tests/${group}/group"
 
-       if ! declare -fF prepare_device >/dev/null; then
-               _warning "${category} does not define prepare_device()"
-               return
-       fi
-
-       if ! prepare; then
-               _output_notrun "$category/***"
-               return
+       if declare -fF group_requires >/dev/null && ! group_requires; then
+               _output_notrun "${group}/***"
+               return 0
        fi
 
-       declare -a CATEGORY_TEST_DEVS
-       local test_dev
-       for test_dev in "${TEST_DEVS[@]}"; do
-               if prepare_device; then
-                       CATEGORY_TEST_DEVS+=("$test_dev")
-               fi
-       done
-       if [[ ${#CATEGORY_TEST_DEVS} -eq 0 ]]; then
-               _output_notrun "$category/***"
-               return
+       if declare -fF group_device_requires >/dev/null; then
+               local i
+               for i in "${!TEST_DEVS[@]}"; do
+                       TEST_DEV="${TEST_DEVS[$i]}"
+                       if ! group_device_requires; then
+                               _output_notrun "${group}/*** => $(basename "$TEST_DEV")"
+                               unset TEST_DEVS[$i]
+                       fi
+               done
+               # Fix the array indices.
+               TEST_DEVS=("${TEST_DEVS[@]}")
+               unset TEST_DEV
        fi
 
-       unset prepare prepare_device
-
        local ret=0
-       local seq
-       while IFS= read -r -d '' seq; do
-               if ! ( _run_test "${category}/${seq}" ); then
+       local test_name
+       for test_name in "${tests[@]}"; do
+               if ! ( _run_test "$test_name" ); then
                        ret=1
                fi
-       done < <(find "tests/${category}" -mindepth 1 -maxdepth 1 -type f \
-                -name '[0-9][0-9][0-9]' -printf '%P\0' | sort -z)
+       done
        return $ret
 }
 
@@ -424,9 +445,8 @@ _find_sysfs_dir() {
 }
 
 declare -A TEST_DEV_SYSFS_DIRS
-_check_test_devs() {
+_check() {
        local test_dev
-
        for test_dev in "${TEST_DEVS[@]}"; do
                if [[ ! -e $test_dev ]]; then
                        _error "${test_dev} does not exist"
@@ -440,42 +460,36 @@ _check_test_devs() {
                fi
                TEST_DEV_SYSFS_DIRS["$test_dev"]="$sysfs_dir"
        done
-}
 
-_run_tests() {
+       local test_name group prev_group
+       local tests=()
        local ret=0
-       local category
-       while IFS= read -r -d '' category; do
-               if ! ( _run_category "${category}" ); then
-                       ret=1
+       while IFS= read -r -d '' test_name; do
+               group="${test_name%/*}"
+               if [[ $group != $prev_group ]]; then
+                       prev_group="$group"
+                       if ! ( _run_group "${tests[@]}" ); then
+                               ret=1
+                       fi
                fi
-       done < <(find tests -mindepth 1 -maxdepth 1 -type d -printf '%P\0' | sort -z)
+               tests+=("$test_name")
+       done < <(_find_tests "$@" | sort -zu)
+
+       if ! ( _run_group "${tests[@]}" ); then
+               ret=1
+       fi
+
        return $ret
 }
 
 usage () {
        USAGE_STRING="\
-usage: $0 [-g group] [-x exclude_group] [test...]
-       $0 -h
+usage: $0 [options] [group-or-test...]
 
-Test groups:
-  -g group    run tests belonging to this group; may be specified multiple
-              times
-  -x group    don't run tests belonging to this group; takes precedence over
-              -g, may be specified multiple times
+Run blktests
 
 Miscellaneous:
-  -h    display this help message and exit
-
-Examples:
-Run the default set of tests, i.e., the \"auto\" group:
-    ./check
-Run all NVMe and SCSI tests except for those that involve discard:
-    ./check -g nvme -g scsi -x discard
-Run two specific tests:
-    ./check block/001 block/002
-Run a specific test in addition to the default set of tests:
-    ./check -g auto block/003"
+  -h    display this help message and exit"
 
        case "$1" in
                out)
@@ -489,44 +503,25 @@ Run a specific test in addition to the default set of tests:
        esac
 }
 
-declare -A INCLUDE_GROUPS
-declare -A EXCLUDE_GROUPS
-declare -A TESTS
-
-while getopts "g:x:h" OPT; do
+while getopts "h" OPT; do
        case "$OPT" in
-               g)
-                       INCLUDE_GROUPS["$OPTARG"]=1
-                       ;;
-               x)
-                       EXCLUDE_GROUPS["$OPTARG"]=1
-                       ;;
                h)
-                       usage out;
+                       usage out
                        ;;
                *)
-                       usage err;
+                       usage err
                        ;;
        esac
 done
 
 shift $((OPTIND - 1))
 
-for test in "$@"; do
-       TESTS["$test"]=1
-done
-
-if [[ ${#TESTS[@]} -eq 0 && ${#INCLUDE_GROUPS[@]} -eq 0 ]]; then
-       INCLUDE_GROUPS[auto]=1
-fi
-
-if ! . config; then
-       exit 1
+if [[ -r config ]]; then
+       . config
 fi
 
 if [[ ! -v TEST_DEVS ]]; then
-       _error "\$TEST_DEVS not defined in ./config"
+       TEST_DEVS=()
 fi
 
-_check_test_devs
-_run_tests
+_check "$@"
index b9cd5ba88e28b28281190b60023965714c1f2f5d..5c47d318e544be6d04ff54e80635d38d67df1cc1 100644 (file)
--- a/common/rc
+++ b/common/rc
@@ -17,6 +17,8 @@
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
+shopt -s extglob
+
 # Include fio helpers by default.
 . common/fio
 
diff --git a/new b/new
index 93daa3825baf06ee74f68697c4a372302ca33f17..db804e58ecd184924b0ac524f4dfdb831a1a1599 100755 (executable)
--- a/new
+++ b/new
@@ -42,32 +42,32 @@ prompt_yes_no() {
        fi
 }
 
-echo "Available test categories:"
-while IFS= read -r -d '' category; do
-       if [[ $category != meta ]]; then
-               echo "    ${category}"
+echo "Available test groups:"
+while IFS= read -r -d '' group; do
+       if [[ $group != meta ]]; then
+               echo "    ${group}"
        fi
 done < <(find tests -mindepth 1 -maxdepth 1 -type d -printf '%P\0')
 
-read -r -p "Category for new test (pick one of the above or create a new one): " category
+read -r -p "Category for new test (pick one of the above or create a new one): " group
 
-if [[ -z $category ]]; then
+if [[ -z $group ]]; then
        exit 1
 fi
 
-if [[ $category =~ [[:space:]] ]]; then
-       _error "category name must not contain whitespace"
+if [[ $group =~ [[:space:]/] ]]; then
+       _error 'group name must not contain whitespace or "/"'
 fi
 
-if [[ ! -e tests/${category} ]]; then
+if [[ ! -e tests/${group} ]]; then
        if ! prompt_yes_no "Category does not exist; create it?"; then
                exit 1
        fi
-       mkdir -p "tests/${category}"
-       cat << EOF > "tests/${category}/category"
+       mkdir -p "tests/${group}"
+       cat << EOF > "tests/${group}/group"
 #!/bin/bash
 #
-# TODO: provide a brief description of the category here.
+# TODO: provide a brief description of the group here.
 #
 # Copyright (C) $(date +%Y) TODO YOUR NAME HERE
 #
@@ -84,42 +84,46 @@ if [[ ! -e tests/${category} ]]; then
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
-# TODO: source any more common helpers needed for this category script.
-# Anything sourced here will also be available in the test scripts.
-# Additionally, any functions defined here (except for prepare() and
-# prepare_device()) will also be available in the test scripts.
-. common/rc
+# TODO: source any common helpers needed for this group. Anything sourced here
+# will also be available in the test scripts. Additionally, any functions
+# defined here will also be available in the test scripts. Note that common/rc
+# and common/fio are automatically sourced for all tests.
+# . common/foo
 
-# TODO: prepare() should check whether tests in this category can be run. If
-# so, it should return 0. Otherwise, it should return non-zero and set the
-# \$SKIP_REASON variable. Usually, prepare() just needs to check that any
-# necessary programs and kernel features are available using the _have_foo
-# helpers. If prepare() returns non-zero, all tests in this category will be
-# skipped.
-prepare() {
+# TODO: if this test group has any extra requirements, it should define a
+# group_requires() function. If tests in this group can be run,
+# group_requires() should return 0. Otherwise, it should return non-zero and
+# set the \$SKIP_REASON variable.
+#
+# Usually, group_requires() just needs to check that any necessary programs and
+# kernel features are available using the _have_foo helpers. If
+# group_requires() returns non-zero, all tests in this group will be skipped.
+group_requires() {
        _have_root
 }
 
-# TODO: prepare_device() should check whether tests in this category can be run
-# on the given test device. \$TEST_DEV is the full path of the block device
-# (e.g., /dev/nvme0n1 or /dev/sda1), and \$TEST_DEV_SYSFS is the sysfs path of
-# the disk (not the partition, e.g., /sys/block/nvme0n1 or /sys/block/sda). If
-# tests in this category can be run on the test device, it should return zero.
-# Otherwise, it should return non-zero and set the \$SKIP_REASON variable.
-# Usually, prepare_device() just needs to check that the test device is the
-# right type of hardware or supports any necessary features using the
-# _test_dev_foo helpers. Tests in this category will only be run on devices for
-# which prepare_device() returns zero.
-prepare_device() {
-       return 0
-}
+# TODO: if this test group has extra requirements for what devices it can be
+# run on, it should define a group_device_requires() function. If tests in this
+# group can be run on the test device, it should return zero. Otherwise, it
+# should return non-zero and set the \$SKIP_REASON variable. \$TEST_DEV is the
+# full path of the block device (e.g., /dev/nvme0n1 or /dev/sda1), and
+# \$TEST_DEV_SYSFS is the sysfs path of the disk (not the partition, e.g.,
+# /sys/block/nvme0n1 or /sys/block/sda).
+#
+# Usually, group_device_requires() just needs to check that the test device is
+# the right type of hardware or supports any necessary features using the
+# _test_dev_foo helpers. If group_device_requires() returns non-zero, all tests
+# in this group will be skipped on that device.
+# group_device_requires() {
+#      _test_dev_is_foo && _test_dev_supports_bar
+# }
 EOF
-       echo "Created tests/${category}/category"
+       echo "Created tests/${group}/group"
 fi
 
 for ((i = 1; ; i++)); do
        seq="$(printf "%03d" $i)"
-       test_name="${category}/${seq}"
+       test_name="${group}/${seq}"
        if [[ ! -e tests/${test_name} ]]; then
                break
        fi
@@ -155,42 +159,48 @@ cat << EOF > "tests/${test_name}"
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
-# TODO: if this test shouldn't be run by default, remove the "auto" group. If
-# this test runs quickly, add it to the "quick" group. If this test honors the
-# configured \$TIMEOUT, add it to the "timed" group.
-# Add any other groups describing what functionality this tests (e.g.,
-# "discard" or "hotplug"). Feel free to create new groups if it makes sense.
-TEST_GROUPS=($category auto)
 # TODO: fill in a very brief description of what this test does. The
 # description should complete the sentence "This test will...". For example,
 # "run a mixed read/write workload" would be a good description.
 DESCRIPTION=""
 
+# TODO: if this test completes quickly (i.e., in ~30 seconds or less on
+# reasonable hardware), uncomment the line below.
+# QUICK=1
+
+# TODO: if this test honors the configured \$TIMEOUT, uncomment the line below.
+# TIMED=1
+
 # TODO: dmesg is checked after each test run by default. You can suppress this
 # by defining:
 # CHECK_DMESG=0
 # Alternatively, you can filter out any unimportant messages in dmesg like so:
 # DMESG_FILTER="grep -v sysfs"
 
-# TODO: if this test has any extra requirements, it should define a prepare()
-# function. If the test can be run, prepare() should return 0. Otherwise, it
-# should return non-zero and set the \$SKIP_REASON variable. Usually, prepare()
-# just needs to check that any necessary programs and kernel features are
-# available using the _have_foo helpers. If prepare() returns non-zero, the
-# test is skipped.
-# prepare() {
+# TODO: if this test has any extra requirements, it should define a requires()
+# function. If the test can be run, requires() should return 0. Otherwise, it
+# should return non-zero and set the \$SKIP_REASON variable. Usually,
+# requires() just needs to check that any necessary programs and kernel
+# features are available using the _have_foo helpers. If requires() returns
+# non-zero, the test is skipped.
+# requires() {
 #      _have_foo
 # }
 
 # TODO: if this test has extra requirements for what devices it can be run on,
-# it should define a prepare_device() function. If the test can be run on
-# \$TEST_DEV, then prepare_device() should return zero. Otherwise, it should
-# return non-zero and set the \$SKIP_REASON variable. Usually, prepare_device()
-# just needs to check that the test device is the right type of hardware or
-# supports any necessary features using the _test_dev_foo helpers. The test
-# will only be run on devices for which prepare_device() returns zero.
-# prepare_device() {
-#      _test_dev_foo
+# it should define a device_requires() function. If this test can be run on the
+# test device, it should return zero. Otherwise, it should return non-zero and
+# set the \$SKIP_REASON variable. \$TEST_DEV is the full path of the block
+# device (e.g., /dev/nvme0n1 or /dev/sda1), and \$TEST_DEV_SYSFS is the sysfs
+# path of the disk (not the partition, e.g., /sys/block/nvme0n1 or
+# /sys/block/sda).
+#
+# Usually, device_requires() just needs to check that the test device is the
+# right type of hardware or supports any necessary features using the
+# _test_dev_foo helpers. If device_requires() returns non-zero, the test will
+# be skipped on that device.
+# device_requires() {
+#      _test_dev_is_foo && _test_dev_supports_bar
 # }
 
 # TODO: define the test. The output of this function (stdout and stderr) will
@@ -211,6 +221,8 @@ DESCRIPTION=""
 #    - \$TEST_RUN -- an associative array of additional test data to display
 #                   after the test is run and store for comparison on future
 #                   test runs. Use like TEST_RUN[iops]="\$(measure_iops)".
+#    - \$TIMEOUT -- an optional timeout configured by the user. If possible, limit
+#                  the runtime of the entire test to this value if it is set.
 #
 # Many tests do not need a test device (usually because they set up their own
 # virtual devices, like null-blk or loop). These tests should define the test()
@@ -236,7 +248,7 @@ test() {
 #   E.g., TEST_NAME and GROUPS. Variables local to the test are lowercase
 #   with underscores.
 # - Functions defined by the testing framework, including helpers, have a leading
-#   underscore. E.g., _have_scsi_debug. Functions local to the test or category
+#   underscore. E.g., _have_scsi_debug. Functions local to the test or group
 #   should not have a leading underscore.
 # - Use the bash [[ ]] form of tests instead of [ ].
 # - Always quote variable expansions unless the variable is a number or inside of
index 66a0bc44d1f0aa2c2a7f7fa4e8a41030f4c971cc..8b60eeb96d081d242fdd5db977f0a65907af3682 100755 (executable)
 
 . common/scsi_debug
 
-TEST_GROUPS=(block auto timed hotplug)
 DESCRIPTION="stress device hotplugging"
+TIMED=1
 
-prepare() {
+requires() {
        _have_scsi_debug
 }
 
index d8f6f0c14da030274872f17655e1ac48de213ed9..310e866a0daf38196434545232b9afb2152d3764 100755 (executable)
 
 . common/scsi_debug
 
-TEST_GROUPS=(block auto quick blktrace hotplug)
 DESCRIPTION="remove a device while running blktrace"
+QUICK=1
 
-prepare() {
+requires() {
        _have_blktrace && _have_scsi_debug
 }
 
index 127a4021d1fb461b5489702b5cddb610a90d126e..87e30a36e8c202d4d94e559bb9a2765b14f80398 100755 (executable)
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
-TEST_GROUPS=(block auto timed discard)
 DESCRIPTION="run various discard sizes"
+TIMED=1
 
-prepare() {
+requires() {
        _have_fio
 }
 
-prepare_device() {
+device_requires() {
        _test_dev_can_discard
 }
 
index f79dcb9b11b51b46859ec52d5e62231f11333fa3..754d30260d63cabb700923a64bba122f636b2c55 100755 (executable)
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
-TEST_GROUPS=(block auto timed flush)
 DESCRIPTION="run lots of flushes"
+TIMED=1
 
-prepare() {
+requires() {
        _have_fio
 }
 
index 751799ea4c7f69d0503b5d52f8fbb5f00b68d992..19784fc90c5a1c43f6c1d0cfc8c2ad964d12e429 100755 (executable)
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
-TEST_GROUPS=(block auto timed sched)
 DESCRIPTION="switch schedulers while doing IO"
+TIMED=1
 
-prepare() {
+requires() {
        _have_fio
 }
 
index aae91c3e5268b7cf0a5c595b6c02940dc666fae6..86f4845f2d73e82ff653b6d8774a200c17350d6c 100755 (executable)
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
-TEST_GROUPS=(block auto timed)
 DESCRIPTION="run null-blk in blocking mode"
+TIMED=1
 
-prepare() {
+requires() {
        _have_module null_blk
 }
 
index daa861d7f5f7c397d1122042d7ec3acfe8533eff..23e63513da33af3de7655e1d151333ed5951718a 100755 (executable)
 
 . common/iopoll
 
-TEST_GROUPS=(block auto timed poll)
 DESCRIPTION="test classic and hybrid IO polling"
+TIMED=1
 
-prepare() {
+requires() {
        _have_fio_with_poll
 }
 
-prepare_device() {
+device_requires() {
        _test_dev_supports_io_poll && _test_dev_supports_io_poll_delay
 }
 
similarity index 92%
rename from tests/block/category
rename to tests/block/group
index c4f65eaf002e18f4eb71d1e73dbedf4a4ec03daa..689cafcb96b4919cb041f3beec1068d358c3d348 100644 (file)
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
-. common/rc
-
-prepare() {
+group_requires() {
        _have_root
 }
-
-prepare_device() {
-       return 0
-}
index 2404b77af9f4addddd21e795518ad4abcd6459b0..1f009bdd1439e606acf80be1110eed5c4ff04512 100755 (executable)
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
-TEST_GROUPS=(loop auto quick)
 DESCRIPTION="scan loop device partitions"
+QUICK=1
 
-prepare() {
+requires() {
        _have_program parted
 }
 
similarity index 92%
rename from tests/loop/category
rename to tests/loop/group
index 0e779daa4c7955e758e6c677d1b73f5e9b8c8e5d..5d0a4e5a78767cf5109b8554025312574a5b7983 100644 (file)
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
-. common/rc
-
-prepare() {
+group_requires() {
        _have_root && _have_loop
 }
-
-prepare_device() {
-       return 0
-}
index 8e45ea7d4eb8ae5663a8d43e46756a158c796aab..454fb22554a37628cd97e533a39124d97ce2f002 100755 (executable)
@@ -17,7 +17,6 @@
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
-TEST_GROUPS=(meta)
 DESCRIPTION="do nothing"
 
 test() {
index 440f0964252d00e405de7491e124332a3fd8ab79..5a2cd53f2318849df888b6a992b4c52f309d755b 100755 (executable)
@@ -17,7 +17,6 @@
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
-TEST_GROUPS=(meta)
 DESCRIPTION="do nothing"
 
 test_device() {
index 15e4334551ea9d6893d081613bd68530a93739db..eb79bca15ffbcbdda10d2201bfbb2c0f0c737b02 100755 (executable)
@@ -17,7 +17,6 @@
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
-TEST_GROUPS=(meta)
 DESCRIPTION="exit with non-zero status"
 
 test() {
index bd3faad964de0c43018d5bbb87c186e317fc065b..bafe6c5e8da877a18f93a32172d0d01fa2e4ea7f 100755 (executable)
@@ -17,7 +17,6 @@
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
-TEST_GROUPS=(meta)
 DESCRIPTION="exit with non-zero status"
 
 test_device() {
index 0b0108edfb0afe834730ef976f7f5e5f70c6dcd4..c9909c64c0220fda52d7916d8b1d35f9565e0ed9 100755 (executable)
@@ -17,7 +17,6 @@
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
-TEST_GROUPS=(meta)
 DESCRIPTION="produce bad output"
 
 test() {
index 1a5958245d961e53cfac26d864240db35f207ca8..9d28bdce01d8755f92301d2d2045f4b53d17e239 100755 (executable)
@@ -17,7 +17,6 @@
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
-TEST_GROUPS=(meta)
 DESCRIPTION="produce lots of bad output"
 
 test() {
index cd6bb714bfde13aa4876a16603581ad0fca7697c..2516796a333d36e21527c50453ed3e332e73912e 100755 (executable)
@@ -1,6 +1,6 @@
 #!/bin/bash
 #
-# Test prepare().
+# Test requires().
 #
 # Copyright (C) 2017 Omar Sandoval
 #
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
-TEST_GROUPS=(meta)
-DESCRIPTION="skip in prepare()"
+DESCRIPTION="skip in requires()"
 
-prepare() {
+requires() {
        SKIP_REASON="(╯°□°)╯︵ ┻━┻"
        return 1
 }
index 8ba605eb5c0b6064d64e66baaabeae44124085bb..5d24669b290e9ef283d5ca63ff006771cf6f8d6d 100755 (executable)
@@ -1,6 +1,6 @@
 #!/bin/bash
 #
-# Test prepare_device().
+# Test device_requires().
 #
 # Copyright (C) 2017 Omar Sandoval
 #
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
-TEST_GROUPS=(meta)
-DESCRIPTION="skip in prepare_device()"
+DESCRIPTION="skip in device_requires()"
 
-prepare_device() {
+device_requires() {
        SKIP_REASON="(╯°□°)╯︵ $TEST_DEV ┻━┻"
        return 1
 }
index 15d3d16f3282e73af7bc64f9c8df80f21aa264fc..abeb56e6ad4f63498a69b1579a29ffcb11bf0250 100755 (executable)
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
-TEST_GROUPS=(meta)
 DESCRIPTION="check dmesg"
 
-prepare() {
+requires() {
        _have_writeable_kmsg
 }
 
index 557c4f9cf8e12a5dbaebf3ed52539b056ad559da..c179dad3d7c71632e4937c3109c24a3a7646e3f2 100755 (executable)
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
-TEST_GROUPS=(meta)
 DESCRIPTION="disable check dmesg"
 CHECK_DMESG=0
 
-prepare() {
+requires() {
        _have_writeable_kmsg
 }
 
index db22bea14b7d2ff87a46d8af7900745f7757cda5..010ba4b142b822ab3cd235ea0426f84f449503b5 100755 (executable)
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
-TEST_GROUPS=(meta)
 DESCRIPTION="filter dmesg"
 DMESG_FILTER="grep -v BUG"
 
-prepare() {
+requires() {
        _have_writeable_kmsg
 }
 
index fa14f1b883bde430c25e2696eea67af6f60d4695..a8a27eba7b38ff5b0fbb07af2bb4d991e9a2e3e0 100755 (executable)
@@ -17,7 +17,6 @@
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
-TEST_GROUPS=(meta)
 DESCRIPTION="record pid"
 
 test() {
similarity index 92%
rename from tests/meta/category
rename to tests/meta/group
index d273ed1be2c0852f83eeff0e05a6e09ebe78c5dc..4281ea175a783fb98c8c322ff5a0c786ada673a9 100644 (file)
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
-. common/rc
-
-prepare() {
-       if [[ -v META_PREPARE_SHOULD_FAIL ]]; then
-               SKIP_REASON="META_PREPARE_SHOULD_FAIL"
+group_requires() {
+       if [[ -v META_REQUIRES_SKIP ]]; then
+               SKIP_REASON="META_REQUIRES_SKIP was set"
                return 1
        fi
        return 0
 }
 
-prepare_device() {
-       if [[ -v META_PREPARE_DEVICE_SHOULD_FAIL ]]; then
-               SKIP_REASON="META_PREPARE_DEVICE_SHOULD_FAIL"
+group_device_requires() {
+       if [[ -v META_DEVICE_REQUIRES_SKIP ]]; then
+               SKIP_REASON="META_DEVICE_REQUIRES_SKIP was set"
                return 1
        fi
        return 0