blob: 5f6e1c01a273cf214a5b46329f53de742b374aaf [file] [log] [blame]
#!/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 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: 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). 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
# _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
# }
# TODO: define any helpers that are specific to this group.
EOF
echo "Created tests/${group}/rc"
fi
for ((i = 1; ; i++)); do
seq="$(printf "%03d" $i)"
test_name="${group}/${seq}"
if [[ ! -e tests/${test_name} ]]; then
break
fi
done
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 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 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). 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
# _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
# 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.
#
# 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 guidlines:
# - 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.
# - Use the bash [[ ]] form of tests instead of [ ].
# - 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"