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