You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
432 lines
8.1 KiB
432 lines
8.1 KiB
#!/bin/sh |
|
# |
|
# Copyright (c) Linux Test Project, 2014-2017 |
|
# |
|
# This program 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 program 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. |
|
# |
|
# You should have received a copy of the GNU General Public License along |
|
# with this program; if not, write to the Free Software Foundation, Inc., |
|
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
|
# |
|
# Written by Cyril Hrubis <chrubis@suse.cz> |
|
# |
|
# This is a LTP test library for shell. |
|
# |
|
|
|
export TST_PASS=0 |
|
export TST_FAIL=0 |
|
export TST_BROK=0 |
|
export TST_WARN=0 |
|
export TST_CONF=0 |
|
export TST_COUNT=1 |
|
export TST_ITERATIONS=1 |
|
|
|
. tst_ansi_color.sh |
|
|
|
tst_do_exit() |
|
{ |
|
local ret=0 |
|
|
|
if [ -n "$TST_SETUP_STARTED" -a -n "$TST_CLEANUP" -a \ |
|
-z "$TST_NO_CLEANUP" ]; then |
|
$TST_CLEANUP |
|
fi |
|
|
|
if [ "$TST_NEEDS_DEVICE" = 1 -a "$TST_DEVICE_FLAG" = 1 ]; then |
|
if ! tst_device release "$TST_DEVICE"; then |
|
tst_res TWARN "Failed to release device '$TST_DEVICE'" |
|
fi |
|
fi |
|
|
|
if [ "$TST_NEEDS_TMPDIR" = 1 -a -n "$TST_TMPDIR" ]; then |
|
cd "$LTPROOT" |
|
rm -r "$TST_TMPDIR" |
|
fi |
|
|
|
if [ $TST_FAIL -gt 0 ]; then |
|
ret=$((ret|1)) |
|
fi |
|
|
|
if [ $TST_BROK -gt 0 ]; then |
|
ret=$((ret|2)) |
|
fi |
|
|
|
if [ $TST_WARN -gt 0 ]; then |
|
ret=$((ret|4)) |
|
fi |
|
|
|
if [ $TST_CONF -gt 0 ]; then |
|
ret=$((ret|32)) |
|
fi |
|
|
|
echo |
|
echo "Summary:" |
|
echo "passed $TST_PASS" |
|
echo "failed $TST_FAIL" |
|
echo "skipped $TST_CONF" |
|
echo "warnings $TST_WARN" |
|
|
|
exit $ret |
|
} |
|
|
|
tst_inc_res() |
|
{ |
|
case "$1" in |
|
TPASS) TST_PASS=$((TST_PASS+1));; |
|
TFAIL) TST_FAIL=$((TST_FAIL+1));; |
|
TBROK) TST_BROK=$((TST_BROK+1));; |
|
TWARN) TST_WARN=$((TST_WARN+1));; |
|
TCONF) TST_CONF=$((TST_CONF+1));; |
|
TINFO) ;; |
|
*) tst_brk TBROK "Invalid resm type '$1'";; |
|
esac |
|
} |
|
|
|
tst_res() |
|
{ |
|
local res=$1 |
|
shift |
|
|
|
tst_color_enabled |
|
local color=$? |
|
|
|
tst_inc_res "$res" |
|
|
|
printf "$TCID $TST_COUNT " |
|
tst_print_colored $res "$res: " |
|
echo "$@" |
|
} |
|
|
|
tst_brk() |
|
{ |
|
local res=$1 |
|
shift |
|
|
|
tst_res "$res" "$@" |
|
tst_do_exit |
|
} |
|
|
|
ROD_SILENT() |
|
{ |
|
tst_rod $@ > /dev/null 2>&1 |
|
if [ $? -ne 0 ]; then |
|
tst_brk TBROK "$@ failed" |
|
fi |
|
} |
|
|
|
ROD() |
|
{ |
|
tst_rod "$@" |
|
if [ $? -ne 0 ]; then |
|
tst_brk TBROK "$@ failed" |
|
fi |
|
} |
|
|
|
EXPECT_PASS() |
|
{ |
|
tst_rod "$@" |
|
if [ $? -eq 0 ]; then |
|
tst_res TPASS "$@ passed as expected" |
|
else |
|
tst_res TFAIL "$@ failed unexpectedly" |
|
fi |
|
} |
|
|
|
EXPECT_FAIL() |
|
{ |
|
# redirect stderr since we expect the command to fail |
|
tst_rod "$@" 2> /dev/null |
|
if [ $? -ne 0 ]; then |
|
tst_res TPASS "$@ failed as expected" |
|
else |
|
tst_res TFAIL "$@ passed unexpectedly" |
|
fi |
|
} |
|
|
|
tst_umount() |
|
{ |
|
local device="$1" |
|
local i=0 |
|
|
|
if ! grep -q "$device" /proc/mounts; then |
|
tst_res TINFO "The $device is not mounted, skipping umount" |
|
return |
|
fi |
|
|
|
while [ "$i" -lt 50 ]; do |
|
if umount "$device" > /dev/null; then |
|
return |
|
fi |
|
|
|
i=$((i+1)) |
|
|
|
tst_res TINFO "umount($device) failed, try $i ..." |
|
tst_res TINFO "Likely gvfsd-trash is probing newly mounted "\ |
|
"fs, kill it to speed up tests." |
|
|
|
tst_sleep 100ms |
|
done |
|
|
|
tst_res TWARN "Failed to umount($device) after 50 retries" |
|
} |
|
|
|
tst_mkfs() |
|
{ |
|
local fs_type=$1 |
|
local device=$2 |
|
shift 2 |
|
local fs_opts="$@" |
|
|
|
if [ -z "$fs_type" ]; then |
|
tst_brk TBROK "No fs_type specified" |
|
fi |
|
|
|
if [ -z "$device" ]; then |
|
tst_brk TBROK "No device specified" |
|
fi |
|
|
|
tst_res TINFO "Formatting $device with $fs_type extra opts='$fs_opts'" |
|
|
|
ROD_SILENT mkfs.$fs_type $fs_opts $device |
|
} |
|
|
|
tst_check_cmds() |
|
{ |
|
local cmd |
|
for cmd in $*; do |
|
if ! command -v $cmd > /dev/null 2>&1; then |
|
tst_brk TCONF "'$cmd' not found" |
|
fi |
|
done |
|
} |
|
|
|
tst_is_int() |
|
{ |
|
[ "$1" -eq "$1" ] 2>/dev/null |
|
return $? |
|
} |
|
|
|
tst_usage() |
|
{ |
|
if [ -n "$TST_USAGE" ]; then |
|
$TST_USAGE |
|
else |
|
echo "usage: $0" |
|
echo "OPTIONS" |
|
fi |
|
|
|
echo "-h Prints this help" |
|
echo "-i n Execute test n times" |
|
} |
|
|
|
tst_resstr() |
|
{ |
|
echo "$TST_PASS$TST_FAIL$TST_CONF" |
|
} |
|
|
|
tst_rescmp() |
|
{ |
|
local res=$(tst_resstr) |
|
|
|
if [ "$1" = "$res" ]; then |
|
tst_brk TBROK "Test didn't report any results" |
|
fi |
|
} |
|
|
|
tst_run() |
|
{ |
|
local tst_i |
|
|
|
if [ -n "$TST_TEST_PATH" ]; then |
|
for tst_i in $(grep TST_ "$TST_TEST_PATH" | sed 's/.*TST_//; s/[="} \t\/:`].*//'); do |
|
case "$tst_i" in |
|
SETUP|CLEANUP|TESTFUNC|ID|CNT);; |
|
OPTS|USAGE|PARSE_ARGS|POS_ARGS);; |
|
NEEDS_ROOT|NEEDS_TMPDIR|NEEDS_DEVICE|DEVICE);; |
|
NEEDS_CMDS|NEEDS_MODULE|MODPATH|DATAROOT);; |
|
*) tst_res TWARN "Reserved variable TST_$tst_i used!";; |
|
esac |
|
done |
|
fi |
|
|
|
local name |
|
|
|
OPTIND=1 |
|
|
|
while getopts "hi:$TST_OPTS" name $TST_ARGS; do |
|
case $name in |
|
'h') tst_usage; exit 0;; |
|
'i') TST_ITERATIONS=$OPTARG;; |
|
'?') tst_usage; exit 2;; |
|
*) $TST_PARSE_ARGS "$name" "$OPTARG";; |
|
esac |
|
done |
|
|
|
if ! tst_is_int "$TST_ITERATIONS"; then |
|
tst_brk TBROK "Expected number (-i) not '$TST_ITERATIONS'" |
|
fi |
|
|
|
if [ "$TST_ITERATIONS" -le 0 ]; then |
|
tst_brk TBROK "Number of iterations (-i) must be > 0" |
|
fi |
|
|
|
if [ "$TST_NEEDS_ROOT" = 1 ]; then |
|
if [ "$(id -ru)" != 0 ]; then |
|
tst_brk TCONF "Must be super/root for this test!" |
|
fi |
|
fi |
|
|
|
tst_check_cmds $TST_NEEDS_CMDS |
|
|
|
if [ "$TST_NEEDS_TMPDIR" = 1 ]; then |
|
if [ -z "$TMPDIR" ]; then |
|
export TMPDIR="/tmp" |
|
fi |
|
|
|
TST_TMPDIR=$(mktemp -d "$TMPDIR/LTP_$TST_ID.XXXXXXXXXX") |
|
|
|
chmod 777 "$TST_TMPDIR" |
|
|
|
TST_STARTWD=$(pwd) |
|
|
|
cd "$TST_TMPDIR" |
|
fi |
|
|
|
if [ "$TST_NEEDS_DEVICE" = 1 ]; then |
|
if [ -z ${TST_TMPDIR} ]; then |
|
tst_brk "Use TST_NEEDS_TMPDIR must be set for TST_NEEDS_DEVICE" |
|
fi |
|
|
|
TST_DEVICE=$(tst_device acquire) |
|
|
|
if [ -z "$TST_DEVICE" ]; then |
|
tst_brk "Failed to acquire device" |
|
fi |
|
|
|
TST_DEVICE_FLAG=1 |
|
fi |
|
|
|
if [ -n "$TST_NEEDS_MODULE" ]; then |
|
for tst_module in "$TST_NEEDS_MODULE" \ |
|
"$LTPROOT/testcases/bin/$TST_NEEDS_MODULE" \ |
|
"$TST_STARTWD/$TST_NEEDS_MODULE"; do |
|
|
|
if [ -f "$tst_module" ]; then |
|
TST_MODPATH="$tst_module" |
|
break |
|
fi |
|
done |
|
|
|
if [ -z "$TST_MODPATH" ]; then |
|
tst_brk TCONF "Failed to find module '$TST_NEEDS_MODULE'" |
|
else |
|
tst_res TINFO "Found module at '$TST_MODPATH'" |
|
fi |
|
fi |
|
|
|
if [ -n "$TST_SETUP" ]; then |
|
TST_SETUP_STARTED=1 |
|
$TST_SETUP |
|
fi |
|
|
|
#TODO check that test reports some results for each test function call |
|
while [ $TST_ITERATIONS -gt 0 ]; do |
|
if [ -n "$TST_CNT" ]; then |
|
if type test1 > /dev/null 2>&1; then |
|
for tst_i in $(seq $TST_CNT); do |
|
local res=$(tst_resstr) |
|
$TST_TESTFUNC$tst_i |
|
tst_rescmp "$res" |
|
TST_COUNT=$((TST_COUNT+1)) |
|
done |
|
else |
|
for tst_i in $(seq $TST_CNT); do |
|
local res=$(tst_resstr) |
|
$TST_TESTFUNC $tst_i |
|
tst_rescmp "$res" |
|
TST_COUNT=$((TST_COUNT+1)) |
|
done |
|
fi |
|
else |
|
local res=$(tst_resstr) |
|
$TST_TESTFUNC |
|
tst_rescmp "$res" |
|
TST_COUNT=$((TST_COUNT+1)) |
|
fi |
|
TST_ITERATIONS=$((TST_ITERATIONS-1)) |
|
done |
|
|
|
tst_do_exit |
|
} |
|
|
|
if TST_TEST_PATH=$(which $0) 2>/dev/null; then |
|
if ! grep -q tst_run "$TST_TEST_PATH"; then |
|
tst_brk TBROK "Test $0 must call tst_run!" |
|
fi |
|
fi |
|
|
|
if [ -z "$TST_ID" ]; then |
|
tst_brk TBROK "TST_ID is not defined" |
|
fi |
|
export TST_ID="$TST_ID" |
|
|
|
if [ -z "$TST_TESTFUNC" ]; then |
|
tst_brk TBROK "TST_TESTFUNC is not defined" |
|
fi |
|
|
|
if [ -n "$TST_CNT" ]; then |
|
if ! tst_is_int "$TST_CNT"; then |
|
tst_brk TBROK "TST_CNT must be integer" |
|
fi |
|
|
|
if [ "$TST_CNT" -le 0 ]; then |
|
tst_brk TBROK "TST_CNT must be > 0" |
|
fi |
|
fi |
|
|
|
if [ -n "$TST_POS_ARGS" ]; then |
|
if ! tst_is_int "$TST_POS_ARGS"; then |
|
tst_brk TBROK "TST_POS_ARGS must be integer" |
|
fi |
|
|
|
if [ "$TST_POS_ARGS" -le 0 ]; then |
|
tst_brk TBROK "TST_POS_ARGS must be > 0" |
|
fi |
|
fi |
|
|
|
if [ -z "$LTPROOT" ]; then |
|
export LTPROOT="$PWD" |
|
export TST_DATAROOT="$LTPROOT/datafiles" |
|
else |
|
export TST_DATAROOT="$LTPROOT/testcases/data/$TST_ID" |
|
fi |
|
|
|
TST_ARGS="$@" |
|
|
|
while getopts ":hi:$TST_OPTS" tst_name; do |
|
case $tst_name in |
|
'h') TST_PRINT_HELP=1;; |
|
*);; |
|
esac |
|
done |
|
|
|
shift $((OPTIND - 1)) |
|
|
|
if [ -n "$TST_POS_ARGS" ]; then |
|
if [ -z "$TST_PRINT_HELP" -a $# -ne "$TST_POS_ARGS" ]; then |
|
tst_brk TBROK "Invalid number of positional paramters:"\ |
|
"have ($@) $#, expected ${TST_POS_ARGS}" |
|
fi |
|
else |
|
if [ -z "$TST_PRINT_HELP" -a $# -ne 0 ]; then |
|
tst_brk TBROK "Unexpected positional arguments '$@'" |
|
fi |
|
fi
|
|
|