1#!/bin/sh 2# 3# Copyright (c) Linux Test Project, 2014-2017 4# 5# This program is free software; you can redistribute it and/or modify 6# it under the terms of the GNU General Public License as published by 7# the Free Software Foundation; either version 2 of the License, or 8# (at your option) any later version. 9# 10# This program is distributed in the hope that it will be useful, 11# but WITHOUT ANY WARRANTY; without even the implied warranty of 12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13# GNU General Public License for more details. 14# 15# You should have received a copy of the GNU General Public License along 16# with this program; if not, write to the Free Software Foundation, Inc., 17# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 18# 19# Written by Cyril Hrubis <chrubis@suse.cz> 20# 21# This is a LTP test library for shell. 22# 23 24export TST_PASS=0 25export TST_FAIL=0 26export TST_BROK=0 27export TST_WARN=0 28export TST_CONF=0 29export TST_COUNT=1 30export TST_ITERATIONS=1 31export TST_TMPDIR_RHOST=0 32 33. tst_ansi_color.sh 34 35tst_do_exit() 36{ 37 local ret=0 38 39 if [ -n "$TST_SETUP_STARTED" -a -n "$TST_CLEANUP" -a \ 40 -z "$TST_NO_CLEANUP" ]; then 41 $TST_CLEANUP 42 fi 43 44 if [ "$TST_NEEDS_DEVICE" = 1 -a "$TST_DEVICE_FLAG" = 1 ]; then 45 if ! tst_device release "$TST_DEVICE"; then 46 tst_res TWARN "Failed to release device '$TST_DEVICE'" 47 fi 48 fi 49 50 if [ "$TST_NEEDS_TMPDIR" = 1 -a -n "$TST_TMPDIR" ]; then 51 cd "$LTPROOT" 52 rm -r "$TST_TMPDIR" 53 [ "$TST_TMPDIR_RHOST" = 1 ] && tst_cleanup_rhost 54 fi 55 56 if [ $TST_FAIL -gt 0 ]; then 57 ret=$((ret|1)) 58 fi 59 60 if [ $TST_BROK -gt 0 ]; then 61 ret=$((ret|2)) 62 fi 63 64 if [ $TST_WARN -gt 0 ]; then 65 ret=$((ret|4)) 66 fi 67 68 if [ $TST_CONF -gt 0 ]; then 69 ret=$((ret|32)) 70 fi 71 72 echo 73 echo "Summary:" 74 echo "passed $TST_PASS" 75 echo "failed $TST_FAIL" 76 echo "skipped $TST_CONF" 77 echo "warnings $TST_WARN" 78 79 exit $ret 80} 81 82tst_inc_res() 83{ 84 case "$1" in 85 TPASS) TST_PASS=$((TST_PASS+1));; 86 TFAIL) TST_FAIL=$((TST_FAIL+1));; 87 TBROK) TST_BROK=$((TST_BROK+1));; 88 TWARN) TST_WARN=$((TST_WARN+1));; 89 TCONF) TST_CONF=$((TST_CONF+1));; 90 TINFO) ;; 91 *) tst_brk TBROK "Invalid resm type '$1'";; 92 esac 93} 94 95tst_res() 96{ 97 local res=$1 98 shift 99 100 tst_color_enabled 101 local color=$? 102 103 tst_inc_res "$res" 104 105 printf "$TCID $TST_COUNT " 106 tst_print_colored $res "$res: " 107 echo "$@" 108} 109 110tst_brk() 111{ 112 local res=$1 113 shift 114 115 tst_res "$res" "$@" 116 tst_do_exit 117} 118 119ROD_SILENT() 120{ 121 tst_rod $@ > /dev/null 2>&1 122 if [ $? -ne 0 ]; then 123 tst_brk TBROK "$@ failed" 124 fi 125} 126 127ROD() 128{ 129 tst_rod "$@" 130 if [ $? -ne 0 ]; then 131 tst_brk TBROK "$@ failed" 132 fi 133} 134 135EXPECT_PASS() 136{ 137 tst_rod "$@" 138 if [ $? -eq 0 ]; then 139 tst_res TPASS "$@ passed as expected" 140 else 141 tst_res TFAIL "$@ failed unexpectedly" 142 fi 143} 144 145EXPECT_FAIL() 146{ 147 # redirect stderr since we expect the command to fail 148 tst_rod "$@" 2> /dev/null 149 if [ $? -ne 0 ]; then 150 tst_res TPASS "$@ failed as expected" 151 else 152 tst_res TFAIL "$@ passed unexpectedly" 153 fi 154} 155 156tst_umount() 157{ 158 local device="$1" 159 local i=0 160 161 if ! grep -q "$device" /proc/mounts; then 162 tst_res TINFO "The $device is not mounted, skipping umount" 163 return 164 fi 165 166 while [ "$i" -lt 50 ]; do 167 if umount "$device" > /dev/null; then 168 return 169 fi 170 171 i=$((i+1)) 172 173 tst_res TINFO "umount($device) failed, try $i ..." 174 tst_res TINFO "Likely gvfsd-trash is probing newly mounted "\ 175 "fs, kill it to speed up tests." 176 177 tst_sleep 100ms 178 done 179 180 tst_res TWARN "Failed to umount($device) after 50 retries" 181} 182 183tst_mkfs() 184{ 185 local fs_type=$1 186 local device=$2 187 shift 2 188 local fs_opts="$@" 189 190 if [ -z "$fs_type" ]; then 191 tst_brk TBROK "No fs_type specified" 192 fi 193 194 if [ -z "$device" ]; then 195 tst_brk TBROK "No device specified" 196 fi 197 198 tst_res TINFO "Formatting $device with $fs_type extra opts='$fs_opts'" 199 200 ROD_SILENT mkfs.$fs_type $fs_opts $device 201} 202 203tst_check_cmds() 204{ 205 local cmd 206 for cmd in $*; do 207 if ! command -v $cmd > /dev/null 2>&1; then 208 tst_brk TCONF "'$cmd' not found" 209 fi 210 done 211} 212 213tst_is_int() 214{ 215 [ "$1" -eq "$1" ] 2>/dev/null 216 return $? 217} 218 219tst_usage() 220{ 221 if [ -n "$TST_USAGE" ]; then 222 $TST_USAGE 223 else 224 echo "usage: $0" 225 echo "OPTIONS" 226 fi 227 228 echo "-h Prints this help" 229 echo "-i n Execute test n times" 230} 231 232tst_resstr() 233{ 234 echo "$TST_PASS$TST_FAIL$TST_CONF" 235} 236 237tst_rescmp() 238{ 239 local res=$(tst_resstr) 240 241 if [ "$1" = "$res" ]; then 242 tst_brk TBROK "Test didn't report any results" 243 fi 244} 245 246tst_run() 247{ 248 local tst_i 249 250 if [ -n "$TST_TEST_PATH" ]; then 251 for tst_i in $(grep TST_ "$TST_TEST_PATH" | sed 's/.*TST_//; s/[="} \t\/:`].*//'); do 252 case "$tst_i" in 253 SETUP|CLEANUP|TESTFUNC|ID|CNT);; 254 OPTS|USAGE|PARSE_ARGS|POS_ARGS);; 255 NEEDS_ROOT|NEEDS_TMPDIR|NEEDS_DEVICE|DEVICE);; 256 NEEDS_CMDS|NEEDS_MODULE|MODPATH|DATAROOT);; 257 *) tst_res TWARN "Reserved variable TST_$tst_i used!";; 258 esac 259 done 260 fi 261 262 local name 263 264 OPTIND=1 265 266 while getopts "hi:$TST_OPTS" name $TST_ARGS; do 267 case $name in 268 'h') tst_usage; exit 0;; 269 'i') TST_ITERATIONS=$OPTARG;; 270 '?') tst_usage; exit 2;; 271 *) $TST_PARSE_ARGS "$name" "$OPTARG";; 272 esac 273 done 274 275 if ! tst_is_int "$TST_ITERATIONS"; then 276 tst_brk TBROK "Expected number (-i) not '$TST_ITERATIONS'" 277 fi 278 279 if [ "$TST_ITERATIONS" -le 0 ]; then 280 tst_brk TBROK "Number of iterations (-i) must be > 0" 281 fi 282 283 if [ "$TST_NEEDS_ROOT" = 1 ]; then 284 if [ "$(id -ru)" != 0 ]; then 285 tst_brk TCONF "Must be super/root for this test!" 286 fi 287 fi 288 289 tst_check_cmds $TST_NEEDS_CMDS 290 291 if [ "$TST_NEEDS_TMPDIR" = 1 ]; then 292 if [ -z "$TMPDIR" ]; then 293 export TMPDIR="/tmp" 294 fi 295 296 TST_TMPDIR=$(mktemp -d "$TMPDIR/LTP_$TST_ID.XXXXXXXXXX") 297 298 chmod 777 "$TST_TMPDIR" 299 300 TST_STARTWD=$(pwd) 301 302 cd "$TST_TMPDIR" 303 fi 304 305 if [ "$TST_NEEDS_DEVICE" = 1 ]; then 306 if [ -z ${TST_TMPDIR} ]; then 307 tst_brk "Use TST_NEEDS_TMPDIR must be set for TST_NEEDS_DEVICE" 308 fi 309 310 TST_DEVICE=$(tst_device acquire) 311 312 if [ -z "$TST_DEVICE" ]; then 313 tst_brk "Failed to acquire device" 314 fi 315 316 TST_DEVICE_FLAG=1 317 fi 318 319 if [ -n "$TST_NEEDS_MODULE" ]; then 320 for tst_module in "$TST_NEEDS_MODULE" \ 321 "$LTPROOT/testcases/bin/$TST_NEEDS_MODULE" \ 322 "$TST_STARTWD/$TST_NEEDS_MODULE"; do 323 324 if [ -f "$tst_module" ]; then 325 TST_MODPATH="$tst_module" 326 break 327 fi 328 done 329 330 if [ -z "$TST_MODPATH" ]; then 331 tst_brk TCONF "Failed to find module '$TST_NEEDS_MODULE'" 332 else 333 tst_res TINFO "Found module at '$TST_MODPATH'" 334 fi 335 fi 336 337 if [ -n "$TST_SETUP" ]; then 338 TST_SETUP_STARTED=1 339 $TST_SETUP 340 fi 341 342 #TODO check that test reports some results for each test function call 343 while [ $TST_ITERATIONS -gt 0 ]; do 344 if [ -n "$TST_CNT" ]; then 345 if type test1 > /dev/null 2>&1; then 346 for tst_i in $(seq $TST_CNT); do 347 local res=$(tst_resstr) 348 $TST_TESTFUNC$tst_i 349 tst_rescmp "$res" 350 TST_COUNT=$((TST_COUNT+1)) 351 done 352 else 353 for tst_i in $(seq $TST_CNT); do 354 local res=$(tst_resstr) 355 $TST_TESTFUNC $tst_i 356 tst_rescmp "$res" 357 TST_COUNT=$((TST_COUNT+1)) 358 done 359 fi 360 else 361 local res=$(tst_resstr) 362 $TST_TESTFUNC 363 tst_rescmp "$res" 364 TST_COUNT=$((TST_COUNT+1)) 365 fi 366 TST_ITERATIONS=$((TST_ITERATIONS-1)) 367 done 368 369 tst_do_exit 370} 371 372if TST_TEST_PATH=$(which $0) 2>/dev/null; then 373 if ! grep -q tst_run "$TST_TEST_PATH"; then 374 tst_brk TBROK "Test $0 must call tst_run!" 375 fi 376fi 377 378if [ -z "$TST_ID" ]; then 379 filename=$(basename $0) 380 TST_ID=${filename%%.*} 381fi 382export TST_ID="$TST_ID" 383 384if [ -z "$TST_TESTFUNC" ]; then 385 tst_brk TBROK "TST_TESTFUNC is not defined" 386fi 387 388if [ -n "$TST_CNT" ]; then 389 if ! tst_is_int "$TST_CNT"; then 390 tst_brk TBROK "TST_CNT must be integer" 391 fi 392 393 if [ "$TST_CNT" -le 0 ]; then 394 tst_brk TBROK "TST_CNT must be > 0" 395 fi 396fi 397 398if [ -n "$TST_POS_ARGS" ]; then 399 if ! tst_is_int "$TST_POS_ARGS"; then 400 tst_brk TBROK "TST_POS_ARGS must be integer" 401 fi 402 403 if [ "$TST_POS_ARGS" -le 0 ]; then 404 tst_brk TBROK "TST_POS_ARGS must be > 0" 405 fi 406fi 407 408if [ -z "$LTPROOT" ]; then 409 export LTPROOT="$PWD" 410 export TST_DATAROOT="$LTPROOT/datafiles" 411else 412 export TST_DATAROOT="$LTPROOT/testcases/data/$TST_ID" 413fi 414 415TST_ARGS="$@" 416 417while getopts ":hi:$TST_OPTS" tst_name; do 418 case $tst_name in 419 'h') TST_PRINT_HELP=1;; 420 *);; 421 esac 422done 423 424shift $((OPTIND - 1)) 425 426if [ -n "$TST_POS_ARGS" ]; then 427 if [ -z "$TST_PRINT_HELP" -a $# -ne "$TST_POS_ARGS" ]; then 428 tst_brk TBROK "Invalid number of positional paramters:"\ 429 "have ($@) $#, expected ${TST_POS_ARGS}" 430 fi 431else 432 if [ -z "$TST_PRINT_HELP" -a $# -ne 0 ]; then 433 tst_brk TBROK "Unexpected positional arguments '$@'" 434 fi 435fi 436