xref: /netbsd-src/external/bsd/atf/dist/atf-c++/atf-c++-api.3 (revision d780102efefa02003390cc43ea410dbd0ebb4a85)
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