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