xref: /freebsd/contrib/atf/atf-sh/libatf-sh.subr (revision 83a1ee578c9d1ab7013e997289c7cd470c0e6902)
1c243e490SMarcel Moolenaar# Copyright (c) 2007 The NetBSD Foundation, Inc.
2c243e490SMarcel Moolenaar# All rights reserved.
3c243e490SMarcel Moolenaar#
4c243e490SMarcel Moolenaar# Redistribution and use in source and binary forms, with or without
5c243e490SMarcel Moolenaar# modification, are permitted provided that the following conditions
6c243e490SMarcel Moolenaar# are met:
7c243e490SMarcel Moolenaar# 1. Redistributions of source code must retain the above copyright
8c243e490SMarcel Moolenaar#    notice, this list of conditions and the following disclaimer.
9c243e490SMarcel Moolenaar# 2. Redistributions in binary form must reproduce the above copyright
10c243e490SMarcel Moolenaar#    notice, this list of conditions and the following disclaimer in the
11c243e490SMarcel Moolenaar#    documentation and/or other materials provided with the distribution.
12c243e490SMarcel Moolenaar#
13c243e490SMarcel Moolenaar# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND
14c243e490SMarcel Moolenaar# CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
15c243e490SMarcel Moolenaar# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
16c243e490SMarcel Moolenaar# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17c243e490SMarcel Moolenaar# IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY
18c243e490SMarcel Moolenaar# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19c243e490SMarcel Moolenaar# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
20c243e490SMarcel Moolenaar# GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21c243e490SMarcel Moolenaar# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
22c243e490SMarcel Moolenaar# IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
23c243e490SMarcel Moolenaar# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
24c243e490SMarcel Moolenaar# IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25c243e490SMarcel Moolenaar
26c243e490SMarcel Moolenaar# ------------------------------------------------------------------------
27c243e490SMarcel Moolenaar# GLOBAL VARIABLES
28c243e490SMarcel Moolenaar# ------------------------------------------------------------------------
29c243e490SMarcel Moolenaar
30c243e490SMarcel Moolenaar# Values for the expect property.
31c243e490SMarcel MoolenaarExpect=pass
32c243e490SMarcel MoolenaarExpect_Reason=
33c243e490SMarcel Moolenaar
34c243e490SMarcel Moolenaar# A boolean variable that indicates whether we are parsing a test case's
35c243e490SMarcel Moolenaar# head or not.
36c243e490SMarcel MoolenaarParsing_Head=false
37c243e490SMarcel Moolenaar
38c243e490SMarcel Moolenaar# The program name.
39c243e490SMarcel MoolenaarProg_Name=${0##*/}
40c243e490SMarcel Moolenaar
41c243e490SMarcel Moolenaar# The file to which the test case will print its result.
42c243e490SMarcel MoolenaarResults_File=
43c243e490SMarcel Moolenaar
44c243e490SMarcel Moolenaar# The test program's source directory: i.e. where its auxiliary data files
45c243e490SMarcel Moolenaar# and helper utilities can be found.  Can be overriden through the '-s' flag.
46c243e490SMarcel MoolenaarSource_Dir="$(dirname ${0})"
47c243e490SMarcel Moolenaar
48c243e490SMarcel Moolenaar# Indicates the test case we are currently processing.
49c243e490SMarcel MoolenaarTest_Case=
50c243e490SMarcel Moolenaar
51c243e490SMarcel Moolenaar# List of meta-data variables for the current test case.
52c243e490SMarcel MoolenaarTest_Case_Vars=
53c243e490SMarcel Moolenaar
54c243e490SMarcel Moolenaar# The list of all test cases provided by the test program.
55c243e490SMarcel MoolenaarTest_Cases=
56c243e490SMarcel Moolenaar
57c243e490SMarcel Moolenaar# ------------------------------------------------------------------------
58c243e490SMarcel Moolenaar# PUBLIC INTERFACE
59c243e490SMarcel Moolenaar# ------------------------------------------------------------------------
60c243e490SMarcel Moolenaar
61c243e490SMarcel Moolenaar#
62c243e490SMarcel Moolenaar# atf_add_test_case tc-name
63c243e490SMarcel Moolenaar#
64c243e490SMarcel Moolenaar#   Adds the given test case to the list of test cases that form the test
65c243e490SMarcel Moolenaar#   program.  The name provided here must be accompanied by two functions
66c243e490SMarcel Moolenaar#   named after it: <tc-name>_head and <tc-name>_body, and optionally by
67c243e490SMarcel Moolenaar#   a <tc-name>_cleanup function.
68c243e490SMarcel Moolenaar#
69c243e490SMarcel Moolenaaratf_add_test_case()
70c243e490SMarcel Moolenaar{
71c243e490SMarcel Moolenaar    Test_Cases="${Test_Cases} ${1}"
72c243e490SMarcel Moolenaar}
73c243e490SMarcel Moolenaar
74c243e490SMarcel Moolenaar#
75c243e490SMarcel Moolenaar# atf_check cmd expcode expout experr
76c243e490SMarcel Moolenaar#
77c243e490SMarcel Moolenaar#   Executes atf-check with given arguments and automatically calls
78c243e490SMarcel Moolenaar#   atf_fail in case of failure.
79c243e490SMarcel Moolenaar#
80c243e490SMarcel Moolenaaratf_check()
81c243e490SMarcel Moolenaar{
82c243e490SMarcel Moolenaar    ${Atf_Check} "${@}" || \
83c243e490SMarcel Moolenaar        atf_fail "atf-check failed; see the output of the test for details"
84c243e490SMarcel Moolenaar}
85c243e490SMarcel Moolenaar
86c243e490SMarcel Moolenaar#
870677dfd1SJulio Merino# atf_check_equal expected_expression actual_expression
88c243e490SMarcel Moolenaar#
890677dfd1SJulio Merino#   Checks that expected_expression's value matches actual_expression's
900677dfd1SJulio Merino#   and, if not, raises an error.  Ideally expected_expression and
910677dfd1SJulio Merino#   actual_expression should be provided quoted (not expanded) so that
920677dfd1SJulio Merino#   the error message is helpful; otherwise it will only show the values,
930677dfd1SJulio Merino#   not the expressions themselves.
94c243e490SMarcel Moolenaar#
95c243e490SMarcel Moolenaaratf_check_equal()
96c243e490SMarcel Moolenaar{
97c243e490SMarcel Moolenaar    eval _val1=\"${1}\"
98c243e490SMarcel Moolenaar    eval _val2=\"${2}\"
99c243e490SMarcel Moolenaar    test "${_val1}" = "${_val2}" || \
100c243e490SMarcel Moolenaar        atf_fail "${1} != ${2} (${_val1} != ${_val2})"
101c243e490SMarcel Moolenaar}
102c243e490SMarcel Moolenaar
103c243e490SMarcel Moolenaar#
104c203bd70SAlex Richardson# atf_check_not_equal expected_expression actual_expression
105c203bd70SAlex Richardson#
106c203bd70SAlex Richardson#   Checks that expected_expression's value does not match actual_expression's
107c203bd70SAlex Richardson#   and, if it does, raises an error.  Ideally expected_expression and
108c203bd70SAlex Richardson#   actual_expression should be provided quoted (not expanded) so that
109c203bd70SAlex Richardson#   the error message is helpful; otherwise it will only show the values,
110c203bd70SAlex Richardson#   not the expressions themselves.
111c203bd70SAlex Richardson#
112c203bd70SAlex Richardsonatf_check_not_equal()
113c203bd70SAlex Richardson{
114c203bd70SAlex Richardson    eval _val1=\"${1}\"
115c203bd70SAlex Richardson    eval _val2=\"${2}\"
116c203bd70SAlex Richardson    test "${_val1}" != "${_val2}" || \
117c203bd70SAlex Richardson        atf_fail "${1} == ${2} (${_val1} == ${_val2})"
118c203bd70SAlex Richardson}
119c203bd70SAlex Richardson
120c203bd70SAlex Richardson#
121c243e490SMarcel Moolenaar# atf_config_get varname [defvalue]
122c243e490SMarcel Moolenaar#
123c243e490SMarcel Moolenaar#   Prints the value of a configuration variable.  If it is not
124c243e490SMarcel Moolenaar#   defined, prints the given default value.
125c243e490SMarcel Moolenaar#
126c243e490SMarcel Moolenaaratf_config_get()
127c243e490SMarcel Moolenaar{
128c243e490SMarcel Moolenaar    _varname="__tc_config_var_$(_atf_normalize ${1})"
129c243e490SMarcel Moolenaar    if [ ${#} -eq 1 ]; then
130c243e490SMarcel Moolenaar        eval _value=\"\${${_varname}-__unset__}\"
131c243e490SMarcel Moolenaar        [ "${_value}" = __unset__ ] && \
132c243e490SMarcel Moolenaar            _atf_error 1 "Could not find configuration variable \`${1}'"
133c243e490SMarcel Moolenaar        echo ${_value}
134c243e490SMarcel Moolenaar    elif [ ${#} -eq 2 ]; then
135c243e490SMarcel Moolenaar        eval echo \${${_varname}-${2}}
136c243e490SMarcel Moolenaar    else
137c243e490SMarcel Moolenaar        _atf_error 1 "Incorrect number of parameters for atf_config_get"
138c243e490SMarcel Moolenaar    fi
139c243e490SMarcel Moolenaar}
140c243e490SMarcel Moolenaar
141c243e490SMarcel Moolenaar#
142c243e490SMarcel Moolenaar# atf_config_has varname
143c243e490SMarcel Moolenaar#
144c243e490SMarcel Moolenaar#   Returns a boolean indicating if the given configuration variable is
145c243e490SMarcel Moolenaar#   defined or not.
146c243e490SMarcel Moolenaar#
147c243e490SMarcel Moolenaaratf_config_has()
148c243e490SMarcel Moolenaar{
149c243e490SMarcel Moolenaar    _varname="__tc_config_var_$(_atf_normalize ${1})"
150c243e490SMarcel Moolenaar    eval _value=\"\${${_varname}-__unset__}\"
151c243e490SMarcel Moolenaar    [ "${_value}" != __unset__ ]
152c243e490SMarcel Moolenaar}
153c243e490SMarcel Moolenaar
154c243e490SMarcel Moolenaar#
155c243e490SMarcel Moolenaar# atf_expect_death reason
156c243e490SMarcel Moolenaar#
157c243e490SMarcel Moolenaar#   Sets the expectations to 'death'.
158c243e490SMarcel Moolenaar#
159c243e490SMarcel Moolenaaratf_expect_death()
160c243e490SMarcel Moolenaar{
161c243e490SMarcel Moolenaar    _atf_validate_expect
162c243e490SMarcel Moolenaar
163c243e490SMarcel Moolenaar    Expect=death
164c243e490SMarcel Moolenaar    _atf_create_resfile "expected_death: ${*}"
165c243e490SMarcel Moolenaar}
166c243e490SMarcel Moolenaar
167c243e490SMarcel Moolenaar#
168c243e490SMarcel Moolenaar# atf_expect_timeout reason
169c243e490SMarcel Moolenaar#
170c243e490SMarcel Moolenaar#   Sets the expectations to 'timeout'.
171c243e490SMarcel Moolenaar#
172c243e490SMarcel Moolenaaratf_expect_timeout()
173c243e490SMarcel Moolenaar{
174c243e490SMarcel Moolenaar    _atf_validate_expect
175c243e490SMarcel Moolenaar
176c243e490SMarcel Moolenaar    Expect=timeout
177c243e490SMarcel Moolenaar    _atf_create_resfile "expected_timeout: ${*}"
178c243e490SMarcel Moolenaar}
179c243e490SMarcel Moolenaar
180c243e490SMarcel Moolenaar#
181c243e490SMarcel Moolenaar# atf_expect_exit exitcode reason
182c243e490SMarcel Moolenaar#
183c243e490SMarcel Moolenaar#   Sets the expectations to 'exit'.
184c243e490SMarcel Moolenaar#
185c243e490SMarcel Moolenaaratf_expect_exit()
186c243e490SMarcel Moolenaar{
187c243e490SMarcel Moolenaar    _exitcode="${1}"; shift
188c243e490SMarcel Moolenaar
189c243e490SMarcel Moolenaar    _atf_validate_expect
190c243e490SMarcel Moolenaar
191c243e490SMarcel Moolenaar    Expect=exit
192c243e490SMarcel Moolenaar    if [ "${_exitcode}" = "-1" ]; then
193c243e490SMarcel Moolenaar        _atf_create_resfile "expected_exit: ${*}"
194c243e490SMarcel Moolenaar    else
195c243e490SMarcel Moolenaar        _atf_create_resfile "expected_exit(${_exitcode}): ${*}"
196c243e490SMarcel Moolenaar    fi
197c243e490SMarcel Moolenaar}
198c243e490SMarcel Moolenaar
199c243e490SMarcel Moolenaar#
200c243e490SMarcel Moolenaar# atf_expect_fail reason
201c243e490SMarcel Moolenaar#
202c243e490SMarcel Moolenaar#   Sets the expectations to 'fail'.
203c243e490SMarcel Moolenaar#
204c243e490SMarcel Moolenaaratf_expect_fail()
205c243e490SMarcel Moolenaar{
206c243e490SMarcel Moolenaar    _atf_validate_expect
207c243e490SMarcel Moolenaar
208c243e490SMarcel Moolenaar    Expect=fail
209c243e490SMarcel Moolenaar    Expect_Reason="${*}"
210c243e490SMarcel Moolenaar}
211c243e490SMarcel Moolenaar
212c243e490SMarcel Moolenaar#
213c243e490SMarcel Moolenaar# atf_expect_pass
214c243e490SMarcel Moolenaar#
215c243e490SMarcel Moolenaar#   Sets the expectations to 'pass'.
216c243e490SMarcel Moolenaar#
217c243e490SMarcel Moolenaaratf_expect_pass()
218c243e490SMarcel Moolenaar{
219c243e490SMarcel Moolenaar    _atf_validate_expect
220c243e490SMarcel Moolenaar
221c243e490SMarcel Moolenaar    Expect=pass
222c243e490SMarcel Moolenaar    Expect_Reason=
223c243e490SMarcel Moolenaar}
224c243e490SMarcel Moolenaar
225c243e490SMarcel Moolenaar#
226c243e490SMarcel Moolenaar# atf_expect_signal signo reason
227c243e490SMarcel Moolenaar#
228c243e490SMarcel Moolenaar#   Sets the expectations to 'signal'.
229c243e490SMarcel Moolenaar#
230c243e490SMarcel Moolenaaratf_expect_signal()
231c243e490SMarcel Moolenaar{
232c243e490SMarcel Moolenaar    _signo="${1}"; shift
233c243e490SMarcel Moolenaar
234c243e490SMarcel Moolenaar    _atf_validate_expect
235c243e490SMarcel Moolenaar
236c243e490SMarcel Moolenaar    Expect=signal
237c243e490SMarcel Moolenaar    if [ "${_signo}" = "-1" ]; then
238c243e490SMarcel Moolenaar        _atf_create_resfile "expected_signal: ${*}"
239c243e490SMarcel Moolenaar    else
240c243e490SMarcel Moolenaar        _atf_create_resfile "expected_signal(${_signo}): ${*}"
241c243e490SMarcel Moolenaar    fi
242c243e490SMarcel Moolenaar}
243c243e490SMarcel Moolenaar
244c243e490SMarcel Moolenaar#
245c243e490SMarcel Moolenaar# atf_expected_failure msg1 [.. msgN]
246c243e490SMarcel Moolenaar#
247c243e490SMarcel Moolenaar#   Makes the test case report an expected failure with the given error
248c243e490SMarcel Moolenaar#   message.  Multiple words can be provided, which are concatenated with
249c243e490SMarcel Moolenaar#   a single blank space.
250c243e490SMarcel Moolenaar#
251c243e490SMarcel Moolenaaratf_expected_failure()
252c243e490SMarcel Moolenaar{
253c243e490SMarcel Moolenaar    _atf_create_resfile "expected_failure: ${Expect_Reason}: ${*}"
254c243e490SMarcel Moolenaar    exit 0
255c243e490SMarcel Moolenaar}
256c243e490SMarcel Moolenaar
257c243e490SMarcel Moolenaar#
258c243e490SMarcel Moolenaar# atf_fail msg1 [.. msgN]
259c243e490SMarcel Moolenaar#
260c243e490SMarcel Moolenaar#   Makes the test case fail with the given error message.  Multiple
261c243e490SMarcel Moolenaar#   words can be provided, in which case they are joined by a single
262c243e490SMarcel Moolenaar#   blank space.
263c243e490SMarcel Moolenaar#
264c243e490SMarcel Moolenaaratf_fail()
265c243e490SMarcel Moolenaar{
266c243e490SMarcel Moolenaar    case "${Expect}" in
267c243e490SMarcel Moolenaar        fail)
268c243e490SMarcel Moolenaar            atf_expected_failure "${@}"
269c243e490SMarcel Moolenaar            ;;
270c243e490SMarcel Moolenaar        pass)
271c243e490SMarcel Moolenaar            _atf_create_resfile "failed: ${*}"
272c243e490SMarcel Moolenaar            exit 1
273c243e490SMarcel Moolenaar            ;;
274c243e490SMarcel Moolenaar        *)
275c243e490SMarcel Moolenaar            _atf_error 128 "Unreachable"
276c243e490SMarcel Moolenaar            ;;
277c243e490SMarcel Moolenaar    esac
278c243e490SMarcel Moolenaar}
279c243e490SMarcel Moolenaar
280c243e490SMarcel Moolenaar#
281c243e490SMarcel Moolenaar# atf_get varname
282c243e490SMarcel Moolenaar#
283c243e490SMarcel Moolenaar#   Prints the value of a test case-specific variable.  Given that one
284c243e490SMarcel Moolenaar#   should not get the value of non-existent variables, it is fine to
285c243e490SMarcel Moolenaar#   always use this function as 'val=$(atf_get var)'.
286c243e490SMarcel Moolenaar#
287c243e490SMarcel Moolenaaratf_get()
288c243e490SMarcel Moolenaar{
289c243e490SMarcel Moolenaar    eval echo \${__tc_var_${Test_Case}_$(_atf_normalize ${1})}
290c243e490SMarcel Moolenaar}
291c243e490SMarcel Moolenaar
292c243e490SMarcel Moolenaar#
293c243e490SMarcel Moolenaar# atf_get_srcdir
294c243e490SMarcel Moolenaar#
295c243e490SMarcel Moolenaar#   Prints the value of the test case's source directory.
296c243e490SMarcel Moolenaar#
297c243e490SMarcel Moolenaaratf_get_srcdir()
298c243e490SMarcel Moolenaar{
299c243e490SMarcel Moolenaar    echo ${Source_Dir}
300c243e490SMarcel Moolenaar}
301c243e490SMarcel Moolenaar
302c243e490SMarcel Moolenaar#
303c243e490SMarcel Moolenaar# atf_pass
304c243e490SMarcel Moolenaar#
305c243e490SMarcel Moolenaar#   Makes the test case pass.  Shouldn't be used in general, as a test
306c243e490SMarcel Moolenaar#   case that does not explicitly fail is assumed to pass.
307c243e490SMarcel Moolenaar#
308c243e490SMarcel Moolenaaratf_pass()
309c243e490SMarcel Moolenaar{
310c243e490SMarcel Moolenaar    case "${Expect}" in
311c243e490SMarcel Moolenaar        fail)
312c243e490SMarcel Moolenaar            Expect=pass
313c243e490SMarcel Moolenaar            atf_fail "Test case was expecting a failure but got a pass instead"
314c243e490SMarcel Moolenaar            ;;
315c243e490SMarcel Moolenaar        pass)
316c243e490SMarcel Moolenaar            _atf_create_resfile passed
317c243e490SMarcel Moolenaar            exit 0
318c243e490SMarcel Moolenaar            ;;
319c243e490SMarcel Moolenaar        *)
320c243e490SMarcel Moolenaar            _atf_error 128 "Unreachable"
321c243e490SMarcel Moolenaar            ;;
322c243e490SMarcel Moolenaar    esac
323c243e490SMarcel Moolenaar}
324c243e490SMarcel Moolenaar
325c243e490SMarcel Moolenaar#
326c243e490SMarcel Moolenaar# atf_require_prog prog
327c243e490SMarcel Moolenaar#
328c243e490SMarcel Moolenaar#   Checks that the given program name (either provided as an absolute
329c243e490SMarcel Moolenaar#   path or as a plain file name) can be found.  If it is not available,
330c243e490SMarcel Moolenaar#   automatically skips the test case with an appropriate message.
331c243e490SMarcel Moolenaar#
332c243e490SMarcel Moolenaar#   Relative paths are not allowed because the test case cannot predict
333c243e490SMarcel Moolenaar#   where it will be executed from.
334c243e490SMarcel Moolenaar#
335c243e490SMarcel Moolenaaratf_require_prog()
336c243e490SMarcel Moolenaar{
337c243e490SMarcel Moolenaar    _prog=
338c243e490SMarcel Moolenaar    case ${1} in
339c243e490SMarcel Moolenaar    /*)
340c243e490SMarcel Moolenaar        _prog="${1}"
341c243e490SMarcel Moolenaar        [ -x ${_prog} ] || \
342c243e490SMarcel Moolenaar            atf_skip "The required program ${1} could not be found"
343c243e490SMarcel Moolenaar        ;;
344c243e490SMarcel Moolenaar    */*)
345c243e490SMarcel Moolenaar        atf_fail "atf_require_prog does not accept relative path names \`${1}'"
346c243e490SMarcel Moolenaar        ;;
347c243e490SMarcel Moolenaar    *)
348c243e490SMarcel Moolenaar        _prog=$(_atf_find_in_path "${1}")
349c243e490SMarcel Moolenaar        [ -n "${_prog}" ] || \
350c243e490SMarcel Moolenaar            atf_skip "The required program ${1} could not be found" \
351c243e490SMarcel Moolenaar                     "in the PATH"
352c243e490SMarcel Moolenaar        ;;
353c243e490SMarcel Moolenaar    esac
354c243e490SMarcel Moolenaar}
355c243e490SMarcel Moolenaar
356c243e490SMarcel Moolenaar#
357*83a1ee57SDag-Erling Smørgrav# atf_require_kmod kmod
358*83a1ee57SDag-Erling Smørgrav#
359*83a1ee57SDag-Erling Smørgrav#   Checks that the given kmod is loaded.  If it is not, automatically
360*83a1ee57SDag-Erling Smørgrav#   skips the test case with an appropriate message.
361*83a1ee57SDag-Erling Smørgrav#
362*83a1ee57SDag-Erling Smørgravatf_require_kmod()
363*83a1ee57SDag-Erling Smørgrav{
364*83a1ee57SDag-Erling Smørgrav    kldstat -q "${1}" || \
365*83a1ee57SDag-Erling Smørgrav        atf_skip "The required kmod ${1} is not loaded"
366*83a1ee57SDag-Erling Smørgrav}
367*83a1ee57SDag-Erling Smørgrav
368*83a1ee57SDag-Erling Smørgrav#
369c243e490SMarcel Moolenaar# atf_set varname val1 [.. valN]
370c243e490SMarcel Moolenaar#
371c243e490SMarcel Moolenaar#   Sets the test case's variable 'varname' to the specified values
372c243e490SMarcel Moolenaar#   which are concatenated using a single blank space.  This function
373d4d14d96SIgor Ostapenko#   is supposed to be called from the test case's head only.
374c243e490SMarcel Moolenaar#
375c243e490SMarcel Moolenaaratf_set()
376c243e490SMarcel Moolenaar{
377c243e490SMarcel Moolenaar    ${Parsing_Head} || \
378c243e490SMarcel Moolenaar        _atf_error 128 "atf_set called from the test case's body"
379c243e490SMarcel Moolenaar
380c243e490SMarcel Moolenaar    Test_Case_Vars="${Test_Case_Vars} ${1}"
381c243e490SMarcel Moolenaar    _var=$(_atf_normalize ${1}); shift
382c243e490SMarcel Moolenaar    eval __tc_var_${Test_Case}_${_var}=\"\${*}\"
383c243e490SMarcel Moolenaar}
384c243e490SMarcel Moolenaar
385c243e490SMarcel Moolenaar#
386c243e490SMarcel Moolenaar# atf_skip msg1 [.. msgN]
387c243e490SMarcel Moolenaar#
388c243e490SMarcel Moolenaar#   Skips the test case because of the reason provided.  Multiple words
389c243e490SMarcel Moolenaar#   can be given, in which case they are joined by a single blank space.
390c243e490SMarcel Moolenaar#
391c243e490SMarcel Moolenaaratf_skip()
392c243e490SMarcel Moolenaar{
393c243e490SMarcel Moolenaar    _atf_create_resfile "skipped: ${*}"
394c243e490SMarcel Moolenaar    exit 0
395c243e490SMarcel Moolenaar}
396c243e490SMarcel Moolenaar
397c243e490SMarcel Moolenaar#
398c243e490SMarcel Moolenaar# atf_test_case tc-name cleanup
399c243e490SMarcel Moolenaar#
400c243e490SMarcel Moolenaar#   Defines a new test case named tc-name.  The name provided here must be
401c243e490SMarcel Moolenaar#   accompanied by two functions named after it: <tc-name>_head and
402c243e490SMarcel Moolenaar#   <tc-name>_body.  If cleanup is set to 'cleanup', then this also expects
403c243e490SMarcel Moolenaar#   a <tc-name>_cleanup function to be defined.
404c243e490SMarcel Moolenaar#
405c243e490SMarcel Moolenaaratf_test_case()
406c243e490SMarcel Moolenaar{
407c243e490SMarcel Moolenaar    eval "${1}_head() { :; }"
408c243e490SMarcel Moolenaar    eval "${1}_body() { atf_fail 'Test case not implemented'; }"
409c243e490SMarcel Moolenaar    if [ "${2}" = cleanup ]; then
410c243e490SMarcel Moolenaar        eval __has_cleanup_${1}=true
411c243e490SMarcel Moolenaar        eval "${1}_cleanup() { :; }"
412c243e490SMarcel Moolenaar    else
413c243e490SMarcel Moolenaar        eval "${1}_cleanup() {
414c243e490SMarcel Moolenaar            _atf_error 1 'Test case ${1} declared without a cleanup routine'; }"
415c243e490SMarcel Moolenaar    fi
416c243e490SMarcel Moolenaar}
417c243e490SMarcel Moolenaar
418c243e490SMarcel Moolenaar# ------------------------------------------------------------------------
419c243e490SMarcel Moolenaar# PRIVATE INTERFACE
420c243e490SMarcel Moolenaar# ------------------------------------------------------------------------
421c243e490SMarcel Moolenaar
422c243e490SMarcel Moolenaar#
423c243e490SMarcel Moolenaar# _atf_config_set varname val1 [.. valN]
424c243e490SMarcel Moolenaar#
425c243e490SMarcel Moolenaar#   Sets the test case's private variable 'varname' to the specified
426c243e490SMarcel Moolenaar#   values which are concatenated using a single blank space.
427c243e490SMarcel Moolenaar#
428c243e490SMarcel Moolenaar_atf_config_set()
429c243e490SMarcel Moolenaar{
430c243e490SMarcel Moolenaar    _var=$(_atf_normalize ${1}); shift
431c243e490SMarcel Moolenaar    eval __tc_config_var_${_var}=\"\${*}\"
432c243e490SMarcel Moolenaar    Config_Vars="${Config_Vars} __tc_config_var_${_var}"
433c243e490SMarcel Moolenaar}
434c243e490SMarcel Moolenaar
435c243e490SMarcel Moolenaar#
436c243e490SMarcel Moolenaar# _atf_config_set_str varname=val
437c243e490SMarcel Moolenaar#
438c243e490SMarcel Moolenaar#   Sets the test case's private variable 'varname' to the specified
439c243e490SMarcel Moolenaar#   value.  The parameter is of the form 'varname=val'.
440c243e490SMarcel Moolenaar#
441c243e490SMarcel Moolenaar_atf_config_set_from_str()
442c243e490SMarcel Moolenaar{
443c243e490SMarcel Moolenaar    _oldifs=${IFS}
444c243e490SMarcel Moolenaar    IFS='='
445c243e490SMarcel Moolenaar    set -- ${*}
446c243e490SMarcel Moolenaar    _var=${1}
447c243e490SMarcel Moolenaar    shift
448c243e490SMarcel Moolenaar    _val="${@}"
449c243e490SMarcel Moolenaar    IFS=${_oldifs}
450c243e490SMarcel Moolenaar    _atf_config_set "${_var}" "${_val}"
451c243e490SMarcel Moolenaar}
452c243e490SMarcel Moolenaar
453c243e490SMarcel Moolenaar#
454c243e490SMarcel Moolenaar# _atf_create_resfile contents
455c243e490SMarcel Moolenaar#
456c243e490SMarcel Moolenaar#   Creates the results file.
457c243e490SMarcel Moolenaar#
458c243e490SMarcel Moolenaar_atf_create_resfile()
459c243e490SMarcel Moolenaar{
460c243e490SMarcel Moolenaar    if [ -n "${Results_File}" ]; then
461c243e490SMarcel Moolenaar        echo "${*}" >"${Results_File}" || \
462c243e490SMarcel Moolenaar            _atf_error 128 "Cannot create results file '${Results_File}'"
463c243e490SMarcel Moolenaar    else
464c243e490SMarcel Moolenaar        echo "${*}"
465c243e490SMarcel Moolenaar    fi
466c243e490SMarcel Moolenaar}
467c243e490SMarcel Moolenaar
468c243e490SMarcel Moolenaar#
469c243e490SMarcel Moolenaar# _atf_error error_code [msg1 [.. msgN]]
470c243e490SMarcel Moolenaar#
471c243e490SMarcel Moolenaar#   Prints the given error message (which can be composed of multiple
472c243e490SMarcel Moolenaar#   arguments, in which case are joined by a single space) and exits
473c243e490SMarcel Moolenaar#   with the specified error code.
474c243e490SMarcel Moolenaar#
475c243e490SMarcel Moolenaar#   This must not be used by test programs themselves (hence making
476c243e490SMarcel Moolenaar#   the function private) to indicate a test case's failure.  They
477c243e490SMarcel Moolenaar#   have to use the atf_fail function.
478c243e490SMarcel Moolenaar#
479c243e490SMarcel Moolenaar_atf_error()
480c243e490SMarcel Moolenaar{
481c243e490SMarcel Moolenaar    _error_code="${1}"; shift
482c243e490SMarcel Moolenaar
483c243e490SMarcel Moolenaar    echo "${Prog_Name}: ERROR:" "$@" 1>&2
484c243e490SMarcel Moolenaar    exit ${_error_code}
485c243e490SMarcel Moolenaar}
486c243e490SMarcel Moolenaar
487c243e490SMarcel Moolenaar#
488c243e490SMarcel Moolenaar# _atf_warning msg1 [.. msgN]
489c243e490SMarcel Moolenaar#
490c243e490SMarcel Moolenaar#   Prints the given warning message (which can be composed of multiple
491c243e490SMarcel Moolenaar#   arguments, in which case are joined by a single space).
492c243e490SMarcel Moolenaar#
493c243e490SMarcel Moolenaar_atf_warning()
494c243e490SMarcel Moolenaar{
495c243e490SMarcel Moolenaar    echo "${Prog_Name}: WARNING:" "$@" 1>&2
496c243e490SMarcel Moolenaar}
497c243e490SMarcel Moolenaar
498c243e490SMarcel Moolenaar#
499c243e490SMarcel Moolenaar# _atf_find_in_path program
500c243e490SMarcel Moolenaar#
501c243e490SMarcel Moolenaar#   Looks for a program in the path and prints the full path to it or
502c243e490SMarcel Moolenaar#   nothing if it could not be found.  It also returns true in case of
503c243e490SMarcel Moolenaar#   success.
504c243e490SMarcel Moolenaar#
505c243e490SMarcel Moolenaar_atf_find_in_path()
506c243e490SMarcel Moolenaar{
507c243e490SMarcel Moolenaar    _prog="${1}"
508c243e490SMarcel Moolenaar
509c243e490SMarcel Moolenaar    _oldifs=${IFS}
510c243e490SMarcel Moolenaar    IFS=:
511c243e490SMarcel Moolenaar    for _dir in ${PATH}
512c243e490SMarcel Moolenaar    do
513c243e490SMarcel Moolenaar        if [ -x ${_dir}/${_prog} ]; then
514c243e490SMarcel Moolenaar            IFS=${_oldifs}
515c243e490SMarcel Moolenaar            echo ${_dir}/${_prog}
516c243e490SMarcel Moolenaar            return 0
517c243e490SMarcel Moolenaar        fi
518c243e490SMarcel Moolenaar    done
519c243e490SMarcel Moolenaar    IFS=${_oldifs}
520c243e490SMarcel Moolenaar
521c243e490SMarcel Moolenaar    return 1
522c243e490SMarcel Moolenaar}
523c243e490SMarcel Moolenaar
524c243e490SMarcel Moolenaar#
525c243e490SMarcel Moolenaar# _atf_has_tc name
526c243e490SMarcel Moolenaar#
527c243e490SMarcel Moolenaar#   Returns true if the given test case exists.
528c243e490SMarcel Moolenaar#
529c243e490SMarcel Moolenaar_atf_has_tc()
530c243e490SMarcel Moolenaar{
531c243e490SMarcel Moolenaar    for _tc in ${Test_Cases}; do
532c243e490SMarcel Moolenaar        [ "${_tc}" != "${1}" ] || return 0
533c243e490SMarcel Moolenaar    done
534c243e490SMarcel Moolenaar    return 1
535c243e490SMarcel Moolenaar}
536c243e490SMarcel Moolenaar
537c243e490SMarcel Moolenaar#
538c243e490SMarcel Moolenaar# _atf_list_tcs
539c243e490SMarcel Moolenaar#
540c243e490SMarcel Moolenaar#   Describes all test cases and prints the list to the standard output.
541c243e490SMarcel Moolenaar#
542c243e490SMarcel Moolenaar_atf_list_tcs()
543c243e490SMarcel Moolenaar{
544c243e490SMarcel Moolenaar    echo 'Content-Type: application/X-atf-tp; version="1"'
545c243e490SMarcel Moolenaar    echo
546c243e490SMarcel Moolenaar
547c243e490SMarcel Moolenaar    set -- ${Test_Cases}
548c243e490SMarcel Moolenaar    while [ ${#} -gt 0 ]; do
549c243e490SMarcel Moolenaar        _atf_parse_head ${1}
550c243e490SMarcel Moolenaar
551c243e490SMarcel Moolenaar        echo "ident: $(atf_get ident)"
552c243e490SMarcel Moolenaar        for _var in ${Test_Case_Vars}; do
553c243e490SMarcel Moolenaar            [ "${_var}" != "ident" ] && echo "${_var}: $(atf_get ${_var})"
554c243e490SMarcel Moolenaar        done
555c243e490SMarcel Moolenaar
556c243e490SMarcel Moolenaar        [ ${#} -gt 1 ] && echo
557c243e490SMarcel Moolenaar        shift
558c243e490SMarcel Moolenaar    done
559c243e490SMarcel Moolenaar}
560c243e490SMarcel Moolenaar
561c243e490SMarcel Moolenaar#
562c243e490SMarcel Moolenaar# _atf_normalize str
563c243e490SMarcel Moolenaar#
564c243e490SMarcel Moolenaar#   Normalizes a string so that it is a valid shell variable name.
565c243e490SMarcel Moolenaar#
566c243e490SMarcel Moolenaar_atf_normalize()
567c243e490SMarcel Moolenaar{
568c203bd70SAlex Richardson    # Check if the string contains any of the forbidden characters using
569c203bd70SAlex Richardson    # POSIX parameter expansion (the ${var//} string substitution is
570c203bd70SAlex Richardson    # unfortunately not supported in POSIX sh) and only use tr(1) then.
571c203bd70SAlex Richardson    # tr(1) is generally not a builtin, so doing the substring check first
572c203bd70SAlex Richardson    # avoids unnecessary fork()+execve() calls. As this function is called
573c203bd70SAlex Richardson    # many times in each test script startup, those overheads add up
574c203bd70SAlex Richardson    # (especially when running on emulated platforms such as QEMU).
575c203bd70SAlex Richardson    if [ "${1#*[.-]}" != "$1" ]; then
576c203bd70SAlex Richardson        echo "$1" | tr .- __
577c203bd70SAlex Richardson    else
578c203bd70SAlex Richardson        echo "$1"
579c203bd70SAlex Richardson    fi
580c243e490SMarcel Moolenaar}
581c243e490SMarcel Moolenaar
582c243e490SMarcel Moolenaar#
583c243e490SMarcel Moolenaar# _atf_parse_head tcname
584c243e490SMarcel Moolenaar#
585c243e490SMarcel Moolenaar#   Evaluates a test case's head to gather its variables and prepares the
586c243e490SMarcel Moolenaar#   test program to run it.
587c243e490SMarcel Moolenaar#
588c243e490SMarcel Moolenaar_atf_parse_head()
589c243e490SMarcel Moolenaar{
590c243e490SMarcel Moolenaar    Parsing_Head=true
591c243e490SMarcel Moolenaar
592c243e490SMarcel Moolenaar    Test_Case="${1}"
593c243e490SMarcel Moolenaar    Test_Case_Vars=
594c243e490SMarcel Moolenaar
595c243e490SMarcel Moolenaar    if _atf_has_cleanup "${1}"; then
596c243e490SMarcel Moolenaar        atf_set has.cleanup "true"
597c243e490SMarcel Moolenaar    fi
598c243e490SMarcel Moolenaar
599c243e490SMarcel Moolenaar    ${1}_head
600c243e490SMarcel Moolenaar    atf_set ident "${1}"
601c243e490SMarcel Moolenaar
602c243e490SMarcel Moolenaar    Parsing_Head=false
603c243e490SMarcel Moolenaar}
604c243e490SMarcel Moolenaar
605c243e490SMarcel Moolenaar#
606c243e490SMarcel Moolenaar# _atf_run_tc tc
607c243e490SMarcel Moolenaar#
608c243e490SMarcel Moolenaar#   Runs the specified test case.  Prints its exit status to the
609c243e490SMarcel Moolenaar#   standard output and returns a boolean indicating if the test was
610c243e490SMarcel Moolenaar#   successful or not.
611c243e490SMarcel Moolenaar#
612c243e490SMarcel Moolenaar_atf_run_tc()
613c243e490SMarcel Moolenaar{
614c243e490SMarcel Moolenaar    case ${1} in
615c243e490SMarcel Moolenaar    *:*)
616c243e490SMarcel Moolenaar        _tcname=${1%%:*}
617c243e490SMarcel Moolenaar        _tcpart=${1#*:}
618c243e490SMarcel Moolenaar
619c243e490SMarcel Moolenaar        if [ "${_tcpart}" != body -a "${_tcpart}" != cleanup ]; then
620c243e490SMarcel Moolenaar            _atf_syntax_error "Unknown test case part \`${_tcpart}'"
621c243e490SMarcel Moolenaar        fi
622c243e490SMarcel Moolenaar        ;;
623c243e490SMarcel Moolenaar
624c243e490SMarcel Moolenaar    *)
625c243e490SMarcel Moolenaar        _tcname=${1}
626c243e490SMarcel Moolenaar        _tcpart=body
627c243e490SMarcel Moolenaar        ;;
628c243e490SMarcel Moolenaar    esac
629c243e490SMarcel Moolenaar
630c243e490SMarcel Moolenaar    _atf_has_tc "${_tcname}" || _atf_syntax_error "Unknown test case \`${1}'"
631c243e490SMarcel Moolenaar
632c243e490SMarcel Moolenaar    if [ "${__RUNNING_INSIDE_ATF_RUN}" != "internal-yes-value" ]; then
6330677dfd1SJulio Merino        _atf_warning "Running test cases outside of kyua(1) is unsupported"
634c243e490SMarcel Moolenaar        _atf_warning "No isolation nor timeout control is being applied;" \
635c243e490SMarcel Moolenaar            "you may get unexpected failures; see atf-test-case(4)"
636c243e490SMarcel Moolenaar    fi
637c243e490SMarcel Moolenaar
638c243e490SMarcel Moolenaar    _atf_parse_head ${_tcname}
639c243e490SMarcel Moolenaar
640c243e490SMarcel Moolenaar    case ${_tcpart} in
641c243e490SMarcel Moolenaar    body)
642c243e490SMarcel Moolenaar        if ${_tcname}_body; then
643c243e490SMarcel Moolenaar            _atf_validate_expect
644c243e490SMarcel Moolenaar            _atf_create_resfile passed
645c243e490SMarcel Moolenaar        else
646c243e490SMarcel Moolenaar            Expect=pass
647c243e490SMarcel Moolenaar            atf_fail "Test case body returned a non-ok exit code, but" \
648c243e490SMarcel Moolenaar                "this is not allowed"
649c243e490SMarcel Moolenaar        fi
650c243e490SMarcel Moolenaar        ;;
651c243e490SMarcel Moolenaar    cleanup)
652c243e490SMarcel Moolenaar        if _atf_has_cleanup "${_tcname}"; then
653c243e490SMarcel Moolenaar            ${_tcname}_cleanup || _atf_error 128 "The test case cleanup" \
654c243e490SMarcel Moolenaar                "returned a non-ok exit code, but this is not allowed"
655c243e490SMarcel Moolenaar        fi
656c243e490SMarcel Moolenaar        ;;
657c243e490SMarcel Moolenaar    *)
658c243e490SMarcel Moolenaar        _atf_error 128 "Unknown test case part"
659c243e490SMarcel Moolenaar        ;;
660c243e490SMarcel Moolenaar    esac
661c243e490SMarcel Moolenaar}
662c243e490SMarcel Moolenaar
663c243e490SMarcel Moolenaar#
664c243e490SMarcel Moolenaar# _atf_syntax_error msg1 [.. msgN]
665c243e490SMarcel Moolenaar#
666c243e490SMarcel Moolenaar#   Formats and prints a syntax error message and terminates the
667c243e490SMarcel Moolenaar#   program prematurely.
668c243e490SMarcel Moolenaar#
669c243e490SMarcel Moolenaar_atf_syntax_error()
670c243e490SMarcel Moolenaar{
671c243e490SMarcel Moolenaar    echo "${Prog_Name}: ERROR: ${@}" 1>&2
672c243e490SMarcel Moolenaar    echo "${Prog_Name}: See atf-test-program(1) for usage details." 1>&2
673c243e490SMarcel Moolenaar    exit 1
674c243e490SMarcel Moolenaar}
675c243e490SMarcel Moolenaar
676c243e490SMarcel Moolenaar#
677c243e490SMarcel Moolenaar# _atf_has_cleanup tc-name
678c243e490SMarcel Moolenaar#
679c243e490SMarcel Moolenaar#   Returns a boolean indicating if the given test case has a cleanup
680c243e490SMarcel Moolenaar#   routine or not.
681c243e490SMarcel Moolenaar#
682c243e490SMarcel Moolenaar_atf_has_cleanup()
683c243e490SMarcel Moolenaar{
684c243e490SMarcel Moolenaar    _found=true
685c243e490SMarcel Moolenaar    eval "[ x\"\${__has_cleanup_${1}}\" = xtrue ] || _found=false"
686c243e490SMarcel Moolenaar    [ "${_found}" = true ]
687c243e490SMarcel Moolenaar}
688c243e490SMarcel Moolenaar
689c243e490SMarcel Moolenaar#
690c243e490SMarcel Moolenaar# _atf_validate_expect
691c243e490SMarcel Moolenaar#
692c243e490SMarcel Moolenaar#   Ensures that the current test case state is correct regarding the expect
693c243e490SMarcel Moolenaar#   status.
694c243e490SMarcel Moolenaar#
695c243e490SMarcel Moolenaar_atf_validate_expect()
696c243e490SMarcel Moolenaar{
697c243e490SMarcel Moolenaar    case "${Expect}" in
698c243e490SMarcel Moolenaar        death)
699c243e490SMarcel Moolenaar            Expect=pass
700c243e490SMarcel Moolenaar            atf_fail "Test case was expected to terminate abruptly but it" \
701c243e490SMarcel Moolenaar                "continued execution"
702c243e490SMarcel Moolenaar            ;;
703c243e490SMarcel Moolenaar        exit)
704c243e490SMarcel Moolenaar            Expect=pass
705c243e490SMarcel Moolenaar            atf_fail "Test case was expected to exit cleanly but it continued" \
706c243e490SMarcel Moolenaar                "execution"
707c243e490SMarcel Moolenaar            ;;
708c243e490SMarcel Moolenaar        fail)
709c243e490SMarcel Moolenaar            Expect=pass
710c243e490SMarcel Moolenaar            atf_fail "Test case was expecting a failure but none were raised"
711c243e490SMarcel Moolenaar            ;;
712c243e490SMarcel Moolenaar        pass)
713c243e490SMarcel Moolenaar            ;;
714c243e490SMarcel Moolenaar        signal)
715c243e490SMarcel Moolenaar            Expect=pass
716c243e490SMarcel Moolenaar            atf_fail "Test case was expected to receive a termination signal" \
717c243e490SMarcel Moolenaar                "but it continued execution"
718c243e490SMarcel Moolenaar            ;;
719c243e490SMarcel Moolenaar        timeout)
720c243e490SMarcel Moolenaar            Expect=pass
721c243e490SMarcel Moolenaar            atf_fail "Test case was expected to hang but it continued execution"
722c243e490SMarcel Moolenaar            ;;
723c243e490SMarcel Moolenaar        *)
724c243e490SMarcel Moolenaar            _atf_error 128 "Unreachable"
725c243e490SMarcel Moolenaar            ;;
726c243e490SMarcel Moolenaar    esac
727c243e490SMarcel Moolenaar}
728c243e490SMarcel Moolenaar
729c243e490SMarcel Moolenaar#
730c243e490SMarcel Moolenaar# _atf_warning [msg1 [.. msgN]]
731c243e490SMarcel Moolenaar#
732c243e490SMarcel Moolenaar#   Prints the given warning message (which can be composed of multiple
733c243e490SMarcel Moolenaar#   arguments, in which case are joined by a single space).
734c243e490SMarcel Moolenaar#
735c243e490SMarcel Moolenaar#   This must not be used by test programs themselves (hence making
736c243e490SMarcel Moolenaar#   the function private).
737c243e490SMarcel Moolenaar#
738c243e490SMarcel Moolenaar_atf_warning()
739c243e490SMarcel Moolenaar{
740c243e490SMarcel Moolenaar    echo "${Prog_Name}: WARNING:" "$@" 1>&2
741c243e490SMarcel Moolenaar}
742c243e490SMarcel Moolenaar
743c243e490SMarcel Moolenaar#
744c243e490SMarcel Moolenaar# main [options] test_case
745c243e490SMarcel Moolenaar#
746c243e490SMarcel Moolenaar#   Test program's entry point.
747c243e490SMarcel Moolenaar#
748c243e490SMarcel Moolenaarmain()
749c243e490SMarcel Moolenaar{
750c243e490SMarcel Moolenaar    # Process command-line options first.
751c243e490SMarcel Moolenaar    _numargs=${#}
752c243e490SMarcel Moolenaar    _lflag=false
753c243e490SMarcel Moolenaar    while getopts :lr:s:v: arg; do
754c243e490SMarcel Moolenaar        case ${arg} in
755c243e490SMarcel Moolenaar        l)
756c243e490SMarcel Moolenaar            _lflag=true
757c243e490SMarcel Moolenaar            ;;
758c243e490SMarcel Moolenaar
759c243e490SMarcel Moolenaar        r)
760c243e490SMarcel Moolenaar            Results_File=${OPTARG}
761c243e490SMarcel Moolenaar            ;;
762c243e490SMarcel Moolenaar
763c243e490SMarcel Moolenaar        s)
764c243e490SMarcel Moolenaar            Source_Dir=${OPTARG}
765c243e490SMarcel Moolenaar            ;;
766c243e490SMarcel Moolenaar
767c243e490SMarcel Moolenaar        v)
768c243e490SMarcel Moolenaar            _atf_config_set_from_str "${OPTARG}"
769c243e490SMarcel Moolenaar            ;;
770c243e490SMarcel Moolenaar
771c243e490SMarcel Moolenaar        \?)
772c243e490SMarcel Moolenaar            _atf_syntax_error "Unknown option -${OPTARG}."
773c243e490SMarcel Moolenaar            # NOTREACHED
774c243e490SMarcel Moolenaar            ;;
775c243e490SMarcel Moolenaar        esac
776c243e490SMarcel Moolenaar    done
777c203bd70SAlex Richardson    shift $((OPTIND - 1))
778c243e490SMarcel Moolenaar
779c243e490SMarcel Moolenaar    case ${Source_Dir} in
780c243e490SMarcel Moolenaar        /*)
781c243e490SMarcel Moolenaar            ;;
782c243e490SMarcel Moolenaar        *)
783c243e490SMarcel Moolenaar            Source_Dir=$(pwd)/${Source_Dir}
784c243e490SMarcel Moolenaar            ;;
785c243e490SMarcel Moolenaar    esac
786c243e490SMarcel Moolenaar    [ -f ${Source_Dir}/${Prog_Name} ] || \
787c243e490SMarcel Moolenaar        _atf_error 1 "Cannot find the test program in the source" \
788c243e490SMarcel Moolenaar                     "directory \`${Source_Dir}'"
789c243e490SMarcel Moolenaar
790c243e490SMarcel Moolenaar    # Call the test program's hook to register all available test cases.
791c243e490SMarcel Moolenaar    atf_init_test_cases
792c243e490SMarcel Moolenaar
793c243e490SMarcel Moolenaar    # Run or list test cases.
794c243e490SMarcel Moolenaar    if `${_lflag}`; then
795c243e490SMarcel Moolenaar        if [ ${#} -gt 0 ]; then
796c243e490SMarcel Moolenaar            _atf_syntax_error "Cannot provide test case names with -l"
797c243e490SMarcel Moolenaar        fi
798c243e490SMarcel Moolenaar        _atf_list_tcs
799c243e490SMarcel Moolenaar    else
800c243e490SMarcel Moolenaar        if [ ${#} -eq 0 ]; then
801c243e490SMarcel Moolenaar            _atf_syntax_error "Must provide a test case name"
802c243e490SMarcel Moolenaar        elif [ ${#} -gt 1 ]; then
803c243e490SMarcel Moolenaar            _atf_syntax_error "Cannot provide more than one test case name"
804c243e490SMarcel Moolenaar        else
805c243e490SMarcel Moolenaar            _atf_run_tc "${1}"
806c243e490SMarcel Moolenaar        fi
807c243e490SMarcel Moolenaar    fi
808c243e490SMarcel Moolenaar}
809c243e490SMarcel Moolenaar
810c243e490SMarcel Moolenaar# vim: syntax=sh:expandtab:shiftwidth=4:softtabstop=4
811