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*d780102eSjmmv.Dd November 15, 2013 30e2207522Sjmmv.Dt ATF-C++-API 3 31e2207522Sjmmv.Os 32e2207522Sjmmv.Sh NAME 330659fc67Sjmmv.Nm atf-c++-api , 34e2207522Sjmmv.Nm ATF_ADD_TEST_CASE , 35edebbb8eSjmmv.Nm ATF_CHECK_ERRNO , 36e2207522Sjmmv.Nm ATF_FAIL , 37e2207522Sjmmv.Nm ATF_INIT_TEST_CASES , 38e2207522Sjmmv.Nm ATF_PASS , 39895f502bSjmmv.Nm ATF_REQUIRE , 40895f502bSjmmv.Nm ATF_REQUIRE_EQ , 41edebbb8eSjmmv.Nm ATF_REQUIRE_ERRNO , 42eb215e31Sjmmv.Nm ATF_REQUIRE_IN , 430ebb519dSjmmv.Nm ATF_REQUIRE_MATCH , 44eb215e31Sjmmv.Nm ATF_REQUIRE_NOT_IN , 45895f502bSjmmv.Nm ATF_REQUIRE_THROW , 460ebb519dSjmmv.Nm ATF_REQUIRE_THROW_RE , 47e2207522Sjmmv.Nm ATF_SKIP , 48e2207522Sjmmv.Nm ATF_TEST_CASE , 49e2207522Sjmmv.Nm ATF_TEST_CASE_BODY , 50e2207522Sjmmv.Nm ATF_TEST_CASE_CLEANUP , 51e2207522Sjmmv.Nm ATF_TEST_CASE_HEAD , 524e036686Sjmmv.Nm ATF_TEST_CASE_NAME , 534e036686Sjmmv.Nm ATF_TEST_CASE_USE , 549b3149ccSjmmv.Nm ATF_TEST_CASE_WITH_CLEANUP , 559b3149ccSjmmv.Nm ATF_TEST_CASE_WITHOUT_HEAD , 560659fc67Sjmmv.Nm atf::utils::cat_file , 570659fc67Sjmmv.Nm atf::utils::compare_file , 580659fc67Sjmmv.Nm atf::utils::copy_file , 590659fc67Sjmmv.Nm atf::utils::create_file , 600659fc67Sjmmv.Nm atf::utils::file_exists , 610659fc67Sjmmv.Nm atf::utils::fork , 620659fc67Sjmmv.Nm atf::utils::grep_collection , 630659fc67Sjmmv.Nm atf::utils::grep_file , 640659fc67Sjmmv.Nm atf::utils::grep_string , 650659fc67Sjmmv.Nm atf::utils::redirect , 660659fc67Sjmmv.Nm atf::utils::wait 67e2207522Sjmmv.Nd C++ API to write ATF-based test programs 68e2207522Sjmmv.Sh SYNOPSIS 69e2207522Sjmmv.In atf-c++.hpp 70e2207522Sjmmv.Fn ATF_ADD_TEST_CASE "tcs" "name" 71edebbb8eSjmmv.Fn ATF_CHECK_ERRNO "exp_errno" "bool_expression" 72e2207522Sjmmv.Fn ATF_FAIL "reason" 73e2207522Sjmmv.Fn ATF_INIT_TEST_CASES "tcs" 74e2207522Sjmmv.Fn ATF_PASS 75895f502bSjmmv.Fn ATF_REQUIRE "expression" 76895f502bSjmmv.Fn ATF_REQUIRE_EQ "expression_1" "expression_2" 77edebbb8eSjmmv.Fn ATF_REQUIRE_ERRNO "exp_errno" "bool_expression" 78eb215e31Sjmmv.Fn ATF_REQUIRE_IN "element" "collection" 790ebb519dSjmmv.Fn ATF_REQUIRE_MATCH "regexp" "string_expression" 80eb215e31Sjmmv.Fn ATF_REQUIRE_NOT_IN "element" "collection" 81895f502bSjmmv.Fn ATF_REQUIRE_THROW "expected_exception" "statement" 820ebb519dSjmmv.Fn ATF_REQUIRE_THROW_RE "expected_exception" "regexp" "statement" 83e2207522Sjmmv.Fn ATF_SKIP "reason" 84e2207522Sjmmv.Fn ATF_TEST_CASE "name" 85e2207522Sjmmv.Fn ATF_TEST_CASE_BODY "name" 86e2207522Sjmmv.Fn ATF_TEST_CASE_CLEANUP "name" 87e2207522Sjmmv.Fn ATF_TEST_CASE_HEAD "name" 884e036686Sjmmv.Fn ATF_TEST_CASE_NAME "name" 894e036686Sjmmv.Fn ATF_TEST_CASE_USE "name" 90e2207522Sjmmv.Fn ATF_TEST_CASE_WITH_CLEANUP "name" 919b3149ccSjmmv.Fn ATF_TEST_CASE_WITHOUT_HEAD "name" 920659fc67Sjmmv.Ft void 930659fc67Sjmmv.Fo atf::utils::cat_file 940659fc67Sjmmv.Fa "const std::string& path" 950659fc67Sjmmv.Fa "const std::string& prefix" 960659fc67Sjmmv.Fc 970659fc67Sjmmv.Ft bool 980659fc67Sjmmv.Fo atf::utils::compare_file 990659fc67Sjmmv.Fa "const std::string& path" 1000659fc67Sjmmv.Fa "const std::string& contents" 1010659fc67Sjmmv.Fc 1020659fc67Sjmmv.Ft void 1030659fc67Sjmmv.Fo atf::utils::copy_file 1040659fc67Sjmmv.Fa "const std::string& source" 1050659fc67Sjmmv.Fa "const std::string& destination" 1060659fc67Sjmmv.Fc 1070659fc67Sjmmv.Ft void 1080659fc67Sjmmv.Fo atf::utils::create_file 1090659fc67Sjmmv.Fa "const std::string& path" 1100659fc67Sjmmv.Fa "const std::string& contents" 1110659fc67Sjmmv.Fc 1120659fc67Sjmmv.Ft void 1130659fc67Sjmmv.Fo atf::utils::file_exists 1140659fc67Sjmmv.Fa "const std::string& path" 1150659fc67Sjmmv.Fc 1160659fc67Sjmmv.Ft pid_t 1170659fc67Sjmmv.Fo atf::utils::fork 1180659fc67Sjmmv.Fa "void" 1190659fc67Sjmmv.Fc 1200659fc67Sjmmv.Ft bool 1210659fc67Sjmmv.Fo atf::utils::grep_collection 1220659fc67Sjmmv.Fa "const std::string& regexp" 1230659fc67Sjmmv.Fa "const Collection& collection" 1240659fc67Sjmmv.Fc 1250659fc67Sjmmv.Ft bool 1260659fc67Sjmmv.Fo atf::utils::grep_file 1270659fc67Sjmmv.Fa "const std::string& regexp" 1280659fc67Sjmmv.Fa "const std::string& path" 1290659fc67Sjmmv.Fc 1300659fc67Sjmmv.Ft bool 1310659fc67Sjmmv.Fo atf::utils::grep_string 1320659fc67Sjmmv.Fa "const std::string& regexp" 1330659fc67Sjmmv.Fa "const std::string& path" 1340659fc67Sjmmv.Fc 1350659fc67Sjmmv.Ft void 1360659fc67Sjmmv.Fo atf::utils::redirect 1370659fc67Sjmmv.Fa "const int fd" 1380659fc67Sjmmv.Fa "const std::string& path" 1390659fc67Sjmmv.Fc 1400659fc67Sjmmv.Ft void 1410659fc67Sjmmv.Fo atf::utils::wait 1420659fc67Sjmmv.Fa "const pid_t pid" 1430659fc67Sjmmv.Fa "const int expected_exit_status" 1440659fc67Sjmmv.Fa "const std::string& expected_stdout" 1450659fc67Sjmmv.Fa "const std::string& expected_stderr" 1460659fc67Sjmmv.Fc 147e2207522Sjmmv.Sh DESCRIPTION 148*d780102eSjmmvATF provides a C++ programming interface to implement test programs. 149*d780102eSjmmvC++-based test programs follow this template: 150e2207522Sjmmv.Bd -literal -offset indent 151e2207522Sjmmvextern "C" { 152e2207522Sjmmv.Ns ... C-specific includes go here ... 153e2207522Sjmmv} 154e2207522Sjmmv 155e2207522Sjmmv.Ns ... C++-specific includes go here ... 156e2207522Sjmmv 157e2207522Sjmmv#include <atf-c++.hpp> 158e2207522Sjmmv 159e2207522SjmmvATF_TEST_CASE(tc1); 160e2207522SjmmvATF_TEST_CASE_HEAD(tc1) 161e2207522Sjmmv{ 162e2207522Sjmmv ... first test case's header ... 163e2207522Sjmmv} 164e2207522SjmmvATF_TEST_CASE_BODY(tc1) 165e2207522Sjmmv{ 166e2207522Sjmmv ... first test case's body ... 167e2207522Sjmmv} 168e2207522Sjmmv 169e2207522SjmmvATF_TEST_CASE_WITH_CLEANUP(tc2); 170e2207522SjmmvATF_TEST_CASE_HEAD(tc2) 171e2207522Sjmmv{ 172e2207522Sjmmv ... second test case's header ... 173e2207522Sjmmv} 174e2207522SjmmvATF_TEST_CASE_BODY(tc2) 175e2207522Sjmmv{ 176e2207522Sjmmv ... second test case's body ... 177e2207522Sjmmv} 178e2207522SjmmvATF_TEST_CASE_CLEANUP(tc2) 179e2207522Sjmmv{ 180e2207522Sjmmv ... second test case's cleanup ... 181e2207522Sjmmv} 182e2207522Sjmmv 1839b3149ccSjmmvATF_TEST_CASE(tc3); 1849b3149ccSjmmvATF_TEST_CASE_BODY(tc3) 1859b3149ccSjmmv{ 1869b3149ccSjmmv ... third test case's body ... 1879b3149ccSjmmv} 1889b3149ccSjmmv 189e2207522Sjmmv.Ns ... additional test cases ... 190e2207522Sjmmv 191e2207522SjmmvATF_INIT_TEST_CASES(tcs) 192e2207522Sjmmv{ 1939b3149ccSjmmv ATF_ADD_TEST_CASE(tcs, tc1); 1949b3149ccSjmmv ATF_ADD_TEST_CASE(tcs, tc2); 1959b3149ccSjmmv ATF_ADD_TEST_CASE(tcs, tc3); 196e2207522Sjmmv ... add additional test cases ... 197e2207522Sjmmv} 198e2207522Sjmmv.Ed 199e2207522Sjmmv.Ss Definition of test cases 200e2207522SjmmvTest cases have an identifier and are composed of three different parts: 201e2207522Sjmmvthe header, the body and an optional cleanup routine, all of which are 202e2207522Sjmmvdescribed in 203edebbb8eSjmmv.Xr atf-test-case 4 . 204e2207522SjmmvTo define test cases, one can use the 2059b3149ccSjmmv.Fn ATF_TEST_CASE , 206e2207522Sjmmv.Fn ATF_TEST_CASE_WITH_CLEANUP 2079b3149ccSjmmvor the 2089b3149ccSjmmv.Fn ATF_TEST_CASE_WITHOUT_HEAD 209e2207522Sjmmvmacros, which take a single parameter specifiying the test case's 210e2207522Sjmmvname. 2119b3149ccSjmmv.Fn ATF_TEST_CASE , 2129b3149ccSjmmvrequires to define a head and a body for the test case, 2139b3149ccSjmmv.Fn ATF_TEST_CASE_WITH_CLEANUP 2149b3149ccSjmmvrequires to define a head, a body and a cleanup for the test case and 2159b3149ccSjmmv.Fn ATF_TEST_CASE_WITHOUT_HEAD 2169b3149ccSjmmvrequires only a body for the test case. 217e2207522SjmmvIt is important to note that these 218e2207522Sjmmv.Em do not 219e2207522Sjmmvset the test case up for execution when the program is run. 220e2207522SjmmvIn order to do so, a later registration is needed through the 221e2207522Sjmmv.Fn ATF_ADD_TEST_CASE 222e2207522Sjmmvmacro detailed in 223e2207522Sjmmv.Sx Program initialization . 224e2207522Sjmmv.Pp 225e2207522SjmmvLater on, one must define the three parts of the body by means of three 226e2207522Sjmmvfunctions. 227e2207522SjmmvTheir headers are given by the 228e2207522Sjmmv.Fn ATF_TEST_CASE_HEAD , 229e2207522Sjmmv.Fn ATF_TEST_CASE_BODY 230e2207522Sjmmvand 231e2207522Sjmmv.Fn ATF_TEST_CASE_CLEANUP 232e2207522Sjmmvmacros, all of which take the test case's name. 233e2207522SjmmvFollowing each of these, a block of code is expected, surrounded by the 234e2207522Sjmmvopening and closing brackets. 2354e036686Sjmmv.Pp 2364e036686SjmmvAdditionally, the 2374e036686Sjmmv.Fn ATF_TEST_CASE_NAME 2384e036686Sjmmvmacro can be used to obtain the name of the class corresponding to a 2394e036686Sjmmvparticular test case, as the name is internally manged by the library to 2404e036686Sjmmvprevent clashes with other user identifiers. 2414e036686SjmmvSimilarly, the 2424e036686Sjmmv.Fn ATF_TEST_CASE_USE 2434e036686Sjmmvmacro can be executed on a particular test case to mark it as "used" and 2444e036686Sjmmvthus prevent compiler warnings regarding unused symbols. 2454e036686SjmmvNote that 2464e036686Sjmmv.Em you should never have to use these macros during regular operation. 247e2207522Sjmmv.Ss Program initialization 248e2207522SjmmvThe library provides a way to easily define the test program's 249e2207522Sjmmv.Fn main 250e2207522Sjmmvfunction. 251e2207522SjmmvYou should never define one on your own, but rely on the 252e2207522Sjmmvlibrary to do it for you. 253e2207522SjmmvThis is done by using the 254e2207522Sjmmv.Fn ATF_INIT_TEST_CASES 255e2207522Sjmmvmacro, which is passed the name of the list that will hold the test cases. 256e2207522SjmmvThis name can be whatever you want as long as it is a valid variable value. 257e2207522Sjmmv.Pp 258e2207522SjmmvAfter the macro, you are supposed to provide the body of a function, which 259e2207522Sjmmvshould only use the 260e2207522Sjmmv.Fn ATF_ADD_TEST_CASE 261e2207522Sjmmvmacro to register the test cases the test program will execute. 262e2207522SjmmvThe first parameter of this macro matches the name you provided in the 263e2207522Sjmmvformer call. 264e2207522Sjmmv.Ss Header definitions 265e2207522SjmmvThe test case's header can define the meta-data by using the 2660659fc67Sjmmv.Fn set_md_var 267e2207522Sjmmvmethod, which takes two parameters: the first one specifies the 268e2207522Sjmmvmeta-data variable to be set and the second one specifies its value. 269e2207522SjmmvBoth of them are strings. 270e2207522Sjmmv.Ss Configuration variables 271e2207522SjmmvThe test case has read-only access to the current configuration variables 272e2207522Sjmmvby means of the 273e2207522Sjmmv.Ft bool 274e2207522Sjmmv.Fn has_config_var 275e2207522Sjmmvand the 276e2207522Sjmmv.Ft std::string 277e2207522Sjmmv.Fn get_config_var 278e2207522Sjmmvmethods, which can be called in any of the three parts of a test case. 279e2207522Sjmmv.Ss Access to the source directory 280e2207522SjmmvIt is possible to get the path to the test case's source directory from any 281e2207522Sjmmvof its three components by querying the 282e2207522Sjmmv.Sq srcdir 283e2207522Sjmmvconfiguration variable. 284e2207522Sjmmv.Ss Requiring programs 285e2207522SjmmvAside from the 286e2207522Sjmmv.Va require.progs 287e2207522Sjmmvmeta-data variable available in the header only, one can also check for 288e2207522Sjmmvadditional programs in the test case's body by using the 289e2207522Sjmmv.Fn require_prog 290e2207522Sjmmvfunction, which takes the base name or full path of a single binary. 291e2207522SjmmvRelative paths are forbidden. 292e2207522SjmmvIf it is not found, the test case will be automatically skipped. 293e2207522Sjmmv.Ss Test case finalization 294e2207522SjmmvThe test case finalizes either when the body reaches its end, at which 295e2207522Sjmmvpoint the test is assumed to have 296e2207522Sjmmv.Em passed , 297e2207522Sjmmvor at any explicit call to 298e2207522Sjmmv.Fn ATF_PASS , 299e2207522Sjmmv.Fn ATF_FAIL 300e2207522Sjmmvor 301e2207522Sjmmv.Fn ATF_SKIP . 302e2207522SjmmvThese three macros terminate the execution of the test case immediately. 303e2207522SjmmvThe cleanup routine will be processed afterwards in a completely automated 304e2207522Sjmmvway, regardless of the test case's termination reason. 305e2207522Sjmmv.Pp 306e2207522Sjmmv.Fn ATF_PASS 307e2207522Sjmmvdoes not take any parameters. 308e2207522Sjmmv.Fn ATF_FAIL 309e2207522Sjmmvand 310e2207522Sjmmv.Fn ATF_SKIP 311e2207522Sjmmvtake a single string that describes why the test case failed or 312e2207522Sjmmvwas skipped, respectively. 313e2207522SjmmvIt is very important to provide a clear error message in both cases so that 314e2207522Sjmmvthe user can quickly know why the test did not pass. 315edebbb8eSjmmv.Ss Expectations 316edebbb8eSjmmvEverything explained in the previous section changes when the test case 317edebbb8eSjmmvexpectations are redefined by the programmer. 318edebbb8eSjmmv.Pp 319edebbb8eSjmmvEach test case has an internal state called 320edebbb8eSjmmv.Sq expect 321edebbb8eSjmmvthat describes what the test case expectations are at any point in time. 322edebbb8eSjmmvThe value of this property can change during execution by any of: 323edebbb8eSjmmv.Bl -tag -width indent 324edebbb8eSjmmv.It Fn expect_death "reason" 325edebbb8eSjmmvExpects the test case to exit prematurely regardless of the nature of the 326edebbb8eSjmmvexit. 327edebbb8eSjmmv.It Fn expect_exit "exitcode" "reason" 328edebbb8eSjmmvExpects the test case to exit cleanly. 329edebbb8eSjmmvIf 330edebbb8eSjmmv.Va exitcode 331edebbb8eSjmmvis not 332edebbb8eSjmmv.Sq -1 , 333edebbb8eSjmmv.Xr atf-run 1 334edebbb8eSjmmvwill validate that the exit code of the test case matches the one provided 335edebbb8eSjmmvin this call. 336edebbb8eSjmmvOtherwise, the exact value will be ignored. 337edebbb8eSjmmv.It Fn expect_fail "reason" 338edebbb8eSjmmvAny failure (be it fatal or non-fatal) raised in this mode is recorded. 339edebbb8eSjmmvHowever, such failures do not report the test case as failed; instead, the 340edebbb8eSjmmvtest case finalizes cleanly and is reported as 341edebbb8eSjmmv.Sq expected failure ; 342edebbb8eSjmmvthis report includes the provided 343edebbb8eSjmmv.Fa reason 344edebbb8eSjmmvas part of it. 345edebbb8eSjmmvIf no error is raised while running in this mode, then the test case is 346edebbb8eSjmmvreported as 347edebbb8eSjmmv.Sq failed . 348edebbb8eSjmmv.Pp 349edebbb8eSjmmvThis mode is useful to reproduce actual known bugs in tests. 350edebbb8eSjmmvWhenever the developer fixes the bug later on, the test case will start 351edebbb8eSjmmvreporting a failure, signaling the developer that the test case must be 352edebbb8eSjmmvadjusted to the new conditions. 353edebbb8eSjmmvIn this situation, it is useful, for example, to set 354edebbb8eSjmmv.Fa reason 355edebbb8eSjmmvas the bug number for tracking purposes. 356edebbb8eSjmmv.It Fn expect_pass 357edebbb8eSjmmvThis is the normal mode of execution. 358edebbb8eSjmmvIn this mode, any failure is reported as such to the user and the test case 359edebbb8eSjmmvis marked as 360edebbb8eSjmmv.Sq failed . 3610ebb519dSjmmv.It Fn expect_race "reason" 3620ebb519dSjmmvAny failure or timeout during the execution of the test case will be 3630ebb519dSjmmvconsidered as if a race condition has been triggered and reported as such. 3640ebb519dSjmmvIf no problems arise, the test will continue execution as usual. 365edebbb8eSjmmv.It Fn expect_signal "signo" "reason" 366edebbb8eSjmmvExpects the test case to terminate due to the reception of a signal. 367edebbb8eSjmmvIf 368edebbb8eSjmmv.Va signo 369edebbb8eSjmmvis not 370edebbb8eSjmmv.Sq -1 , 371edebbb8eSjmmv.Xr atf-run 1 372edebbb8eSjmmvwill validate that the signal that terminated the test case matches the one 373edebbb8eSjmmvprovided in this call. 374edebbb8eSjmmvOtherwise, the exact value will be ignored. 375edebbb8eSjmmv.It Fn expect_timeout "reason" 376edebbb8eSjmmvExpects the test case to execute for longer than its timeout. 377edebbb8eSjmmv.El 378e2207522Sjmmv.Ss Helper macros for common checks 379e2207522SjmmvThe library provides several macros that are very handy in multiple 380e2207522Sjmmvsituations. 381e2207522SjmmvThese basically check some condition after executing a given statement or 382e2207522Sjmmvprocessing a given expression and, if the condition is not met, they 383e2207522Sjmmvautomatically call 384e2207522Sjmmv.Fn ATF_FAIL 385e2207522Sjmmvwith an appropriate error message. 386e2207522Sjmmv.Pp 387895f502bSjmmv.Fn ATF_REQUIRE 388e2207522Sjmmvtakes an expression and raises a failure if it evaluates to false. 389e2207522Sjmmv.Pp 390895f502bSjmmv.Fn ATF_REQUIRE_EQ 391e2207522Sjmmvtakes two expressions and raises a failure if the two do not evaluate to 392e2207522Sjmmvthe same exact value. 393e2207522Sjmmv.Pp 394eb215e31Sjmmv.Fn ATF_REQUIRE_IN 395eb215e31Sjmmvtakes an element and a collection and validates that the element is present in 396eb215e31Sjmmvthe collection. 397eb215e31Sjmmv.Pp 3980ebb519dSjmmv.Fn ATF_REQUIRE_MATCH 3990ebb519dSjmmvtakes a regular expression and a string and raises a failure if the regular 4000ebb519dSjmmvexpression does not match the string. 4010ebb519dSjmmv.Pp 402eb215e31Sjmmv.Fn ATF_REQUIRE_NOT_IN 403eb215e31Sjmmvtakes an element and a collection and validates that the element is not present 404eb215e31Sjmmvin the collection. 405eb215e31Sjmmv.Pp 406895f502bSjmmv.Fn ATF_REQUIRE_THROW 407edebbb8eSjmmvtakes the name of an exception and a statement and raises a failure if 408edebbb8eSjmmvthe statement does not throw the specified exception. 4090659fc67Sjmmv.Fn ATF_REQUIRE_THROW_RE 4100ebb519dSjmmvtakes the name of an exception, a regular expresion and a statement and raises a 4110ebb519dSjmmvfailure if the statement does not throw the specified exception and if the 4120ebb519dSjmmvmessage of the exception does not match the regular expression. 413edebbb8eSjmmv.Pp 414edebbb8eSjmmv.Fn ATF_CHECK_ERRNO 415edebbb8eSjmmvand 416edebbb8eSjmmv.Fn ATF_REQUIRE_ERRNO 417edebbb8eSjmmvtake, first, the error code that the check is expecting to find in the 418edebbb8eSjmmv.Va errno 419edebbb8eSjmmvvariable and, second, a boolean expression that, if evaluates to true, 420edebbb8eSjmmvmeans that a call failed and 421edebbb8eSjmmv.Va errno 422edebbb8eSjmmvhas to be checked against the first value. 4230659fc67Sjmmv.Ss Utility functions 4240659fc67SjmmvThe following functions are provided as part of the 4250659fc67Sjmmv.Nm 4260659fc67SjmmvAPI to simplify the creation of a variety of tests. 4270659fc67SjmmvIn particular, these are useful to write tests for command-line interfaces. 4280659fc67Sjmmv.Pp 4290659fc67Sjmmv.Ft void 4300659fc67Sjmmv.Fo atf::utils::cat_file 4310659fc67Sjmmv.Fa "const std::string& path" 4320659fc67Sjmmv.Fa "const std::string& prefix" 4330659fc67Sjmmv.Fc 434*d780102eSjmmv.Bd -ragged -offset indent 4350659fc67SjmmvPrints the contents of 4360659fc67Sjmmv.Fa path 4370659fc67Sjmmvto the standard output, prefixing every line with the string in 4380659fc67Sjmmv.Fa prefix . 4390659fc67Sjmmv.Ed 4400659fc67Sjmmv.Pp 4410659fc67Sjmmv.Ft bool 4420659fc67Sjmmv.Fo atf::utils::compare_file 4430659fc67Sjmmv.Fa "const std::string& path" 4440659fc67Sjmmv.Fa "const std::string& contents" 4450659fc67Sjmmv.Fc 446*d780102eSjmmv.Bd -ragged -offset indent 4470659fc67SjmmvReturns true if the given 4480659fc67Sjmmv.Fa path 4490659fc67Sjmmvmatches exactly the expected inlined 4500659fc67Sjmmv.Fa contents . 4510659fc67Sjmmv.Ed 4520659fc67Sjmmv.Pp 4530659fc67Sjmmv.Ft void 4540659fc67Sjmmv.Fo atf::utils::copy_file 4550659fc67Sjmmv.Fa "const std::string& source" 4560659fc67Sjmmv.Fa "const std::string& destination" 4570659fc67Sjmmv.Fc 458*d780102eSjmmv.Bd -ragged -offset indent 4590659fc67SjmmvCopies the file 4600659fc67Sjmmv.Fa source 4610659fc67Sjmmvto 4620659fc67Sjmmv.Fa destination . 4630659fc67SjmmvThe permissions of the file are preserved during the code. 4640659fc67Sjmmv.Ed 4650659fc67Sjmmv.Pp 4660659fc67Sjmmv.Ft void 4670659fc67Sjmmv.Fo atf::utils::create_file 4680659fc67Sjmmv.Fa "const std::string& path" 4690659fc67Sjmmv.Fa "const std::string& contents" 4700659fc67Sjmmv.Fc 471*d780102eSjmmv.Bd -ragged -offset indent 4720659fc67SjmmvCreates 4730659fc67Sjmmv.Fa file 4740659fc67Sjmmvwith the text given in 4750659fc67Sjmmv.Fa contents . 4760659fc67Sjmmv.Ed 4770659fc67Sjmmv.Pp 4780659fc67Sjmmv.Ft void 4790659fc67Sjmmv.Fo atf::utils::file_exists 4800659fc67Sjmmv.Fa "const std::string& path" 4810659fc67Sjmmv.Fc 482*d780102eSjmmv.Bd -ragged -offset indent 4830659fc67SjmmvChecks if 4840659fc67Sjmmv.Fa path 4850659fc67Sjmmvexists. 4860659fc67Sjmmv.Ed 4870659fc67Sjmmv.Pp 4880659fc67Sjmmv.Ft pid_t 4890659fc67Sjmmv.Fo atf::utils::fork 4900659fc67Sjmmv.Fa "void" 4910659fc67Sjmmv.Fc 492*d780102eSjmmv.Bd -ragged -offset indent 4930659fc67SjmmvForks a process and redirects the standard output and standard error of the 4940659fc67Sjmmvchild to files for later validation with 4950659fc67Sjmmv.Fn atf::utils::wait . 4960659fc67SjmmvFails the test case if the fork fails, so this does not return an error. 4970659fc67Sjmmv.Ed 4980659fc67Sjmmv.Pp 4990659fc67Sjmmv.Ft bool 5000659fc67Sjmmv.Fo atf::utils::grep_collection 5010659fc67Sjmmv.Fa "const std::string& regexp" 5020659fc67Sjmmv.Fa "const Collection& collection" 5030659fc67Sjmmv.Fc 504*d780102eSjmmv.Bd -ragged -offset indent 5050659fc67SjmmvSearches for the regular expression 5060659fc67Sjmmv.Fa regexp 5070659fc67Sjmmvin any of the strings contained in the 5080659fc67Sjmmv.Fa collection . 5090659fc67SjmmvThis is a template that accepts any one-dimensional container of strings. 5100659fc67Sjmmv.Ed 5110659fc67Sjmmv.Pp 5120659fc67Sjmmv.Ft bool 5130659fc67Sjmmv.Fo atf::utils::grep_file 5140659fc67Sjmmv.Fa "const std::string& regexp" 5150659fc67Sjmmv.Fa "const std::string& path" 5160659fc67Sjmmv.Fc 517*d780102eSjmmv.Bd -ragged -offset indent 5180659fc67SjmmvSearches for the regular expression 5190659fc67Sjmmv.Fa regexp 5200659fc67Sjmmvin the file 5210659fc67Sjmmv.Fa path . 5220659fc67SjmmvThe variable arguments are used to construct the regular expression. 5230659fc67Sjmmv.Ed 5240659fc67Sjmmv.Pp 5250659fc67Sjmmv.Ft bool 5260659fc67Sjmmv.Fo atf::utils::grep_string 5270659fc67Sjmmv.Fa "const std::string& regexp" 5280659fc67Sjmmv.Fa "const std::string& str" 5290659fc67Sjmmv.Fc 530*d780102eSjmmv.Bd -ragged -offset indent 5310659fc67SjmmvSearches for the regular expression 5320659fc67Sjmmv.Fa regexp 5330659fc67Sjmmvin the string 5340659fc67Sjmmv.Fa str . 5350659fc67Sjmmv.Ed 5360659fc67Sjmmv.Ft void 5370659fc67Sjmmv.Fo atf::utils::redirect 5380659fc67Sjmmv.Fa "const int fd" 5390659fc67Sjmmv.Fa "const std::string& path" 5400659fc67Sjmmv.Fc 541*d780102eSjmmv.Bd -ragged -offset indent 5420659fc67SjmmvRedirects the given file descriptor 5430659fc67Sjmmv.Fa fd 5440659fc67Sjmmvto the file 5450659fc67Sjmmv.Fa path . 5460659fc67SjmmvThis function exits the process in case of an error and does not properly mark 5470659fc67Sjmmvthe test case as failed. 5480659fc67SjmmvAs a result, it should only be used in subprocesses of the test case; specially 5490659fc67Sjmmvthose spawned by 5500659fc67Sjmmv.Fn atf::utils::fork . 5510659fc67Sjmmv.Ed 5520659fc67Sjmmv.Pp 5530659fc67Sjmmv.Ft void 5540659fc67Sjmmv.Fo atf::utils::wait 5550659fc67Sjmmv.Fa "const pid_t pid" 5560659fc67Sjmmv.Fa "const int expected_exit_status" 5570659fc67Sjmmv.Fa "const std::string& expected_stdout" 5580659fc67Sjmmv.Fa "const std::string& expected_stderr" 5590659fc67Sjmmv.Fc 560*d780102eSjmmv.Bd -ragged -offset indent 5610659fc67SjmmvWaits and validates the result of a subprocess spawned with 5620659fc67Sjmmv.Fn atf::utils::wait . 5630659fc67SjmmvThe validation involves checking that the subprocess exited cleanly and returned 5640659fc67Sjmmvthe code specified in 5650659fc67Sjmmv.Fa expected_exit_status 5660659fc67Sjmmvand that its standard output and standard error match the strings given in 5670659fc67Sjmmv.Fa expected_stdout 5680659fc67Sjmmvand 5690659fc67Sjmmv.Fa expected_stderr . 5700659fc67Sjmmv.Pp 5710659fc67SjmmvIf any of the 5720659fc67Sjmmv.Fa expected_stdout 5730659fc67Sjmmvor 5740659fc67Sjmmv.Fa expected_stderr 5750659fc67Sjmmvstrings are prefixed with 5760659fc67Sjmmv.Sq save: , 5770659fc67Sjmmvthen they specify the name of the file into which to store the stdout or stderr 5780659fc67Sjmmvof the subprocess, and no comparison is performed. 5790659fc67Sjmmv.Ed 580e2207522Sjmmv.Sh EXAMPLES 581e2207522SjmmvThe following shows a complete test program with a single test case that 582e2207522Sjmmvvalidates the addition operator: 583e2207522Sjmmv.Bd -literal -offset indent 584e2207522Sjmmv#include <atf-c++.hpp> 585e2207522Sjmmv 586e2207522SjmmvATF_TEST_CASE(addition); 587e2207522SjmmvATF_TEST_CASE_HEAD(addition) 588e2207522Sjmmv{ 5890659fc67Sjmmv set_md_var("descr", "Sample tests for the addition operator"); 590e2207522Sjmmv} 591e2207522SjmmvATF_TEST_CASE_BODY(addition) 592e2207522Sjmmv{ 593895f502bSjmmv ATF_REQUIRE_EQ(0 + 0, 0); 594895f502bSjmmv ATF_REQUIRE_EQ(0 + 1, 1); 595895f502bSjmmv ATF_REQUIRE_EQ(1 + 0, 1); 596e2207522Sjmmv 597895f502bSjmmv ATF_REQUIRE_EQ(1 + 1, 2); 598e2207522Sjmmv 599895f502bSjmmv ATF_REQUIRE_EQ(100 + 200, 300); 600e2207522Sjmmv} 601e2207522Sjmmv 602edebbb8eSjmmvATF_TEST_CASE(open_failure); 603edebbb8eSjmmvATF_TEST_CASE_HEAD(open_failure) 604edebbb8eSjmmv{ 6050659fc67Sjmmv set_md_var("descr", "Sample tests for the open function"); 606edebbb8eSjmmv} 607edebbb8eSjmmvATF_TEST_CASE_BODY(open_failure) 608edebbb8eSjmmv{ 609895f502bSjmmv ATF_REQUIRE_ERRNO(ENOENT, open("non-existent", O_RDONLY) == -1); 610edebbb8eSjmmv} 611edebbb8eSjmmv 612edebbb8eSjmmvATF_TEST_CASE(known_bug); 613edebbb8eSjmmvATF_TEST_CASE_HEAD(known_bug) 614edebbb8eSjmmv{ 6150659fc67Sjmmv set_md_var("descr", "Reproduces a known bug"); 616edebbb8eSjmmv} 617edebbb8eSjmmvATF_TEST_CASE_BODY(known_bug) 618edebbb8eSjmmv{ 619edebbb8eSjmmv expect_fail("See bug number foo/bar"); 620895f502bSjmmv ATF_REQUIRE_EQ(3, 1 + 1); 621edebbb8eSjmmv expect_pass(); 622895f502bSjmmv ATF_REQUIRE_EQ(3, 1 + 2); 623edebbb8eSjmmv} 624edebbb8eSjmmv 625e2207522SjmmvATF_INIT_TEST_CASES(tcs) 626e2207522Sjmmv{ 627e2207522Sjmmv ATF_ADD_TEST_CASE(tcs, addition); 628edebbb8eSjmmv ATF_ADD_TEST_CASE(tcs, open_failure); 629edebbb8eSjmmv ATF_ADD_TEST_CASE(tcs, known_bug); 630e2207522Sjmmv} 631e2207522Sjmmv.Ed 632e2207522Sjmmv.Sh SEE ALSO 633e2207522Sjmmv.Xr atf-test-program 1 , 634edebbb8eSjmmv.Xr atf-test-case 4 , 635edebbb8eSjmmv.Xr atf 7 636