blob: d84f01d62e302d3b6dc6496b6ad6d7db4207d2ee [file]
#!/bin/bash
# SPDX-License-Identifier: GPL-3.0+
# Copyright (C) 2017 Omar Sandoval
set -e
shopt -s extglob
_error() {
echo "$0: $*" >&2
exit 1
}
prompt_yes_no() {
if [[ $2 =~ ^[Yy] ]]; then
local default=0
local prompt="$1 [Y/n] "
else
local default=1
local prompt="$1 [y/N] "
fi
local yn
read -r -n 1 -p "${prompt}" yn
if [[ -n "${yn}" ]]; then
echo
fi
if [[ "${yn}" =~ ^[Yy] ]]; then
return 0
elif [[ "${yn}" =~ ^[Nn] ]]; then
return 1
else
return $default
fi
}
echo "Available test groups:"
find tests -mindepth 1 -maxdepth 1 -type d -not -name meta -printf ' %P\n' | sort
read -r -p "Category for new test (pick one of the above or create a new one): " group
if [[ -z $group ]]; then
exit 1
fi
if [[ $group =~ [[:space:]/] ]]; then
_error 'group name must not contain whitespace or "/"'
fi
if [[ ! -e tests/${group} ]]; then
if ! prompt_yes_no "Category does not exist; create it?"; then
exit 1
fi
mkdir -p "tests/${group}"
cat << EOF > "tests/${group}/rc"
#!/bin/bash
# SPDX-License-Identifier: GPL-3.0+
# Copyright (C) $(date +%Y) TODO YOUR NAME HERE
#
# TODO: provide a brief description of the group here.
. common/rc
# TODO: source any more common helpers needed for this group.
# . common/foo
# TODO: if this test group has any extra requirements, it should define a
# group_requires() function. If tests in this group cannot be run,
# group_requires() should add strings to the \$SKIP_REASONS array which
# describe why the group cannot be run.
#
# Usually, group_requires() just needs to check that any necessary programs and
# kernel features are available using the _have_foo helpers. If
# group_requires() adds strings to \$SKIP_REASONS, all tests in this group will
# be skipped.
group_requires() {
_have_root
}
# 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 cannot be run on the test device, it should add strings to
# \$SKIP_REASONS. \$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
# the target device is a partition device, \$TEST_DEV_PART_SYSFS is the sysfs
# path of the partition device (e.g., /sys/block/nvme0n1/nvme0n1p1 or
# /sys/block/sda/sda1). Otherwise, \$TEST_DEV_PART_SYSFS is an empty string.
#
# 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
# _require_test_dev_foo helpers. If group_device_requires() adds strings to
# \$SKIP_REASONS, all tests in this group will be skipped on that device.
# group_device_requires() {
# _require_test_dev_is_foo && _require_test_dev_supports_bar
# }
# TODO: define any helpers that are specific to this group.
EOF
echo "Created tests/${group}/rc"
fi
seq=0
for test in tests/"$group"/+([0-9]); do
if [[ -e $test ]]; then
seq=${test##tests/"${group}"/+(0)}
fi
done
test_name="${group}/$(printf "%03d" $((seq + 1)))"
cat << EOF > "tests/${test_name}"
#!/bin/bash
# SPDX-License-Identifier: GPL-3.0+
# Copyright (C) $(date +%Y) TODO YOUR NAME HERE
#
# TODO: provide a description of the test here, i.e., what it tests and how. If
# this is a regression test for a patch, reference the patch title:
#
# Regression test for patch "blk-stat: fix blk_stat_sum() if all samples are
# batched".
#
# For a commit, use the first 12 characters of the commit hash and the one-line
# commit summary:
#
# Regression test for commit efd4b81abbe1 ("blk-stat: fix blk_stat_sum() if all
# samples are batched").
. tests/${group}/rc
# TODO: source any more common helpers needed for this test.
# 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.
# This is for tests that can potentially run for a long time but where it's
# possible to limit the runtime (e.g., with the \`timeout\` command or with
# fio --runtime, which is what the _run_fio helper does). A test shouldn't be
# both QUICK and TIMED.
# TIMED=1
# TODO: dmesg is checked for oopses, warnings, etc. 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 can be run for both regular block devices and zoned block
# devices, uncomment the line below.
# CAN_BE_ZONED=1
# TODO: if this test has any extra requirements, it should define a requires()
# function. If the test cannot be run, requires() should add strings to
# \$SKIP_REASONS. Usually, requires() just needs to check that any necessary
# programs and kernel features are available using the _have_foo helpers.
# If requires() adds strings to \$SKIP_REASONS, 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 device_requires() function. If this test cannot be run on
# the test device, it should add strings to \$SKIP_REASONS. \$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 the target device is a partition
# device, \$TEST_DEV_PART_SYSFS is the sysfs path of the partition device
# (e.g., /sys/block/nvme0n1/nvme0n1p1 or /sys/block/sda/sda1). Otherwise,
# \$TEST_DEV_PART_SYSFS is an empty string.
#
# Usually, device_requires() just needs to check that the test device is the
# right type of hardware or supports any necessary features using the
# _require_test_dev_foo helpers. If device_requires() adds strings to
# \$SKIP_REASONS, the test will be skipped on that device.
# device_requires() {
# _require_test_dev_is_foo && _require_test_dev_supports_bar
# }
# TODO: if the test case can run the same test for different conditions, define
# the helper function "set_conditions". When no argument is specified, return
# the number of condition variations. Blktests repeats the test case as many
# times as the returned number. When its argument is specified, refer to it as
# the condition variation index and set up the conditions for it. Also set the
# global variable COND_DESC which is printed at the test case run and used for
# the result directory name. Blktests calls set_conditions() before each run of
# the test case incrementing the argument index from 0.
# set_conditions() {
# local index=\$1
#
# if [[ -z \$index ]]; then
# echo 2 # return number of condition variations
# return
# fi
#
# # Set test conditions based on the $index
# ...
# COND_DESC="Describe the conditions shortly"
# }
# TODO: define the test. The output of this function (stdout and stderr) will
# be compared to tests/\${TEST_NAME}.out. If it does not match, the test is
# considered a failure. If the test runs a command which has unnecessary
# output, either redirect that output to \$FULL or /dev/null, or filter out the
# unimportant parts (e.g., with grep or the _filter_foo helpers).
#
# Additionally, if the test function returns non-zero, it is considered a
# failure. You should prefer letting the test fail because of broken output
# over, say, checking the exit status of every command you run.
#
# If the test cannot be run, this function may add strings to \$SKIP_REASONS
# and return. In that case, the return value and output are ignored, and the
# test is considered skipped. This should only be done when the requirements
# can only be detected with a non-trivial amount of setup; use
# group_requires(), requires(), and/or device_requires() instead when possible.
#
# Various variables are defined for the test:
# - \$TEST_NAME -- the full name of the test.
# - \$TMPDIR -- a temporary directory deleted after the test is run.
# - \$SRCDIR -- absolute path of the src/ subdirectory
# - \$FULL -- a file where the test may log verbose output (e.g., the output
# of fio or mkfs).
# - \$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()
# function.
#
# Tests that require a test device should rename test() to test_device(). These
# tests will be run with a few more variables defined:
# - \$TEST_DEV -- the block device to run the test on (e.g., /dev/sda1).
# - \$TEST_DEV_SYSFS -- the sysfs directory of the device (e.g.,
# /sys/block/sda). In general, you should use the
# _test_dev_queue_{get,set} helpers. If the device is a
# partition, this is the directory of its holder
# device.
# - \$TEST_DEV_PART_SYSFS -- the sysfs directory of the device if the device
# is a partition device (e.g.,
# /sys/block/sda/sda1). If the device is not a
# partition, this is an empty string.
test() {
echo "Running \${TEST_NAME}"
# TODO: fill in the test case.
echo "Test complete"
}
# Finally, some coding style guidelines:
# - Indent with tabs.
# - Don't add a space before the parentheses or a newline before the curly brace
# in function definitions.
# - Variables set and used by the testing framework are in caps with underscores.
# E.g., TEST_NAME and GROUPS. Variables local to the test are lowercase
# with underscores.
# - Functions defined by the testing framework or group scripts, including
# helpers, have a leading underscore. E.g., _have_scsi_debug. Functions local
# to the test should not have a leading underscore.
# - Both [[ ]] form and [ ] form are fine for tests. [[ ]] is preferred.
# - Always quote variable expansions unless the variable is a number or inside of
# a [[ ]] test.
# - Use the \$() form of command substitution instead of backticks.
# - Use bash for loops instead of seq. E.g., for ((i = 0; i < 10; i++)), not
# for i in \$(seq 0 9).
#
# Please run \`make check\` after your test is done to check for shell
# scripting errors and other mistakes.
EOF
chmod +x "tests/${test_name}"
echo "Created tests/${test_name}"
cat << EOF > "tests/${test_name}.out"
Running ${test_name}
Test complete
EOF
echo "Created tests/${test_name}.out"