Sync usage with man page.
[netbsd-mini2440.git] / external / bsd / atf / dist / atf-sh / atf.footer.subr
blob2a11d5f6bb41d7c2a9302af44655fd432040cf31
2 # Automated Testing Framework (atf)
4 # Copyright (c) 2007, 2008 The NetBSD Foundation, Inc.
5 # All rights reserved.
7 # Redistribution and use in source and binary forms, with or without
8 # modification, are permitted provided that the following conditions
9 # are met:
10 # 1. Redistributions of source code must retain the above copyright
11 #    notice, this list of conditions and the following disclaimer.
12 # 2. Redistributions in binary form must reproduce the above copyright
13 #    notice, this list of conditions and the following disclaimer in the
14 #    documentation and/or other materials provided with the distribution.
16 # THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND
17 # CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
18 # INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19 # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 # IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY
21 # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
23 # GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
25 # IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
26 # OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27 # IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 # File: atf.footer.subr
33 #   This file provides the test program's entry point and auxiliary
34 #   functions used during testing.
37 # ------------------------------------------------------------------------
38 # GLOBAL VARIABLES
39 # ------------------------------------------------------------------------
41 # Values of configuration variables obtained from atf-config.
42 Atf_Arch=$(atf-config -t atf_arch)
43 Atf_Cleanup=$(atf-config -t atf_libexecdir)/atf-cleanup
44 Atf_Exec=$(atf-config -t atf_libexecdir)/atf-exec
45 Atf_Format=$(atf-config -t atf_libexecdir)/atf-format
46 Atf_Machine=$(atf-config -t atf_machine)
48 # List of configuration variables set through the command line.  Needed
49 # during shortcut execution.
50 Config_Vars=
52 # List of blocked signals, to be processed when unblocked.
53 Held_Signals=
55 # A boolean variable that indicates whether we are parsing a test case's
56 # head or not.
57 Parsing_Head=false
59 # The file descriptor on which the test program will print the results of
60 # the test cases.
61 Results_Fd=1
63 # The file to which the test case will print its result.
64 Results_File=
66 # The test program's source directory: i.e. where its auxiliary data files
67 # and helper utilities can be found.  Defaults to the current directory
68 # but can be overriden through the '-s' flag.
69 Source_Dir=.
71 # Indicates the test case we are currently processing.
72 Test_Case=
74 # The list of all test cases provided by the test program.
75 # Subset of ${Defined_Test_Cases}.
76 Test_Cases=
78 # The test case's work directory.  The semantics of this variable are a
79 # bit screwed.  When running the parent program (not the test case's body),
80 # this points to the test _program_'s directory.  When we have reexecuted
81 # the code through _atf_shortcut_exec, this points to the test _case_'s
82 # work directory, which is a subdirectory of the other one.
83 Work_Dir=
85 # ------------------------------------------------------------------------
86 # PUBLIC INTERFACE
87 # ------------------------------------------------------------------------
90 # atf_add_test_case tc-name
92 #   Adds the given test case to the list of test cases that form the test
93 #   program.  The name provided here must be accompanied by two functions
94 #   named after it: <tc-name>_head and <tc-name>_body, and optionally by
95 #   a <tc-name>_cleanup function.
97 atf_add_test_case()
99     _atf_is_tc_defined "${1}" || \
100         _atf_error 128 "Test case ${1} was not correctly defined by" \
101                        "this test program"
102     Test_Cases="${Test_Cases} ${1}"
106 # atf_check cmd expcode expout experr
108 #   Executes atf-check with given arguments and automatically calls
109 #   atf_fail in case of failure.
111 atf_check()
113     atf-check "${@}" || \
114         atf_fail "atf-check failed; see the output of the test for details"
118 # atf_check_equal expr1 expr2
120 #   Checks that expr1's value matches expr2's and, if not, raises an
121 #   error.  Ideally expr1 and expr2 should be provided quoted (not
122 #   expanded) so that the error message is helpful; otherwise it will
123 #   only show the values, not the expressions themselves.
125 atf_check_equal()
127     eval _val1=\"${1}\"
128     eval _val2=\"${2}\"
129     test "${_val1}" = "${_val2}" || \
130         atf_fail "${1} != ${2} (${_val1} != ${_val2})"
134 # atf_config_get varname [defvalue]
136 #   Prints the value of a configuration variable.  If it is not
137 #   defined, prints the given default value.
139 atf_config_get()
141     _varname="__tc_config_var_$(_atf_normalize ${1})"
142     if [ ${#} -eq 1 ]; then
143         eval _value=\"\${${_varname}-__unset__}\"
144         [ "${_value}" = __unset__ ] && \
145             _atf_error 1 "Could not find configuration variable \`${1}'"
146         echo ${_value}
147     elif [ ${#} -eq 2 ]; then
148         eval echo \${${_varname}-${2}}
149     else
150         _atf_error 1 "Incorrect number of parameters for atf_config_get"
151     fi
155 # atf_config_has varname
157 #   Returns a boolean indicating if the given configuration variable is
158 #   defined or not.
160 atf_config_has()
162     _varname="__tc_config_var_$(_atf_normalize ${1})"
163     eval _value=\"\${${_varname}-__unset__}\"
164     [ "${_value}" != __unset__ ]
168 # atf_fail msg1 [.. msgN]
170 #   Makes the test case fail with the given error message.  Multiple
171 #   words can be provided, in which case they are joined by a single
172 #   blank space.
174 atf_fail()
176     echo "failed, ${*}" >>${Results_File}
177     exit 1
181 # atf_get varname
183 #   Prints the value of a test case-specific variable.  Given that one
184 #   should not get the value of non-existent variables, it is fine to
185 #   always use this function as 'val=$(atf_get var)'.
187 atf_get()
189     eval echo \${__tc_var_${Test_Case}_$(_atf_normalize ${1})}
193 # atf_get_srcdir
195 #   Prints the value of the test case's source directory.
197 atf_get_srcdir()
199     _atf_internal_get srcdir
203 # atf_pass msg1 [.. msgN]
205 #   Makes the test case pass.  Shouldn't be used in general, as a test
206 #   case that does not explicitly fail is assumed to pass.
208 atf_pass()
210     echo "passed" >>${Results_File}
211     exit 0
215 # atf_require_prog prog
217 #   Checks that the given program name (either provided as an absolute
218 #   path or as a plain file name) can be found.  If it is not available,
219 #   automatically skips the test case with an appropriate message.
221 #   Relative paths are not allowed because the test case cannot predict
222 #   where it will be executed from.
224 atf_require_prog()
226     _prog=
227     case ${1} in
228     /*)
229         _prog="${1}"
230         [ -x ${_prog} ] || \
231             atf_skip "The required program ${1} could not be found"
232         ;;
233     */*)
234         _atf_error 128 "atf_require_prog does not accept relative" \
235                        "path names \`${1}'"
236         ;;
237     *)
238         _prog=$(_atf_find_in_path "${1}")
239         [ -n "${_prog}" ] || \
240             atf_skip "The required program ${1} could not be found" \
241                      "in the PATH"
242         ;;
243     esac
247 # atf_set varname val1 [.. valN]
249 #   Sets the test case's variable 'varname' to the specified values
250 #   which are concatenated using a single blank space.  This function
251 #   is supposed to be called form the test case's head only.
253 atf_set()
255     ${Parsing_Head} || \
256         _atf_error 128 "atf_set called from the test case's body"
258     _var=$(_atf_normalize ${1}); shift
259     eval __tc_var_${Test_Case}_${_var}=\"\${*}\"
263 # atf_skip msg1 [.. msgN]
265 #   Skips the test case because of the reason provided.  Multiple words
266 #   can be given, in which case they are joined by a single blank space.
268 atf_skip()
270     echo "skipped, ${*}" >>${Results_File}
271     exit 0
274 # ------------------------------------------------------------------------
275 # PRIVATE INTERFACE
276 # ------------------------------------------------------------------------
279 # _atf_config_set varname val1 [.. valN]
281 #   Sets the test case's private variable 'varname' to the specified
282 #   values which are concatenated using a single blank space.
284 _atf_config_set()
286     _var=$(_atf_normalize ${1}); shift
287     eval __tc_config_var_${_var}=\"\${*}\"
288     Config_Vars="${Config_Vars} __tc_config_var_${_var}"
292 # _atf_config_set_str varname=val
294 #   Sets the test case's private variable 'varname' to the specified
295 #   value.  The parameter is of the form 'varname=val'.
297 _atf_config_set_from_str()
299     _oldifs=${IFS}
300     IFS='='
301     set -- ${*}
302     _var=${1}
303     shift
304     _val="${@}"
305     IFS=${_oldifs}
306     _atf_config_set "${_var}" "${_val}"
310 # _atf_echo [-l indent] [-t tag] [msg1 [.. msgN]]
312 #   Prints a formatted message using atf-format(1).  See its manual
313 #   page for details on the syntax of this function.
315 _atf_echo()
317     ${Atf_Format} "${@}"
321 # _atf_ensure_boolean var
323 #   Ensures that the test case defined the variable 'var' to a boolean
324 #   value.
326 _atf_ensure_boolean()
328     _atf_ensure_not_empty ${1}
330     case $(atf_get ${1}) in
331     [Yy][Ee][Ss]|[Tt][Rr][Uu][Ee])
332         atf_set ${1} true
333         ;;
334     [Nn][Oo]|[Ff][Aa][Ll][Ss][Ee])
335         atf_set ${1} false
336         ;;
337     *)
338         _atf_error 128 "Invalid value for boolean variable \`${1}'"
339         ;;
340     esac
344 # _atf_ensure_integral var
346 #   Ensures that the test case defined the variable 'var' to an integral
347 #   value.
349 _atf_ensure_integral()
351     _atf_ensure_not_empty ${1}
353     case $(atf_get ${1}) in
354     [0-9]*)
355         ;;
356     *)
357         _atf_error 128 "Invalid value for integral variable \`${1}'"
358         ;;
359     esac
363 # _atf_ensure_not_empty var
365 #   Ensures that the test case defined the variable 'var' to a non-empty
366 #   value.
368 _atf_ensure_not_empty()
370     [ -n "$(atf_get ${1})" ] || \
371         _atf_error 128 "Undefined or empty variable \`${1}'"
375 # _atf_error error_code [msg1 [.. msgN]]
377 #   Prints the given error message (which can be composed of multiple
378 #   arguments, in which case are joined by a single space) and exits
379 #   with the specified error code.
381 #   This must not be used by test programs themselves (hence making
382 #   the function private) to indicate a test case's failure.  They
383 #   have to use the atf_fail function.
385 _atf_error()
387     _error_code="${1}"; shift
389     _atf_echo -r -t "${Prog_Name}: " "ERROR:" "$@" 1>&2
390     exit ${_error_code}
394 # _atf_expand_glob glob
396 #   Prints all test case identifiers that match the provided glob
397 #   pattern.
399 _atf_expand_glob()
401     _glob="${1}"
402     _matched=""
403     set -- ${Test_Cases}
404     while [ ${#} -gt 0 ]; do
405         case "${1}" in
406         ${_glob}) _matched="${_matched} ${1}" ;;
407         *) ;;
408         esac
410         shift
411     done
413     set -- ${_matched}
414     while [ ${#} -gt 0 ]; do
415         echo ${1}
416         shift
417     done
421 # _atf_get_bool varname
423 #   Evaluates a test case-specific variable as a boolean and returns its
424 #   value.
426 _atf_get_bool()
428     eval $(atf_get ${1})
432 # _atf_init_output [tc1 .. tcN]
434 #   Initializes the descriptor where we will send the test case's
435 #   results.
437 _atf_init_output()
439     echo "Content-Type: application/X-atf-tcs; version=\"1\"" \
440         >&${Results_Fd}
441     echo "" >&${Results_Fd}
442     echo "tcs-count: ${#}" >&${Results_Fd}
446 # _atf_internal_get varname
448 #   Prints the value of a test case-specific internal variable.  Given
449 #   that one should not get the value of non-existent variables, it is
450 #   fine to always use this function as 'val=$(_atf_internal_get var)'.
452 _atf_internal_get()
454     eval echo \${__tc_internal_var_${Test_Case}_${1}}
458 # _atf_internal_set varname val1 [.. valN]
460 #   Sets the test case's private variable 'varname' to the specified
461 #   values which are concatenated using a single blank space.
463 _atf_internal_set()
465     _var=${1}; shift
466     eval __tc_internal_var_${Test_Case}_${_var}=\"\${*}\"
470 # _atf_list_tcs [tc1 .. tcN]
472 #   Describes all given test cases and prints the list to the standard
473 #   output.
475 _atf_list_tcs()
477     # Calculate the length of the longest test case name.  Needed for
478     # correct indentation later on.
479     _maxlen=0
480     for _tc in ${*}; do
481         if [ ${#_tc} -gt ${_maxlen} ]; then
482             _maxlen=${#_tc}
483         fi
484     done
486     # Print the list of test cases.
487     _maxlen=$((${_maxlen} + 4))
488     for _tc in ${*}; do
489         _atf_parse_head ${_tc}
490         _atf_echo -t ${_tc} -l ${_maxlen} $(atf_get descr)
491     done
495 # _atf_normalize str
497 #   Normalizes a string so that it is a valid shell variable name.
499 _atf_normalize()
501     echo ${1} | tr .- __
505 # _atf_parse_head tcname
507 #   Evaluates a test case's head to gather its variables and prepares the
508 #   test program to run it.
510 _atf_parse_head()
512     ${Parsing_Head} && _atf_error 128 "_atf_parse_head called recursively"
513     Parsing_Head=true
515     Test_Case="${1}"
517     atf_set ident "${1}"
518     atf_set timeout 300
519     ${1}_head
520     _atf_ensure_not_empty descr
521     _atf_ensure_not_empty ident
522     _atf_ensure_integral timeout
523     test $(atf_get ident) = "${1}" || \
524         _atf_error 128 "Test case redefined ident"
526     Parsing_Head=false
530 # _atf_parse_props tc
532 #   Runs a test case's body but, before that, handles the default
533 #   properties.  This function must be run in a subshell because the
534 #   test case is designed to abruptly exit the shell when any of
535 #   atf_pass, atf_skip or atf_fail are executed.
537 _atf_run_body()
539     HOME=$(pwd)
540     export HOME
541     unset LANG
542     unset LC_ALL
543     unset LC_COLLATE
544     unset LC_CTYPE
545     unset LC_MESSAGES
546     unset LC_MONETARY
547     unset LC_NUMERIC
548     unset LC_TIME
549     unset TZ
551     umask 0022
553     _arches=$(atf_get require.arch)
554     if [ -n "${_arches}" ]; then
555         found=no
556         for _a in ${_arches}; do
557             if [ ${_a} = ${Atf_Arch} ]; then
558                 found=yes
559                 break
560             fi
561         done
562         [ ${found} = yes ] || \
563             atf_skip "Requires one of the '${_arches}' architectures"
564     fi
566     _machines=$(atf_get require.machine)
567     if [ -n "${_machines}" ]; then
568         found=no
569         for _m in ${_machines}; do
570             if [ ${_m} = ${Atf_Machine} ]; then
571                 found=yes
572                 break
573             fi
574         done
575         [ ${found} = yes ] || \
576             atf_skip "Requires one of the '${_machines}' machine types"
577     fi
579     _vars="$(atf_get require.config)"
580     if [ -n "${_vars}" ]; then
581         for _v in ${_vars}; do
582             if ! atf_config_has ${_v}; then
583                 atf_skip "Required configuration variable ${_v} not defined"
584             fi
585         done
586     fi
588     _progs="$(atf_get require.progs)"
589     if [ -n "${_progs}" ]; then
590         for _p in ${_progs}; do
591             atf_require_prog ${_p}
592         done
593     fi
595     case $(atf_get require.user) in
596     root)
597         [ $(id -u) -eq 0 ] || \
598             atf_skip "Requires root privileges"
599         ;;
600     unprivileged)
601         [ $(id -u) -ne 0 ] || \
602             atf_skip "Requires an unprivileged user"
603         ;;
604     "")
605         ;;
606     *)
607         atf_fail "Invalid value in the require.user property"
608         ;;
609     esac
611     # Previous versions of this code reverted all signal handlers to their
612     # default behavior at this point.  We do not need to do this any more
613     # because this piece of code is run in a clean sub-shell (through the
614     # _atf_shortcut_exec call), i.e. a completely re-executed shell, and
615     # we have not messed with signal handlers at all until this point.
617     ${1}_body
621 # _atf_run_tc tc nrest
623 #   Runs the specified test case.  Prints its exit status to the
624 #   standard output and returns a boolean indicating if the test was
625 #   successful or not.  The 'nrest' parameter indicates how many test
626 #   cases are left for execution.
628 _atf_run_tc()
630     _atf_parse_head ${1}
632     # Block some signals while we mess with temporary files so that we can
633     # clean them up later on.
634     Held_Signals=
635     trap _atf_sighup_handler SIGHUP
636     trap _atf_sigint_handler SIGINT
637     trap _atf_sigterm_handler SIGTERM
639     echo "tc-start: ${Test_Case}" >&${Results_Fd}
641     _atf_internal_set srcdir "${Source_Dir}"
643     Results_File=$(mktemp ${Work_Dir}/atf.XXXXXX)
645     _workdir=$(mktemp -d ${Work_Dir}/atf.XXXXXX)
646     if [ ${?} -eq 0 ]; then
647         _atf_shortcut_exec ${1} ${_workdir}
648         _ret=$?
649         if [ -f ${_workdir}/atf.timed.out ]; then
650             ( atf_fail "Test case timed out after $(atf_get timeout) seconds" )
651             _ret=${?}
652         fi
653         ( cd ${_workdir} ; ${1}_cleanup )
654         if [ ${2} -gt 1 ]; then
655             echo __atf_tc_separator__
656             echo __atf_tc_separator__ 1>&2
657         fi
658         ${Atf_Cleanup} ${_workdir}
659     else
660         ( atf_fail "Could not create the work directory" )
661         _ret=${?}
662     fi
664     # Set a default exit status if the test case did not report any.
665     if [ -z "$(cat ${Results_File})" ]; then
666         if [ -n "${Held_Signals}" ]; then
667             ( atf_fail "Test case was interrupted by${Held_Signals}" )
668         else
669             ( atf_fail "Test case did not report any status; bogus test" )
670         fi
671     fi
673     # Print the result of the test case and clean up the temporary file.
674     echo "tc-end: ${Test_Case}, $(cat ${Results_File})" >&${Results_Fd}
675     rm -f ${Results_File}
676     Results_File=
678     Test_Case=
680     # Restore blocked signals and process them.
681     trap - SIGHUP SIGINT SIGTERM
682     for s in ${Held_Signals}; do
683         kill -s ${s} $$
684     done
686     return ${_ret}
690 # _atf_run_tcs [tc1 .. tcN]
692 #   Executes all the given test cases.  Returns 0 if all tests were
693 #   successful, or 1 otherwise.
695 _atf_run_tcs()
697     # Now check that the base work directory exists.  We do not want to
698     # bother creating it.
699     [ -d "${Work_Dir}" ] || \
700         _atf_error 1 "Cannot find the work directory \`${Work_Dir}'"
702     _atf_init_output "${@}"
704     _ok=true
705     while [ ${#} -gt 0 ]; do
706         _atf_run_tc ${1} ${#} || _ok=false
707         shift
708     done
710     ${_ok}
714 # _atf_shortcut_entry
716 #   Secondary entry point for the program.  This is only called internally
717 #   to process a test case's body.  We must do a full re-exec of the script
718 #   in order to change its process group by means of an external tool.
719 #   Yes, this is ugly, but there is no other way to do it -- unless we
720 #   modified the shell interpreter to provide a built-in for changing the
721 #   process group of the current process...
723 #   Keep in sync with _atf_shortcut_exec.
725 _atf_shortcut_entry()
727     # Set global program status.
728     _config_file=${_ATF_CONFIG_FILE}; unset _ATF_CONFIG_FILE
729     Results_Fd=${_ATF_RESULTS_FD}; unset _ATF_RESULTS_FD
730     Results_File=${_ATF_RESULTS_FILE}; unset _ATF_RESULTS_FILE
731     Source_Dir=${_ATF_SOURCE_DIR}; unset _ATF_SOURCE_DIR
732     Work_Dir=${_ATF_WORK_DIR}; unset _ATF_WORK_DIR
734     # Gather specific details of this re-exec.
735     _shortcut_tc=${_ATF_SHORTCUT}; unset _ATF_SHORTCUT
737     # Global initialization, as found in main.
738     if [ -n "${_config_file}" -a -f "${_config_file}" ]; then
739         . ${_config_file}
740         rm ${_config_file}
741     fi
742     _atf_internal_set srcdir "${Source_Dir}"
743     atf_init_test_cases
745     # Test-case specific initialization, as found in _atf_run_tc.
746     _atf_parse_head ${_shortcut_tc}
747     _atf_internal_set srcdir "${Source_Dir}"
749     # Really run the test case's body.  This is the only part that
750     # should remain if we were really able to change the process group
751     # of a sub-shell.
752     cd ${Work_Dir}
753     _atf_run_body ${_shortcut_tc}
754     atf_pass
758 # _atf_shortcut_exec tc
760 #   Re-executes the current script in a different process group in order
761 #   to process the given test case's body.
763 #   Keep in sync with _atf_shortcut_entry.
765 _atf_shortcut_exec()
767     # Save the value of the configuration variables set through -v.
768     # We must do this through a files as there is no other easy way to
769     # preserve spaces in them.  But this can bring raise problems...
770     if [ -n "${Config_Vars}" ]; then
771         _config_file=${Work_Dir}/atf.config.vars
772         for _var in ${Config_Vars}; do
773             _val=$(eval echo \${${_var}})
774             echo ${_var}=\'${_val}\' >>${_config_file}
775         done
776     fi
778     # Now do the real re-execution.
779     ${Atf_Exec} -t $(atf_get timeout):${2}/atf.timed.out env \
780         _ATF_CONFIG_FILE=${_config_file} \
781         _ATF_RESULTS_FD=${Results_Fd} \
782         _ATF_RESULTS_FILE=${Results_File} \
783         _ATF_SHORTCUT=${1} \
784         _ATF_SOURCE_DIR=${Source_Dir} \
785         _ATF_WORK_DIR=${2} \
786         ${Source_Dir}/${Prog_Name}
790 # _atf_sighup_handler
792 #   Handler for the SIGHUP signal that registers its occurrence so that
793 #   it can be processed at a later stage.
795 _atf_sighup_handler()
797     Held_Signals="${Held_Signals} SIGHUP"
801 # _atf_sigint_handler
803 #   Handler for the SIGINT signal that registers its occurrence so that
804 #   it can be processed at a later stage.
806 _atf_sigint_handler()
808     Held_Signals="${Held_Signals} SIGINT"
812 # _atf_sigterm_handler
814 #   Handler for the SIGTERM signal that registers its occurrence so that
815 #   it can be processed at a later stage.
817 _atf_sigterm_handler()
819     Held_Signals="${Held_Signals} SIGTERM"
823 # _atf_syntax_error msg1 [.. msgN]
825 #   Formats and prints a syntax error message and terminates the
826 #   program prematurely.
828 _atf_syntax_error()
830     _atf_echo -r -t "${Prog_Name}: " "ERROR: ${@}" 1>&2
831     _atf_echo -r -t "${Prog_Name}: " "Type \`${Prog_Name} -h' for more" \
832                                      "details." 1>&2
833     exit 1
837 # _atf_is_tc_defined tc-name
839 #   Returns a boolean indicating if the given test case was defined by the
840 #   test program or not.
842 _atf_is_tc_defined()
844     for _tc in ${Defined_Test_Cases}; do
845         [ ${_tc} = ${1} ] && return 0
846     done
847     return 1
851 # _atf_usage
853 #   Prints usage information and exits the program.
855 _atf_usage()
857     _atf_echo -t "Usage: " "${Prog_Name} [options] [test_case1" \
858                            "[.. test_caseN]]"
859     echo
860     _atf_echo "This is an independent atf test program."
861     echo
862     _atf_echo "Available options:"
863     _atf_echo -t "    -h              " "Shows this help message"
864     _atf_echo -t "    -l              " "List test cases and their purpose"
865     _atf_echo -t "    -r fd           " "The file descriptor to which the" \
866                                         "test program will send the results" \
867                                         "of the test cases"
868     _atf_echo -t "    -s srcdir       " "Directory where the test's data" \
869                                         "files are located"
870     _atf_echo -t "    -v var=value    " "Sets the configuration variable" \
871                                         "\`var' to \`value'"
872     _atf_echo -t "    -w workdir      " "Directory where the test's" \
873                                         "temporary files are located"
874     echo
875     _atf_echo "For more details please see atf-test-program(1) and atf(7)."
879 # _atf_warning [msg1 [.. msgN]]
881 #   Prints the given warning message (which can be composed of multiple
882 #   arguments, in which case are joined by a single space).
884 #   This must not be used by test programs themselves (hence making
885 #   the function private).
887 _atf_warning()
889     _atf_echo -r -t "${Prog_Name}: " "WARNING:" "$@" 1>&2
893 # main [options] [test_case1 [.. test_caseN]]
895 #   Test program's entry point.
897 main()
899     # Handle shortcut execution path as early as possible.
900     if [ ${_ATF_SHORTCUT-__unset__} != __unset__ ]; then
901         _atf_shortcut_entry
902         # NOTREACHED
903     fi
905     # The test program's base directory where it will put temporary files.
906     Work_Dir=$(atf-config -t atf_workdir)
908     # Process command-line options first.
909     _numargs=${#}
910     _hflag=false
911     _lflag=false
912     while getopts :hlr:s:v:w: arg; do
913         case ${arg} in
914         h)
915             _hflag=true
916             ;;
918         l)
919             _lflag=true
920             ;;
922         r)
923             Results_Fd=${OPTARG}
924             ;;
926         s)
927             Source_Dir=${OPTARG}
928             ;;
930         v)
931             _atf_config_set_from_str "${OPTARG}"
932             ;;
934         w)
935             Work_Dir=${OPTARG}
936             ;;
938         \?)
939             _atf_syntax_error "Unknown option -${OPTARG}."
940             # NOTREACHED
941             ;;
942         esac
943     done
944     shift `expr ${OPTIND} - 1`
946     if [ ${_hflag} = true ]; then
947         [ ${_numargs} -eq 1 ] || _atf_syntax_error "-h must be given alone."
948         _atf_usage
949         true
950         return
951     fi
953     # First of all, make sure that the source directory is correct.  It
954     # doesn't matter if the user did not change it, because the default
955     # value may not work.  (TODO: It possibly should, even though it is
956     # not a big deal because atf-run deals with this.)
957     case ${Source_Dir} in
958         /*)
959             ;;
960         *)
961             Source_Dir=$(pwd)/${Source_Dir}
962             ;;
963     esac
964     [ -f ${Source_Dir}/${Prog_Name} ] || \
965         _atf_error 1 "Cannot find the test program in the source" \
966                      "directory \`${Source_Dir}'"
968     # Set some global variables useful to the user.  Not specific to the
969     # test case because they may be needed during initialization too.
970     # XXX I'm not too fond on this though.  Sure, it is very useful in some
971     # situations -- such as in NetBSD's fs/tmpfs/* tests where each test
972     # program includes a helper subroutines file -- but there are also
973     # other, maybe better ways to achieve the same.  Because, for example,
974     # at the moment it is not possible to detect failures in the inclusion
975     # and report them nicely.  Plus this change is difficult to implement
976     # in the current C++ API.
977     _atf_internal_set srcdir "${Source_Dir}"
979     # Call the test program's hook to register all available test cases.
980     atf_init_test_cases
982     # Set _tcs to the test cases to run.
983     if [ ${#} -gt 0 ]; then
984         # Expand glob patterns and report erroneous test cases.
985         _tcs=
986         while [ ${#} -gt 0 ]; do
987             _matches=$(_atf_expand_glob "${1}")
988             [ ${#_matches} -eq 0 ] &&
989                 _atf_error 1 "Unknown test case \`${1}'"
991             _tcs="${_tcs} ${_matches}"
992             shift
993         done
994     else
995         _tcs=${Test_Cases}
996     fi
998     # Run or list test cases, restricting them to _tcs.
999     if `${_lflag}`; then
1000         _atf_list_tcs ${_tcs}
1001     else
1002         _atf_run_tcs ${_tcs}
1003     fi
1006 # vim: syntax=sh:expandtab:shiftwidth=4:softtabstop=4