tst_test.sh 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699
  1. #!/bin/sh
  2. # SPDX-License-Identifier: GPL-2.0-or-later
  3. # Copyright (c) Linux Test Project, 2014-2020
  4. # Author: Cyril Hrubis <chrubis@suse.cz>
  5. #
  6. # LTP test library for shell.
  7. [ -n "$TST_LIB_LOADED" ] && return 0
  8. export TST_PASS=0
  9. export TST_FAIL=0
  10. export TST_BROK=0
  11. export TST_WARN=0
  12. export TST_CONF=0
  13. export TST_COUNT=1
  14. export TST_ITERATIONS=1
  15. export TST_TMPDIR_RHOST=0
  16. export TST_LIB_LOADED=1
  17. . tst_ansi_color.sh
  18. . tst_security.sh
  19. # default trap function
  20. trap "tst_brk TBROK 'test interrupted'" INT
  21. _tst_do_exit()
  22. {
  23. local ret=0
  24. TST_DO_EXIT=1
  25. if [ -n "$TST_CLEANUP" -a -z "$TST_NO_CLEANUP" ]; then
  26. $TST_CLEANUP
  27. fi
  28. if [ "$TST_NEEDS_DEVICE" = 1 -a "$TST_DEVICE_FLAG" = 1 ]; then
  29. if ! tst_device release "$TST_DEVICE"; then
  30. tst_res TWARN "Failed to release device '$TST_DEVICE'"
  31. fi
  32. fi
  33. if [ "$TST_NEEDS_TMPDIR" = 1 -a -n "$TST_TMPDIR" ]; then
  34. cd "$LTPROOT"
  35. rm -r "$TST_TMPDIR"
  36. [ "$TST_TMPDIR_RHOST" = 1 ] && tst_cleanup_rhost
  37. fi
  38. if [ -n "$_tst_setup_timer_pid" ]; then
  39. kill $_tst_setup_timer_pid 2>/dev/null
  40. wait $_tst_setup_timer_pid 2>/dev/null
  41. fi
  42. if [ $TST_FAIL -gt 0 ]; then
  43. ret=$((ret|1))
  44. fi
  45. if [ $TST_BROK -gt 0 ]; then
  46. ret=$((ret|2))
  47. fi
  48. if [ $TST_WARN -gt 0 ]; then
  49. ret=$((ret|4))
  50. fi
  51. if [ $TST_CONF -gt 0 -a $TST_PASS -eq 0 ]; then
  52. ret=$((ret|32))
  53. fi
  54. if [ $TST_BROK -gt 0 -o $TST_FAIL -gt 0 -o $TST_WARN -gt 0 ]; then
  55. _tst_check_security_modules
  56. fi
  57. echo
  58. echo "Summary:"
  59. echo "passed $TST_PASS"
  60. echo "failed $TST_FAIL"
  61. echo "skipped $TST_CONF"
  62. echo "warnings $TST_WARN"
  63. exit $ret
  64. }
  65. _tst_inc_res()
  66. {
  67. case "$1" in
  68. TPASS) TST_PASS=$((TST_PASS+1));;
  69. TFAIL) TST_FAIL=$((TST_FAIL+1));;
  70. TBROK) TST_BROK=$((TST_BROK+1));;
  71. TWARN) TST_WARN=$((TST_WARN+1));;
  72. TCONF) TST_CONF=$((TST_CONF+1));;
  73. TINFO) ;;
  74. *) tst_brk TBROK "Invalid res type '$1'";;
  75. esac
  76. }
  77. tst_res()
  78. {
  79. local res=$1
  80. shift
  81. tst_color_enabled
  82. local color=$?
  83. _tst_inc_res "$res"
  84. printf "$TST_ID $TST_COUNT " >&2
  85. tst_print_colored $res "$res: " >&2
  86. echo "$@" >&2
  87. }
  88. tst_brk()
  89. {
  90. local res=$1
  91. shift
  92. if [ "$TST_DO_EXIT" = 1 ]; then
  93. tst_res TWARN "$@"
  94. return
  95. fi
  96. tst_res "$res" "$@"
  97. _tst_do_exit
  98. }
  99. ROD_SILENT()
  100. {
  101. local tst_out="$(tst_rod $@ 2>&1)"
  102. if [ $? -ne 0 ]; then
  103. echo "$tst_out"
  104. tst_brk TBROK "$@ failed"
  105. fi
  106. }
  107. ROD()
  108. {
  109. tst_rod "$@"
  110. if [ $? -ne 0 ]; then
  111. tst_brk TBROK "$@ failed"
  112. fi
  113. }
  114. _tst_expect_pass()
  115. {
  116. local fnc="$1"
  117. shift
  118. tst_rod "$@"
  119. if [ $? -eq 0 ]; then
  120. tst_res TPASS "$@ passed as expected"
  121. return 0
  122. else
  123. $fnc TFAIL "$@ failed unexpectedly"
  124. return 1
  125. fi
  126. }
  127. _tst_expect_fail()
  128. {
  129. local fnc="$1"
  130. shift
  131. # redirect stderr since we expect the command to fail
  132. tst_rod "$@" 2> /dev/null
  133. if [ $? -ne 0 ]; then
  134. tst_res TPASS "$@ failed as expected"
  135. return 0
  136. else
  137. $fnc TFAIL "$@ passed unexpectedly"
  138. return 1
  139. fi
  140. }
  141. EXPECT_PASS()
  142. {
  143. _tst_expect_pass tst_res "$@"
  144. }
  145. EXPECT_PASS_BRK()
  146. {
  147. _tst_expect_pass tst_brk "$@"
  148. }
  149. EXPECT_FAIL()
  150. {
  151. _tst_expect_fail tst_res "$@"
  152. }
  153. EXPECT_FAIL_BRK()
  154. {
  155. _tst_expect_fail tst_brk "$@"
  156. }
  157. TST_RETRY_FN_EXP_BACKOFF()
  158. {
  159. local tst_fun="$1"
  160. local tst_exp=$2
  161. local tst_sec=$(($3 * 1000000))
  162. local tst_delay=1
  163. _tst_multiply_timeout tst_sec
  164. if [ $# -ne 3 ]; then
  165. tst_brk TBROK "TST_RETRY_FN_EXP_BACKOFF expects 3 parameters"
  166. fi
  167. if ! tst_is_int "$tst_sec"; then
  168. tst_brk TBROK "TST_RETRY_FN_EXP_BACKOFF: tst_sec must be integer ('$tst_sec')"
  169. fi
  170. while true; do
  171. eval "$tst_fun"
  172. if [ "$?" = "$tst_exp" ]; then
  173. break
  174. fi
  175. if [ $tst_delay -lt $tst_sec ]; then
  176. tst_sleep ${tst_delay}us
  177. tst_delay=$((tst_delay*2))
  178. else
  179. tst_brk TBROK "\"$tst_fun\" timed out"
  180. fi
  181. done
  182. return $tst_exp
  183. }
  184. TST_RETRY_FUNC()
  185. {
  186. if [ $# -ne 2 ]; then
  187. tst_brk TBROK "TST_RETRY_FUNC expects 2 parameters"
  188. fi
  189. TST_RETRY_FN_EXP_BACKOFF "$1" "$2" 1
  190. return $2
  191. }
  192. TST_RTNL_CHK()
  193. {
  194. local msg1="RTNETLINK answers: Function not implemented"
  195. local msg2="RTNETLINK answers: Operation not supported"
  196. local msg3="RTNETLINK answers: Protocol not supported"
  197. local output="$($@ 2>&1 || echo 'LTP_ERR')"
  198. local msg
  199. echo "$output" | grep -q "LTP_ERR" || return 0
  200. for msg in "$msg1" "$msg2" "$msg3"; do
  201. echo "$output" | grep -q "$msg" && tst_brk TCONF "'$@': $msg"
  202. done
  203. tst_brk TBROK "$@ failed: $output"
  204. }
  205. tst_mount()
  206. {
  207. local mnt_opt mnt_err
  208. if [ -n "$TST_FS_TYPE" ]; then
  209. mnt_opt="-t $TST_FS_TYPE"
  210. mnt_err=" $TST_FS_TYPE type"
  211. fi
  212. ROD_SILENT mkdir -p $TST_MNTPOINT
  213. mount $mnt_opt $TST_DEVICE $TST_MNTPOINT $TST_MNT_PARAMS
  214. local ret=$?
  215. if [ $ret -eq 32 ]; then
  216. tst_brk TCONF "Cannot mount${mnt_err}, missing driver?"
  217. fi
  218. if [ $ret -ne 0 ]; then
  219. tst_brk TBROK "Failed to mount device${mnt_err}: mount exit = $ret"
  220. fi
  221. }
  222. tst_umount()
  223. {
  224. local device="${1:-$TST_DEVICE}"
  225. local i=0
  226. [ -z "$device" ] && return
  227. if ! grep -q "$device" /proc/mounts; then
  228. tst_res TINFO "The $device is not mounted, skipping umount"
  229. return
  230. fi
  231. while [ "$i" -lt 50 ]; do
  232. if umount "$device" > /dev/null; then
  233. return
  234. fi
  235. i=$((i+1))
  236. tst_res TINFO "umount($device) failed, try $i ..."
  237. tst_res TINFO "Likely gvfsd-trash is probing newly mounted "\
  238. "fs, kill it to speed up tests."
  239. tst_sleep 100ms
  240. done
  241. tst_res TWARN "Failed to umount($device) after 50 retries"
  242. }
  243. tst_mkfs()
  244. {
  245. local fs_type=${1:-$TST_FS_TYPE}
  246. local device=${2:-$TST_DEVICE}
  247. [ $# -ge 1 ] && shift
  248. [ $# -ge 1 ] && shift
  249. local fs_opts="$@"
  250. if [ -z "$fs_type" ]; then
  251. tst_brk TBROK "No fs_type specified"
  252. fi
  253. if [ -z "$device" ]; then
  254. tst_brk TBROK "No device specified"
  255. fi
  256. tst_require_cmds mkfs.$fs_type
  257. tst_res TINFO "Formatting $device with $fs_type extra opts='$fs_opts'"
  258. ROD_SILENT mkfs.$fs_type $fs_opts $device
  259. }
  260. tst_cmd_available()
  261. {
  262. if type command > /dev/null 2>&1; then
  263. command -v $1 > /dev/null 2>&1 || return 1
  264. else
  265. which $1 > /dev/null 2>&1
  266. if [ $? -eq 0 ]; then
  267. return 0
  268. elif [ $? -eq 127 ]; then
  269. tst_brk TCONF "missing which command"
  270. else
  271. return 1
  272. fi
  273. fi
  274. }
  275. tst_require_cmds()
  276. {
  277. local cmd
  278. for cmd in $*; do
  279. tst_cmd_available $cmd || tst_brk TCONF "'$cmd' not found"
  280. done
  281. }
  282. tst_check_cmds()
  283. {
  284. local cmd
  285. for cmd in $*; do
  286. if ! tst_cmd_available $cmd; then
  287. tst_res TCONF "'$cmd' not found"
  288. return 1
  289. fi
  290. done
  291. return 0
  292. }
  293. tst_require_drivers()
  294. {
  295. [ $# -eq 0 ] && return 0
  296. local drv
  297. drv="$(tst_check_drivers $@ 2>&1)"
  298. [ $? -ne 0 ] && tst_brk TCONF "$drv driver not available"
  299. return 0
  300. }
  301. tst_is_int()
  302. {
  303. [ "$1" -eq "$1" ] 2>/dev/null
  304. return $?
  305. }
  306. tst_is_num()
  307. {
  308. echo "$1" | grep -Eq '^[-+]?[0-9]+\.?[0-9]*$'
  309. }
  310. tst_usage()
  311. {
  312. if [ -n "$TST_USAGE" ]; then
  313. $TST_USAGE
  314. else
  315. echo "usage: $0"
  316. echo "OPTIONS"
  317. fi
  318. echo "-h Prints this help"
  319. echo "-i n Execute test n times"
  320. }
  321. _tst_resstr()
  322. {
  323. echo "$TST_PASS$TST_FAIL$TST_CONF"
  324. }
  325. _tst_rescmp()
  326. {
  327. local res=$(_tst_resstr)
  328. if [ "$1" = "$res" ]; then
  329. tst_brk TBROK "Test didn't report any results"
  330. fi
  331. }
  332. _tst_multiply_timeout()
  333. {
  334. [ $# -ne 1 ] && tst_brk TBROK "_tst_multiply_timeout expect 1 parameter"
  335. eval "local timeout=\$$1"
  336. LTP_TIMEOUT_MUL=${LTP_TIMEOUT_MUL:-1}
  337. local err="LTP_TIMEOUT_MUL must be number >= 1!"
  338. tst_is_num "$LTP_TIMEOUT_MUL" || tst_brk TBROK "$err ($LTP_TIMEOUT_MUL)"
  339. if ! tst_is_int "$LTP_TIMEOUT_MUL"; then
  340. LTP_TIMEOUT_MUL=$(echo "$LTP_TIMEOUT_MUL" | cut -d. -f1)
  341. LTP_TIMEOUT_MUL=$((LTP_TIMEOUT_MUL+1))
  342. tst_res TINFO "ceiling LTP_TIMEOUT_MUL to $LTP_TIMEOUT_MUL"
  343. fi
  344. [ "$LTP_TIMEOUT_MUL" -ge 1 ] || tst_brk TBROK "$err ($LTP_TIMEOUT_MUL)"
  345. [ "$timeout" -ge 1 ] || tst_brk TBROK "timeout need to be >= 1 ($timeout)"
  346. eval "$1='$((timeout * LTP_TIMEOUT_MUL))'"
  347. return 0
  348. }
  349. _tst_setup_timer()
  350. {
  351. TST_TIMEOUT=${TST_TIMEOUT:-300}
  352. if [ "$TST_TIMEOUT" = -1 ]; then
  353. tst_res TINFO "Timeout per run is disabled"
  354. return
  355. fi
  356. if ! tst_is_int "$TST_TIMEOUT" || [ "$TST_TIMEOUT" -lt 1 ]; then
  357. tst_brk TBROK "TST_TIMEOUT must be int >= 1! ($TST_TIMEOUT)"
  358. fi
  359. local sec=$TST_TIMEOUT
  360. _tst_multiply_timeout sec
  361. local h=$((sec / 3600))
  362. local m=$((sec / 60 % 60))
  363. local s=$((sec % 60))
  364. local pid=$$
  365. tst_res TINFO "timeout per run is ${h}h ${m}m ${s}s"
  366. sleep $sec && tst_res TBROK "test killed, timeout! If you are running on slow machine, try exporting LTP_TIMEOUT_MUL > 1" && kill -9 -$pid &
  367. _tst_setup_timer_pid=$!
  368. }
  369. tst_require_root()
  370. {
  371. if [ "$(id -ru)" != 0 ]; then
  372. tst_brk TCONF "Must be super/root for this test!"
  373. fi
  374. }
  375. tst_require_module()
  376. {
  377. local _tst_module=$1
  378. for tst_module in "$_tst_module" \
  379. "$LTPROOT/testcases/bin/$_tst_module" \
  380. "$TST_STARTWD/$_tst_module"; do
  381. if [ -f "$tst_module" ]; then
  382. TST_MODPATH="$tst_module"
  383. break
  384. fi
  385. done
  386. if [ -z "$TST_MODPATH" ]; then
  387. tst_brk TCONF "Failed to find module '$_tst_module'"
  388. fi
  389. tst_res TINFO "Found module at '$TST_MODPATH'"
  390. }
  391. tst_run()
  392. {
  393. local _tst_i
  394. local _tst_data
  395. local _tst_max
  396. local _tst_name
  397. if [ -n "$TST_TEST_PATH" ]; then
  398. for _tst_i in $(grep '^[^#]*\bTST_' "$TST_TEST_PATH" | sed 's/.*TST_//; s/[="} \t\/:`].*//'); do
  399. case "$_tst_i" in
  400. DISABLE_APPARMOR|DISABLE_SELINUX);;
  401. SETUP|CLEANUP|TESTFUNC|ID|CNT|MIN_KVER);;
  402. OPTS|USAGE|PARSE_ARGS|POS_ARGS);;
  403. NEEDS_ROOT|NEEDS_TMPDIR|TMPDIR|NEEDS_DEVICE|DEVICE);;
  404. NEEDS_CMDS|NEEDS_MODULE|MODPATH|DATAROOT);;
  405. NEEDS_DRIVERS|FS_TYPE|MNTPOINT|MNT_PARAMS);;
  406. IPV6|IPVER|TEST_DATA|TEST_DATA_IFS);;
  407. RETRY_FUNC|RETRY_FN_EXP_BACKOFF|TIMEOUT);;
  408. NET_DATAROOT|NET_MAX_PKT|NET_RHOST_RUN_DEBUG);;
  409. *) tst_res TWARN "Reserved variable TST_$_tst_i used!";;
  410. esac
  411. done
  412. for _tst_i in $(grep '^[^#]*\b_tst_' "$TST_TEST_PATH" | sed 's/.*_tst_//; s/[="} \t\/:`].*//'); do
  413. tst_res TWARN "Private variable or function _tst_$_tst_i used!"
  414. done
  415. fi
  416. OPTIND=1
  417. while getopts ":hi:$TST_OPTS" _tst_name $TST_ARGS; do
  418. case $_tst_name in
  419. 'h') tst_usage; exit 0;;
  420. 'i') TST_ITERATIONS=$OPTARG;;
  421. '?') tst_usage; exit 2;;
  422. *) $TST_PARSE_ARGS "$_tst_name" "$OPTARG";;
  423. esac
  424. done
  425. if ! tst_is_int "$TST_ITERATIONS"; then
  426. tst_brk TBROK "Expected number (-i) not '$TST_ITERATIONS'"
  427. fi
  428. if [ "$TST_ITERATIONS" -le 0 ]; then
  429. tst_brk TBROK "Number of iterations (-i) must be > 0"
  430. fi
  431. [ "$TST_NEEDS_ROOT" = 1 ] && tst_require_root
  432. [ "$TST_DISABLE_APPARMOR" = 1 ] && tst_disable_apparmor
  433. [ "$TST_DISABLE_SELINUX" = 1 ] && tst_disable_selinux
  434. tst_require_cmds $TST_NEEDS_CMDS
  435. tst_require_drivers $TST_NEEDS_DRIVERS
  436. if [ -n "$TST_MIN_KVER" ]; then
  437. tst_kvcmp -lt "$TST_MIN_KVER" && \
  438. tst_brk TCONF "test requires kernel $TST_MIN_KVER+"
  439. fi
  440. _tst_setup_timer
  441. [ "$TST_NEEDS_DEVICE" = 1 ] && TST_NEEDS_TMPDIR=1
  442. if [ "$TST_NEEDS_TMPDIR" = 1 ]; then
  443. if [ -z "$TMPDIR" ]; then
  444. export TMPDIR="/tmp"
  445. fi
  446. TST_TMPDIR=$(mktemp -d "$TMPDIR/LTP_$TST_ID.XXXXXXXXXX")
  447. chmod 777 "$TST_TMPDIR"
  448. TST_STARTWD=$(pwd)
  449. cd "$TST_TMPDIR"
  450. fi
  451. TST_MNTPOINT="${TST_MNTPOINT:-mntpoint}"
  452. if [ "$TST_NEEDS_DEVICE" = 1 ]; then
  453. TST_DEVICE=$(tst_device acquire)
  454. if [ ! -b "$TST_DEVICE" -o $? -ne 0 ]; then
  455. unset TST_DEVICE
  456. tst_brk TBROK "Failed to acquire device"
  457. fi
  458. TST_DEVICE_FLAG=1
  459. fi
  460. [ -n "$TST_NEEDS_MODULE" ] && tst_require_module "$TST_NEEDS_MODULE"
  461. if [ -n "$TST_SETUP" ]; then
  462. $TST_SETUP
  463. fi
  464. #TODO check that test reports some results for each test function call
  465. while [ $TST_ITERATIONS -gt 0 ]; do
  466. if [ -n "$TST_TEST_DATA" ]; then
  467. tst_require_cmds cut tr wc
  468. _tst_max=$(( $(echo $TST_TEST_DATA | tr -cd "$TST_TEST_DATA_IFS" | wc -c) +1))
  469. for _tst_i in $(seq $_tst_max); do
  470. _tst_data="$(echo "$TST_TEST_DATA" | cut -d"$TST_TEST_DATA_IFS" -f$_tst_i)"
  471. _tst_run_tests "$_tst_data"
  472. done
  473. else
  474. _tst_run_tests
  475. fi
  476. TST_ITERATIONS=$((TST_ITERATIONS-1))
  477. done
  478. _tst_do_exit
  479. }
  480. _tst_run_tests()
  481. {
  482. local _tst_data="$1"
  483. local _tst_i
  484. for _tst_i in $(seq ${TST_CNT:-1}); do
  485. if type ${TST_TESTFUNC}1 > /dev/null 2>&1; then
  486. _tst_run_test "$TST_TESTFUNC$_tst_i" $_tst_i "$_tst_data"
  487. else
  488. _tst_run_test "$TST_TESTFUNC" $_tst_i "$_tst_data"
  489. fi
  490. done
  491. }
  492. _tst_run_test()
  493. {
  494. local _tst_res=$(_tst_resstr)
  495. local _tst_fnc="$1"
  496. shift
  497. $_tst_fnc "$@"
  498. _tst_rescmp "$_tst_res"
  499. TST_COUNT=$((TST_COUNT+1))
  500. }
  501. if [ -z "$TST_ID" ]; then
  502. _tst_filename=$(basename $0) || \
  503. tst_brk TCONF "Failed to set TST_ID from \$0 ('$0'), fix it with setting TST_ID before sourcing tst_test.sh"
  504. TST_ID=${_tst_filename%%.*}
  505. fi
  506. export TST_ID="$TST_ID"
  507. if [ -z "$LTPROOT" ]; then
  508. export LTPROOT="$PWD"
  509. export TST_DATAROOT="$LTPROOT/datafiles"
  510. else
  511. export TST_DATAROOT="$LTPROOT/testcases/data/$TST_ID"
  512. fi
  513. if [ -z "$TST_NO_DEFAULT_RUN" ]; then
  514. if TST_TEST_PATH=$(which $0) 2>/dev/null; then
  515. if ! grep -q tst_run "$TST_TEST_PATH"; then
  516. tst_brk TBROK "Test $0 must call tst_run!"
  517. fi
  518. fi
  519. if [ -z "$TST_TESTFUNC" ]; then
  520. tst_brk TBROK "TST_TESTFUNC is not defined"
  521. fi
  522. TST_TEST_DATA_IFS="${TST_TEST_DATA_IFS:- }"
  523. if [ -n "$TST_CNT" ]; then
  524. if ! tst_is_int "$TST_CNT"; then
  525. tst_brk TBROK "TST_CNT must be integer"
  526. fi
  527. if [ "$TST_CNT" -le 0 ]; then
  528. tst_brk TBROK "TST_CNT must be > 0"
  529. fi
  530. fi
  531. if [ -n "$TST_POS_ARGS" ]; then
  532. if ! tst_is_int "$TST_POS_ARGS"; then
  533. tst_brk TBROK "TST_POS_ARGS must be integer"
  534. fi
  535. if [ "$TST_POS_ARGS" -le 0 ]; then
  536. tst_brk TBROK "TST_POS_ARGS must be > 0"
  537. fi
  538. fi
  539. TST_ARGS="$@"
  540. while getopts ":hi:$TST_OPTS" tst_name; do
  541. case $tst_name in
  542. 'h') TST_PRINT_HELP=1;;
  543. *);;
  544. esac
  545. done
  546. shift $((OPTIND - 1))
  547. if [ -n "$TST_POS_ARGS" ]; then
  548. if [ -z "$TST_PRINT_HELP" -a $# -ne "$TST_POS_ARGS" ]; then
  549. tst_brk TBROK "Invalid number of positional parameters:"\
  550. "have ($@) $#, expected ${TST_POS_ARGS}"
  551. fi
  552. else
  553. if [ -z "$TST_PRINT_HELP" -a $# -ne 0 ]; then
  554. tst_brk TBROK "Unexpected positional arguments '$@'"
  555. fi
  556. fi
  557. fi