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 31 32. tst_ansi_color.sh 33 34tst_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 80tst_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 93tst_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 108tst_brk() 109{ 110 local res=$1 111 shift 112 113 tst_res "$res" "$@" 114 tst_do_exit 115} 116 117ROD_SILENT() 118{ 119 tst_rod $@ > /dev/null 2>&1 120 if [ $? -ne 0 ]; then 121 tst_brk TBROK "$@ failed" 122 fi 123} 124 125ROD() 126{ 127 tst_rod "$@" 128 if [ $? -ne 0 ]; then 129 tst_brk TBROK "$@ failed" 130 fi 131} 132 133EXPECT_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 143EXPECT_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 154tst_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 181tst_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 201tst_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 211tst_is_int() 212{ 213 [ "$1" -eq "$1" ] 2>/dev/null 214 return $? 215} 216 217tst_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 230tst_resstr() 231{ 232 echo "$TST_PASS$TST_FAIL$TST_CONF" 233} 234 235tst_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 244tst_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 370if 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 374fi 375 376if [ -z "$TST_ID" ]; then 377 tst_brk TBROK "TST_ID is not defined" 378fi 379export TST_ID="$TST_ID" 380 381if [ -z "$TST_TESTFUNC" ]; then 382 tst_brk TBROK "TST_TESTFUNC is not defined" 383fi 384 385if [ -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 393fi 394 395if [ -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 403fi 404 405if [ -z "$LTPROOT" ]; then 406 export LTPROOT="$PWD" 407 export TST_DATAROOT="$LTPROOT/datafiles" 408else 409 export TST_DATAROOT="$LTPROOT/testcases/data/$TST_ID" 410fi 411 412TST_ARGS="$@" 413 414while getopts ":hi:$TST_OPTS" tst_name; do 415 case $tst_name in 416 'h') TST_PRINT_HELP=1;; 417 *);; 418 esac 419done 420 421shift $((OPTIND - 1)) 422 423if [ -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 428else 429 if [ -z "$TST_PRINT_HELP" -a $# -ne 0 ]; then 430 tst_brk TBROK "Unexpected positional arguments '$@'" 431 fi 432fi 433