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