xref: /freebsd/contrib/atf/atf-c++/atf-c++.3 (revision a0ee8cc6)
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 October 13, 2014
26.Dt ATF-C++ 3
27.Os
28.Sh NAME
29.Nm atf-c++ ,
30.Nm ATF_ADD_TEST_CASE ,
31.Nm ATF_CHECK_ERRNO ,
32.Nm ATF_FAIL ,
33.Nm ATF_INIT_TEST_CASES ,
34.Nm ATF_PASS ,
35.Nm ATF_REQUIRE ,
36.Nm ATF_REQUIRE_EQ ,
37.Nm ATF_REQUIRE_ERRNO ,
38.Nm ATF_REQUIRE_IN ,
39.Nm ATF_REQUIRE_MATCH ,
40.Nm ATF_REQUIRE_NOT_IN ,
41.Nm ATF_REQUIRE_THROW ,
42.Nm ATF_REQUIRE_THROW_RE ,
43.Nm ATF_SKIP ,
44.Nm ATF_TEST_CASE ,
45.Nm ATF_TEST_CASE_BODY ,
46.Nm ATF_TEST_CASE_CLEANUP ,
47.Nm ATF_TEST_CASE_HEAD ,
48.Nm ATF_TEST_CASE_NAME ,
49.Nm ATF_TEST_CASE_USE ,
50.Nm ATF_TEST_CASE_WITH_CLEANUP ,
51.Nm ATF_TEST_CASE_WITHOUT_HEAD ,
52.Nm atf::utils::cat_file ,
53.Nm atf::utils::compare_file ,
54.Nm atf::utils::copy_file ,
55.Nm atf::utils::create_file ,
56.Nm atf::utils::file_exists ,
57.Nm atf::utils::fork ,
58.Nm atf::utils::grep_collection ,
59.Nm atf::utils::grep_file ,
60.Nm atf::utils::grep_string ,
61.Nm atf::utils::redirect ,
62.Nm atf::utils::wait
63.Nd C++ API to write ATF-based test programs
64.Sh SYNOPSIS
65.In atf-c++.hpp
66.Fn ATF_ADD_TEST_CASE "tcs" "name"
67.Fn ATF_CHECK_ERRNO "expected_errno" "bool_expression"
68.Fn ATF_FAIL "reason"
69.Fn ATF_INIT_TEST_CASES "tcs"
70.Fn ATF_PASS
71.Fn ATF_REQUIRE "expression"
72.Fn ATF_REQUIRE_EQ "expected_expression" "actual_expression"
73.Fn ATF_REQUIRE_ERRNO "expected_errno" "bool_expression"
74.Fn ATF_REQUIRE_IN "element" "collection"
75.Fn ATF_REQUIRE_MATCH "regexp" "string_expression"
76.Fn ATF_REQUIRE_NOT_IN "element" "collection"
77.Fn ATF_REQUIRE_THROW "expected_exception" "statement"
78.Fn ATF_REQUIRE_THROW_RE "expected_exception" "regexp" "statement"
79.Fn ATF_SKIP "reason"
80.Fn ATF_TEST_CASE "name"
81.Fn ATF_TEST_CASE_BODY "name"
82.Fn ATF_TEST_CASE_CLEANUP "name"
83.Fn ATF_TEST_CASE_HEAD "name"
84.Fn ATF_TEST_CASE_NAME "name"
85.Fn ATF_TEST_CASE_USE "name"
86.Fn ATF_TEST_CASE_WITH_CLEANUP "name"
87.Fn ATF_TEST_CASE_WITHOUT_HEAD "name"
88.Ft void
89.Fo atf::utils::cat_file
90.Fa "const std::string& path"
91.Fa "const std::string& prefix"
92.Fc
93.Ft bool
94.Fo atf::utils::compare_file
95.Fa "const std::string& path"
96.Fa "const std::string& contents"
97.Fc
98.Ft void
99.Fo atf::utils::copy_file
100.Fa "const std::string& source"
101.Fa "const std::string& destination"
102.Fc
103.Ft void
104.Fo atf::utils::create_file
105.Fa "const std::string& path"
106.Fa "const std::string& contents"
107.Fc
108.Ft void
109.Fo atf::utils::file_exists
110.Fa "const std::string& path"
111.Fc
112.Ft pid_t
113.Fo atf::utils::fork
114.Fa "void"
115.Fc
116.Ft bool
117.Fo atf::utils::grep_collection
118.Fa "const std::string& regexp"
119.Fa "const Collection& collection"
120.Fc
121.Ft bool
122.Fo atf::utils::grep_file
123.Fa "const std::string& regexp"
124.Fa "const std::string& path"
125.Fc
126.Ft bool
127.Fo atf::utils::grep_string
128.Fa "const std::string& regexp"
129.Fa "const std::string& path"
130.Fc
131.Ft void
132.Fo atf::utils::redirect
133.Fa "const int fd"
134.Fa "const std::string& path"
135.Fc
136.Ft void
137.Fo atf::utils::wait
138.Fa "const pid_t pid"
139.Fa "const int expected_exit_status"
140.Fa "const std::string& expected_stdout"
141.Fa "const std::string& expected_stderr"
142.Fc
143.Sh DESCRIPTION
144ATF provides a C++ programming interface to implement test programs.
145C++-based test programs follow this template:
146.Bd -literal -offset indent
147extern "C" {
148.Ns ... C-specific includes go here ...
149}
150
151.Ns ... C++-specific includes go here ...
152
153#include <atf-c++.hpp>
154
155ATF_TEST_CASE(tc1);
156ATF_TEST_CASE_HEAD(tc1)
157{
158    ... first test case's header ...
159}
160ATF_TEST_CASE_BODY(tc1)
161{
162    ... first test case's body ...
163}
164
165ATF_TEST_CASE_WITH_CLEANUP(tc2);
166ATF_TEST_CASE_HEAD(tc2)
167{
168    ... second test case's header ...
169}
170ATF_TEST_CASE_BODY(tc2)
171{
172    ... second test case's body ...
173}
174ATF_TEST_CASE_CLEANUP(tc2)
175{
176    ... second test case's cleanup ...
177}
178
179ATF_TEST_CASE(tc3);
180ATF_TEST_CASE_BODY(tc3)
181{
182    ... third test case's body ...
183}
184
185.Ns ... additional test cases ...
186
187ATF_INIT_TEST_CASES(tcs)
188{
189    ATF_ADD_TEST_CASE(tcs, tc1);
190    ATF_ADD_TEST_CASE(tcs, tc2);
191    ATF_ADD_TEST_CASE(tcs, tc3);
192    ... add additional test cases ...
193}
194.Ed
195.Ss Definition of test cases
196Test cases have an identifier and are composed of three different parts:
197the header, the body and an optional cleanup routine, all of which are
198described in
199.Xr atf-test-case 4 .
200To define test cases, one can use the
201.Fn ATF_TEST_CASE ,
202.Fn ATF_TEST_CASE_WITH_CLEANUP
203or the
204.Fn ATF_TEST_CASE_WITHOUT_HEAD
205macros, which take a single parameter specifiying the test case's
206name.
207.Fn ATF_TEST_CASE ,
208requires to define a head and a body for the test case,
209.Fn ATF_TEST_CASE_WITH_CLEANUP
210requires to define a head, a body and a cleanup for the test case and
211.Fn ATF_TEST_CASE_WITHOUT_HEAD
212requires only a body for the test case.
213It is important to note that these
214.Em do not
215set the test case up for execution when the program is run.
216In order to do so, a later registration is needed through the
217.Fn ATF_ADD_TEST_CASE
218macro detailed in
219.Sx Program initialization .
220.Pp
221Later on, one must define the three parts of the body by means of three
222functions.
223Their headers are given by the
224.Fn ATF_TEST_CASE_HEAD ,
225.Fn ATF_TEST_CASE_BODY
226and
227.Fn ATF_TEST_CASE_CLEANUP
228macros, all of which take the test case's name.
229Following each of these, a block of code is expected, surrounded by the
230opening and closing brackets.
231.Pp
232Additionally, the
233.Fn ATF_TEST_CASE_NAME
234macro can be used to obtain the name of the class corresponding to a
235particular test case, as the name is internally manged by the library to
236prevent clashes with other user identifiers.
237Similarly, the
238.Fn ATF_TEST_CASE_USE
239macro can be executed on a particular test case to mark it as "used" and
240thus prevent compiler warnings regarding unused symbols.
241Note that
242.Em you should never have to use these macros during regular operation.
243.Ss Program initialization
244The library provides a way to easily define the test program's
245.Fn main
246function.
247You should never define one on your own, but rely on the
248library to do it for you.
249This is done by using the
250.Fn ATF_INIT_TEST_CASES
251macro, which is passed the name of the list that will hold the test cases.
252This name can be whatever you want as long as it is a valid variable value.
253.Pp
254After the macro, you are supposed to provide the body of a function, which
255should only use the
256.Fn ATF_ADD_TEST_CASE
257macro to register the test cases the test program will execute.
258The first parameter of this macro matches the name you provided in the
259former call.
260.Ss Header definitions
261The test case's header can define the meta-data by using the
262.Fn set_md_var
263method, which takes two parameters: the first one specifies the
264meta-data variable to be set and the second one specifies its value.
265Both of them are strings.
266.Ss Configuration variables
267The test case has read-only access to the current configuration variables
268by means of the
269.Ft bool
270.Fn has_config_var
271and the
272.Ft std::string
273.Fn get_config_var
274methods, which can be called in any of the three parts of a test case.
275.Ss Access to the source directory
276It is possible to get the path to the test case's source directory from any
277of its three components by querying the
278.Sq srcdir
279configuration variable.
280.Ss Requiring programs
281Aside from the
282.Va require.progs
283meta-data variable available in the header only, one can also check for
284additional programs in the test case's body by using the
285.Fn require_prog
286function, which takes the base name or full path of a single binary.
287Relative paths are forbidden.
288If it is not found, the test case will be automatically skipped.
289.Ss Test case finalization
290The test case finalizes either when the body reaches its end, at which
291point the test is assumed to have
292.Em passed ,
293or at any explicit call to
294.Fn ATF_PASS ,
295.Fn ATF_FAIL
296or
297.Fn ATF_SKIP .
298These three macros terminate the execution of the test case immediately.
299The cleanup routine will be processed afterwards in a completely automated
300way, regardless of the test case's termination reason.
301.Pp
302.Fn ATF_PASS
303does not take any parameters.
304.Fn ATF_FAIL
305and
306.Fn ATF_SKIP
307take a single string that describes why the test case failed or
308was skipped, respectively.
309It is very important to provide a clear error message in both cases so that
310the user can quickly know why the test did not pass.
311.Ss Expectations
312Everything explained in the previous section changes when the test case
313expectations are redefined by the programmer.
314.Pp
315Each test case has an internal state called
316.Sq expect
317that describes what the test case expectations are at any point in time.
318The value of this property can change during execution by any of:
319.Bl -tag -width indent
320.It Fn expect_death "reason"
321Expects the test case to exit prematurely regardless of the nature of the
322exit.
323.It Fn expect_exit "exitcode" "reason"
324Expects the test case to exit cleanly.
325If
326.Va exitcode
327is not
328.Sq -1 ,
329the runtime engine will validate that the exit code of the test case
330matches the one provided in this call.
331Otherwise, the exact value will be ignored.
332.It Fn expect_fail "reason"
333Any failure (be it fatal or non-fatal) raised in this mode is recorded.
334However, such failures do not report the test case as failed; instead, the
335test case finalizes cleanly and is reported as
336.Sq expected failure ;
337this report includes the provided
338.Fa reason
339as part of it.
340If no error is raised while running in this mode, then the test case is
341reported as
342.Sq failed .
343.Pp
344This mode is useful to reproduce actual known bugs in tests.
345Whenever the developer fixes the bug later on, the test case will start
346reporting a failure, signaling the developer that the test case must be
347adjusted to the new conditions.
348In this situation, it is useful, for example, to set
349.Fa reason
350as the bug number for tracking purposes.
351.It Fn expect_pass
352This is the normal mode of execution.
353In this mode, any failure is reported as such to the user and the test case
354is marked as
355.Sq failed .
356.It Fn expect_race "reason"
357Any failure or timeout during the execution of the test case will be
358considered as if a race condition has been triggered and reported as such.
359If no problems arise, the test will continue execution as usual.
360.It Fn expect_signal "signo" "reason"
361Expects the test case to terminate due to the reception of a signal.
362If
363.Va signo
364is not
365.Sq -1 ,
366the runtime engine will validate that the signal that terminated the test
367case matches the one provided in this call.
368Otherwise, the exact value will be ignored.
369.It Fn expect_timeout "reason"
370Expects the test case to execute for longer than its timeout.
371.El
372.Ss Helper macros for common checks
373The library provides several macros that are very handy in multiple
374situations.
375These basically check some condition after executing a given statement or
376processing a given expression and, if the condition is not met, they
377automatically call
378.Fn ATF_FAIL
379with an appropriate error message.
380.Pp
381.Fn ATF_REQUIRE
382takes an expression and raises a failure if it evaluates to false.
383.Pp
384.Fn ATF_REQUIRE_EQ
385takes two expressions and raises a failure if the two do not evaluate to
386the same exact value.
387The common style is to put the expected value in the first parameter and the
388actual value in the second parameter.
389.Pp
390.Fn ATF_REQUIRE_IN
391takes an element and a collection and validates that the element is present in
392the collection.
393.Pp
394.Fn ATF_REQUIRE_MATCH
395takes a regular expression and a string and raises a failure if the regular
396expression does not match the string.
397.Pp
398.Fn ATF_REQUIRE_NOT_IN
399takes an element and a collection and validates that the element is not present
400in the collection.
401.Pp
402.Fn ATF_REQUIRE_THROW
403takes the name of an exception and a statement and raises a failure if
404the statement does not throw the specified exception.
405.Fn ATF_REQUIRE_THROW_RE
406takes the name of an exception, a regular expresion and a statement and raises a
407failure if the statement does not throw the specified exception and if the
408message of the exception does not match the regular expression.
409.Pp
410.Fn ATF_CHECK_ERRNO
411and
412.Fn ATF_REQUIRE_ERRNO
413take, first, the error code that the check is expecting to find in the
414.Va errno
415variable and, second, a boolean expression that, if evaluates to true,
416means that a call failed and
417.Va errno
418has to be checked against the first value.
419.Ss Utility functions
420The following functions are provided as part of the
421.Nm
422API to simplify the creation of a variety of tests.
423In particular, these are useful to write tests for command-line interfaces.
424.Pp
425.Ft void
426.Fo atf::utils::cat_file
427.Fa "const std::string& path"
428.Fa "const std::string& prefix"
429.Fc
430.Bd -ragged -offset indent
431Prints the contents of
432.Fa path
433to the standard output, prefixing every line with the string in
434.Fa prefix .
435.Ed
436.Pp
437.Ft bool
438.Fo atf::utils::compare_file
439.Fa "const std::string& path"
440.Fa "const std::string& contents"
441.Fc
442.Bd -ragged -offset indent
443Returns true if the given
444.Fa path
445matches exactly the expected inlined
446.Fa contents .
447.Ed
448.Pp
449.Ft void
450.Fo atf::utils::copy_file
451.Fa "const std::string& source"
452.Fa "const std::string& destination"
453.Fc
454.Bd -ragged -offset indent
455Copies the file
456.Fa source
457to
458.Fa destination .
459The permissions of the file are preserved during the code.
460.Ed
461.Pp
462.Ft void
463.Fo atf::utils::create_file
464.Fa "const std::string& path"
465.Fa "const std::string& contents"
466.Fc
467.Bd -ragged -offset indent
468Creates
469.Fa file
470with the text given in
471.Fa contents .
472.Ed
473.Pp
474.Ft void
475.Fo atf::utils::file_exists
476.Fa "const std::string& path"
477.Fc
478.Bd -ragged -offset indent
479Checks if
480.Fa path
481exists.
482.Ed
483.Pp
484.Ft pid_t
485.Fo atf::utils::fork
486.Fa "void"
487.Fc
488.Bd -ragged -offset indent
489Forks a process and redirects the standard output and standard error of the
490child to files for later validation with
491.Fn atf::utils::wait .
492Fails the test case if the fork fails, so this does not return an error.
493.Ed
494.Pp
495.Ft bool
496.Fo atf::utils::grep_collection
497.Fa "const std::string& regexp"
498.Fa "const Collection& collection"
499.Fc
500.Bd -ragged -offset indent
501Searches for the regular expression
502.Fa regexp
503in any of the strings contained in the
504.Fa collection .
505This is a template that accepts any one-dimensional container of strings.
506.Ed
507.Pp
508.Ft bool
509.Fo atf::utils::grep_file
510.Fa "const std::string& regexp"
511.Fa "const std::string& path"
512.Fc
513.Bd -ragged -offset indent
514Searches for the regular expression
515.Fa regexp
516in the file
517.Fa path .
518The variable arguments are used to construct the regular expression.
519.Ed
520.Pp
521.Ft bool
522.Fo atf::utils::grep_string
523.Fa "const std::string& regexp"
524.Fa "const std::string& str"
525.Fc
526.Bd -ragged -offset indent
527Searches for the regular expression
528.Fa regexp
529in the string
530.Fa str .
531.Ed
532.Ft void
533.Fo atf::utils::redirect
534.Fa "const int fd"
535.Fa "const std::string& path"
536.Fc
537.Bd -ragged -offset indent
538Redirects the given file descriptor
539.Fa fd
540to the file
541.Fa path .
542This function exits the process in case of an error and does not properly mark
543the test case as failed.
544As a result, it should only be used in subprocesses of the test case; specially
545those spawned by
546.Fn atf::utils::fork .
547.Ed
548.Pp
549.Ft void
550.Fo atf::utils::wait
551.Fa "const pid_t pid"
552.Fa "const int expected_exit_status"
553.Fa "const std::string& expected_stdout"
554.Fa "const std::string& expected_stderr"
555.Fc
556.Bd -ragged -offset indent
557Waits and validates the result of a subprocess spawned with
558.Fn atf::utils::wait .
559The validation involves checking that the subprocess exited cleanly and returned
560the code specified in
561.Fa expected_exit_status
562and that its standard output and standard error match the strings given in
563.Fa expected_stdout
564and
565.Fa expected_stderr .
566.Pp
567If any of the
568.Fa expected_stdout
569or
570.Fa expected_stderr
571strings are prefixed with
572.Sq save: ,
573then they specify the name of the file into which to store the stdout or stderr
574of the subprocess, and no comparison is performed.
575.Ed
576.Sh ENVIRONMENT
577The following variables are recognized by
578.Nm
579but should not be overridden other than for testing purposes:
580.Pp
581.Bl -tag -width ATFXBUILDXCXXFLAGSXX -compact
582.It Va ATF_BUILD_CC
583Path to the C compiler.
584.It Va ATF_BUILD_CFLAGS
585C compiler flags.
586.It Va ATF_BUILD_CPP
587Path to the C/C++ preprocessor.
588.It Va ATF_BUILD_CPPFLAGS
589C/C++ preprocessor flags.
590.It Va ATF_BUILD_CXX
591Path to the C++ compiler.
592.It Va ATF_BUILD_CXXFLAGS
593C++ compiler flags.
594.El
595.Sh EXAMPLES
596The following shows a complete test program with a single test case that
597validates the addition operator:
598.Bd -literal -offset indent
599#include <atf-c++.hpp>
600
601ATF_TEST_CASE(addition);
602ATF_TEST_CASE_HEAD(addition)
603{
604    set_md_var("descr", "Sample tests for the addition operator");
605}
606ATF_TEST_CASE_BODY(addition)
607{
608    ATF_REQUIRE_EQ(0, 0 + 0);
609    ATF_REQUIRE_EQ(1, 0 + 1);
610    ATF_REQUIRE_EQ(1, 1 + 0);
611
612    ATF_REQUIRE_EQ(2, 1 + 1);
613
614    ATF_REQUIRE_EQ(300, 100 + 200);
615}
616
617ATF_TEST_CASE(open_failure);
618ATF_TEST_CASE_HEAD(open_failure)
619{
620    set_md_var("descr", "Sample tests for the open function");
621}
622ATF_TEST_CASE_BODY(open_failure)
623{
624    ATF_REQUIRE_ERRNO(ENOENT, open("non-existent", O_RDONLY) == -1);
625}
626
627ATF_TEST_CASE(known_bug);
628ATF_TEST_CASE_HEAD(known_bug)
629{
630    set_md_var("descr", "Reproduces a known bug");
631}
632ATF_TEST_CASE_BODY(known_bug)
633{
634    expect_fail("See bug number foo/bar");
635    ATF_REQUIRE_EQ(3, 1 + 1);
636    expect_pass();
637    ATF_REQUIRE_EQ(3, 1 + 2);
638}
639
640ATF_INIT_TEST_CASES(tcs)
641{
642    ATF_ADD_TEST_CASE(tcs, addition);
643    ATF_ADD_TEST_CASE(tcs, open_failure);
644    ATF_ADD_TEST_CASE(tcs, known_bug);
645}
646.Ed
647.Sh SEE ALSO
648.Xr atf-test-program 1 ,
649.Xr atf-test-case 4
650