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