1#!/bin/sh 2# SPDX-License-Identifier: GPL-2.0-or-later 3# Copyright (c) Linux Test Project, 2014-2022 4# Author: Cyril Hrubis <chrubis@suse.cz> 5# 6# LTP test library for shell. 7 8[ -n "$TST_LIB_LOADED" ] && return 0 9 10export TST_PASS=0 11export TST_FAIL=0 12export TST_BROK=0 13export TST_WARN=0 14export TST_CONF=0 15export TST_COUNT=1 16export TST_ITERATIONS=1 17export TST_TMPDIR_RHOST=0 18export TST_LIB_LOADED=1 19 20. tst_ansi_color.sh 21. tst_security.sh 22 23# default trap function 24trap "tst_brk TBROK 'test interrupted'" INT 25trap "unset _tst_setup_timer_pid; tst_brk TBROK 'test terminated'" TERM 26 27_tst_do_cleanup() 28{ 29 if [ -n "$TST_DO_CLEANUP" -a -n "$TST_CLEANUP" -a -z "$TST_NO_CLEANUP" ]; then 30 if command -v $TST_CLEANUP >/dev/null 2>/dev/null; then 31 $TST_CLEANUP 32 else 33 tst_res TWARN "TST_CLEANUP=$TST_CLEANUP declared, but function not defined (or cmd not found)" 34 fi 35 fi 36 TST_DO_CLEANUP= 37} 38 39_tst_do_exit() 40{ 41 local ret=0 42 TST_DO_EXIT=1 43 44 _tst_do_cleanup 45 46 cd "$LTPROOT" 47 [ "$TST_MOUNT_FLAG" = 1 ] && tst_umount 48 49 if [ "$TST_NEEDS_DEVICE" = 1 -a "$TST_DEVICE_FLAG" = 1 ]; then 50 if ! tst_device release "$TST_DEVICE"; then 51 tst_res TWARN "Failed to release device '$TST_DEVICE'" 52 fi 53 fi 54 55 if [ "$TST_NEEDS_TMPDIR" = 1 -a -n "$TST_TMPDIR" ]; then 56 rm -r "$TST_TMPDIR" 57 [ "$TST_TMPDIR_RHOST" = 1 ] && tst_cleanup_rhost 58 fi 59 60 if [ -n "$TST_NEEDS_CHECKPOINTS" -a -f "$LTP_IPC_PATH" ]; then 61 rm $LTP_IPC_PATH 62 fi 63 64 _tst_cleanup_timer 65 66 if [ $TST_FAIL -gt 0 ]; then 67 ret=$((ret|1)) 68 fi 69 70 if [ $TST_BROK -gt 0 ]; then 71 ret=$((ret|2)) 72 fi 73 74 if [ $TST_WARN -gt 0 ]; then 75 ret=$((ret|4)) 76 fi 77 78 if [ $TST_CONF -gt 0 -a $TST_PASS -eq 0 ]; then 79 ret=$((ret|32)) 80 fi 81 82 if [ $TST_BROK -gt 0 -o $TST_FAIL -gt 0 -o $TST_WARN -gt 0 ]; then 83 _tst_check_security_modules 84 fi 85 86 cat >&2 << EOF 87 88Summary: 89passed $TST_PASS 90failed $TST_FAIL 91broken $TST_BROK 92skipped $TST_CONF 93warnings $TST_WARN 94EOF 95 96 exit $ret 97} 98 99_tst_inc_res() 100{ 101 case "$1" in 102 TPASS) TST_PASS=$((TST_PASS+1));; 103 TFAIL) TST_FAIL=$((TST_FAIL+1));; 104 TBROK) TST_BROK=$((TST_BROK+1));; 105 TWARN) TST_WARN=$((TST_WARN+1));; 106 TCONF) TST_CONF=$((TST_CONF+1));; 107 TINFO) ;; 108 *) tst_brk TBROK "Invalid res type '$1'";; 109 esac 110} 111 112tst_res() 113{ 114 local res=$1 115 shift 116 117 _tst_inc_res "$res" 118 119 printf "$TST_ID $TST_COUNT " >&2 120 tst_print_colored $res "$res: " >&2 121 echo "$@" >&2 122} 123 124tst_brk() 125{ 126 local res=$1 127 shift 128 129 if [ "$TST_DO_EXIT" = 1 ]; then 130 tst_res TWARN "$@" 131 return 132 fi 133 134 tst_res "$res" "$@" 135 _tst_do_exit 136} 137 138ROD_SILENT() 139{ 140 local tst_out 141 142 tst_out="$(tst_rod $@ 2>&1)" 143 if [ $? -ne 0 ]; then 144 echo "$tst_out" 145 tst_brk TBROK "$@ failed" 146 fi 147} 148 149ROD() 150{ 151 tst_rod "$@" 152 if [ $? -ne 0 ]; then 153 tst_brk TBROK "$@ failed" 154 fi 155} 156 157_tst_expect_pass() 158{ 159 local fnc="$1" 160 shift 161 162 tst_rod "$@" 163 if [ $? -eq 0 ]; then 164 tst_res TPASS "$@ passed as expected" 165 return 0 166 else 167 $fnc TFAIL "$@ failed unexpectedly" 168 return 1 169 fi 170} 171 172_tst_expect_fail() 173{ 174 local fnc="$1" 175 shift 176 177 # redirect stderr since we expect the command to fail 178 tst_rod "$@" 2> /dev/null 179 if [ $? -ne 0 ]; then 180 tst_res TPASS "$@ failed as expected" 181 return 0 182 else 183 $fnc TFAIL "$@ passed unexpectedly" 184 return 1 185 fi 186} 187 188EXPECT_PASS() 189{ 190 _tst_expect_pass tst_res "$@" 191} 192 193EXPECT_PASS_BRK() 194{ 195 _tst_expect_pass tst_brk "$@" 196} 197 198EXPECT_FAIL() 199{ 200 _tst_expect_fail tst_res "$@" 201} 202 203EXPECT_FAIL_BRK() 204{ 205 _tst_expect_fail tst_brk "$@" 206} 207 208TST_RETRY_FN_EXP_BACKOFF() 209{ 210 local tst_fun="$1" 211 local tst_exp=$2 212 local tst_sec=$(($3 * 1000000)) 213 local tst_delay=1 214 215 _tst_multiply_timeout tst_sec 216 217 if [ $# -ne 3 ]; then 218 tst_brk TBROK "TST_RETRY_FN_EXP_BACKOFF expects 3 parameters" 219 fi 220 221 if ! tst_is_int "$tst_sec"; then 222 tst_brk TBROK "TST_RETRY_FN_EXP_BACKOFF: tst_sec must be integer ('$tst_sec')" 223 fi 224 225 while true; do 226 eval "$tst_fun" 227 if [ "$?" = "$tst_exp" ]; then 228 break 229 fi 230 231 if [ $tst_delay -lt $tst_sec ]; then 232 tst_sleep ${tst_delay}us 233 tst_delay=$((tst_delay*2)) 234 else 235 tst_brk TBROK "\"$tst_fun\" timed out" 236 fi 237 done 238 239 return $tst_exp 240} 241 242TST_RETRY_FUNC() 243{ 244 if [ $# -ne 2 ]; then 245 tst_brk TBROK "TST_RETRY_FUNC expects 2 parameters" 246 fi 247 248 TST_RETRY_FN_EXP_BACKOFF "$1" "$2" 1 249 return $2 250} 251 252TST_RTNL_CHK() 253{ 254 local msg1="RTNETLINK answers: Function not implemented" 255 local msg2="RTNETLINK answers: Operation not supported" 256 local msg3="RTNETLINK answers: Protocol not supported" 257 local output="$($@ 2>&1 || echo 'LTP_ERR')" 258 local msg 259 260 echo "$output" | grep -q "LTP_ERR" || return 0 261 262 for msg in "$msg1" "$msg2" "$msg3"; do 263 echo "$output" | grep -q "$msg" && tst_brk TCONF "'$@': $msg" 264 done 265 266 tst_brk TBROK "$@ failed: $output" 267} 268 269TST_CHECKPOINT_WAIT() 270{ 271 ROD tst_checkpoint wait 10000 "$1" 272} 273 274TST_CHECKPOINT_WAKE() 275{ 276 ROD tst_checkpoint wake 10000 "$1" 1 277} 278 279TST_CHECKPOINT_WAKE2() 280{ 281 ROD tst_checkpoint wake 10000 "$1" "$2" 282} 283 284TST_CHECKPOINT_WAKE_AND_WAIT() 285{ 286 TST_CHECKPOINT_WAKE "$1" 287 TST_CHECKPOINT_WAIT "$1" 288} 289 290tst_mount() 291{ 292 local mnt_opt mnt_err mnt_real 293 294 if [ -n "$TST_FS_TYPE" ]; then 295 mnt_opt="-t $TST_FS_TYPE" 296 mnt_err=" $TST_FS_TYPE type" 297 fi 298 local cmd="mount $mnt_opt $TST_DEVICE $TST_MNTPOINT $TST_MNT_PARAMS" 299 300 ROD_SILENT mkdir -p $TST_MNTPOINT 301 tst_res TINFO "Mounting device: $cmd" 302 $cmd 303 local ret=$? 304 305 if [ $ret -eq 32 ]; then 306 tst_brk TCONF "Cannot mount${mnt_err}, missing driver?" 307 fi 308 309 if [ $ret -ne 0 ]; then 310 tst_brk TBROK "Failed to mount device${mnt_err}: mount exit = $ret" 311 fi 312} 313 314tst_umount() 315{ 316 local mntpoint="${1:-$TST_MNTPOINT}" 317 local i=0 318 319 [ -z "$mntpoint" ] && return 320 321 if ! echo "$mntpoint" | grep -q ^/; then 322 tst_brk TCONF "The '$mntpoint' is not an absolute path" 323 fi 324 325 if ! grep -q "${mntpoint%/}" /proc/mounts; then 326 tst_res TINFO "The '$mntpoint' is not mounted, skipping umount" 327 return 328 fi 329 330 while [ "$i" -lt 50 ]; do 331 if umount "$mntpoint" > /dev/null; then 332 return 333 fi 334 335 i=$((i+1)) 336 337 tst_res TINFO "umount($mntpoint) failed, try $i ..." 338 tst_res TINFO "Likely gvfsd-trash is probing newly mounted "\ 339 "fs, kill it to speed up tests." 340 341 tst_sleep 100ms 342 done 343 344 tst_res TWARN "Failed to umount($mntpoint) after 50 retries" 345} 346 347tst_mkfs() 348{ 349 local opts 350 local fs_type=${1:-$TST_FS_TYPE} 351 [ $# -ge 1 ] && shift 352 353 opts="$@" 354 355 if [ "$fs_type" = tmpfs ]; then 356 tst_res TINFO "Skipping mkfs for TMPFS filesystem" 357 return 358 fi 359 360 if [ -z "$opts" ]; then 361 if [ "$TST_NEEDS_DEVICE" != 1 ]; then 362 tst_brk "Using default parameters in tst_mkfs requires TST_NEEDS_DEVICE=1" 363 fi 364 opts="$TST_DEVICE" 365 fi 366 367 tst_require_cmds mkfs.$fs_type 368 369 tst_res TINFO "Formatting $fs_type with opts='$opts'" 370 ROD_SILENT mkfs.$fs_type $opts 371} 372 373# Detect whether running under hypervisor: Microsoft Hyper-V 374# Return 0: running under Hyper-V 375# Return 1: not running under Hyper-V (bare metal, other hypervisor or 376# failure of detection) 377tst_virt_hyperv() 378{ 379 local v 380 381 tst_cmd_available systemd-detect-virt || return 1 382 383 v="$(systemd-detect-virt)" 384 385 [ $? -eq 0 ] || return 1 386 [ "$v" = "microsoft" ] || return 1 387 388 return 0 389} 390 391tst_cmd_available() 392{ 393 command -v $1 >/dev/null 2>&1 394} 395 396tst_require_cmds() 397{ 398 local cmd 399 for cmd in $*; do 400 tst_cmd_available $cmd || tst_brk TCONF "'$cmd' not found" 401 done 402} 403 404tst_check_cmds() 405{ 406 local cmd 407 for cmd in $*; do 408 if ! tst_cmd_available $cmd; then 409 tst_res TCONF "'$cmd' not found" 410 return 1 411 fi 412 done 413 return 0 414} 415 416tst_require_drivers() 417{ 418 [ $# -eq 0 ] && return 0 419 420 local drv 421 422 drv="$(tst_check_drivers $@ 2>&1)" 423 424 [ $? -ne 0 ] && tst_brk TCONF "$drv driver not available" 425 return 0 426} 427 428tst_require_kconfigs() 429{ 430 local delim 431 432 if [ $# -gt 2 ]; then 433 return 0 434 elif [ $# -eq 1 ]; then 435 delim="$TST_NEEDS_KCONFIGS_IFS" 436 else 437 delim="$2" 438 fi 439 440 [ -z "$1" ] && return 0 441 442 tst_check_kconfigs "$1" "$delim" > /dev/null 443 444 [ $? -ne 0 ] && tst_brk TCONF "Aborting due to unsuitable kernel config, see above!" 445 return 0 446} 447 448tst_is_int() 449{ 450 [ "$1" -eq "$1" ] 2>/dev/null 451 return $? 452} 453 454tst_is_num() 455{ 456 echo "$1" | grep -Eq '^[-+]?[0-9]+\.?[0-9]*$' 457} 458 459tst_usage() 460{ 461 if [ -n "$TST_USAGE" ]; then 462 $TST_USAGE 463 else 464 echo "usage: $0" 465 echo 466 echo "Options" 467 echo "-------" 468 fi 469 470 echo "-h Prints this help" 471 echo "-i n Execute test n times" 472 473 cat << EOF 474 475Environment Variables 476--------------------- 477KCONFIG_PATH Specify kernel config file 478KCONFIG_SKIP_CHECK Skip kernel config check if variable set (not set by default) 479LTPROOT Prefix for installed LTP (default: /opt/ltp) 480LTP_COLORIZE_OUTPUT Force colorized output behaviour (y/1 always, n/0: never) 481LTP_DEV Path to the block device to be used (for .needs_device) 482LTP_DEV_FS_TYPE Filesystem used for testing (default: ext2) 483LTP_SINGLE_FS_TYPE Testing only - specifies filesystem instead all supported (for TST_ALL_FILESYSTEMS=1) 484LTP_TIMEOUT_MUL Timeout multiplier (must be a number >=1, ceiled to int) 485TMPDIR Base directory for template directory (for .needs_tmpdir, default: /tmp) 486EOF 487} 488 489_tst_resstr() 490{ 491 echo "$TST_PASS$TST_FAIL$TST_CONF" 492} 493 494_tst_rescmp() 495{ 496 local res=$(_tst_resstr) 497 498 if [ "$1" = "$res" ]; then 499 tst_brk TBROK "Test didn't report any results" 500 fi 501} 502 503_tst_multiply_timeout() 504{ 505 [ $# -ne 1 ] && tst_brk TBROK "_tst_multiply_timeout expect 1 parameter" 506 eval "local timeout=\$$1" 507 508 LTP_TIMEOUT_MUL=${LTP_TIMEOUT_MUL:-1} 509 510 local err="LTP_TIMEOUT_MUL must be number >= 1!" 511 512 tst_is_num "$LTP_TIMEOUT_MUL" || tst_brk TBROK "$err ($LTP_TIMEOUT_MUL)" 513 514 if ! tst_is_int "$LTP_TIMEOUT_MUL"; then 515 LTP_TIMEOUT_MUL=$(echo "$LTP_TIMEOUT_MUL" | cut -d. -f1) 516 LTP_TIMEOUT_MUL=$((LTP_TIMEOUT_MUL+1)) 517 tst_res TINFO "ceiling LTP_TIMEOUT_MUL to $LTP_TIMEOUT_MUL" 518 fi 519 520 [ "$LTP_TIMEOUT_MUL" -ge 1 ] || tst_brk TBROK "$err ($LTP_TIMEOUT_MUL)" 521 [ "$timeout" -ge 1 ] || tst_brk TBROK "timeout need to be >= 1 ($timeout)" 522 523 eval "$1='$((timeout * LTP_TIMEOUT_MUL))'" 524 return 0 525} 526 527_tst_cleanup_timer() 528{ 529 if [ -n "$_tst_setup_timer_pid" ]; then 530 kill -TERM $_tst_setup_timer_pid 2>/dev/null 531 # kill is successful only on test timeout 532 wait $_tst_setup_timer_pid 2>/dev/null || true 533 fi 534} 535 536_tst_setup_timer() 537{ 538 TST_TIMEOUT=${TST_TIMEOUT:-300} 539 540 if [ "$TST_TIMEOUT" = -1 ]; then 541 tst_res TINFO "Timeout per run is disabled" 542 return 543 fi 544 545 if ! tst_is_int "$TST_TIMEOUT" || [ "$TST_TIMEOUT" -lt 1 ]; then 546 tst_brk TBROK "TST_TIMEOUT must be int >= 1! ($TST_TIMEOUT)" 547 fi 548 549 local sec=$TST_TIMEOUT 550 _tst_multiply_timeout sec 551 local h=$((sec / 3600)) 552 local m=$((sec / 60 % 60)) 553 local s=$((sec % 60)) 554 local pid=$$ 555 556 tst_res TINFO "timeout per run is ${h}h ${m}m ${s}s" 557 558 _tst_cleanup_timer 559 560 tst_timeout_kill $sec $pid & 561 562 _tst_setup_timer_pid=$! 563 564 while true; do 565 local state 566 567 state=$(cut -d' ' -f3 "/proc/$_tst_setup_timer_pid/stat") 568 569 if [ "$state" = "S" ]; then 570 break; 571 fi 572 573 tst_sleep 1ms 574 done 575} 576 577tst_require_root() 578{ 579 if [ "$(id -ru)" != 0 ]; then 580 tst_brk TCONF "Must be super/root for this test!" 581 fi 582} 583 584tst_require_module() 585{ 586 local _tst_module=$1 587 588 for tst_module in "$_tst_module" \ 589 "$LTPROOT/testcases/bin/$_tst_module" \ 590 "$TST_STARTWD/$_tst_module"; do 591 592 if [ -f "$tst_module" ]; then 593 TST_MODPATH="$tst_module" 594 break 595 fi 596 done 597 598 if [ -z "$TST_MODPATH" ]; then 599 tst_brk TCONF "Failed to find module '$_tst_module'" 600 fi 601 602 tst_res TINFO "Found module at '$TST_MODPATH'" 603} 604 605tst_set_timeout() 606{ 607 TST_TIMEOUT="$1" 608 _tst_setup_timer 609} 610 611_tst_init_checkpoints() 612{ 613 local pagesize 614 615 LTP_IPC_PATH="/dev/shm/ltp_${TST_ID}_$$" 616 pagesize=$(tst_getconf PAGESIZE) 617 if [ $? -ne 0 ]; then 618 tst_brk TBROK "tst_getconf PAGESIZE failed" 619 fi 620 ROD_SILENT dd if=/dev/zero of="$LTP_IPC_PATH" bs="$pagesize" count=1 621 ROD_SILENT chmod 600 "$LTP_IPC_PATH" 622 export LTP_IPC_PATH 623} 624 625_prepare_device() 626{ 627 if [ "$TST_FORMAT_DEVICE" = 1 ]; then 628 tst_device clear "$TST_DEVICE" 629 tst_mkfs $TST_FS_TYPE $TST_DEV_FS_OPTS $TST_DEVICE $TST_DEV_EXTRA_OPTS 630 fi 631 632 if [ "$TST_MOUNT_DEVICE" = 1 ]; then 633 tst_mount 634 TST_MOUNT_FLAG=1 635 fi 636} 637 638_tst_run_tcases_per_fs() 639{ 640 local fs 641 local filesystems 642 643 filesystems="$(tst_supported_fs -s "$TST_SKIP_FILESYSTEMS")" 644 if [ $? -ne 0 ]; then 645 tst_brk TCONF "There are no supported filesystems or all skipped" 646 fi 647 648 for fs in $filesystems; do 649 tst_res TINFO "=== Testing on $fs ===" 650 TST_FS_TYPE="$fs" 651 _tst_run_iterations 652 done 653} 654 655tst_run() 656{ 657 local _tst_i 658 local _tst_data 659 local _tst_max 660 local _tst_name 661 local _tst_pattern='[='\''"} \t\/:`$\;|].*' 662 local ret 663 664 if [ -n "$TST_TEST_PATH" ]; then 665 for _tst_i in $(grep '^[^#]*\bTST_' "$TST_TEST_PATH" | sed "s/.*TST_//; s/$_tst_pattern//"); do 666 case "$_tst_i" in 667 ALL_FILESYSTEMS|DISABLE_APPARMOR|DISABLE_SELINUX);; 668 SETUP|CLEANUP|TESTFUNC|ID|CNT|MIN_KVER);; 669 OPTS|USAGE|PARSE_ARGS|POS_ARGS);; 670 NEEDS_ROOT|NEEDS_TMPDIR|TMPDIR|NEEDS_DEVICE|DEVICE);; 671 NEEDS_CMDS|NEEDS_MODULE|MODPATH|DATAROOT);; 672 NEEDS_DRIVERS|FS_TYPE|MNTPOINT|MNT_PARAMS);; 673 NEEDS_KCONFIGS|NEEDS_KCONFIGS_IFS);; 674 IPV6|IPV6_FLAG|IPVER|TEST_DATA|TEST_DATA_IFS);; 675 RETRY_FUNC|RETRY_FN_EXP_BACKOFF|TIMEOUT);; 676 NET_DATAROOT|NET_MAX_PKT|NET_RHOST_RUN_DEBUG|NETLOAD_CLN_NUMBER);; 677 NET_SKIP_VARIABLE_INIT|NEEDS_CHECKPOINTS);; 678 CHECKPOINT_WAIT|CHECKPOINT_WAKE);; 679 CHECKPOINT_WAKE2|CHECKPOINT_WAKE_AND_WAIT);; 680 DEV_EXTRA_OPTS|DEV_FS_OPTS|FORMAT_DEVICE|MOUNT_DEVICE);; 681 SKIP_FILESYSTEMS|SKIP_IN_LOCKDOWN|SKIP_IN_SECUREBOOT);; 682 *) tst_res TWARN "Reserved variable TST_$_tst_i used!";; 683 esac 684 done 685 686 for _tst_i in $(grep '^[^#]*\b_tst_' "$TST_TEST_PATH" | sed "s/.*_tst_//; s/$_tst_pattern//"); do 687 tst_res TWARN "Private variable or function _tst_$_tst_i used!" 688 done 689 fi 690 691 if ! tst_is_int "$TST_ITERATIONS"; then 692 tst_brk TBROK "Expected number (-i) not '$TST_ITERATIONS'" 693 fi 694 695 if [ "$TST_ITERATIONS" -lt 0 ]; then 696 tst_brk TBROK "Number of iterations (-i) must be >= 0" 697 fi 698 699 [ "$TST_NEEDS_ROOT" = 1 ] && tst_require_root 700 701 if [ "$TST_SKIP_IN_SECUREBOOT" = 1 ] && tst_secureboot_enabled; then 702 tst_brk TCONF "SecureBoot enabled, skipping test" 703 fi 704 705 if [ "$TST_SKIP_IN_LOCKDOWN" = 1 ] && tst_lockdown_enabled; then 706 tst_brk TCONF "Kernel is locked down, skipping test" 707 fi 708 709 [ "$TST_DISABLE_APPARMOR" = 1 ] && tst_disable_apparmor 710 [ "$TST_DISABLE_SELINUX" = 1 ] && tst_disable_selinux 711 712 tst_require_cmds $TST_NEEDS_CMDS 713 tst_require_kconfigs "$TST_NEEDS_KCONFIGS" 714 tst_require_drivers $TST_NEEDS_DRIVERS 715 716 if [ -n "$TST_MIN_KVER" ]; then 717 tst_kvcmp -lt "$TST_MIN_KVER" && \ 718 tst_brk TCONF "test requires kernel $TST_MIN_KVER+" 719 fi 720 721 [ -n "$TST_NEEDS_MODULE" ] && tst_require_module "$TST_NEEDS_MODULE" 722 723 [ "$TST_MOUNT_DEVICE" = 1 ] && TST_FORMAT_DEVICE=1 724 [ "$TST_FORMAT_DEVICE" = 1 -o "$TST_ALL_FILESYSTEMS" = 1 ] && TST_NEEDS_DEVICE=1 725 [ "$TST_NEEDS_DEVICE" = 1 ] && TST_NEEDS_TMPDIR=1 726 727 if [ "$TST_NEEDS_TMPDIR" = 1 ]; then 728 if [ -z "$TMPDIR" ]; then 729 export TMPDIR="/tmp" 730 fi 731 732 TST_TMPDIR=$(mktemp -d "$TMPDIR/LTP_$TST_ID.XXXXXXXXXX") 733 # remove possible trailing slash or double slashes from TMPDIR 734 TST_TMPDIR=$(echo "$TST_TMPDIR" | sed 's~/\+~/~g') 735 736 chmod 777 "$TST_TMPDIR" 737 738 TST_STARTWD=$(pwd) 739 cd "$TST_TMPDIR" 740 fi 741 742 # needs to be after cd $TST_TMPDIR to keep test_dev.img under $TST_TMPDIR 743 if [ "$TST_NEEDS_DEVICE" = 1 ]; then 744 TST_DEVICE=$(tst_device acquire) 745 746 if [ ! -b "$TST_DEVICE" -o $? -ne 0 ]; then 747 unset TST_DEVICE 748 tst_brk TBROK "Failed to acquire device" 749 fi 750 TST_DEVICE_FLAG=1 751 752 if [ -z "$TST_FS_TYPE" ]; then 753 export TST_FS_TYPE="${LTP_DEV_FS_TYPE:-ext2}" 754 fi 755 fi 756 757 if [ "$TST_ALL_FILESYSTEMS" != 1 -a "$TST_SKIP_FILESYSTEMS" ]; then 758 if ! tst_supported_fs -s "$TST_SKIP_FILESYSTEMS" -d . > /dev/null; then 759 tst_brk TCONF "filesystem is not supported by the test" 760 fi 761 762 tst_res TINFO "filesystem is supported by the test" 763 fi 764 765 [ -n "$TST_NEEDS_CHECKPOINTS" ] && _tst_init_checkpoints 766 767 TST_MNTPOINT="${TST_MNTPOINT:-$PWD/mntpoint}" 768 769 if [ "$TST_ALL_FILESYSTEMS" = 1 ]; then 770 _tst_run_tcases_per_fs 771 else 772 _tst_run_iterations 773 fi 774 775 _tst_do_exit 776} 777 778_tst_run_iterations() 779{ 780 local _tst_i=$TST_ITERATIONS 781 local _tst_j 782 783 [ "$TST_NEEDS_TMPDIR" = 1 ] && cd "$TST_TMPDIR" 784 785 _prepare_device 786 787 _tst_setup_timer 788 789 if [ -n "$TST_SETUP" ]; then 790 if command -v $TST_SETUP >/dev/null 2>/dev/null; then 791 TST_DO_CLEANUP=1 792 $TST_SETUP 793 else 794 tst_brk TBROK "TST_SETUP=$TST_SETUP declared, but function not defined (or cmd not found)" 795 fi 796 fi 797 798 #TODO check that test reports some results for each test function call 799 while [ $_tst_i -gt 0 ]; do 800 if [ -n "$TST_TEST_DATA" ]; then 801 tst_require_cmds cut tr wc 802 _tst_max=$(( $(echo $TST_TEST_DATA | tr -cd "$TST_TEST_DATA_IFS" | wc -c) +1)) 803 for _tst_j in $(seq $_tst_max); do 804 _tst_data="$(echo "$TST_TEST_DATA" | cut -d"$TST_TEST_DATA_IFS" -f$_tst_j)" 805 _tst_run_tests "$_tst_data" 806 done 807 else 808 _tst_run_tests 809 fi 810 _tst_i=$((_tst_i-1)) 811 done 812 813 _tst_do_cleanup 814 815 if [ "$TST_MOUNT_FLAG" = 1 ]; then 816 cd "$LTPROOT" 817 tst_umount 818 TST_MOUNT_FLAG= 819 fi 820} 821 822_tst_run_tests() 823{ 824 local _tst_data="$1" 825 local _tst_i 826 827 TST_DO_CLEANUP=1 828 for _tst_i in $(seq ${TST_CNT:-1}); do 829 if command -v ${TST_TESTFUNC}1 > /dev/null 2>&1; then 830 _tst_run_test "$TST_TESTFUNC$_tst_i" $_tst_i "$_tst_data" 831 else 832 _tst_run_test "$TST_TESTFUNC" $_tst_i "$_tst_data" 833 fi 834 done 835} 836 837_tst_run_test() 838{ 839 local _tst_res=$(_tst_resstr) 840 local _tst_fnc="$1" 841 shift 842 843 $_tst_fnc "$@" 844 _tst_rescmp "$_tst_res" 845 TST_COUNT=$((TST_COUNT+1)) 846} 847 848export LC_ALL=C 849 850if [ -z "$TST_ID" ]; then 851 _tst_filename=$(basename $0) || \ 852 tst_brk TCONF "Failed to set TST_ID from \$0 ('$0'), fix it with setting TST_ID before sourcing tst_test.sh" 853 TST_ID=${_tst_filename%%.*} 854fi 855export TST_ID="$TST_ID" 856 857if [ -z "$LTPROOT" ]; then 858 export LTPROOT="$PWD" 859 export TST_DATAROOT="$LTPROOT/datafiles" 860else 861 export TST_DATAROOT="$LTPROOT/testcases/data/$TST_ID" 862fi 863 864if [ -z "$TST_NO_DEFAULT_RUN" ]; then 865 if TST_TEST_PATH=$(command -v $0) 2>/dev/null; then 866 if ! grep -q tst_run "$TST_TEST_PATH"; then 867 tst_brk TBROK "Test $0 must call tst_run!" 868 fi 869 fi 870 871 if [ -z "$TST_TESTFUNC" ]; then 872 tst_brk TBROK "TST_TESTFUNC is not defined" 873 fi 874 875 TST_TEST_DATA_IFS="${TST_TEST_DATA_IFS:- }" 876 877 TST_NEEDS_KCONFIGS_IFS="${TST_NEEDS_KCONFIGS_IFS:-,}" 878 879 if [ -n "$TST_CNT" ]; then 880 if ! tst_is_int "$TST_CNT"; then 881 tst_brk TBROK "TST_CNT must be integer" 882 fi 883 884 if [ "$TST_CNT" -le 0 ]; then 885 tst_brk TBROK "TST_CNT must be > 0" 886 fi 887 fi 888 889 if [ -n "$TST_POS_ARGS" ]; then 890 if ! tst_is_int "$TST_POS_ARGS"; then 891 tst_brk TBROK "TST_POS_ARGS must be integer" 892 fi 893 894 if [ "$TST_POS_ARGS" -le 0 ]; then 895 tst_brk TBROK "TST_POS_ARGS must be > 0" 896 fi 897 fi 898 899 TST_ARGS="$@" 900 901 OPTIND=1 902 903 while getopts ":hi:$TST_OPTS" _tst_name $TST_ARGS; do 904 case $_tst_name in 905 'h') tst_usage; exit 0;; 906 'i') TST_ITERATIONS=$OPTARG;; 907 '?') tst_usage; exit 2;; 908 *) $TST_PARSE_ARGS "$_tst_name" "$OPTARG";; 909 esac 910 done 911 912 shift $((OPTIND - 1)) 913 914 if [ -n "$TST_POS_ARGS" ]; then 915 if [ $# -ne "$TST_POS_ARGS" ]; then 916 tst_brk TBROK "Invalid number of positional parameters:"\ 917 "have ($@) $#, expected ${TST_POS_ARGS}" 918 fi 919 else 920 if [ $# -ne 0 ]; then 921 tst_brk TBROK "Unexpected positional arguments '$@'" 922 fi 923 fi 924fi 925