10677dfd1SJulio Merino.\" Copyright (c) 2008 The NetBSD Foundation, Inc. 20677dfd1SJulio Merino.\" All rights reserved. 30677dfd1SJulio Merino.\" 40677dfd1SJulio Merino.\" Redistribution and use in source and binary forms, with or without 50677dfd1SJulio Merino.\" modification, are permitted provided that the following conditions 60677dfd1SJulio Merino.\" are met: 70677dfd1SJulio Merino.\" 1. Redistributions of source code must retain the above copyright 80677dfd1SJulio Merino.\" notice, this list of conditions and the following disclaimer. 90677dfd1SJulio Merino.\" 2. Redistributions in binary form must reproduce the above copyright 100677dfd1SJulio Merino.\" notice, this list of conditions and the following disclaimer in the 110677dfd1SJulio Merino.\" documentation and/or other materials provided with the distribution. 120677dfd1SJulio Merino.\" 130677dfd1SJulio Merino.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND 140677dfd1SJulio Merino.\" CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, 150677dfd1SJulio Merino.\" INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 160677dfd1SJulio Merino.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 170677dfd1SJulio Merino.\" IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY 180677dfd1SJulio Merino.\" DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 190677dfd1SJulio Merino.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 200677dfd1SJulio Merino.\" GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 210677dfd1SJulio Merino.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 220677dfd1SJulio Merino.\" IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 230677dfd1SJulio Merino.\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 240677dfd1SJulio Merino.\" IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25*83a1ee57SDag-Erling Smørgrav.Dd May 11, 2025 260677dfd1SJulio Merino.Dt ATF-C++ 3 270677dfd1SJulio Merino.Os 280677dfd1SJulio Merino.Sh NAME 290677dfd1SJulio Merino.Nm atf-c++ , 300677dfd1SJulio Merino.Nm ATF_ADD_TEST_CASE , 310677dfd1SJulio Merino.Nm ATF_CHECK_ERRNO , 320677dfd1SJulio Merino.Nm ATF_FAIL , 330677dfd1SJulio Merino.Nm ATF_INIT_TEST_CASES , 340677dfd1SJulio Merino.Nm ATF_PASS , 350677dfd1SJulio Merino.Nm ATF_REQUIRE , 360677dfd1SJulio Merino.Nm ATF_REQUIRE_EQ , 370677dfd1SJulio Merino.Nm ATF_REQUIRE_ERRNO , 380677dfd1SJulio Merino.Nm ATF_REQUIRE_IN , 390677dfd1SJulio Merino.Nm ATF_REQUIRE_MATCH , 400677dfd1SJulio Merino.Nm ATF_REQUIRE_NOT_IN , 410677dfd1SJulio Merino.Nm ATF_REQUIRE_THROW , 420677dfd1SJulio Merino.Nm ATF_REQUIRE_THROW_RE , 430677dfd1SJulio Merino.Nm ATF_SKIP , 440677dfd1SJulio Merino.Nm ATF_TEST_CASE , 450677dfd1SJulio Merino.Nm ATF_TEST_CASE_BODY , 460677dfd1SJulio Merino.Nm ATF_TEST_CASE_CLEANUP , 470677dfd1SJulio Merino.Nm ATF_TEST_CASE_HEAD , 480677dfd1SJulio Merino.Nm ATF_TEST_CASE_NAME , 490677dfd1SJulio Merino.Nm ATF_TEST_CASE_USE , 500677dfd1SJulio Merino.Nm ATF_TEST_CASE_WITH_CLEANUP , 510677dfd1SJulio Merino.Nm ATF_TEST_CASE_WITHOUT_HEAD , 520677dfd1SJulio Merino.Nm atf::utils::cat_file , 530677dfd1SJulio Merino.Nm atf::utils::compare_file , 540677dfd1SJulio Merino.Nm atf::utils::copy_file , 550677dfd1SJulio Merino.Nm atf::utils::create_file , 560677dfd1SJulio Merino.Nm atf::utils::file_exists , 570677dfd1SJulio Merino.Nm atf::utils::fork , 580677dfd1SJulio Merino.Nm atf::utils::grep_collection , 590677dfd1SJulio Merino.Nm atf::utils::grep_file , 600677dfd1SJulio Merino.Nm atf::utils::grep_string , 610677dfd1SJulio Merino.Nm atf::utils::redirect , 620677dfd1SJulio Merino.Nm atf::utils::wait 630677dfd1SJulio Merino.Nd C++ API to write ATF-based test programs 640677dfd1SJulio Merino.Sh SYNOPSIS 650677dfd1SJulio Merino.In atf-c++.hpp 660677dfd1SJulio Merino.Fn ATF_ADD_TEST_CASE "tcs" "name" 670677dfd1SJulio Merino.Fn ATF_CHECK_ERRNO "expected_errno" "bool_expression" 680677dfd1SJulio Merino.Fn ATF_FAIL "reason" 690677dfd1SJulio Merino.Fn ATF_INIT_TEST_CASES "tcs" 700677dfd1SJulio Merino.Fn ATF_PASS 710677dfd1SJulio Merino.Fn ATF_REQUIRE "expression" 720677dfd1SJulio Merino.Fn ATF_REQUIRE_EQ "expected_expression" "actual_expression" 730677dfd1SJulio Merino.Fn ATF_REQUIRE_ERRNO "expected_errno" "bool_expression" 740677dfd1SJulio Merino.Fn ATF_REQUIRE_IN "element" "collection" 750677dfd1SJulio Merino.Fn ATF_REQUIRE_MATCH "regexp" "string_expression" 760677dfd1SJulio Merino.Fn ATF_REQUIRE_NOT_IN "element" "collection" 770677dfd1SJulio Merino.Fn ATF_REQUIRE_THROW "expected_exception" "statement" 780677dfd1SJulio Merino.Fn ATF_REQUIRE_THROW_RE "expected_exception" "regexp" "statement" 790677dfd1SJulio Merino.Fn ATF_SKIP "reason" 800677dfd1SJulio Merino.Fn ATF_TEST_CASE "name" 810677dfd1SJulio Merino.Fn ATF_TEST_CASE_BODY "name" 820677dfd1SJulio Merino.Fn ATF_TEST_CASE_CLEANUP "name" 830677dfd1SJulio Merino.Fn ATF_TEST_CASE_HEAD "name" 840677dfd1SJulio Merino.Fn ATF_TEST_CASE_NAME "name" 850677dfd1SJulio Merino.Fn ATF_TEST_CASE_USE "name" 860677dfd1SJulio Merino.Fn ATF_TEST_CASE_WITH_CLEANUP "name" 870677dfd1SJulio Merino.Fn ATF_TEST_CASE_WITHOUT_HEAD "name" 880677dfd1SJulio Merino.Ft void 890677dfd1SJulio Merino.Fo atf::utils::cat_file 900677dfd1SJulio Merino.Fa "const std::string& path" 910677dfd1SJulio Merino.Fa "const std::string& prefix" 920677dfd1SJulio Merino.Fc 930677dfd1SJulio Merino.Ft bool 940677dfd1SJulio Merino.Fo atf::utils::compare_file 950677dfd1SJulio Merino.Fa "const std::string& path" 960677dfd1SJulio Merino.Fa "const std::string& contents" 970677dfd1SJulio Merino.Fc 980677dfd1SJulio Merino.Ft void 990677dfd1SJulio Merino.Fo atf::utils::copy_file 1000677dfd1SJulio Merino.Fa "const std::string& source" 1010677dfd1SJulio Merino.Fa "const std::string& destination" 1020677dfd1SJulio Merino.Fc 1030677dfd1SJulio Merino.Ft void 1040677dfd1SJulio Merino.Fo atf::utils::create_file 1050677dfd1SJulio Merino.Fa "const std::string& path" 1060677dfd1SJulio Merino.Fa "const std::string& contents" 1070677dfd1SJulio Merino.Fc 1080677dfd1SJulio Merino.Ft void 1090677dfd1SJulio Merino.Fo atf::utils::file_exists 1100677dfd1SJulio Merino.Fa "const std::string& path" 1110677dfd1SJulio Merino.Fc 1120677dfd1SJulio Merino.Ft pid_t 1130677dfd1SJulio Merino.Fo atf::utils::fork 1140677dfd1SJulio Merino.Fa "void" 1150677dfd1SJulio Merino.Fc 1160677dfd1SJulio Merino.Ft bool 1170677dfd1SJulio Merino.Fo atf::utils::grep_collection 1180677dfd1SJulio Merino.Fa "const std::string& regexp" 1190677dfd1SJulio Merino.Fa "const Collection& collection" 1200677dfd1SJulio Merino.Fc 1210677dfd1SJulio Merino.Ft bool 1220677dfd1SJulio Merino.Fo atf::utils::grep_file 1230677dfd1SJulio Merino.Fa "const std::string& regexp" 1240677dfd1SJulio Merino.Fa "const std::string& path" 1250677dfd1SJulio Merino.Fc 1260677dfd1SJulio Merino.Ft bool 1270677dfd1SJulio Merino.Fo atf::utils::grep_string 1280677dfd1SJulio Merino.Fa "const std::string& regexp" 1290677dfd1SJulio Merino.Fa "const std::string& path" 1300677dfd1SJulio Merino.Fc 1310677dfd1SJulio Merino.Ft void 1320677dfd1SJulio Merino.Fo atf::utils::redirect 1330677dfd1SJulio Merino.Fa "const int fd" 1340677dfd1SJulio Merino.Fa "const std::string& path" 1350677dfd1SJulio Merino.Fc 1360677dfd1SJulio Merino.Ft void 1370677dfd1SJulio Merino.Fo atf::utils::wait 1380677dfd1SJulio Merino.Fa "const pid_t pid" 1390677dfd1SJulio Merino.Fa "const int expected_exit_status" 1400677dfd1SJulio Merino.Fa "const std::string& expected_stdout" 1410677dfd1SJulio Merino.Fa "const std::string& expected_stderr" 1420677dfd1SJulio Merino.Fc 1430677dfd1SJulio Merino.Sh DESCRIPTION 1440677dfd1SJulio MerinoATF provides a C++ programming interface to implement test programs. 1450677dfd1SJulio MerinoC++-based test programs follow this template: 1460677dfd1SJulio Merino.Bd -literal -offset indent 1470677dfd1SJulio Merinoextern "C" { 148af6edc1bSEnji Cooper\&... C-specific includes go here ... 1490677dfd1SJulio Merino} 1500677dfd1SJulio Merino 151af6edc1bSEnji Cooper\&... C++-specific includes go here ... 1520677dfd1SJulio Merino 1530677dfd1SJulio Merino#include <atf-c++.hpp> 1540677dfd1SJulio Merino 1550677dfd1SJulio MerinoATF_TEST_CASE(tc1); 1560677dfd1SJulio MerinoATF_TEST_CASE_HEAD(tc1) 1570677dfd1SJulio Merino{ 1580677dfd1SJulio Merino ... first test case's header ... 1590677dfd1SJulio Merino} 1600677dfd1SJulio MerinoATF_TEST_CASE_BODY(tc1) 1610677dfd1SJulio Merino{ 1620677dfd1SJulio Merino ... first test case's body ... 1630677dfd1SJulio Merino} 1640677dfd1SJulio Merino 1650677dfd1SJulio MerinoATF_TEST_CASE_WITH_CLEANUP(tc2); 1660677dfd1SJulio MerinoATF_TEST_CASE_HEAD(tc2) 1670677dfd1SJulio Merino{ 1680677dfd1SJulio Merino ... second test case's header ... 1690677dfd1SJulio Merino} 1700677dfd1SJulio MerinoATF_TEST_CASE_BODY(tc2) 1710677dfd1SJulio Merino{ 1720677dfd1SJulio Merino ... second test case's body ... 1730677dfd1SJulio Merino} 1740677dfd1SJulio MerinoATF_TEST_CASE_CLEANUP(tc2) 1750677dfd1SJulio Merino{ 1760677dfd1SJulio Merino ... second test case's cleanup ... 1770677dfd1SJulio Merino} 1780677dfd1SJulio Merino 1790677dfd1SJulio MerinoATF_TEST_CASE(tc3); 1800677dfd1SJulio MerinoATF_TEST_CASE_BODY(tc3) 1810677dfd1SJulio Merino{ 1820677dfd1SJulio Merino ... third test case's body ... 1830677dfd1SJulio Merino} 1840677dfd1SJulio Merino 185af6edc1bSEnji Cooper\&... additional test cases ... 1860677dfd1SJulio Merino 1870677dfd1SJulio MerinoATF_INIT_TEST_CASES(tcs) 1880677dfd1SJulio Merino{ 1890677dfd1SJulio Merino ATF_ADD_TEST_CASE(tcs, tc1); 1900677dfd1SJulio Merino ATF_ADD_TEST_CASE(tcs, tc2); 1910677dfd1SJulio Merino ATF_ADD_TEST_CASE(tcs, tc3); 1920677dfd1SJulio Merino ... add additional test cases ... 1930677dfd1SJulio Merino} 1940677dfd1SJulio Merino.Ed 1950677dfd1SJulio Merino.Ss Definition of test cases 1960677dfd1SJulio MerinoTest cases have an identifier and are composed of three different parts: 1970677dfd1SJulio Merinothe header, the body and an optional cleanup routine, all of which are 1980677dfd1SJulio Merinodescribed in 1990677dfd1SJulio Merino.Xr atf-test-case 4 . 2000677dfd1SJulio MerinoTo define test cases, one can use the 2010677dfd1SJulio Merino.Fn ATF_TEST_CASE , 2020677dfd1SJulio Merino.Fn ATF_TEST_CASE_WITH_CLEANUP 2030677dfd1SJulio Merinoor the 2040677dfd1SJulio Merino.Fn ATF_TEST_CASE_WITHOUT_HEAD 205af6edc1bSEnji Coopermacros, which take a single parameter specifying the test case's 2060677dfd1SJulio Merinoname. 2070677dfd1SJulio Merino.Fn ATF_TEST_CASE , 2080677dfd1SJulio Merinorequires to define a head and a body for the test case, 2090677dfd1SJulio Merino.Fn ATF_TEST_CASE_WITH_CLEANUP 2100677dfd1SJulio Merinorequires to define a head, a body and a cleanup for the test case and 2110677dfd1SJulio Merino.Fn ATF_TEST_CASE_WITHOUT_HEAD 2120677dfd1SJulio Merinorequires only a body for the test case. 2130677dfd1SJulio MerinoIt is important to note that these 2140677dfd1SJulio Merino.Em do not 2150677dfd1SJulio Merinoset the test case up for execution when the program is run. 2160677dfd1SJulio MerinoIn order to do so, a later registration is needed through the 2170677dfd1SJulio Merino.Fn ATF_ADD_TEST_CASE 2180677dfd1SJulio Merinomacro detailed in 2190677dfd1SJulio Merino.Sx Program initialization . 2200677dfd1SJulio Merino.Pp 2210677dfd1SJulio MerinoLater on, one must define the three parts of the body by means of three 2220677dfd1SJulio Merinofunctions. 2230677dfd1SJulio MerinoTheir headers are given by the 2240677dfd1SJulio Merino.Fn ATF_TEST_CASE_HEAD , 2250677dfd1SJulio Merino.Fn ATF_TEST_CASE_BODY 2260677dfd1SJulio Merinoand 2270677dfd1SJulio Merino.Fn ATF_TEST_CASE_CLEANUP 2280677dfd1SJulio Merinomacros, all of which take the test case's name. 2290677dfd1SJulio MerinoFollowing each of these, a block of code is expected, surrounded by the 2300677dfd1SJulio Merinoopening and closing brackets. 2310677dfd1SJulio Merino.Pp 2320677dfd1SJulio MerinoAdditionally, the 2330677dfd1SJulio Merino.Fn ATF_TEST_CASE_NAME 2340677dfd1SJulio Merinomacro can be used to obtain the name of the class corresponding to a 235af6edc1bSEnji Cooperparticular test case, as the name is internally managed by the library to 2360677dfd1SJulio Merinoprevent clashes with other user identifiers. 2370677dfd1SJulio MerinoSimilarly, the 2380677dfd1SJulio Merino.Fn ATF_TEST_CASE_USE 2390677dfd1SJulio Merinomacro can be executed on a particular test case to mark it as "used" and 2400677dfd1SJulio Merinothus prevent compiler warnings regarding unused symbols. 2410677dfd1SJulio MerinoNote that 2420677dfd1SJulio Merino.Em you should never have to use these macros during regular operation. 2430677dfd1SJulio Merino.Ss Program initialization 2440677dfd1SJulio MerinoThe library provides a way to easily define the test program's 2450677dfd1SJulio Merino.Fn main 2460677dfd1SJulio Merinofunction. 2470677dfd1SJulio MerinoYou should never define one on your own, but rely on the 2480677dfd1SJulio Merinolibrary to do it for you. 2490677dfd1SJulio MerinoThis is done by using the 2500677dfd1SJulio Merino.Fn ATF_INIT_TEST_CASES 2510677dfd1SJulio Merinomacro, which is passed the name of the list that will hold the test cases. 2520677dfd1SJulio MerinoThis name can be whatever you want as long as it is a valid variable value. 2530677dfd1SJulio Merino.Pp 2540677dfd1SJulio MerinoAfter the macro, you are supposed to provide the body of a function, which 2550677dfd1SJulio Merinoshould only use the 2560677dfd1SJulio Merino.Fn ATF_ADD_TEST_CASE 2570677dfd1SJulio Merinomacro to register the test cases the test program will execute. 2580677dfd1SJulio MerinoThe first parameter of this macro matches the name you provided in the 2590677dfd1SJulio Merinoformer call. 2600677dfd1SJulio Merino.Ss Header definitions 2610677dfd1SJulio MerinoThe test case's header can define the meta-data by using the 2620677dfd1SJulio Merino.Fn set_md_var 2630677dfd1SJulio Merinomethod, which takes two parameters: the first one specifies the 2640677dfd1SJulio Merinometa-data variable to be set and the second one specifies its value. 2650677dfd1SJulio MerinoBoth of them are strings. 2660677dfd1SJulio Merino.Ss Configuration variables 2670677dfd1SJulio MerinoThe test case has read-only access to the current configuration variables 2680677dfd1SJulio Merinoby means of the 2690677dfd1SJulio Merino.Ft bool 2700677dfd1SJulio Merino.Fn has_config_var 2710677dfd1SJulio Merinoand the 2720677dfd1SJulio Merino.Ft std::string 2730677dfd1SJulio Merino.Fn get_config_var 2740677dfd1SJulio Merinomethods, which can be called in any of the three parts of a test case. 2750677dfd1SJulio Merino.Ss Access to the source directory 2760677dfd1SJulio MerinoIt is possible to get the path to the test case's source directory from any 2770677dfd1SJulio Merinoof its three components by querying the 2780677dfd1SJulio Merino.Sq srcdir 2790677dfd1SJulio Merinoconfiguration variable. 280*83a1ee57SDag-Erling Smørgrav.Ss Requiring kernel modules 281*83a1ee57SDag-Erling SmørgravAside from the 282*83a1ee57SDag-Erling Smørgrav.Va require.kmods 283*83a1ee57SDag-Erling Smørgravmeta-data variable available in the header only, one can also check for 284*83a1ee57SDag-Erling Smørgravadditional kernel modules in the test case's body by using the 285*83a1ee57SDag-Erling Smørgrav.Fn require_kmod 286*83a1ee57SDag-Erling Smørgravfunction, which takes the name of a single module. 287*83a1ee57SDag-Erling SmørgravIf it is not found, the test case will be automatically skipped. 2880677dfd1SJulio Merino.Ss Requiring programs 2890677dfd1SJulio MerinoAside from the 2900677dfd1SJulio Merino.Va require.progs 2910677dfd1SJulio Merinometa-data variable available in the header only, one can also check for 2920677dfd1SJulio Merinoadditional programs in the test case's body by using the 2930677dfd1SJulio Merino.Fn require_prog 2940677dfd1SJulio Merinofunction, which takes the base name or full path of a single binary. 2950677dfd1SJulio MerinoRelative paths are forbidden. 2960677dfd1SJulio MerinoIf it is not found, the test case will be automatically skipped. 2970677dfd1SJulio Merino.Ss Test case finalization 2980677dfd1SJulio MerinoThe test case finalizes either when the body reaches its end, at which 2990677dfd1SJulio Merinopoint the test is assumed to have 3000677dfd1SJulio Merino.Em passed , 3010677dfd1SJulio Merinoor at any explicit call to 3020677dfd1SJulio Merino.Fn ATF_PASS , 3030677dfd1SJulio Merino.Fn ATF_FAIL 3040677dfd1SJulio Merinoor 3050677dfd1SJulio Merino.Fn ATF_SKIP . 3060677dfd1SJulio MerinoThese three macros terminate the execution of the test case immediately. 3070677dfd1SJulio MerinoThe cleanup routine will be processed afterwards in a completely automated 3080677dfd1SJulio Merinoway, regardless of the test case's termination reason. 3090677dfd1SJulio Merino.Pp 3100677dfd1SJulio Merino.Fn ATF_PASS 3110677dfd1SJulio Merinodoes not take any parameters. 3120677dfd1SJulio Merino.Fn ATF_FAIL 3130677dfd1SJulio Merinoand 3140677dfd1SJulio Merino.Fn ATF_SKIP 3150677dfd1SJulio Merinotake a single string that describes why the test case failed or 3160677dfd1SJulio Merinowas skipped, respectively. 3170677dfd1SJulio MerinoIt is very important to provide a clear error message in both cases so that 3180677dfd1SJulio Merinothe user can quickly know why the test did not pass. 3190677dfd1SJulio Merino.Ss Expectations 3200677dfd1SJulio MerinoEverything explained in the previous section changes when the test case 3210677dfd1SJulio Merinoexpectations are redefined by the programmer. 3220677dfd1SJulio Merino.Pp 3230677dfd1SJulio MerinoEach test case has an internal state called 3240677dfd1SJulio Merino.Sq expect 3250677dfd1SJulio Merinothat describes what the test case expectations are at any point in time. 3260677dfd1SJulio MerinoThe value of this property can change during execution by any of: 3270677dfd1SJulio Merino.Bl -tag -width indent 3280677dfd1SJulio Merino.It Fn expect_death "reason" 3290677dfd1SJulio MerinoExpects the test case to exit prematurely regardless of the nature of the 3300677dfd1SJulio Merinoexit. 3310677dfd1SJulio Merino.It Fn expect_exit "exitcode" "reason" 3320677dfd1SJulio MerinoExpects the test case to exit cleanly. 3330677dfd1SJulio MerinoIf 3340677dfd1SJulio Merino.Va exitcode 3350677dfd1SJulio Merinois not 3360677dfd1SJulio Merino.Sq -1 , 3370677dfd1SJulio Merinothe runtime engine will validate that the exit code of the test case 3380677dfd1SJulio Merinomatches the one provided in this call. 3390677dfd1SJulio MerinoOtherwise, the exact value will be ignored. 3400677dfd1SJulio Merino.It Fn expect_fail "reason" 3410677dfd1SJulio MerinoAny failure (be it fatal or non-fatal) raised in this mode is recorded. 3420677dfd1SJulio MerinoHowever, such failures do not report the test case as failed; instead, the 3430677dfd1SJulio Merinotest case finalizes cleanly and is reported as 3440677dfd1SJulio Merino.Sq expected failure ; 3450677dfd1SJulio Merinothis report includes the provided 3460677dfd1SJulio Merino.Fa reason 3470677dfd1SJulio Merinoas part of it. 3480677dfd1SJulio MerinoIf no error is raised while running in this mode, then the test case is 3490677dfd1SJulio Merinoreported as 3500677dfd1SJulio Merino.Sq failed . 3510677dfd1SJulio Merino.Pp 3520677dfd1SJulio MerinoThis mode is useful to reproduce actual known bugs in tests. 3530677dfd1SJulio MerinoWhenever the developer fixes the bug later on, the test case will start 3540677dfd1SJulio Merinoreporting a failure, signaling the developer that the test case must be 3550677dfd1SJulio Merinoadjusted to the new conditions. 3560677dfd1SJulio MerinoIn this situation, it is useful, for example, to set 3570677dfd1SJulio Merino.Fa reason 3580677dfd1SJulio Merinoas the bug number for tracking purposes. 3590677dfd1SJulio Merino.It Fn expect_pass 3600677dfd1SJulio MerinoThis is the normal mode of execution. 3610677dfd1SJulio MerinoIn this mode, any failure is reported as such to the user and the test case 3620677dfd1SJulio Merinois marked as 3630677dfd1SJulio Merino.Sq failed . 3640677dfd1SJulio Merino.It Fn expect_race "reason" 3650677dfd1SJulio MerinoAny failure or timeout during the execution of the test case will be 3660677dfd1SJulio Merinoconsidered as if a race condition has been triggered and reported as such. 3670677dfd1SJulio MerinoIf no problems arise, the test will continue execution as usual. 3680677dfd1SJulio Merino.It Fn expect_signal "signo" "reason" 3690677dfd1SJulio MerinoExpects the test case to terminate due to the reception of a signal. 3700677dfd1SJulio MerinoIf 3710677dfd1SJulio Merino.Va signo 3720677dfd1SJulio Merinois not 3730677dfd1SJulio Merino.Sq -1 , 3740677dfd1SJulio Merinothe runtime engine will validate that the signal that terminated the test 3750677dfd1SJulio Merinocase matches the one provided in this call. 3760677dfd1SJulio MerinoOtherwise, the exact value will be ignored. 3770677dfd1SJulio Merino.It Fn expect_timeout "reason" 3780677dfd1SJulio MerinoExpects the test case to execute for longer than its timeout. 3790677dfd1SJulio Merino.El 3800677dfd1SJulio Merino.Ss Helper macros for common checks 3810677dfd1SJulio MerinoThe library provides several macros that are very handy in multiple 3820677dfd1SJulio Merinosituations. 3830677dfd1SJulio MerinoThese basically check some condition after executing a given statement or 3840677dfd1SJulio Merinoprocessing a given expression and, if the condition is not met, they 3850677dfd1SJulio Merinoautomatically call 3860677dfd1SJulio Merino.Fn ATF_FAIL 3870677dfd1SJulio Merinowith an appropriate error message. 3880677dfd1SJulio Merino.Pp 3890677dfd1SJulio Merino.Fn ATF_REQUIRE 3900677dfd1SJulio Merinotakes an expression and raises a failure if it evaluates to false. 3910677dfd1SJulio Merino.Pp 3920677dfd1SJulio Merino.Fn ATF_REQUIRE_EQ 3930677dfd1SJulio Merinotakes two expressions and raises a failure if the two do not evaluate to 3940677dfd1SJulio Merinothe same exact value. 3950677dfd1SJulio MerinoThe common style is to put the expected value in the first parameter and the 3960677dfd1SJulio Merinoactual value in the second parameter. 3970677dfd1SJulio Merino.Pp 3980677dfd1SJulio Merino.Fn ATF_REQUIRE_IN 3990677dfd1SJulio Merinotakes an element and a collection and validates that the element is present in 4000677dfd1SJulio Merinothe collection. 4010677dfd1SJulio Merino.Pp 4020677dfd1SJulio Merino.Fn ATF_REQUIRE_MATCH 4030677dfd1SJulio Merinotakes a regular expression and a string and raises a failure if the regular 4040677dfd1SJulio Merinoexpression does not match the string. 4050677dfd1SJulio Merino.Pp 4060677dfd1SJulio Merino.Fn ATF_REQUIRE_NOT_IN 4070677dfd1SJulio Merinotakes an element and a collection and validates that the element is not present 4080677dfd1SJulio Merinoin the collection. 4090677dfd1SJulio Merino.Pp 4100677dfd1SJulio Merino.Fn ATF_REQUIRE_THROW 4110677dfd1SJulio Merinotakes the name of an exception and a statement and raises a failure if 4120677dfd1SJulio Merinothe statement does not throw the specified exception. 4130677dfd1SJulio Merino.Fn ATF_REQUIRE_THROW_RE 414c203bd70SAlex Richardsontakes the name of an exception, a regular expression and a statement, and raises 415c203bd70SAlex Richardsona failure if the statement does not throw the specified exception and if the 4160677dfd1SJulio Merinomessage of the exception does not match the regular expression. 4170677dfd1SJulio Merino.Pp 4180677dfd1SJulio Merino.Fn ATF_CHECK_ERRNO 4190677dfd1SJulio Merinoand 4200677dfd1SJulio Merino.Fn ATF_REQUIRE_ERRNO 4210677dfd1SJulio Merinotake, first, the error code that the check is expecting to find in the 4220677dfd1SJulio Merino.Va errno 4230677dfd1SJulio Merinovariable and, second, a boolean expression that, if evaluates to true, 4240677dfd1SJulio Merinomeans that a call failed and 4250677dfd1SJulio Merino.Va errno 4260677dfd1SJulio Merinohas to be checked against the first value. 4270677dfd1SJulio Merino.Ss Utility functions 4280677dfd1SJulio MerinoThe following functions are provided as part of the 4290677dfd1SJulio Merino.Nm 4300677dfd1SJulio MerinoAPI to simplify the creation of a variety of tests. 4310677dfd1SJulio MerinoIn particular, these are useful to write tests for command-line interfaces. 4320677dfd1SJulio Merino.Pp 4330677dfd1SJulio Merino.Ft void 4340677dfd1SJulio Merino.Fo atf::utils::cat_file 4350677dfd1SJulio Merino.Fa "const std::string& path" 4360677dfd1SJulio Merino.Fa "const std::string& prefix" 4370677dfd1SJulio Merino.Fc 4380677dfd1SJulio Merino.Bd -ragged -offset indent 4390677dfd1SJulio MerinoPrints the contents of 4400677dfd1SJulio Merino.Fa path 4410677dfd1SJulio Merinoto the standard output, prefixing every line with the string in 4420677dfd1SJulio Merino.Fa prefix . 4430677dfd1SJulio Merino.Ed 4440677dfd1SJulio Merino.Pp 4450677dfd1SJulio Merino.Ft bool 4460677dfd1SJulio Merino.Fo atf::utils::compare_file 4470677dfd1SJulio Merino.Fa "const std::string& path" 4480677dfd1SJulio Merino.Fa "const std::string& contents" 4490677dfd1SJulio Merino.Fc 4500677dfd1SJulio Merino.Bd -ragged -offset indent 4510677dfd1SJulio MerinoReturns true if the given 4520677dfd1SJulio Merino.Fa path 4530677dfd1SJulio Merinomatches exactly the expected inlined 4540677dfd1SJulio Merino.Fa contents . 4550677dfd1SJulio Merino.Ed 4560677dfd1SJulio Merino.Pp 4570677dfd1SJulio Merino.Ft void 4580677dfd1SJulio Merino.Fo atf::utils::copy_file 4590677dfd1SJulio Merino.Fa "const std::string& source" 4600677dfd1SJulio Merino.Fa "const std::string& destination" 4610677dfd1SJulio Merino.Fc 4620677dfd1SJulio Merino.Bd -ragged -offset indent 4630677dfd1SJulio MerinoCopies the file 4640677dfd1SJulio Merino.Fa source 4650677dfd1SJulio Merinoto 4660677dfd1SJulio Merino.Fa destination . 4670677dfd1SJulio MerinoThe permissions of the file are preserved during the code. 4680677dfd1SJulio Merino.Ed 4690677dfd1SJulio Merino.Pp 4700677dfd1SJulio Merino.Ft void 4710677dfd1SJulio Merino.Fo atf::utils::create_file 4720677dfd1SJulio Merino.Fa "const std::string& path" 4730677dfd1SJulio Merino.Fa "const std::string& contents" 4740677dfd1SJulio Merino.Fc 4750677dfd1SJulio Merino.Bd -ragged -offset indent 4760677dfd1SJulio MerinoCreates 4770677dfd1SJulio Merino.Fa file 4780677dfd1SJulio Merinowith the text given in 4790677dfd1SJulio Merino.Fa contents . 4800677dfd1SJulio Merino.Ed 4810677dfd1SJulio Merino.Pp 4820677dfd1SJulio Merino.Ft void 4830677dfd1SJulio Merino.Fo atf::utils::file_exists 4840677dfd1SJulio Merino.Fa "const std::string& path" 4850677dfd1SJulio Merino.Fc 4860677dfd1SJulio Merino.Bd -ragged -offset indent 4870677dfd1SJulio MerinoChecks if 4880677dfd1SJulio Merino.Fa path 4890677dfd1SJulio Merinoexists. 4900677dfd1SJulio Merino.Ed 4910677dfd1SJulio Merino.Pp 4920677dfd1SJulio Merino.Ft pid_t 4930677dfd1SJulio Merino.Fo atf::utils::fork 4940677dfd1SJulio Merino.Fa "void" 4950677dfd1SJulio Merino.Fc 4960677dfd1SJulio Merino.Bd -ragged -offset indent 4970677dfd1SJulio MerinoForks a process and redirects the standard output and standard error of the 4980677dfd1SJulio Merinochild to files for later validation with 4990677dfd1SJulio Merino.Fn atf::utils::wait . 5000677dfd1SJulio MerinoFails the test case if the fork fails, so this does not return an error. 5010677dfd1SJulio Merino.Ed 5020677dfd1SJulio Merino.Pp 5030677dfd1SJulio Merino.Ft bool 5040677dfd1SJulio Merino.Fo atf::utils::grep_collection 5050677dfd1SJulio Merino.Fa "const std::string& regexp" 5060677dfd1SJulio Merino.Fa "const Collection& collection" 5070677dfd1SJulio Merino.Fc 5080677dfd1SJulio Merino.Bd -ragged -offset indent 5090677dfd1SJulio MerinoSearches for the regular expression 5100677dfd1SJulio Merino.Fa regexp 5110677dfd1SJulio Merinoin any of the strings contained in the 5120677dfd1SJulio Merino.Fa collection . 5130677dfd1SJulio MerinoThis is a template that accepts any one-dimensional container of strings. 5140677dfd1SJulio Merino.Ed 5150677dfd1SJulio Merino.Pp 5160677dfd1SJulio Merino.Ft bool 5170677dfd1SJulio Merino.Fo atf::utils::grep_file 5180677dfd1SJulio Merino.Fa "const std::string& regexp" 5190677dfd1SJulio Merino.Fa "const std::string& path" 5200677dfd1SJulio Merino.Fc 5210677dfd1SJulio Merino.Bd -ragged -offset indent 5220677dfd1SJulio MerinoSearches for the regular expression 5230677dfd1SJulio Merino.Fa regexp 5240677dfd1SJulio Merinoin the file 5250677dfd1SJulio Merino.Fa path . 5260677dfd1SJulio MerinoThe variable arguments are used to construct the regular expression. 5270677dfd1SJulio Merino.Ed 5280677dfd1SJulio Merino.Pp 5290677dfd1SJulio Merino.Ft bool 5300677dfd1SJulio Merino.Fo atf::utils::grep_string 5310677dfd1SJulio Merino.Fa "const std::string& regexp" 5320677dfd1SJulio Merino.Fa "const std::string& str" 5330677dfd1SJulio Merino.Fc 5340677dfd1SJulio Merino.Bd -ragged -offset indent 5350677dfd1SJulio MerinoSearches for the regular expression 5360677dfd1SJulio Merino.Fa regexp 5370677dfd1SJulio Merinoin the string 5380677dfd1SJulio Merino.Fa str . 5390677dfd1SJulio Merino.Ed 5400677dfd1SJulio Merino.Ft void 5410677dfd1SJulio Merino.Fo atf::utils::redirect 5420677dfd1SJulio Merino.Fa "const int fd" 5430677dfd1SJulio Merino.Fa "const std::string& path" 5440677dfd1SJulio Merino.Fc 5450677dfd1SJulio Merino.Bd -ragged -offset indent 5460677dfd1SJulio MerinoRedirects the given file descriptor 5470677dfd1SJulio Merino.Fa fd 5480677dfd1SJulio Merinoto the file 5490677dfd1SJulio Merino.Fa path . 5500677dfd1SJulio MerinoThis function exits the process in case of an error and does not properly mark 5510677dfd1SJulio Merinothe test case as failed. 5520677dfd1SJulio MerinoAs a result, it should only be used in subprocesses of the test case; specially 5530677dfd1SJulio Merinothose spawned by 5540677dfd1SJulio Merino.Fn atf::utils::fork . 5550677dfd1SJulio Merino.Ed 5560677dfd1SJulio Merino.Pp 5570677dfd1SJulio Merino.Ft void 5580677dfd1SJulio Merino.Fo atf::utils::wait 5590677dfd1SJulio Merino.Fa "const pid_t pid" 5600677dfd1SJulio Merino.Fa "const int expected_exit_status" 5610677dfd1SJulio Merino.Fa "const std::string& expected_stdout" 5620677dfd1SJulio Merino.Fa "const std::string& expected_stderr" 5630677dfd1SJulio Merino.Fc 5640677dfd1SJulio Merino.Bd -ragged -offset indent 5650677dfd1SJulio MerinoWaits and validates the result of a subprocess spawned with 5660677dfd1SJulio Merino.Fn atf::utils::wait . 5670677dfd1SJulio MerinoThe validation involves checking that the subprocess exited cleanly and returned 5680677dfd1SJulio Merinothe code specified in 5690677dfd1SJulio Merino.Fa expected_exit_status 5700677dfd1SJulio Merinoand that its standard output and standard error match the strings given in 5710677dfd1SJulio Merino.Fa expected_stdout 5720677dfd1SJulio Merinoand 5730677dfd1SJulio Merino.Fa expected_stderr . 5740677dfd1SJulio Merino.Pp 5750677dfd1SJulio MerinoIf any of the 5760677dfd1SJulio Merino.Fa expected_stdout 5770677dfd1SJulio Merinoor 5780677dfd1SJulio Merino.Fa expected_stderr 5790677dfd1SJulio Merinostrings are prefixed with 5800677dfd1SJulio Merino.Sq save: , 5810677dfd1SJulio Merinothen they specify the name of the file into which to store the stdout or stderr 5820677dfd1SJulio Merinoof the subprocess, and no comparison is performed. 5830677dfd1SJulio Merino.Ed 5840677dfd1SJulio Merino.Sh ENVIRONMENT 5850677dfd1SJulio MerinoThe following variables are recognized by 5860677dfd1SJulio Merino.Nm 5870677dfd1SJulio Merinobut should not be overridden other than for testing purposes: 5880677dfd1SJulio Merino.Pp 5890677dfd1SJulio Merino.Bl -tag -width ATFXBUILDXCXXFLAGSXX -compact 5900677dfd1SJulio Merino.It Va ATF_BUILD_CC 5910677dfd1SJulio MerinoPath to the C compiler. 5920677dfd1SJulio Merino.It Va ATF_BUILD_CFLAGS 5930677dfd1SJulio MerinoC compiler flags. 5940677dfd1SJulio Merino.It Va ATF_BUILD_CPP 5950677dfd1SJulio MerinoPath to the C/C++ preprocessor. 5960677dfd1SJulio Merino.It Va ATF_BUILD_CPPFLAGS 5970677dfd1SJulio MerinoC/C++ preprocessor flags. 5980677dfd1SJulio Merino.It Va ATF_BUILD_CXX 5990677dfd1SJulio MerinoPath to the C++ compiler. 6000677dfd1SJulio Merino.It Va ATF_BUILD_CXXFLAGS 6010677dfd1SJulio MerinoC++ compiler flags. 6020677dfd1SJulio Merino.El 6030677dfd1SJulio Merino.Sh EXAMPLES 6040677dfd1SJulio MerinoThe following shows a complete test program with a single test case that 6050677dfd1SJulio Merinovalidates the addition operator: 6060677dfd1SJulio Merino.Bd -literal -offset indent 6070677dfd1SJulio Merino#include <atf-c++.hpp> 6080677dfd1SJulio Merino 6090677dfd1SJulio MerinoATF_TEST_CASE(addition); 6100677dfd1SJulio MerinoATF_TEST_CASE_HEAD(addition) 6110677dfd1SJulio Merino{ 6120677dfd1SJulio Merino set_md_var("descr", "Sample tests for the addition operator"); 6130677dfd1SJulio Merino} 6140677dfd1SJulio MerinoATF_TEST_CASE_BODY(addition) 6150677dfd1SJulio Merino{ 6160677dfd1SJulio Merino ATF_REQUIRE_EQ(0, 0 + 0); 6170677dfd1SJulio Merino ATF_REQUIRE_EQ(1, 0 + 1); 6180677dfd1SJulio Merino ATF_REQUIRE_EQ(1, 1 + 0); 6190677dfd1SJulio Merino 6200677dfd1SJulio Merino ATF_REQUIRE_EQ(2, 1 + 1); 6210677dfd1SJulio Merino 6220677dfd1SJulio Merino ATF_REQUIRE_EQ(300, 100 + 200); 6230677dfd1SJulio Merino} 6240677dfd1SJulio Merino 6250677dfd1SJulio MerinoATF_TEST_CASE(open_failure); 6260677dfd1SJulio MerinoATF_TEST_CASE_HEAD(open_failure) 6270677dfd1SJulio Merino{ 6280677dfd1SJulio Merino set_md_var("descr", "Sample tests for the open function"); 6290677dfd1SJulio Merino} 6300677dfd1SJulio MerinoATF_TEST_CASE_BODY(open_failure) 6310677dfd1SJulio Merino{ 6320677dfd1SJulio Merino ATF_REQUIRE_ERRNO(ENOENT, open("non-existent", O_RDONLY) == -1); 6330677dfd1SJulio Merino} 6340677dfd1SJulio Merino 6350677dfd1SJulio MerinoATF_TEST_CASE(known_bug); 6360677dfd1SJulio MerinoATF_TEST_CASE_HEAD(known_bug) 6370677dfd1SJulio Merino{ 6380677dfd1SJulio Merino set_md_var("descr", "Reproduces a known bug"); 6390677dfd1SJulio Merino} 6400677dfd1SJulio MerinoATF_TEST_CASE_BODY(known_bug) 6410677dfd1SJulio Merino{ 6420677dfd1SJulio Merino expect_fail("See bug number foo/bar"); 6430677dfd1SJulio Merino ATF_REQUIRE_EQ(3, 1 + 1); 6440677dfd1SJulio Merino expect_pass(); 6450677dfd1SJulio Merino ATF_REQUIRE_EQ(3, 1 + 2); 6460677dfd1SJulio Merino} 6470677dfd1SJulio Merino 6480677dfd1SJulio MerinoATF_INIT_TEST_CASES(tcs) 6490677dfd1SJulio Merino{ 6500677dfd1SJulio Merino ATF_ADD_TEST_CASE(tcs, addition); 6510677dfd1SJulio Merino ATF_ADD_TEST_CASE(tcs, open_failure); 6520677dfd1SJulio Merino ATF_ADD_TEST_CASE(tcs, known_bug); 6530677dfd1SJulio Merino} 6540677dfd1SJulio Merino.Ed 6550677dfd1SJulio Merino.Sh SEE ALSO 6560677dfd1SJulio Merino.Xr atf-test-program 1 , 6570677dfd1SJulio Merino.Xr atf-test-case 4 658