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