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