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 June 08, 2017 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