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 LTP_RET_VAL=0 25 export TST_COUNT=1 26 export TST_LIB_LOADED=1 27 export TST_TMPDIR_RHOST=0 28 29 . tst_ansi_color.sh 30 31 # Exit values map 32 tst_flag2mask() 33 { 34 case "$1" in 35 TPASS) return 0;; 36 TFAIL) return 1;; 37 TBROK) return 2;; 38 TWARN) return 4;; 39 TINFO) return 16;; 40 TCONF) return 32;; 41 *) tst_brkm TBROK "Invalid resm type '$1'";; 42 esac 43 } 44 45 tst_resm() 46 { 47 local ttype="$1" 48 49 tst_flag2mask "$ttype" 50 local mask=$? 51 LTP_RET_VAL=$((LTP_RET_VAL|mask)) 52 53 local ret=$1 54 shift 55 56 printf "$TCID $TST_COUNT " 57 tst_print_colored $ret "$ret:" 58 echo " $@" 59 60 case "$ret" in 61 TPASS|TFAIL) 62 TST_COUNT=$((TST_COUNT+1));; 63 esac 64 } 65 66 tst_brkm() 67 { 68 case "$1" in 69 TFAIL) ;; 70 TBROK) ;; 71 TCONF) ;; 72 *) tst_brkm TBROK "Invalid tst_brkm type '$1'";; 73 esac 74 75 local ret=$1 76 shift 77 tst_resm "$ret" "$@" 78 tst_exit 79 } 80 81 tst_record_childstatus() 82 { 83 if [ $# -ne 1 ]; then 84 tst_brkm TBROK "Requires child pid as parameter" 85 fi 86 87 local child_pid=$1 88 local ret=0 89 90 wait $child_pid 91 ret=$? 92 if [ $ret -eq 127 ]; then 93 tst_brkm TBROK "Child process pid='$child_pid' does not exist" 94 fi 95 LTP_RET_VAL=$((LTP_RET_VAL|ret)) 96 } 97 98 tst_require_root() 99 { 100 if [ "$(id -ru)" != 0 ]; then 101 tst_brkm TCONF "Must be super/root for this test!" 102 fi 103 } 104 105 tst_exit() 106 { 107 if [ -n "${TST_CLEANUP:-}" -a -z "${TST_NO_CLEANUP:-}" ]; then 108 $TST_CLEANUP 109 fi 110 111 if [ -n "${LTP_IPC_PATH:-}" -a -f "${LTP_IPC_PATH:-}" ]; then 112 rm -f "$LTP_IPC_PATH" 113 fi 114 115 # Mask out TINFO 116 exit $((LTP_RET_VAL & ~16)) 117 } 118 119 tst_tmpdir() 120 { 121 if [ -z "$TMPDIR" ]; then 122 export TMPDIR="/tmp" 123 fi 124 125 TST_TMPDIR=$(mktemp -d "$TMPDIR/$TCID.XXXXXXXXXX") 126 127 chmod 777 "$TST_TMPDIR" 128 129 TST_STARTWD=$(pwd) 130 131 cd "$TST_TMPDIR" 132 } 133 134 tst_rmdir() 135 { 136 if [ -n "$TST_TMPDIR" ]; then 137 cd "$LTPROOT" 138 rm -r "$TST_TMPDIR" 139 [ "$TST_TMPDIR_RHOST" = 1 ] && tst_cleanup_rhost 140 fi 141 } 142 143 # 144 # Checks if commands passed as arguments exists 145 # 146 tst_check_cmds() 147 { 148 local cmd 149 for cmd in $*; do 150 if ! command -v $cmd > /dev/null 2>&1; then 151 tst_brkm TCONF "'$cmd' not found" 152 fi 153 done 154 } 155 156 # tst_retry "command" [times] 157 # try run command for specified times, default is 3. 158 # Function returns 0 if succeed in RETRIES times or the last retcode the cmd 159 # returned 160 tst_retry() 161 { 162 local cmd="$1" 163 local RETRIES=${2:-"3"} 164 local i=$RETRIES 165 166 while [ $i -gt 0 ]; do 167 eval "$cmd" 168 ret=$? 169 if [ $ret -eq 0 ]; then 170 break 171 fi 172 i=$((i-1)) 173 sleep 1 174 done 175 176 if [ $ret -ne 0 ]; then 177 tst_resm TINFO "Failed to execute '$cmd' after $RETRIES retries" 178 fi 179 180 return $ret 181 } 182 183 # tst_timeout "command arg1 arg2 ..." timeout 184 # Runs command for specified timeout (in seconds). 185 # Function returns retcode of command or 1 if arguments are invalid. 186 tst_timeout() 187 { 188 local command=$1 189 local timeout=$(echo $2 | grep -o "^[0-9]\+$") 190 191 # command must be non-empty string with command to run 192 if [ -z "$command" ]; then 193 echo "first argument must be non-empty string" 194 return 1 195 fi 196 197 # accept only numbers as timeout 198 if [ -z "$timeout" ]; then 199 echo "only numbers as second argument" 200 return 1 201 fi 202 203 setsid sh -c "eval $command" 2>&1 & 204 local pid=$! 205 while [ $timeout -gt 0 ]; do 206 kill -s 0 $pid 2>/dev/null 207 if [ $? -ne 0 ]; then 208 break 209 fi 210 timeout=$((timeout - 1)) 211 sleep 1 212 done 213 214 local ret=0 215 if [ $timeout -le 0 ]; then 216 ret=128 217 kill -TERM -- -$pid 218 fi 219 220 wait $pid 221 ret=$((ret | $?)) 222 223 return $ret 224 } 225 226 ROD_SILENT() 227 { 228 $@ > /dev/null 2>&1 229 if [ $? -ne 0 ]; then 230 tst_brkm TBROK "$@ failed" 231 fi 232 } 233 234 ROD_BASE() 235 { 236 local cmd 237 local arg 238 local file 239 local flag 240 241 for arg; do 242 file="${arg#\>}" 243 if [ "$file" != "$arg" ]; then 244 flag=1 245 if [ -n "$file" ]; then 246 break 247 fi 248 continue 249 fi 250 251 if [ -n "$flag" ]; then 252 file="$arg" 253 break 254 fi 255 256 cmd="$cmd $arg" 257 done 258 259 if [ -n "$flag" ]; then 260 $cmd > $file 261 else 262 $@ 263 fi 264 } 265 266 ROD() 267 { 268 ROD_BASE "$@" 269 if [ $? -ne 0 ]; then 270 tst_brkm TBROK "$@ failed" 271 fi 272 } 273 274 EXPECT_PASS() 275 { 276 ROD_BASE "$@" 277 if [ $? -eq 0 ]; then 278 tst_resm TPASS "$@ passed as expected" 279 else 280 tst_resm TFAIL "$@ failed unexpectedly" 281 fi 282 } 283 284 EXPECT_FAIL() 285 { 286 # redirect stderr since we expect the command to fail 287 ROD_BASE "$@" 2> /dev/null 288 if [ $? -ne 0 ]; then 289 tst_resm TPASS "$@ failed as expected" 290 else 291 tst_resm TFAIL "$@ passed unexpectedly" 292 fi 293 } 294 295 tst_mkfs() 296 { 297 local fs_type=$1 298 local device=$2 299 shift 2 300 local fs_opts="$@" 301 302 if [ -z "$fs_type" ]; then 303 tst_brkm TBROK "No fs_type specified" 304 fi 305 306 if [ -z "$device" ]; then 307 tst_brkm TBROK "No device specified" 308 fi 309 310 tst_resm TINFO "Formatting $device with $fs_type extra opts='$fs_opts'" 311 312 ROD_SILENT mkfs.$fs_type $fs_opts $device 313 } 314 315 tst_umount() 316 { 317 local device="$1" 318 local i=0 319 320 if ! grep -q "$device" /proc/mounts; then 321 tst_resm TINFO "The $device is not mounted, skipping umount" 322 return 323 fi 324 325 while [ "$i" -lt 50 ]; do 326 if umount "$device" > /dev/null; then 327 return 328 fi 329 330 i=$((i+1)) 331 332 tst_resm TINFO "umount($device) failed, try $i ..." 333 tst_resm TINFO "Likely gvfsd-trash is probing newly mounted "\ 334 "fs, kill it to speed up tests." 335 336 tst_sleep 100ms 337 done 338 339 tst_resm TWARN "Failed to umount($device) after 50 retries" 340 } 341 342 # Check a module file existence 343 # Should be called after tst_tmpdir() 344 tst_module_exists() 345 { 346 local mod_name="$1" 347 348 if [ -f "$mod_name" ]; then 349 TST_MODPATH="$mod_name" 350 return 351 fi 352 353 local mod_path="$LTPROOT/testcases/bin/$mod_name" 354 if [ -f "$mod_path" ]; then 355 TST_MODPATH="$mod_path" 356 return 357 fi 358 359 if [ -n "$TST_TMPDIR" ]; then 360 mod_path="$TST_STARTWD/$mod_name" 361 if [ -f "$mod_path" ]; then 362 TST_MODPATH="$mod_path" 363 return 364 fi 365 fi 366 367 tst_brkm TCONF "Failed to find module '$mod_name'" 368 } 369 370 # Appends LTP path when doing su 371 tst_su() 372 { 373 local usr="$1" 374 shift 375 376 su "$usr" -c "PATH=\$PATH:$LTPROOT/testcases/bin/ $@" 377 } 378 379 TST_CHECKPOINT_WAIT() 380 { 381 ROD tst_checkpoint wait 10000 "$1" 382 } 383 384 TST_CHECKPOINT_WAKE() 385 { 386 ROD tst_checkpoint wake 10000 "$1" 1 387 } 388 389 TST_CHECKPOINT_WAKE2() 390 { 391 ROD tst_checkpoint wake 10000 "$1" "$2" 392 } 393 394 TST_CHECKPOINT_WAKE_AND_WAIT() 395 { 396 TST_CHECKPOINT_WAKE "$1" 397 TST_CHECKPOINT_WAIT "$1" 398 } 399 400 # Check that test name is set 401 if [ -z "$TCID" ]; then 402 tst_brkm TBROK "TCID is not defined" 403 fi 404 405 if [ -z "$TST_TOTAL" ]; then 406 tst_brkm TBROK "TST_TOTAL is not defined" 407 fi 408 409 export TCID="$TCID" 410 export TST_TOTAL="$TST_TOTAL" 411 412 # Setup LTPROOT, default to current directory if not set 413 if [ -z "$LTPROOT" ]; then 414 export LTPROOT="$PWD" 415 export LTP_DATAROOT="$LTPROOT/datafiles" 416 else 417 export LTP_DATAROOT="$LTPROOT/testcases/data/$TCID" 418 fi 419 420 if [ "$TST_NEEDS_CHECKPOINTS" = "1" ]; then 421 LTP_IPC_PATH="/dev/shm/ltp_${TCID}_$$" 422 423 LTP_IPC_SIZE=$(getconf PAGESIZE) 424 if [ $? -ne 0 ]; then 425 tst_brkm TBROK "getconf PAGESIZE failed" 426 fi 427 428 ROD_SILENT dd if=/dev/zero of="$LTP_IPC_PATH" bs="$LTP_IPC_SIZE" count=1 429 ROD_SILENT chmod 600 "$LTP_IPC_PATH" 430 export LTP_IPC_PATH 431 fi 432