xref: /netbsd-src/external/bsd/atf/dist/atf-sh/atf-sh-api.3 (revision 7f0357d3ca8d67ce8c4a975dd152ea499195e78e)
1e2207522Sjmmv.\"
2e2207522Sjmmv.\" Automated Testing Framework (atf)
3e2207522Sjmmv.\"
4a551a20fSjmmv.\" Copyright (c) 2008 The NetBSD Foundation, Inc.
5e2207522Sjmmv.\" All rights reserved.
6e2207522Sjmmv.\"
7e2207522Sjmmv.\" Redistribution and use in source and binary forms, with or without
8e2207522Sjmmv.\" modification, are permitted provided that the following conditions
9e2207522Sjmmv.\" are met:
10e2207522Sjmmv.\" 1. Redistributions of source code must retain the above copyright
11e2207522Sjmmv.\"    notice, this list of conditions and the following disclaimer.
12e2207522Sjmmv.\" 2. Redistributions in binary form must reproduce the above copyright
13e2207522Sjmmv.\"    notice, this list of conditions and the following disclaimer in the
14e2207522Sjmmv.\"    documentation and/or other materials provided with the distribution.
15e2207522Sjmmv.\"
16e2207522Sjmmv.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND
17e2207522Sjmmv.\" CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
18e2207522Sjmmv.\" INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19e2207522Sjmmv.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20e2207522Sjmmv.\" IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY
21e2207522Sjmmv.\" DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22e2207522Sjmmv.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
23e2207522Sjmmv.\" GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24e2207522Sjmmv.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
25e2207522Sjmmv.\" IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
26e2207522Sjmmv.\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27e2207522Sjmmv.\" IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28e2207522Sjmmv.\"
29*7f0357d3Skre.Dd May 15, 2017
30e2207522Sjmmv.Dt ATF-SH-API 3
31e2207522Sjmmv.Os
32e2207522Sjmmv.Sh NAME
33e2207522Sjmmv.Nm atf_add_test_case ,
34e2207522Sjmmv.Nm atf_check ,
35e2207522Sjmmv.Nm atf_check_equal ,
36e2207522Sjmmv.Nm atf_config_get ,
37e2207522Sjmmv.Nm atf_config_has ,
38edebbb8eSjmmv.Nm atf_expect_death ,
39edebbb8eSjmmv.Nm atf_expect_exit ,
40edebbb8eSjmmv.Nm atf_expect_fail ,
41edebbb8eSjmmv.Nm atf_expect_pass ,
42edebbb8eSjmmv.Nm atf_expect_signal ,
43edebbb8eSjmmv.Nm atf_expect_timeout ,
44e2207522Sjmmv.Nm atf_fail ,
45e2207522Sjmmv.Nm atf_get ,
46e2207522Sjmmv.Nm atf_get_srcdir ,
47e2207522Sjmmv.Nm atf_pass ,
48e2207522Sjmmv.Nm atf_require_prog ,
49e2207522Sjmmv.Nm atf_set ,
50edebbb8eSjmmv.Nm atf_skip ,
51895f502bSjmmv.Nm atf_test_case
52e2207522Sjmmv.Nd POSIX shell API to write ATF-based test programs
53e2207522Sjmmv.Sh SYNOPSIS
54*7f0357d3Skre.Ic atf_add_test_case Dq name
55*7f0357d3Skre.br
56*7f0357d3Skre.Ic atf_check Dq command
57*7f0357d3Skre.br
58*7f0357d3Skre.Ic atf_check_equal Do expr1 Dc Dq expr2
59*7f0357d3Skre.br
60*7f0357d3Skre.Ic atf_config_get Dq var_name
61*7f0357d3Skre.br
62*7f0357d3Skre.Ic atf_config_has Dq var_name
63*7f0357d3Skre.br
64*7f0357d3Skre.Ic atf_expect_death Do reason Dc Dq \&...
65*7f0357d3Skre.br
66*7f0357d3Skre.Ic atf_expect_exit Do exitcode Dc Do reason Dc Dq \&...
67*7f0357d3Skre.br
68*7f0357d3Skre.Ic atf_expect_fail Do reason Dc Dq \&...
69*7f0357d3Skre.br
70*7f0357d3Skre.Ic atf_expect_pass
71*7f0357d3Skre.br
72*7f0357d3Skre.Ic atf_expect_signal Do signo Dc Do reason Dc Dq \&...
73*7f0357d3Skre.br
74*7f0357d3Skre.Ic atf_expect_timeout Do reason Dc Dq \&...
75*7f0357d3Skre.br
76*7f0357d3Skre.Ic atf_fail Dq reason
77*7f0357d3Skre.br
78*7f0357d3Skre.Ic atf_get Dq var_name
79*7f0357d3Skre.br
80*7f0357d3Skre.Ic atf_get_srcdir
81*7f0357d3Skre.br
82*7f0357d3Skre.Ic atf_pass
83*7f0357d3Skre.br
84*7f0357d3Skre.Ic atf_require_prog Dq prog_name
85*7f0357d3Skre.br
86*7f0357d3Skre.Ic atf_set Do var_name Dc Dq value
87*7f0357d3Skre.br
88*7f0357d3Skre.Ic atf_skip Dq reason
89*7f0357d3Skre.br
90*7f0357d3Skre.Ic atf_test_case Do name Dc Dq cleanup
91*7f0357d3Skre.br
92e2207522Sjmmv.Sh DESCRIPTION
93e2207522SjmmvATF
94e2207522Sjmmvprovides a simple but powerful interface to easily write test programs in
95e2207522Sjmmvthe POSIX shell language.
96e2207522SjmmvThese are extremely helpful given that they are trivial to write due to the
97e2207522Sjmmvlanguage simplicity and the great deal of available external tools, so they
98e2207522Sjmmvare often ideal to test other applications at the user level.
99e2207522Sjmmv.Pp
1009b3149ccSjmmvTest programs written using this library must be run using the
1019b3149ccSjmmv.Xr atf-sh 1
1029b3149ccSjmmvinterpreter by putting the following on their very first line:
1039b3149ccSjmmv.Bd -literal -offset indent
1049b3149ccSjmmv#! /usr/bin/env atf-sh
1059b3149ccSjmmv.Ed
106e2207522Sjmmv.Pp
107e2207522SjmmvShell-based test programs always follow this template:
108e2207522Sjmmv.Bd -literal -offset indent
109e2207522Sjmmvatf_test_case tc1
110e2207522Sjmmvtc1_head() {
111e2207522Sjmmv    ... first test case's header ...
112e2207522Sjmmv}
113e2207522Sjmmvtc1_body() {
114e2207522Sjmmv    ... first test case's body ...
115e2207522Sjmmv}
116e2207522Sjmmv
117edebbb8eSjmmvatf_test_case tc2 cleanup
118e2207522Sjmmvtc2_head() {
119e2207522Sjmmv    ... second test case's header ...
120e2207522Sjmmv}
121e2207522Sjmmvtc2_body() {
122e2207522Sjmmv    ... second test case's body ...
123e2207522Sjmmv}
124e2207522Sjmmvtc2_cleanup() {
125e2207522Sjmmv    ... second test case's cleanup ...
126e2207522Sjmmv}
127e2207522Sjmmv
128e2207522Sjmmv.Ns ... additional test cases ...
129e2207522Sjmmv
130e2207522Sjmmvatf_init_test_cases() {
131e2207522Sjmmv    atf_add_test_case tc1
132e2207522Sjmmv    atf_add_test_case tc2
133e2207522Sjmmv    ... add additional test cases ...
134e2207522Sjmmv}
135e2207522Sjmmv.Ed
136*7f0357d3Skre.Pp
137*7f0357d3SkreAll of these functions are required to return with an exit-status of
138*7f0357d3Skrezero, or ATF will determine that the test is faulty.
139*7f0357d3SkreIn particular, this means that none may end with a conditional like:
140*7f0357d3Skre.Bd -literal -offset indent
141*7f0357d3Skreatf_sh_function() {
142*7f0357d3Skre    ... appropriate code here ...
143*7f0357d3Skre    condition-test && {
144*7f0357d3Skre	... more code here ...
145*7f0357d3Skre    }
146*7f0357d3Skre}
147*7f0357d3Skre.Ed
148*7f0357d3Skre.Pp
149*7f0357d3Skreas if condition-test fails
150*7f0357d3Skrethe return code from atf_sh_function will not be 0.
151*7f0357d3SkreThis can be corrected by adding
152*7f0357d3Skre.Bd -literal -offset indent
153*7f0357d3Skre    return 0
154*7f0357d3Skre.Ed
155*7f0357d3Skre.Pp
156*7f0357d3Skrebefore the end of the function, or by writing it as
157*7f0357d3Skre.Bd -literal -offset indent
158*7f0357d3Skreatf_sh_function() {
159*7f0357d3Skre    ... appropriate code here ...
160*7f0357d3Skre    if condition-test
161*7f0357d3Skre    then
162*7f0357d3Skre	... more code here ...
163*7f0357d3Skre    fi
164*7f0357d3Skre}
165*7f0357d3Skre.Ed
166e2207522Sjmmv.Ss Definition of test cases
167e2207522SjmmvTest cases have an identifier and are composed of three different parts:
168e2207522Sjmmvthe header, the body and an optional cleanup routine, all of which are
169e2207522Sjmmvdescribed in
170edebbb8eSjmmv.Xr atf-test-case 4 .
171e2207522SjmmvTo define test cases, one can use the
172*7f0357d3Skre.Ic atf_test_case
173edebbb8eSjmmvfunction, which takes a first parameter specifiying the test case's
174e2207522Sjmmvname and instructs the library to set things up to accept it as a valid
175e2207522Sjmmvtest case.
176edebbb8eSjmmvThe second parameter is optional and, if provided, must be
177edebbb8eSjmmv.Sq cleanup ;
178edebbb8eSjmmvproviding this parameter allows defining a cleanup routine for the test
179edebbb8eSjmmvcase.
180edebbb8eSjmmvIt is important to note that this function
181e2207522Sjmmv.Em does not
182e2207522Sjmmvset the test case up for execution when the program is run.
183e2207522SjmmvIn order to do so, a later registration is needed through the
184*7f0357d3Skre.Ic atf_add_test_case
185e2207522Sjmmvfunction detailed in
186e2207522Sjmmv.Sx Program initialization .
187e2207522Sjmmv.Pp
188e2207522SjmmvLater on, one must define the three parts of the body by providing two
189e2207522Sjmmvor three functions (remember that the cleanup routine is optional).
190e2207522SjmmvThese functions are named after the test case's identifier, and are
191*7f0357d3Skre.Ic <id>_head ,
192*7f0357d3Skre.Ic <id>_body
193e2207522Sjmmvand
194*7f0357d3Skre.Ic <id>_cleanup.
195e2207522SjmmvNone of these take parameters when executed.
196e2207522Sjmmv.Ss Program initialization
197e2207522SjmmvThe test program must define an
198*7f0357d3Skre.Ic atf_init_test_cases
199e2207522Sjmmvfunction, which is in charge of registering the test cases that will be
200e2207522Sjmmvexecuted at run time by using the
201*7f0357d3Skre.Ic atf_add_test_case
202e2207522Sjmmvfunction, which takes the name of a test case as its single parameter.
203e2207522SjmmvThis main function should not do anything else, except maybe sourcing
204*7f0357d3Skreauxiliary source files that define extra variables and functions,
205*7f0357d3Skreor perhaps running simple tests to determine which test cases to add.
206e2207522Sjmmv.Ss Configuration variables
207e2207522SjmmvThe test case has read-only access to the current configuration variables
208e2207522Sjmmvthrough the
209*7f0357d3Skre.Ic atf_config_has
210e2207522Sjmmvand
211*7f0357d3Skre.Ic atf_config_get
212e2207522Sjmmvmethods.
213e2207522SjmmvThe former takes a single parameter specifying a variable name and returns
214e2207522Sjmmva boolean indicating whether the variable is defined or not.
215e2207522SjmmvThe latter can take one or two parameters.
216e2207522SjmmvIf it takes only one, it specifies the variable from which to get the
217e2207522Sjmmvvalue, and this variable must be defined.
218e2207522SjmmvIf it takes two, the second one specifies a default value to be returned
219e2207522Sjmmvif the variable is not available.
220e2207522Sjmmv.Ss Access to the source directory
221e2207522SjmmvIt is possible to get the path to the test case's source directory from
222e2207522Sjmmvanywhere in the test program by using the
223*7f0357d3Skre.Ic atf_get_srcdir
224e2207522Sjmmvfunction.
225e2207522SjmmvIt is interesting to note that this can be used inside
226*7f0357d3Skre.Ic atf_init_test_cases
227e2207522Sjmmvto silently include additional helper files from the source directory.
228e2207522Sjmmv.Ss Requiring programs
229e2207522SjmmvAside from the
230e2207522Sjmmv.Va require.progs
231e2207522Sjmmvmeta-data variable available in the header only, one can also check for
232e2207522Sjmmvadditional programs in the test case's body by using the
233*7f0357d3Skre.Ic atf_require_prog
234e2207522Sjmmvfunction, which takes the base name or full path of a single binary.
235e2207522SjmmvRelative paths are forbidden.
236e2207522SjmmvIf it is not found, the test case will be automatically skipped.
237e2207522Sjmmv.Ss Test case finalization
238e2207522SjmmvThe test case finalizes either when the body reaches its end, at which
239e2207522Sjmmvpoint the test is assumed to have
240e2207522Sjmmv.Em passed ,
241e2207522Sjmmvor at any explicit call to
242*7f0357d3Skre.Ic atf_pass ,
243*7f0357d3Skre.Ic atf_fail
244*7f0357d3Skre.Ic atf_skip .
245e2207522SjmmvThese three functions terminate the execution of the test case immediately.
246e2207522SjmmvThe cleanup routine will be processed afterwards in a completely automated
247e2207522Sjmmvway, regardless of the test case's termination reason.
248e2207522Sjmmv.Pp
249e2207522Sjmmv.Fn atf_pass
250e2207522Sjmmvdoes not take any parameters.
251e2207522Sjmmv.Fn atf_fail
252e2207522Sjmmvand
253e2207522Sjmmv.Fn atf_skip
254e2207522Sjmmvtake a single string parameter that describes why the test case failed or
255e2207522Sjmmvwas skipped, respectively.
256e2207522SjmmvIt is very important to provide a clear error message in both cases so that
257e2207522Sjmmvthe user can quickly know why the test did not pass.
258*7f0357d3SkreThis message must be a single line (no embedded newline characers.)
259edebbb8eSjmmv.Ss Expectations
260edebbb8eSjmmvEverything explained in the previous section changes when the test case
261edebbb8eSjmmvexpectations are redefined by the programmer.
262edebbb8eSjmmv.Pp
263edebbb8eSjmmvEach test case has an internal state called
264edebbb8eSjmmv.Sq expect
265edebbb8eSjmmvthat describes what the test case expectations are at any point in time.
266edebbb8eSjmmvThe value of this property can change during execution by any of:
267edebbb8eSjmmv.Bl -tag -width indent
268*7f0357d3Skre.It Ic atf_expect_death Do reason Dc Dq \&...
269edebbb8eSjmmvExpects the test case to exit prematurely regardless of the nature of the
270edebbb8eSjmmvexit.
271*7f0357d3Skre.It Ic atf_expect_exit Do exitcode Dc Do reason Dc Dq \&...
272edebbb8eSjmmvExpects the test case to exit cleanly.
273edebbb8eSjmmvIf
274edebbb8eSjmmv.Va exitcode
275edebbb8eSjmmvis not
276*7f0357d3Skre.Sq \-1 ,
277edebbb8eSjmmv.Xr atf-run 1
278edebbb8eSjmmvwill validate that the exit code of the test case matches the one provided
279edebbb8eSjmmvin this call.
280edebbb8eSjmmvOtherwise, the exact value will be ignored.
281*7f0357d3Skre.It Ic atf_expect_fail Dq reason
282edebbb8eSjmmvAny failure raised in this mode is recorded, but such failures do not report
283edebbb8eSjmmvthe test case as failed; instead, the test case finalizes cleanly and is
284edebbb8eSjmmvreported as
285edebbb8eSjmmv.Sq expected failure ;
286edebbb8eSjmmvthis report includes the provided
287edebbb8eSjmmv.Fa reason
288edebbb8eSjmmvas part of it.
289edebbb8eSjmmvIf no error is raised while running in this mode, then the test case is
290edebbb8eSjmmvreported as
291edebbb8eSjmmv.Sq failed .
292edebbb8eSjmmv.Pp
293edebbb8eSjmmvThis mode is useful to reproduce actual known bugs in tests.
294edebbb8eSjmmvWhenever the developer fixes the bug later on, the test case will start
295edebbb8eSjmmvreporting a failure, signaling the developer that the test case must be
296edebbb8eSjmmvadjusted to the new conditions.
297edebbb8eSjmmvIn this situation, it is useful, for example, to set
298*7f0357d3Skre.Va reason
299edebbb8eSjmmvas the bug number for tracking purposes.
300*7f0357d3Skre.It Ic atf_expect_pass
301edebbb8eSjmmvThis is the normal mode of execution.
302edebbb8eSjmmvIn this mode, any failure is reported as such to the user and the test case
303edebbb8eSjmmvis marked as
304edebbb8eSjmmv.Sq failed .
305*7f0357d3Skre.It Ic atf_expect_signal Do signo Dc Do reason Dc Dq \&...
306edebbb8eSjmmvExpects the test case to terminate due to the reception of a signal.
307edebbb8eSjmmvIf
308edebbb8eSjmmv.Va signo
309edebbb8eSjmmvis not
310*7f0357d3Skre.Sq \-1 ,
311edebbb8eSjmmv.Xr atf-run 1
312edebbb8eSjmmvwill validate that the signal that terminated the test case matches the one
313edebbb8eSjmmvprovided in this call.
314edebbb8eSjmmvOtherwise, the exact value will be ignored.
315*7f0357d3Skre.It Ic atf_expect_timeout Do reason Dc Dq \&...
316edebbb8eSjmmvExpects the test case to execute for longer than its timeout.
317edebbb8eSjmmv.El
318e2207522Sjmmv.Ss Helper functions for common checks
319*7f0357d3Skre.Ic atf_check Oo options Oc command Op args
320e2207522Sjmmv.Pp
32112aa0b5aSjmmvThis function wraps the execution of the
32212aa0b5aSjmmv.Nm atf-check
32312aa0b5aSjmmvtool and makes the test case fail if the tool reports failure.
32412aa0b5aSjmmvYou should always use this function instead of the tool in your scripts.
32512aa0b5aSjmmvFor more details on the parameters of this function, refer to
32612aa0b5aSjmmv.Xr atf-check 1 .
327e2207522Sjmmv.Pp
328*7f0357d3Skre.Ic atf_check_equal expr1 expr2
329e2207522Sjmmv.Pp
330e2207522SjmmvThis function takes two expressions, evaluates them and, if their
331e2207522Sjmmvresults differ, aborts the test case with an appropriate failure message.
332e2207522Sjmmv.Sh EXAMPLES
333e2207522SjmmvThe following shows a complete test program with a single test case that
334e2207522Sjmmvvalidates the addition operator:
335e2207522Sjmmv.Bd -literal -offset indent
336e2207522Sjmmvatf_test_case addition
337e2207522Sjmmvaddition_head() {
338e2207522Sjmmv    atf_set "descr" "Sample tests for the addition operator"
339e2207522Sjmmv}
340e2207522Sjmmvaddition_body() {
341e2207522Sjmmv    atf_check_equal $((0 + 0)) 0
342e2207522Sjmmv    atf_check_equal $((0 + 1)) 1
343e2207522Sjmmv    atf_check_equal $((1 + 0)) 0
344e2207522Sjmmv
345e2207522Sjmmv    atf_check_equal $((1 + 1)) 2
346e2207522Sjmmv
347e2207522Sjmmv    atf_check_equal $((100 + 200)) 300
348e2207522Sjmmv}
349e2207522Sjmmv
350e2207522Sjmmvatf_init_test_cases() {
351e2207522Sjmmv    atf_add_test_case addition
352e2207522Sjmmv}
353e2207522Sjmmv.Ed
354e2207522Sjmmv.Pp
355e2207522SjmmvThis other example shows how to include a file with extra helper functions
356e2207522Sjmmvin the test program:
357e2207522Sjmmv.Bd -literal -offset indent
358e2207522Sjmmv.Ns ... definition of test cases ...
359e2207522Sjmmv
360e2207522Sjmmvatf_init_test_cases() {
361e2207522Sjmmv    . $(atf_get_srcdir)/helper_functions.sh
362e2207522Sjmmv
363e2207522Sjmmv    atf_add_test_case foo1
364e2207522Sjmmv    atf_add_test_case foo2
365e2207522Sjmmv}
366e2207522Sjmmv.Ed
367e2207522Sjmmv.Pp
368e2207522SjmmvThis example demonstrates the use of the very useful
369e2207522Sjmmv.Fn atf_check
370e2207522Sjmmvfunction:
371e2207522Sjmmv.Bd -literal -offset indent
372e2207522Sjmmv# Check for silent output
373d780102eSjmmvatf_check -s exit:0 -o empty -e empty 'true'
374e2207522Sjmmv
375e2207522Sjmmv# Check for silent output and failure
376d780102eSjmmvatf_check -s exit:1 -o empty -e empty 'false'
377e2207522Sjmmv
378e2207522Sjmmv# Check for known stdout and silent stderr
379e2207522Sjmmvecho foo >expout
380d780102eSjmmvatf_check -s exit:0 -o file:expout -e empty 'echo foo'
381e2207522Sjmmv
382e2207522Sjmmv# Generate a file for later inspection
383d780102eSjmmvatf_check -s exit:0 -o save:stdout -e empty 'ls'
384e2207522Sjmmvgrep foo ls || atf_fail "foo file not found in listing"
385d780102eSjmmv
386d780102eSjmmv# Or just do the match along the way
387d780102eSjmmvatf_check -s exit:0 -o match:"^foo$" -e empty 'ls'
388e2207522Sjmmv.Ed
389e2207522Sjmmv.Sh SEE ALSO
3909b3149ccSjmmv.Xr atf-sh 1 ,
391e2207522Sjmmv.Xr atf-test-program 1 ,
392edebbb8eSjmmv.Xr atf-test-case 4 ,
393edebbb8eSjmmv.Xr atf 7
394