libatf-sh.subr revision 275988
1240116Smarcel# Copyright (c) 2007 The NetBSD Foundation, Inc. 2240116Smarcel# All rights reserved. 3240116Smarcel# 4240116Smarcel# Redistribution and use in source and binary forms, with or without 5240116Smarcel# modification, are permitted provided that the following conditions 6240116Smarcel# are met: 7240116Smarcel# 1. Redistributions of source code must retain the above copyright 8240116Smarcel# notice, this list of conditions and the following disclaimer. 9240116Smarcel# 2. Redistributions in binary form must reproduce the above copyright 10240116Smarcel# notice, this list of conditions and the following disclaimer in the 11240116Smarcel# documentation and/or other materials provided with the distribution. 12240116Smarcel# 13240116Smarcel# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND 14240116Smarcel# CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, 15240116Smarcel# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 16240116Smarcel# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17240116Smarcel# IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY 18240116Smarcel# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19240116Smarcel# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 20240116Smarcel# GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21240116Smarcel# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 22240116Smarcel# IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 23240116Smarcel# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 24240116Smarcel# IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25240116Smarcel 26240116Smarcel# ------------------------------------------------------------------------ 27240116Smarcel# GLOBAL VARIABLES 28240116Smarcel# ------------------------------------------------------------------------ 29240116Smarcel 30240116Smarcel# Values for the expect property. 31240116SmarcelExpect=pass 32240116SmarcelExpect_Reason= 33240116Smarcel 34240116Smarcel# A boolean variable that indicates whether we are parsing a test case's 35240116Smarcel# head or not. 36240116SmarcelParsing_Head=false 37240116Smarcel 38240116Smarcel# The program name. 39240116SmarcelProg_Name=${0##*/} 40240116Smarcel 41240116Smarcel# The file to which the test case will print its result. 42240116SmarcelResults_File= 43240116Smarcel 44240116Smarcel# The test program's source directory: i.e. where its auxiliary data files 45240116Smarcel# and helper utilities can be found. Can be overriden through the '-s' flag. 46240116SmarcelSource_Dir="$(dirname ${0})" 47240116Smarcel 48240116Smarcel# Indicates the test case we are currently processing. 49240116SmarcelTest_Case= 50240116Smarcel 51240116Smarcel# List of meta-data variables for the current test case. 52240116SmarcelTest_Case_Vars= 53240116Smarcel 54240116Smarcel# The list of all test cases provided by the test program. 55240116SmarcelTest_Cases= 56240116Smarcel 57240116Smarcel# ------------------------------------------------------------------------ 58240116Smarcel# PUBLIC INTERFACE 59240116Smarcel# ------------------------------------------------------------------------ 60240116Smarcel 61240116Smarcel# 62240116Smarcel# atf_add_test_case tc-name 63240116Smarcel# 64240116Smarcel# Adds the given test case to the list of test cases that form the test 65240116Smarcel# program. The name provided here must be accompanied by two functions 66240116Smarcel# named after it: <tc-name>_head and <tc-name>_body, and optionally by 67240116Smarcel# a <tc-name>_cleanup function. 68240116Smarcel# 69240116Smarcelatf_add_test_case() 70240116Smarcel{ 71240116Smarcel Test_Cases="${Test_Cases} ${1}" 72240116Smarcel} 73240116Smarcel 74240116Smarcel# 75240116Smarcel# atf_check cmd expcode expout experr 76240116Smarcel# 77240116Smarcel# Executes atf-check with given arguments and automatically calls 78240116Smarcel# atf_fail in case of failure. 79240116Smarcel# 80240116Smarcelatf_check() 81240116Smarcel{ 82240116Smarcel ${Atf_Check} "${@}" || \ 83240116Smarcel atf_fail "atf-check failed; see the output of the test for details" 84240116Smarcel} 85240116Smarcel 86240116Smarcel# 87275988Sngie# atf_check_equal expected_expression actual_expression 88240116Smarcel# 89275988Sngie# Checks that expected_expression's value matches actual_expression's 90275988Sngie# and, if not, raises an error. Ideally expected_expression and 91275988Sngie# actual_expression should be provided quoted (not expanded) so that 92275988Sngie# the error message is helpful; otherwise it will only show the values, 93275988Sngie# not the expressions themselves. 94240116Smarcel# 95240116Smarcelatf_check_equal() 96240116Smarcel{ 97240116Smarcel eval _val1=\"${1}\" 98240116Smarcel eval _val2=\"${2}\" 99240116Smarcel test "${_val1}" = "${_val2}" || \ 100240116Smarcel atf_fail "${1} != ${2} (${_val1} != ${_val2})" 101240116Smarcel} 102240116Smarcel 103240116Smarcel# 104240116Smarcel# atf_config_get varname [defvalue] 105240116Smarcel# 106240116Smarcel# Prints the value of a configuration variable. If it is not 107240116Smarcel# defined, prints the given default value. 108240116Smarcel# 109240116Smarcelatf_config_get() 110240116Smarcel{ 111240116Smarcel _varname="__tc_config_var_$(_atf_normalize ${1})" 112240116Smarcel if [ ${#} -eq 1 ]; then 113240116Smarcel eval _value=\"\${${_varname}-__unset__}\" 114240116Smarcel [ "${_value}" = __unset__ ] && \ 115240116Smarcel _atf_error 1 "Could not find configuration variable \`${1}'" 116240116Smarcel echo ${_value} 117240116Smarcel elif [ ${#} -eq 2 ]; then 118240116Smarcel eval echo \${${_varname}-${2}} 119240116Smarcel else 120240116Smarcel _atf_error 1 "Incorrect number of parameters for atf_config_get" 121240116Smarcel fi 122240116Smarcel} 123240116Smarcel 124240116Smarcel# 125240116Smarcel# atf_config_has varname 126240116Smarcel# 127240116Smarcel# Returns a boolean indicating if the given configuration variable is 128240116Smarcel# defined or not. 129240116Smarcel# 130240116Smarcelatf_config_has() 131240116Smarcel{ 132240116Smarcel _varname="__tc_config_var_$(_atf_normalize ${1})" 133240116Smarcel eval _value=\"\${${_varname}-__unset__}\" 134240116Smarcel [ "${_value}" != __unset__ ] 135240116Smarcel} 136240116Smarcel 137240116Smarcel# 138240116Smarcel# atf_expect_death reason 139240116Smarcel# 140240116Smarcel# Sets the expectations to 'death'. 141240116Smarcel# 142240116Smarcelatf_expect_death() 143240116Smarcel{ 144240116Smarcel _atf_validate_expect 145240116Smarcel 146240116Smarcel Expect=death 147240116Smarcel _atf_create_resfile "expected_death: ${*}" 148240116Smarcel} 149240116Smarcel 150240116Smarcel# 151240116Smarcel# atf_expect_timeout reason 152240116Smarcel# 153240116Smarcel# Sets the expectations to 'timeout'. 154240116Smarcel# 155240116Smarcelatf_expect_timeout() 156240116Smarcel{ 157240116Smarcel _atf_validate_expect 158240116Smarcel 159240116Smarcel Expect=timeout 160240116Smarcel _atf_create_resfile "expected_timeout: ${*}" 161240116Smarcel} 162240116Smarcel 163240116Smarcel# 164240116Smarcel# atf_expect_exit exitcode reason 165240116Smarcel# 166240116Smarcel# Sets the expectations to 'exit'. 167240116Smarcel# 168240116Smarcelatf_expect_exit() 169240116Smarcel{ 170240116Smarcel _exitcode="${1}"; shift 171240116Smarcel 172240116Smarcel _atf_validate_expect 173240116Smarcel 174240116Smarcel Expect=exit 175240116Smarcel if [ "${_exitcode}" = "-1" ]; then 176240116Smarcel _atf_create_resfile "expected_exit: ${*}" 177240116Smarcel else 178240116Smarcel _atf_create_resfile "expected_exit(${_exitcode}): ${*}" 179240116Smarcel fi 180240116Smarcel} 181240116Smarcel 182240116Smarcel# 183240116Smarcel# atf_expect_fail reason 184240116Smarcel# 185240116Smarcel# Sets the expectations to 'fail'. 186240116Smarcel# 187240116Smarcelatf_expect_fail() 188240116Smarcel{ 189240116Smarcel _atf_validate_expect 190240116Smarcel 191240116Smarcel Expect=fail 192240116Smarcel Expect_Reason="${*}" 193240116Smarcel} 194240116Smarcel 195240116Smarcel# 196240116Smarcel# atf_expect_pass 197240116Smarcel# 198240116Smarcel# Sets the expectations to 'pass'. 199240116Smarcel# 200240116Smarcelatf_expect_pass() 201240116Smarcel{ 202240116Smarcel _atf_validate_expect 203240116Smarcel 204240116Smarcel Expect=pass 205240116Smarcel Expect_Reason= 206240116Smarcel} 207240116Smarcel 208240116Smarcel# 209240116Smarcel# atf_expect_signal signo reason 210240116Smarcel# 211240116Smarcel# Sets the expectations to 'signal'. 212240116Smarcel# 213240116Smarcelatf_expect_signal() 214240116Smarcel{ 215240116Smarcel _signo="${1}"; shift 216240116Smarcel 217240116Smarcel _atf_validate_expect 218240116Smarcel 219240116Smarcel Expect=signal 220240116Smarcel if [ "${_signo}" = "-1" ]; then 221240116Smarcel _atf_create_resfile "expected_signal: ${*}" 222240116Smarcel else 223240116Smarcel _atf_create_resfile "expected_signal(${_signo}): ${*}" 224240116Smarcel fi 225240116Smarcel} 226240116Smarcel 227240116Smarcel# 228240116Smarcel# atf_expected_failure msg1 [.. msgN] 229240116Smarcel# 230240116Smarcel# Makes the test case report an expected failure with the given error 231240116Smarcel# message. Multiple words can be provided, which are concatenated with 232240116Smarcel# a single blank space. 233240116Smarcel# 234240116Smarcelatf_expected_failure() 235240116Smarcel{ 236240116Smarcel _atf_create_resfile "expected_failure: ${Expect_Reason}: ${*}" 237240116Smarcel exit 0 238240116Smarcel} 239240116Smarcel 240240116Smarcel# 241240116Smarcel# atf_fail msg1 [.. msgN] 242240116Smarcel# 243240116Smarcel# Makes the test case fail with the given error message. Multiple 244240116Smarcel# words can be provided, in which case they are joined by a single 245240116Smarcel# blank space. 246240116Smarcel# 247240116Smarcelatf_fail() 248240116Smarcel{ 249240116Smarcel case "${Expect}" in 250240116Smarcel fail) 251240116Smarcel atf_expected_failure "${@}" 252240116Smarcel ;; 253240116Smarcel pass) 254240116Smarcel _atf_create_resfile "failed: ${*}" 255240116Smarcel exit 1 256240116Smarcel ;; 257240116Smarcel *) 258240116Smarcel _atf_error 128 "Unreachable" 259240116Smarcel ;; 260240116Smarcel esac 261240116Smarcel} 262240116Smarcel 263240116Smarcel# 264240116Smarcel# atf_get varname 265240116Smarcel# 266240116Smarcel# Prints the value of a test case-specific variable. Given that one 267240116Smarcel# should not get the value of non-existent variables, it is fine to 268240116Smarcel# always use this function as 'val=$(atf_get var)'. 269240116Smarcel# 270240116Smarcelatf_get() 271240116Smarcel{ 272240116Smarcel eval echo \${__tc_var_${Test_Case}_$(_atf_normalize ${1})} 273240116Smarcel} 274240116Smarcel 275240116Smarcel# 276240116Smarcel# atf_get_srcdir 277240116Smarcel# 278240116Smarcel# Prints the value of the test case's source directory. 279240116Smarcel# 280240116Smarcelatf_get_srcdir() 281240116Smarcel{ 282240116Smarcel echo ${Source_Dir} 283240116Smarcel} 284240116Smarcel 285240116Smarcel# 286240116Smarcel# atf_pass 287240116Smarcel# 288240116Smarcel# Makes the test case pass. Shouldn't be used in general, as a test 289240116Smarcel# case that does not explicitly fail is assumed to pass. 290240116Smarcel# 291240116Smarcelatf_pass() 292240116Smarcel{ 293240116Smarcel case "${Expect}" in 294240116Smarcel fail) 295240116Smarcel Expect=pass 296240116Smarcel atf_fail "Test case was expecting a failure but got a pass instead" 297240116Smarcel ;; 298240116Smarcel pass) 299240116Smarcel _atf_create_resfile passed 300240116Smarcel exit 0 301240116Smarcel ;; 302240116Smarcel *) 303240116Smarcel _atf_error 128 "Unreachable" 304240116Smarcel ;; 305240116Smarcel esac 306240116Smarcel} 307240116Smarcel 308240116Smarcel# 309240116Smarcel# atf_require_prog prog 310240116Smarcel# 311240116Smarcel# Checks that the given program name (either provided as an absolute 312240116Smarcel# path or as a plain file name) can be found. If it is not available, 313240116Smarcel# automatically skips the test case with an appropriate message. 314240116Smarcel# 315240116Smarcel# Relative paths are not allowed because the test case cannot predict 316240116Smarcel# where it will be executed from. 317240116Smarcel# 318240116Smarcelatf_require_prog() 319240116Smarcel{ 320240116Smarcel _prog= 321240116Smarcel case ${1} in 322240116Smarcel /*) 323240116Smarcel _prog="${1}" 324240116Smarcel [ -x ${_prog} ] || \ 325240116Smarcel atf_skip "The required program ${1} could not be found" 326240116Smarcel ;; 327240116Smarcel */*) 328240116Smarcel atf_fail "atf_require_prog does not accept relative path names \`${1}'" 329240116Smarcel ;; 330240116Smarcel *) 331240116Smarcel _prog=$(_atf_find_in_path "${1}") 332240116Smarcel [ -n "${_prog}" ] || \ 333240116Smarcel atf_skip "The required program ${1} could not be found" \ 334240116Smarcel "in the PATH" 335240116Smarcel ;; 336240116Smarcel esac 337240116Smarcel} 338240116Smarcel 339240116Smarcel# 340240116Smarcel# atf_set varname val1 [.. valN] 341240116Smarcel# 342240116Smarcel# Sets the test case's variable 'varname' to the specified values 343240116Smarcel# which are concatenated using a single blank space. This function 344240116Smarcel# is supposed to be called form the test case's head only. 345240116Smarcel# 346240116Smarcelatf_set() 347240116Smarcel{ 348240116Smarcel ${Parsing_Head} || \ 349240116Smarcel _atf_error 128 "atf_set called from the test case's body" 350240116Smarcel 351240116Smarcel Test_Case_Vars="${Test_Case_Vars} ${1}" 352240116Smarcel _var=$(_atf_normalize ${1}); shift 353240116Smarcel eval __tc_var_${Test_Case}_${_var}=\"\${*}\" 354240116Smarcel} 355240116Smarcel 356240116Smarcel# 357240116Smarcel# atf_skip msg1 [.. msgN] 358240116Smarcel# 359240116Smarcel# Skips the test case because of the reason provided. Multiple words 360240116Smarcel# can be given, in which case they are joined by a single blank space. 361240116Smarcel# 362240116Smarcelatf_skip() 363240116Smarcel{ 364240116Smarcel _atf_create_resfile "skipped: ${*}" 365240116Smarcel exit 0 366240116Smarcel} 367240116Smarcel 368240116Smarcel# 369240116Smarcel# atf_test_case tc-name cleanup 370240116Smarcel# 371240116Smarcel# Defines a new test case named tc-name. The name provided here must be 372240116Smarcel# accompanied by two functions named after it: <tc-name>_head and 373240116Smarcel# <tc-name>_body. If cleanup is set to 'cleanup', then this also expects 374240116Smarcel# a <tc-name>_cleanup function to be defined. 375240116Smarcel# 376240116Smarcelatf_test_case() 377240116Smarcel{ 378240116Smarcel eval "${1}_head() { :; }" 379240116Smarcel eval "${1}_body() { atf_fail 'Test case not implemented'; }" 380240116Smarcel if [ "${2}" = cleanup ]; then 381240116Smarcel eval __has_cleanup_${1}=true 382240116Smarcel eval "${1}_cleanup() { :; }" 383240116Smarcel else 384240116Smarcel eval "${1}_cleanup() { 385240116Smarcel _atf_error 1 'Test case ${1} declared without a cleanup routine'; }" 386240116Smarcel fi 387240116Smarcel} 388240116Smarcel 389240116Smarcel# ------------------------------------------------------------------------ 390240116Smarcel# PRIVATE INTERFACE 391240116Smarcel# ------------------------------------------------------------------------ 392240116Smarcel 393240116Smarcel# 394240116Smarcel# _atf_config_set varname val1 [.. valN] 395240116Smarcel# 396240116Smarcel# Sets the test case's private variable 'varname' to the specified 397240116Smarcel# values which are concatenated using a single blank space. 398240116Smarcel# 399240116Smarcel_atf_config_set() 400240116Smarcel{ 401240116Smarcel _var=$(_atf_normalize ${1}); shift 402240116Smarcel eval __tc_config_var_${_var}=\"\${*}\" 403240116Smarcel Config_Vars="${Config_Vars} __tc_config_var_${_var}" 404240116Smarcel} 405240116Smarcel 406240116Smarcel# 407240116Smarcel# _atf_config_set_str varname=val 408240116Smarcel# 409240116Smarcel# Sets the test case's private variable 'varname' to the specified 410240116Smarcel# value. The parameter is of the form 'varname=val'. 411240116Smarcel# 412240116Smarcel_atf_config_set_from_str() 413240116Smarcel{ 414240116Smarcel _oldifs=${IFS} 415240116Smarcel IFS='=' 416240116Smarcel set -- ${*} 417240116Smarcel _var=${1} 418240116Smarcel shift 419240116Smarcel _val="${@}" 420240116Smarcel IFS=${_oldifs} 421240116Smarcel _atf_config_set "${_var}" "${_val}" 422240116Smarcel} 423240116Smarcel 424240116Smarcel# 425240116Smarcel# _atf_create_resfile contents 426240116Smarcel# 427240116Smarcel# Creates the results file. 428240116Smarcel# 429240116Smarcel_atf_create_resfile() 430240116Smarcel{ 431240116Smarcel if [ -n "${Results_File}" ]; then 432240116Smarcel echo "${*}" >"${Results_File}" || \ 433240116Smarcel _atf_error 128 "Cannot create results file '${Results_File}'" 434240116Smarcel else 435240116Smarcel echo "${*}" 436240116Smarcel fi 437240116Smarcel} 438240116Smarcel 439240116Smarcel# 440240116Smarcel# _atf_error error_code [msg1 [.. msgN]] 441240116Smarcel# 442240116Smarcel# Prints the given error message (which can be composed of multiple 443240116Smarcel# arguments, in which case are joined by a single space) and exits 444240116Smarcel# with the specified error code. 445240116Smarcel# 446240116Smarcel# This must not be used by test programs themselves (hence making 447240116Smarcel# the function private) to indicate a test case's failure. They 448240116Smarcel# have to use the atf_fail function. 449240116Smarcel# 450240116Smarcel_atf_error() 451240116Smarcel{ 452240116Smarcel _error_code="${1}"; shift 453240116Smarcel 454240116Smarcel echo "${Prog_Name}: ERROR:" "$@" 1>&2 455240116Smarcel exit ${_error_code} 456240116Smarcel} 457240116Smarcel 458240116Smarcel# 459240116Smarcel# _atf_warning msg1 [.. msgN] 460240116Smarcel# 461240116Smarcel# Prints the given warning message (which can be composed of multiple 462240116Smarcel# arguments, in which case are joined by a single space). 463240116Smarcel# 464240116Smarcel_atf_warning() 465240116Smarcel{ 466240116Smarcel echo "${Prog_Name}: WARNING:" "$@" 1>&2 467240116Smarcel} 468240116Smarcel 469240116Smarcel# 470240116Smarcel# _atf_find_in_path program 471240116Smarcel# 472240116Smarcel# Looks for a program in the path and prints the full path to it or 473240116Smarcel# nothing if it could not be found. It also returns true in case of 474240116Smarcel# success. 475240116Smarcel# 476240116Smarcel_atf_find_in_path() 477240116Smarcel{ 478240116Smarcel _prog="${1}" 479240116Smarcel 480240116Smarcel _oldifs=${IFS} 481240116Smarcel IFS=: 482240116Smarcel for _dir in ${PATH} 483240116Smarcel do 484240116Smarcel if [ -x ${_dir}/${_prog} ]; then 485240116Smarcel IFS=${_oldifs} 486240116Smarcel echo ${_dir}/${_prog} 487240116Smarcel return 0 488240116Smarcel fi 489240116Smarcel done 490240116Smarcel IFS=${_oldifs} 491240116Smarcel 492240116Smarcel return 1 493240116Smarcel} 494240116Smarcel 495240116Smarcel# 496240116Smarcel# _atf_has_tc name 497240116Smarcel# 498240116Smarcel# Returns true if the given test case exists. 499240116Smarcel# 500240116Smarcel_atf_has_tc() 501240116Smarcel{ 502240116Smarcel for _tc in ${Test_Cases}; do 503240116Smarcel [ "${_tc}" != "${1}" ] || return 0 504240116Smarcel done 505240116Smarcel return 1 506240116Smarcel} 507240116Smarcel 508240116Smarcel# 509240116Smarcel# _atf_list_tcs 510240116Smarcel# 511240116Smarcel# Describes all test cases and prints the list to the standard output. 512240116Smarcel# 513240116Smarcel_atf_list_tcs() 514240116Smarcel{ 515240116Smarcel echo 'Content-Type: application/X-atf-tp; version="1"' 516240116Smarcel echo 517240116Smarcel 518240116Smarcel set -- ${Test_Cases} 519240116Smarcel while [ ${#} -gt 0 ]; do 520240116Smarcel _atf_parse_head ${1} 521240116Smarcel 522240116Smarcel echo "ident: $(atf_get ident)" 523240116Smarcel for _var in ${Test_Case_Vars}; do 524240116Smarcel [ "${_var}" != "ident" ] && echo "${_var}: $(atf_get ${_var})" 525240116Smarcel done 526240116Smarcel 527240116Smarcel [ ${#} -gt 1 ] && echo 528240116Smarcel shift 529240116Smarcel done 530240116Smarcel} 531240116Smarcel 532240116Smarcel# 533240116Smarcel# _atf_normalize str 534240116Smarcel# 535240116Smarcel# Normalizes a string so that it is a valid shell variable name. 536240116Smarcel# 537240116Smarcel_atf_normalize() 538240116Smarcel{ 539240116Smarcel echo ${1} | tr .- __ 540240116Smarcel} 541240116Smarcel 542240116Smarcel# 543240116Smarcel# _atf_parse_head tcname 544240116Smarcel# 545240116Smarcel# Evaluates a test case's head to gather its variables and prepares the 546240116Smarcel# test program to run it. 547240116Smarcel# 548240116Smarcel_atf_parse_head() 549240116Smarcel{ 550240116Smarcel Parsing_Head=true 551240116Smarcel 552240116Smarcel Test_Case="${1}" 553240116Smarcel Test_Case_Vars= 554240116Smarcel 555240116Smarcel if _atf_has_cleanup "${1}"; then 556240116Smarcel atf_set has.cleanup "true" 557240116Smarcel fi 558240116Smarcel 559240116Smarcel ${1}_head 560240116Smarcel atf_set ident "${1}" 561240116Smarcel 562240116Smarcel Parsing_Head=false 563240116Smarcel} 564240116Smarcel 565240116Smarcel# 566240116Smarcel# _atf_run_tc tc 567240116Smarcel# 568240116Smarcel# Runs the specified test case. Prints its exit status to the 569240116Smarcel# standard output and returns a boolean indicating if the test was 570240116Smarcel# successful or not. 571240116Smarcel# 572240116Smarcel_atf_run_tc() 573240116Smarcel{ 574240116Smarcel case ${1} in 575240116Smarcel *:*) 576240116Smarcel _tcname=${1%%:*} 577240116Smarcel _tcpart=${1#*:} 578240116Smarcel 579240116Smarcel if [ "${_tcpart}" != body -a "${_tcpart}" != cleanup ]; then 580240116Smarcel _atf_syntax_error "Unknown test case part \`${_tcpart}'" 581240116Smarcel fi 582240116Smarcel ;; 583240116Smarcel 584240116Smarcel *) 585240116Smarcel _tcname=${1} 586240116Smarcel _tcpart=body 587240116Smarcel ;; 588240116Smarcel esac 589240116Smarcel 590240116Smarcel _atf_has_tc "${_tcname}" || _atf_syntax_error "Unknown test case \`${1}'" 591240116Smarcel 592240116Smarcel if [ "${__RUNNING_INSIDE_ATF_RUN}" != "internal-yes-value" ]; then 593275988Sngie _atf_warning "Running test cases outside of kyua(1) is unsupported" 594240116Smarcel _atf_warning "No isolation nor timeout control is being applied;" \ 595240116Smarcel "you may get unexpected failures; see atf-test-case(4)" 596240116Smarcel fi 597240116Smarcel 598240116Smarcel _atf_parse_head ${_tcname} 599240116Smarcel 600240116Smarcel case ${_tcpart} in 601240116Smarcel body) 602240116Smarcel if ${_tcname}_body; then 603240116Smarcel _atf_validate_expect 604240116Smarcel _atf_create_resfile passed 605240116Smarcel else 606240116Smarcel Expect=pass 607240116Smarcel atf_fail "Test case body returned a non-ok exit code, but" \ 608240116Smarcel "this is not allowed" 609240116Smarcel fi 610240116Smarcel ;; 611240116Smarcel cleanup) 612240116Smarcel if _atf_has_cleanup "${_tcname}"; then 613240116Smarcel ${_tcname}_cleanup || _atf_error 128 "The test case cleanup" \ 614240116Smarcel "returned a non-ok exit code, but this is not allowed" 615240116Smarcel fi 616240116Smarcel ;; 617240116Smarcel *) 618240116Smarcel _atf_error 128 "Unknown test case part" 619240116Smarcel ;; 620240116Smarcel esac 621240116Smarcel} 622240116Smarcel 623240116Smarcel# 624240116Smarcel# _atf_syntax_error msg1 [.. msgN] 625240116Smarcel# 626240116Smarcel# Formats and prints a syntax error message and terminates the 627240116Smarcel# program prematurely. 628240116Smarcel# 629240116Smarcel_atf_syntax_error() 630240116Smarcel{ 631240116Smarcel echo "${Prog_Name}: ERROR: ${@}" 1>&2 632240116Smarcel echo "${Prog_Name}: See atf-test-program(1) for usage details." 1>&2 633240116Smarcel exit 1 634240116Smarcel} 635240116Smarcel 636240116Smarcel# 637240116Smarcel# _atf_has_cleanup tc-name 638240116Smarcel# 639240116Smarcel# Returns a boolean indicating if the given test case has a cleanup 640240116Smarcel# routine or not. 641240116Smarcel# 642240116Smarcel_atf_has_cleanup() 643240116Smarcel{ 644240116Smarcel _found=true 645240116Smarcel eval "[ x\"\${__has_cleanup_${1}}\" = xtrue ] || _found=false" 646240116Smarcel [ "${_found}" = true ] 647240116Smarcel} 648240116Smarcel 649240116Smarcel# 650240116Smarcel# _atf_validate_expect 651240116Smarcel# 652240116Smarcel# Ensures that the current test case state is correct regarding the expect 653240116Smarcel# status. 654240116Smarcel# 655240116Smarcel_atf_validate_expect() 656240116Smarcel{ 657240116Smarcel case "${Expect}" in 658240116Smarcel death) 659240116Smarcel Expect=pass 660240116Smarcel atf_fail "Test case was expected to terminate abruptly but it" \ 661240116Smarcel "continued execution" 662240116Smarcel ;; 663240116Smarcel exit) 664240116Smarcel Expect=pass 665240116Smarcel atf_fail "Test case was expected to exit cleanly but it continued" \ 666240116Smarcel "execution" 667240116Smarcel ;; 668240116Smarcel fail) 669240116Smarcel Expect=pass 670240116Smarcel atf_fail "Test case was expecting a failure but none were raised" 671240116Smarcel ;; 672240116Smarcel pass) 673240116Smarcel ;; 674240116Smarcel signal) 675240116Smarcel Expect=pass 676240116Smarcel atf_fail "Test case was expected to receive a termination signal" \ 677240116Smarcel "but it continued execution" 678240116Smarcel ;; 679240116Smarcel timeout) 680240116Smarcel Expect=pass 681240116Smarcel atf_fail "Test case was expected to hang but it continued execution" 682240116Smarcel ;; 683240116Smarcel *) 684240116Smarcel _atf_error 128 "Unreachable" 685240116Smarcel ;; 686240116Smarcel esac 687240116Smarcel} 688240116Smarcel 689240116Smarcel# 690240116Smarcel# _atf_warning [msg1 [.. msgN]] 691240116Smarcel# 692240116Smarcel# Prints the given warning message (which can be composed of multiple 693240116Smarcel# arguments, in which case are joined by a single space). 694240116Smarcel# 695240116Smarcel# This must not be used by test programs themselves (hence making 696240116Smarcel# the function private). 697240116Smarcel# 698240116Smarcel_atf_warning() 699240116Smarcel{ 700240116Smarcel echo "${Prog_Name}: WARNING:" "$@" 1>&2 701240116Smarcel} 702240116Smarcel 703240116Smarcel# 704240116Smarcel# main [options] test_case 705240116Smarcel# 706240116Smarcel# Test program's entry point. 707240116Smarcel# 708240116Smarcelmain() 709240116Smarcel{ 710240116Smarcel # Process command-line options first. 711240116Smarcel _numargs=${#} 712240116Smarcel _lflag=false 713240116Smarcel while getopts :lr:s:v: arg; do 714240116Smarcel case ${arg} in 715240116Smarcel l) 716240116Smarcel _lflag=true 717240116Smarcel ;; 718240116Smarcel 719240116Smarcel r) 720240116Smarcel Results_File=${OPTARG} 721240116Smarcel ;; 722240116Smarcel 723240116Smarcel s) 724240116Smarcel Source_Dir=${OPTARG} 725240116Smarcel ;; 726240116Smarcel 727240116Smarcel v) 728240116Smarcel _atf_config_set_from_str "${OPTARG}" 729240116Smarcel ;; 730240116Smarcel 731240116Smarcel \?) 732240116Smarcel _atf_syntax_error "Unknown option -${OPTARG}." 733240116Smarcel # NOTREACHED 734240116Smarcel ;; 735240116Smarcel esac 736240116Smarcel done 737240116Smarcel shift `expr ${OPTIND} - 1` 738240116Smarcel 739240116Smarcel case ${Source_Dir} in 740240116Smarcel /*) 741240116Smarcel ;; 742240116Smarcel *) 743240116Smarcel Source_Dir=$(pwd)/${Source_Dir} 744240116Smarcel ;; 745240116Smarcel esac 746240116Smarcel [ -f ${Source_Dir}/${Prog_Name} ] || \ 747240116Smarcel _atf_error 1 "Cannot find the test program in the source" \ 748240116Smarcel "directory \`${Source_Dir}'" 749240116Smarcel 750240116Smarcel # Call the test program's hook to register all available test cases. 751240116Smarcel atf_init_test_cases 752240116Smarcel 753240116Smarcel # Run or list test cases. 754240116Smarcel if `${_lflag}`; then 755240116Smarcel if [ ${#} -gt 0 ]; then 756240116Smarcel _atf_syntax_error "Cannot provide test case names with -l" 757240116Smarcel fi 758240116Smarcel _atf_list_tcs 759240116Smarcel else 760240116Smarcel if [ ${#} -eq 0 ]; then 761240116Smarcel _atf_syntax_error "Must provide a test case name" 762240116Smarcel elif [ ${#} -gt 1 ]; then 763240116Smarcel _atf_syntax_error "Cannot provide more than one test case name" 764240116Smarcel else 765240116Smarcel _atf_run_tc "${1}" 766240116Smarcel fi 767240116Smarcel fi 768240116Smarcel} 769240116Smarcel 770240116Smarcel# vim: syntax=sh:expandtab:shiftwidth=4:softtabstop=4 771