#!/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 # # 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