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