xref: /freebsd/contrib/atf/atf-sh/atf-sh.3 (revision 66df505066f51e6d8411b966765d828817f88971)
1.\" Copyright (c) 2008 The NetBSD Foundation, Inc.
2.\" All rights reserved.
3.\"
4.\" Redistribution and use in source and binary forms, with or without
5.\" modification, are permitted provided that the following conditions
6.\" are met:
7.\" 1. Redistributions of source code must retain the above copyright
8.\"    notice, this list of conditions and the following disclaimer.
9.\" 2. Redistributions in binary form must reproduce the above copyright
10.\"    notice, this list of conditions and the following disclaimer in the
11.\"    documentation and/or other materials provided with the distribution.
12.\"
13.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND
14.\" CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
15.\" INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
16.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17.\" IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY
18.\" DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
20.\" GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
22.\" IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
23.\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
24.\" IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25.Dd January 27, 2021
26.Dt ATF-SH 3
27.Os
28.Sh NAME
29.Nm atf_add_test_case ,
30.Nm atf_check ,
31.Nm atf_check_equal ,
32.Nm atf_check_not_equal ,
33.Nm atf_config_get ,
34.Nm atf_config_has ,
35.Nm atf_expect_death ,
36.Nm atf_expect_exit ,
37.Nm atf_expect_fail ,
38.Nm atf_expect_pass ,
39.Nm atf_expect_signal ,
40.Nm atf_expect_timeout ,
41.Nm atf_fail ,
42.Nm atf_get ,
43.Nm atf_get_srcdir ,
44.Nm atf_init_test_cases ,
45.Nm atf_pass ,
46.Nm atf_require_prog ,
47.Nm atf_set ,
48.Nm atf_skip ,
49.Nm atf_test_case
50.Nd POSIX shell API to write ATF-based test programs
51.Sh SYNOPSIS
52.Nm atf_add_test_case
53.Qq name
54.Nm atf_check
55.Qq command
56.Nm atf_check_equal
57.Qq expected_expression
58.Qq actual_expression
59.Nm atf_check_not_equal
60.Qq expected_expression
61.Qq actual_expression
62.Nm atf_config_get
63.Qq var_name
64.Nm atf_config_has
65.Qq var_name
66.Nm atf_expect_death
67.Qq reason
68.Qq ...
69.Nm atf_expect_exit
70.Qq exitcode
71.Qq reason
72.Qq ...
73.Nm atf_expect_fail
74.Qq reason
75.Qq ...
76.Nm atf_expect_pass
77.Qq
78.Nm atf_expect_signal
79.Qq signo
80.Qq reason
81.Qq ...
82.Nm atf_expect_timeout
83.Qq reason
84.Qq ...
85.Nm atf_fail
86.Qq reason
87.Nm atf_get
88.Qq var_name
89.Nm atf_get_srcdir
90.Nm atf_init_test_cases
91.Qq name
92.Nm atf_pass
93.Nm atf_require_prog
94.Qq prog_name
95.Nm atf_set
96.Qq var_name
97.Qq value
98.Nm atf_skip
99.Qq reason
100.Nm atf_test_case
101.Qq name
102.Qq cleanup
103.Sh DESCRIPTION
104ATF
105provides a simple but powerful interface to easily write test programs in
106the POSIX shell language.
107These are extremely helpful given that they are trivial to write due to the
108language simplicity and the great deal of available external tools, so they
109are often ideal to test other applications at the user level.
110.Pp
111Test programs written using this library must be run using the
112.Xr atf-sh 1
113interpreter by putting the following on their very first line:
114.Bd -literal -offset indent
115#! /usr/bin/env atf-sh
116.Ed
117.Pp
118Shell-based test programs always follow this template:
119.Bd -literal -offset indent
120atf_test_case tc1
121tc1_head() {
122    ... first test case's header ...
123}
124tc1_body() {
125    ... first test case's body ...
126}
127
128atf_test_case tc2 cleanup
129tc2_head() {
130    ... second test case's header ...
131}
132tc2_body() {
133    ... second test case's body ...
134}
135tc2_cleanup() {
136    ... second test case's cleanup ...
137}
138
139\&... additional test cases ...
140
141atf_init_test_cases() {
142    atf_add_test_case tc1
143    atf_add_test_case tc2
144    ... add additional test cases ...
145}
146.Ed
147.Ss Definition of test cases
148Test cases have an identifier and are composed of three different parts:
149the header, the body and an optional cleanup routine, all of which are
150described in
151.Xr atf-test-case 4 .
152To define test cases, one can use the
153.Nm atf_test_case
154function, which takes a first parameter specifying the test case's
155name and instructs the library to set things up to accept it as a valid
156test case.
157The second parameter is optional and, if provided, must be
158.Sq cleanup ;
159providing this parameter allows defining a cleanup routine for the test
160case.
161It is important to note that this function
162.Em does not
163set the test case up for execution when the program is run.
164In order to do so, a later registration is needed through the
165.Nm atf_add_test_case
166function detailed in
167.Sx Program initialization .
168.Pp
169Later on, one must define the three parts of the body by providing two
170or three functions (remember that the cleanup routine is optional).
171These functions are named after the test case's identifier, and are
172.Nm \*(Ltid\*(Gt_head ,
173.Nm \*(Ltid\*(Gt_body
174and
175.Nm \*(Ltid\*(Gt_cleanup .
176None of these take parameters when executed.
177.Ss Program initialization
178The test program must define an
179.Nm atf_init_test_cases
180function, which is in charge of registering the test cases that will be
181executed at run time by using the
182.Nm atf_add_test_case
183function, which takes the name of a test case as its single parameter.
184This main function should not do anything else, except maybe sourcing
185auxiliary source files that define extra variables and functions.
186.Ss Configuration variables
187The test case has read-only access to the current configuration variables
188through the
189.Nm atf_config_has
190and
191.Nm atf_config_get
192methods.
193The former takes a single parameter specifying a variable name and returns
194a boolean indicating whether the variable is defined or not.
195The latter can take one or two parameters.
196If it takes only one, it specifies the variable from which to get the
197value, and this variable must be defined.
198If it takes two, the second one specifies a default value to be returned
199if the variable is not available.
200.Ss Access to the source directory
201It is possible to get the path to the test case's source directory from
202anywhere in the test program by using the
203.Nm atf_get_srcdir
204function.
205It is interesting to note that this can be used inside
206.Nm atf_init_test_cases
207to silently include additional helper files from the source directory.
208.Ss Requiring programs
209Aside from the
210.Va require.progs
211meta-data variable available in the header only, one can also check for
212additional programs in the test case's body by using the
213.Nm atf_require_prog
214function, which takes the base name or full path of a single binary.
215Relative paths are forbidden.
216If it is not found, the test case will be automatically skipped.
217.Ss Test case finalization
218The test case finalizes either when the body reaches its end, at which
219point the test is assumed to have
220.Em passed ,
221or at any explicit call to
222.Nm atf_pass ,
223.Nm atf_fail
224or
225.Nm atf_skip .
226These three functions terminate the execution of the test case immediately.
227The cleanup routine will be processed afterwards in a completely automated
228way, regardless of the test case's termination reason.
229.Pp
230.Nm atf_pass
231does not take any parameters.
232.Nm atf_fail
233and
234.Nm atf_skip
235take a single string parameter that describes why the test case failed or
236was skipped, respectively.
237It is very important to provide a clear error message in both cases so that
238the user can quickly know why the test did not pass.
239.Ss Expectations
240Everything explained in the previous section changes when the test case
241expectations are redefined by the programmer.
242.Pp
243Each test case has an internal state called
244.Sq expect
245that describes what the test case expectations are at any point in time.
246The value of this property can change during execution by any of:
247.Bl -tag -width indent
248.It Nm atf_expect_death Qo reason Qc Qo ... Qc
249Expects the test case to exit prematurely regardless of the nature of the
250exit.
251.It Nm atf_expect_exit Qo exitcode Qc Qo reason Qc Qo ... Qc
252Expects the test case to exit cleanly.
253If
254.Va exitcode
255is not
256.Sq -1 ,
257the runtime engine will validate that the exit code of the test case
258matches the one provided in this call.
259Otherwise, the exact value will be ignored.
260.It Nm atf_expect_fail Qo reason Qc
261Any failure raised in this mode is recorded, but such failures do not report
262the test case as failed; instead, the test case finalizes cleanly and is
263reported as
264.Sq expected failure ;
265this report includes the provided
266.Fa reason
267as part of it.
268If no error is raised while running in this mode, then the test case is
269reported as
270.Sq failed .
271.Pp
272This mode is useful to reproduce actual known bugs in tests.
273Whenever the developer fixes the bug later on, the test case will start
274reporting a failure, signaling the developer that the test case must be
275adjusted to the new conditions.
276In this situation, it is useful, for example, to set
277.Fa reason
278as the bug number for tracking purposes.
279.It Nm atf_expect_pass
280This is the normal mode of execution.
281In this mode, any failure is reported as such to the user and the test case
282is marked as
283.Sq failed .
284.It Nm atf_expect_signal Qo signo Qc Qo reason Qc Qo ... Qc
285Expects the test case to terminate due to the reception of a signal.
286If
287.Va signo
288is not
289.Sq -1 ,
290the runtime engine will validate that the signal that terminated the test
291case matches the one provided in this call.
292Otherwise, the exact value will be ignored.
293.It Nm atf_expect_timeout Qo reason Qc Qo ... Qc
294Expects the test case to execute for longer than its timeout.
295.El
296.Ss Helper functions for common checks
297.Bl -tag -width indent
298.It Nm atf_check Qo [options] Qc Qo command Qc Qo [args] Qc
299Executes a command, performs checks on its exit code and its output, and
300fails the test case if any of the checks is not successful.
301This function is particularly useful in integration tests that verify the
302correct functioning of a binary.
303.Pp
304Internally, this function is just a wrapper over the
305.Xr atf-check 1
306tool (whose manual page provides all details on the calling syntax).
307You should always use the
308.Nm atf_check
309function instead of the
310.Xr atf-check 1
311tool in your scripts; the latter is not even in the path.
312.It Nm atf_check_equal Qo expected_expression Qc Qo actual_expression Qc
313This function takes two expressions, evaluates them and, if their
314results differ, aborts the test case with an appropriate failure message.
315The common style is to put the expected value in the first parameter and the
316actual value in the second parameter.
317.It Nm atf_check_not_equal Qo expected_expression Qc Qo actual_expression Qc
318This function takes two expressions, evaluates them and, if their
319results are equal, aborts the test case with an appropriate failure message.
320The common style is to put the expected value in the first parameter and the
321actual value in the second parameter.
322.El
323.Sh EXAMPLES
324The following shows a complete test program with a single test case that
325validates the addition operator:
326.Bd -literal -offset indent
327atf_test_case addition
328addition_head() {
329    atf_set "descr" "Sample tests for the addition operator"
330}
331addition_body() {
332    atf_check_equal 0 $((0 + 0))
333    atf_check_equal 1 $((0 + 1))
334    atf_check_equal 1 $((1 + 0))
335
336    atf_check_equal 2 $((1 + 1))
337
338    atf_check_equal 300 $((100 + 200))
339}
340
341atf_init_test_cases() {
342    atf_add_test_case addition
343}
344.Ed
345.Pp
346This other example shows how to include a file with extra helper functions
347in the test program:
348.Bd -literal -offset indent
349\&... definition of test cases ...
350
351atf_init_test_cases() {
352    . $(atf_get_srcdir)/helper_functions.sh
353
354    atf_add_test_case foo1
355    atf_add_test_case foo2
356}
357.Ed
358.Pp
359This example demonstrates the use of the very useful
360.Nm atf_check
361function:
362.Bd -literal -offset indent
363# Check for silent output
364atf_check -s exit:0 -o empty -e empty true
365
366# Check for silent output and failure
367atf_check -s exit:1 -o empty -e empty false
368
369# Check for known stdout and silent stderr
370echo foo >expout
371atf_check -s exit:0 -o file:expout -e empty echo foo
372
373# Generate a file for later inspection
374atf_check -s exit:0 -o save:stdout -e empty ls
375grep foo ls || atf_fail "foo file not found in listing"
376
377# Or just do the match along the way
378atf_check -s exit:0 -o match:"^foo$" -e empty ls
379.Ed
380.Sh SEE ALSO
381.Xr atf-check 1 ,
382.Xr atf-sh 1 ,
383.Xr atf-test-program 1 ,
384.Xr atf-test-case 4
385