1.\" 2.\" Automated Testing Framework (atf) 3.\" 4.\" Copyright (c) 2008 The NetBSD Foundation, Inc. 5.\" All rights reserved. 6.\" 7.\" Redistribution and use in source and binary forms, with or without 8.\" modification, are permitted provided that the following conditions 9.\" are met: 10.\" 1. Redistributions of source code must retain the above copyright 11.\" notice, this list of conditions and the following disclaimer. 12.\" 2. Redistributions in binary form must reproduce the above copyright 13.\" notice, this list of conditions and the following disclaimer in the 14.\" documentation and/or other materials provided with the distribution. 15.\" 16.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND 17.\" CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, 18.\" INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 19.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20.\" IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY 21.\" DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 23.\" GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 25.\" IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 26.\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 27.\" IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28.\" 29.Dd November 30, 2012 30.Dt ATF-C-API 3 31.Os 32.Sh NAME 33.Nm atf-c-api , 34.Nm ATF_CHECK , 35.Nm ATF_CHECK_MSG , 36.Nm ATF_CHECK_EQ , 37.Nm ATF_CHECK_EQ_MSG , 38.Nm ATF_CHECK_MATCH , 39.Nm ATF_CHECK_MATCH_MSG , 40.Nm ATF_CHECK_STREQ , 41.Nm ATF_CHECK_STREQ_MSG , 42.Nm ATF_CHECK_ERRNO , 43.Nm ATF_REQUIRE , 44.Nm ATF_REQUIRE_MSG , 45.Nm ATF_REQUIRE_EQ , 46.Nm ATF_REQUIRE_EQ_MSG , 47.Nm ATF_REQUIRE_MATCH , 48.Nm ATF_REQUIRE_MATCH_MSG , 49.Nm ATF_REQUIRE_STREQ , 50.Nm ATF_REQUIRE_STREQ_MSG , 51.Nm ATF_REQUIRE_ERRNO , 52.Nm ATF_TC , 53.Nm ATF_TC_BODY , 54.Nm ATF_TC_BODY_NAME , 55.Nm ATF_TC_CLEANUP , 56.Nm ATF_TC_CLEANUP_NAME , 57.Nm ATF_TC_HEAD , 58.Nm ATF_TC_HEAD_NAME , 59.Nm ATF_TC_NAME , 60.Nm ATF_TC_WITH_CLEANUP , 61.Nm ATF_TC_WITHOUT_HEAD , 62.Nm ATF_TP_ADD_TC , 63.Nm ATF_TP_ADD_TCS , 64.Nm atf_tc_get_config_var , 65.Nm atf_tc_get_config_var_wd , 66.Nm atf_tc_get_config_var_as_bool , 67.Nm atf_tc_get_config_var_as_bool_wd , 68.Nm atf_tc_get_config_var_as_long , 69.Nm atf_tc_get_config_var_as_long_wd , 70.Nm atf_no_error , 71.Nm atf_tc_expect_death , 72.Nm atf_tc_expect_exit , 73.Nm atf_tc_expect_fail , 74.Nm atf_tc_expect_pass , 75.Nm atf_tc_expect_signal , 76.Nm atf_tc_expect_timeout , 77.Nm atf_tc_fail , 78.Nm atf_tc_fail_nonfatal , 79.Nm atf_tc_pass , 80.Nm atf_tc_skip , 81.Nm atf_utils_cat_file , 82.Nm atf_utils_compare_file , 83.Nm atf_utils_copy_file , 84.Nm atf_utils_create_file , 85.Nm atf_utils_file_exists , 86.Nm atf_utils_fork , 87.Nm atf_utils_free_charpp , 88.Nm atf_utils_grep_file , 89.Nm atf_utils_grep_string , 90.Nm atf_utils_readline , 91.Nm atf_utils_redirect , 92.Nm atf_utils_wait 93.Nd C API to write ATF-based test programs 94.Sh SYNOPSIS 95.In atf-c.h 96.Fn ATF_CHECK "expression" 97.Fn ATF_CHECK_MSG "expression" "fail_msg_fmt" ... 98.Fn ATF_CHECK_EQ "expression_1" "expression_2" 99.Fn ATF_CHECK_EQ_MSG "expression_1" "expression_2" "fail_msg_fmt" ... 100.Fn ATF_CHECK_MATCH "regexp" "string" 101.Fn ATF_CHECK_MATCH_MSG "regexp" "string" "fail_msg_fmt" ... 102.Fn ATF_CHECK_STREQ "string_1" "string_2" 103.Fn ATF_CHECK_STREQ_MSG "string_1" "string_2" "fail_msg_fmt" ... 104.Fn ATF_CHECK_ERRNO "exp_errno" "bool_expression" 105.Fn ATF_REQUIRE "expression" 106.Fn ATF_REQUIRE_MSG "expression" "fail_msg_fmt" ... 107.Fn ATF_REQUIRE_EQ "expression_1" "expression_2" 108.Fn ATF_REQUIRE_EQ_MSG "expression_1" "expression_2" "fail_msg_fmt" ... 109.Fn ATF_REQUIRE_MATCH "regexp" "string" 110.Fn ATF_REQUIRE_MATCH_MSG "regexp" "string" "fail_msg_fmt" ... 111.Fn ATF_REQUIRE_STREQ "string_1" "string_2" 112.Fn ATF_REQUIRE_STREQ_MSG "string_1" "string_2" "fail_msg_fmt" ... 113.Fn ATF_REQUIRE_ERRNO "exp_errno" "bool_expression" 114.Fn ATF_TC "name" 115.Fn ATF_TC_BODY "name" "tc" 116.Fn ATF_TC_BODY_NAME "name" 117.Fn ATF_TC_CLEANUP "name" "tc" 118.Fn ATF_TC_CLEANUP_NAME "name" 119.Fn ATF_TC_HEAD "name" "tc" 120.Fn ATF_TC_HEAD_NAME "name" 121.Fn ATF_TC_NAME "name" 122.Fn ATF_TC_WITH_CLEANUP "name" 123.Fn ATF_TC_WITHOUT_HEAD "name" 124.Fn ATF_TP_ADD_TC "tp_name" "tc_name" 125.Fn ATF_TP_ADD_TCS "tp_name" 126.Fn atf_tc_get_config_var "tc" "varname" 127.Fn atf_tc_get_config_var_wd "tc" "variable_name" "default_value" 128.Fn atf_tc_get_config_var_as_bool "tc" "variable_name" 129.Fn atf_tc_get_config_var_as_bool_wd "tc" "variable_name" "default_value" 130.Fn atf_tc_get_config_var_as_long "tc" "variable_name" 131.Fn atf_tc_get_config_var_as_long_wd "tc" "variable_name" "default_value" 132.Fn atf_no_error 133.Fn atf_tc_expect_death "reason" "..." 134.Fn atf_tc_expect_exit "exitcode" "reason" "..." 135.Fn atf_tc_expect_fail "reason" "..." 136.Fn atf_tc_expect_pass 137.Fn atf_tc_expect_signal "signo" "reason" "..." 138.Fn atf_tc_expect_timeout "reason" "..." 139.Fn atf_tc_fail "reason" 140.Fn atf_tc_fail_nonfatal "reason" 141.Fn atf_tc_pass 142.Fn atf_tc_skip "reason" 143.Ft void 144.Fo atf_utils_cat_file 145.Fa "const char *file" 146.Fa "const char *prefix" 147.Fc 148.Ft bool 149.Fo atf_utils_compare_file 150.Fa "const char *file" 151.Fa "const char *contents" 152.Fc 153.Ft void 154.Fo atf_utils_copy_file 155.Fa "const char *source" 156.Fa "const char *destination" 157.Fc 158.Ft void 159.Fo atf_utils_create_file 160.Fa "const char *file" 161.Fa "const char *contents" 162.Fa "..." 163.Fc 164.Ft void 165.Fo atf_utils_file_exists 166.Fa "const char *file" 167.Fc 168.Ft pid_t 169.Fo atf_utils_fork 170.Fa "void" 171.Fc 172.Ft void 173.Fo atf_utils_free_charpp 174.Fa "char **argv" 175.Fc 176.Ft bool 177.Fo atf_utils_grep_file 178.Fa "const char *regexp" 179.Fa "const char *file" 180.Fa "..." 181.Fc 182.Ft bool 183.Fo atf_utils_grep_string 184.Fa "const char *regexp" 185.Fa "const char *str" 186.Fa "..." 187.Fc 188.Ft char * 189.Fo atf_utils_readline 190.Fa "int fd" 191.Fc 192.Ft void 193.Fo atf_utils_redirect 194.Fa "const int fd" 195.Fa "const char *file" 196.Fc 197.Ft void 198.Fo atf_utils_wait 199.Fa "const pid_t pid" 200.Fa "const int expected_exit_status" 201.Fa "const char *expected_stdout" 202.Fa "const char *expected_stderr" 203.Fc 204.Sh DESCRIPTION 205The ATF 206.Pp 207C-based test programs always follow this template: 208.Bd -literal -offset indent 209.Ns ... C-specific includes go here ... 210 211#include <atf-c.h> 212 213ATF_TC(tc1); 214ATF_TC_HEAD(tc1, tc) 215{ 216 ... first test case's header ... 217} 218ATF_TC_BODY(tc1, tc) 219{ 220 ... first test case's body ... 221} 222 223ATF_TC_WITH_CLEANUP(tc2); 224ATF_TC_HEAD(tc2, tc) 225{ 226 ... second test case's header ... 227} 228ATF_TC_BODY(tc2, tc) 229{ 230 ... second test case's body ... 231} 232ATF_TC_CLEANUP(tc2, tc) 233{ 234 ... second test case's cleanup ... 235} 236 237ATF_TC_WITHOUT_HEAD(tc3); 238ATF_TC_BODY(tc3, tc) 239{ 240 ... third test case's body ... 241} 242 243.Ns ... additional test cases ... 244 245ATF_TP_ADD_TCS(tp) 246{ 247 ATF_TP_ADD_TC(tcs, tc1); 248 ATF_TP_ADD_TC(tcs, tc2); 249 ATF_TP_ADD_TC(tcs, tc3); 250 ... add additional test cases ... 251 252 return atf_no_error(); 253} 254.Ed 255.Ss Definition of test cases 256Test cases have an identifier and are composed of three different parts: 257the header, the body and an optional cleanup routine, all of which are 258described in 259.Xr atf-test-case 4 . 260To define test cases, one can use the 261.Fn ATF_TC , 262.Fn ATF_TC_WITH_CLEANUP 263or the 264.Fn ATF_TC_WITHOUT_HEAD 265macros, which take a single parameter specifiying the test case's name. 266.Fn ATF_TC , 267requires to define a head and a body for the test case, 268.Fn ATF_TC_WITH_CLEANUP 269requires to define a head, a body and a cleanup for the test case and 270.Fn ATF_TC_WITHOUT_HEAD 271requires only a body for the test case. 272It is important to note that these 273.Em do not 274set the test case up for execution when the program is run. 275In order to do so, a later registration is needed with the 276.Fn ATF_TP_ADD_TC 277macro detailed in 278.Sx Program initialization . 279.Pp 280Later on, one must define the three parts of the body by means of three 281functions. 282Their headers are given by the 283.Fn ATF_TC_HEAD , 284.Fn ATF_TC_BODY 285and 286.Fn ATF_TC_CLEANUP 287macros, all of which take the test case name provided to the 288.Fn ATF_TC 289.Fn ATF_TC_WITH_CLEANUP , 290or 291.Fn ATF_TC_WITHOUT_HEAD 292macros and the name of the variable that will hold a pointer to the 293test case data. 294Following each of these, a block of code is expected, surrounded by the 295opening and closing brackets. 296.Ss Program initialization 297The library provides a way to easily define the test program's 298.Fn main 299function. 300You should never define one on your own, but rely on the 301library to do it for you. 302This is done by using the 303.Fn ATF_TP_ADD_TCS 304macro, which is passed the name of the object that will hold the test 305cases; i.e. the test program instance. 306This name can be whatever you want as long as it is a valid variable 307identifier. 308.Pp 309After the macro, you are supposed to provide the body of a function, which 310should only use the 311.Fn ATF_TP_ADD_TC 312macro to register the test cases the test program will execute and return 313a success error code. 314The first parameter of this macro matches the name you provided in the 315former call. 316The success status can be returned using the 317.Fn atf_no_error 318function. 319.Ss Header definitions 320The test case's header can define the meta-data by using the 321.Fn atf_tc_set_md_var 322method, which takes three parameters: the first one points to the test 323case data, the second one specifies the meta-data variable to be set 324and the third one specifies its value. 325Both of them are strings. 326.Ss Configuration variables 327The test case has read-only access to the current configuration variables 328by means of the 329.Ft bool 330.Fn atf_tc_has_config_var , 331.Ft const char * 332.Fn atf_tc_get_config_var , 333.Ft const char * 334.Fn atf_tc_get_config_var_wd , 335.Ft bool 336.Fn atf_tc_get_config_var_as_bool , 337.Ft bool 338.Fn atf_tc_get_config_var_as_bool_wd , 339.Ft long 340.Fn atf_tc_get_config_var_as_long , 341and the 342.Ft long 343.Fn atf_tc_get_config_var_as_long_wd 344functions, which can be called in any of the three parts of a test case. 345.Pp 346The 347.Sq _wd 348variants take a default value for the variable which is returned if the 349variable is not defined. 350The other functions without the 351.Sq _wd 352suffix 353.Em require 354the variable to be defined. 355.Ss Access to the source directory 356It is possible to get the path to the test case's source directory from any 357of its three components by querying the 358.Sq srcdir 359configuration variable. 360.Ss Requiring programs 361Aside from the 362.Va require.progs 363meta-data variable available in the header only, one can also check for 364additional programs in the test case's body by using the 365.Fn atf_tc_require_prog 366function, which takes the base name or full path of a single binary. 367Relative paths are forbidden. 368If it is not found, the test case will be automatically skipped. 369.Ss Test case finalization 370The test case finalizes either when the body reaches its end, at which 371point the test is assumed to have 372.Em passed , 373unless any non-fatal errors were raised using 374.Fn atf_tc_fail_nonfatal , 375or at any explicit call to 376.Fn atf_tc_pass , 377.Fn atf_tc_fail 378or 379.Fn atf_tc_skip . 380These three functions terminate the execution of the test case immediately. 381The cleanup routine will be processed afterwards in a completely automated 382way, regardless of the test case's termination reason. 383.Pp 384.Fn atf_tc_pass 385does not take any parameters. 386.Fn atf_tc_fail , 387.Fn atf_tc_fail_nonfatal 388and 389.Fn atf_tc_skip 390take a format string and a variable list of parameters, which describe, in 391a user-friendly manner, why the test case failed or was skipped, 392respectively. 393It is very important to provide a clear error message in both cases so that 394the user can quickly know why the test did not pass. 395.Ss Expectations 396Everything explained in the previous section changes when the test case 397expectations are redefined by the programmer. 398.Pp 399Each test case has an internal state called 400.Sq expect 401that describes what the test case expectations are at any point in time. 402The value of this property can change during execution by any of: 403.Bl -tag -width indent 404.It Fn atf_tc_expect_death "reason" "..." 405Expects the test case to exit prematurely regardless of the nature of the 406exit. 407.It Fn atf_tc_expect_exit "exitcode" "reason" "..." 408Expects the test case to exit cleanly. 409If 410.Va exitcode 411is not 412.Sq -1 , 413.Xr atf-run 1 414will validate that the exit code of the test case matches the one provided 415in this call. 416Otherwise, the exact value will be ignored. 417.It Fn atf_tc_expect_fail "reason" "..." 418Any failure (be it fatal or non-fatal) raised in this mode is recorded. 419However, such failures do not report the test case as failed; instead, the 420test case finalizes cleanly and is reported as 421.Sq expected failure ; 422this report includes the provided 423.Fa reason 424as part of it. 425If no error is raised while running in this mode, then the test case is 426reported as 427.Sq failed . 428.Pp 429This mode is useful to reproduce actual known bugs in tests. 430Whenever the developer fixes the bug later on, the test case will start 431reporting a failure, signaling the developer that the test case must be 432adjusted to the new conditions. 433In this situation, it is useful, for example, to set 434.Fa reason 435as the bug number for tracking purposes. 436.It Fn atf_tc_expect_pass 437This is the normal mode of execution. 438In this mode, any failure is reported as such to the user and the test case 439is marked as 440.Sq failed . 441.It Fn atf_tc_expect_signal "signo" "reason" "..." 442Expects the test case to terminate due to the reception of a signal. 443If 444.Va signo 445is not 446.Sq -1 , 447.Xr atf-run 1 448will validate that the signal that terminated the test case matches the one 449provided in this call. 450Otherwise, the exact value will be ignored. 451.It Fn atf_tc_expect_timeout "reason" "..." 452Expects the test case to execute for longer than its timeout. 453.El 454.Ss Helper macros for common checks 455The library provides several macros that are very handy in multiple 456situations. 457These basically check some condition after executing a given statement or 458processing a given expression and, if the condition is not met, they 459report the test case as failed. 460.Pp 461The 462.Sq REQUIRE 463variant of the macros immediately abort the test case as soon as an error 464condition is detected by calling the 465.Fn atf_tc_fail 466function. 467Use this variant whenever it makes no sense to continue the execution of a 468test case when the checked condition is not met. 469The 470.Sq CHECK 471variant, on the other hand, reports a failure as soon as it is encountered 472using the 473.Fn atf_tc_fail_nonfatal 474function, but the execution of the test case continues as if nothing had 475happened. 476Use this variant whenever the checked condition is important as a result of 477the test case, but there are other conditions that can be subsequently 478checked on the same run without aborting. 479.Pp 480Additionally, the 481.Sq MSG 482variants take an extra set of parameters to explicitly specify the failure 483message. 484This failure message is formatted according to the 485.Xr printf 3 486formatters. 487.Pp 488.Fn ATF_CHECK , 489.Fn ATF_CHECK_MSG , 490.Fn ATF_REQUIRE 491and 492.Fn ATF_REQUIRE_MSG 493take an expression and fail if the expression evaluates to false. 494.Pp 495.Fn ATF_CHECK_EQ , 496.Fn ATF_CHECK_EQ_MSG , 497.Fn ATF_REQUIRE_EQ 498and 499.Fn ATF_REQUIRE_EQ_MSG 500take two expressions and fail if the two evaluated values are not equal. 501.Pp 502.Fn ATF_CHECK_MATCH , 503.Fn ATF_CHECK_MATCH_MSG , 504.Fn ATF_REQUIRE_MATCH 505and 506.Fn ATF_REQUIRE_MATCH_MSG 507take a regular expression and a string and fail if the regular expression does 508not match the given string. 509Note that the regular expression is not anchored, so it will match anywhere in 510the string. 511.Pp 512.Fn ATF_CHECK_STREQ , 513.Fn ATF_CHECK_STREQ_MSG , 514.Fn ATF_REQUIRE_STREQ 515and 516.Fn ATF_REQUIRE_STREQ_MSG 517take two strings and fail if the two are not equal character by character. 518.Pp 519.Fn ATF_CHECK_ERRNO 520and 521.Fn ATF_REQUIRE_ERRNO 522take, first, the error code that the check is expecting to find in the 523.Va errno 524variable and, second, a boolean expression that, if evaluates to true, 525means that a call failed and 526.Va errno 527has to be checked against the first value. 528.Ss Utility functions 529The following functions are provided as part of the 530.Nm 531API to simplify the creation of a variety of tests. 532In particular, these are useful to write tests for command-line interfaces. 533.Pp 534.Ft void 535.Fo atf_utils_cat_file 536.Fa "const char *file" 537.Fa "const char *prefix" 538.Fc 539.Bd -offset indent 540Prints the contents of 541.Fa file 542to the standard output, prefixing every line with the string in 543.Fa prefix . 544.Ed 545.Pp 546.Ft bool 547.Fo atf_utils_compare_file 548.Fa "const char *file" 549.Fa "const char *contents" 550.Fc 551.Bd -offset indent 552Returns true if the given 553.Fa file 554matches exactly the expected inlined 555.Fa contents . 556.Ed 557.Pp 558.Ft void 559.Fo atf_utils_copy_file 560.Fa "const char *source" 561.Fa "const char *destination" 562.Fc 563.Bd -offset indent 564Copies the file 565.Fa source 566to 567.Fa destination . 568The permissions of the file are preserved during the code. 569.Ed 570.Pp 571.Ft void 572.Fo atf_utils_create_file 573.Fa "const char *file" 574.Fa "const char *contents" 575.Fa "..." 576.Fc 577.Bd -offset indent 578Creates 579.Fa file 580with the text given in 581.Fa contents , 582which is a formatting string that uses the rest of the variable arguments. 583.Ed 584.Pp 585.Ft void 586.Fo atf_utils_file_exists 587.Fa "const char *file" 588.Fc 589.Bd -offset indent 590Checks if 591.Fa file 592exists. 593.Ed 594.Pp 595.Ft pid_t 596.Fo atf_utils_fork 597.Fa "void" 598.Fc 599.Bd -offset indent 600Forks a process and redirects the standard output and standard error of the 601child to files for later validation with 602.Fn atf_utils_wait . 603Fails the test case if the fork fails, so this does not return an error. 604.Ed 605.Pp 606.Ft void 607.Fo atf_utils_free_charpp 608.Fa "char **argv" 609.Fc 610.Bd -offset indent 611Frees a dynamically-allocated array of dynamically-allocated strings. 612.Ed 613.Pp 614.Ft bool 615.Fo atf_utils_grep_file 616.Fa "const char *regexp" 617.Fa "const char *file" 618.Fa "..." 619.Fc 620.Bd -offset indent 621Searches for the 622.Fa regexp , 623which is a formatting string representing the regular expression, 624in the 625.Fa file . 626The variable arguments are used to construct the regular expression. 627.Ed 628.Pp 629.Ft bool 630.Fo atf_utils_grep_string 631.Fa "const char *regexp" 632.Fa "const char *str" 633.Fa "..." 634.Fc 635.Bd -offset indent 636Searches for the 637.Fa regexp , 638which is a formatting string representing the regular expression, 639in the literal string 640.Fa str . 641The variable arguments are used to construct the regular expression. 642.Ed 643.Pp 644.Ft char * 645.Fo atf_utils_readline 646.Fa "int fd" 647.Fc 648.Bd -offset indent 649Reads a line from the file descriptor 650.Fa fd . 651The line, if any, is returned as a dynamically-allocated buffer that must be 652released with 653.Xr free 3 . 654If there was nothing to read, returns 655.Sq NULL . 656.Ed 657.Pp 658.Ft void 659.Fo atf_utils_redirect 660.Fa "const int fd" 661.Fa "const char *file" 662.Fc 663.Bd -offset indent 664Redirects the given file descriptor 665.Fa fd 666to 667.Fa file . 668This function exits the process in case of an error and does not properly mark 669the test case as failed. 670As a result, it should only be used in subprocesses of the test case; specially 671those spawned by 672.Fn atf_utils_fork . 673.Ed 674.Pp 675.Ft void 676.Fo atf_utils_wait 677.Fa "const pid_t pid" 678.Fa "const int expected_exit_status" 679.Fa "const char *expected_stdout" 680.Fa "const char *expected_stderr" 681.Fc 682.Bd -offset indent 683Waits and validates the result of a subprocess spawned with 684.Fn atf_utils_wait . 685The validation involves checking that the subprocess exited cleanly and returned 686the code specified in 687.Fa expected_exit_status 688and that its standard output and standard error match the strings given in 689.Fa expected_stdout 690and 691.Fa expected_stderr . 692.Pp 693If any of the 694.Fa expected_stdout 695or 696.Fa expected_stderr 697strings are prefixed with 698.Sq save: , 699then they specify the name of the file into which to store the stdout or stderr 700of the subprocess, and no comparison is performed. 701.Ed 702.Sh EXAMPLES 703The following shows a complete test program with a single test case that 704validates the addition operator: 705.Bd -literal -offset indent 706#include <atf-c.h> 707 708ATF_TC(addition); 709ATF_TC_HEAD(addition, tc) 710{ 711 atf_tc_set_md_var(tc, "descr", 712 "Sample tests for the addition operator"); 713} 714ATF_TC_BODY(addition, tc) 715{ 716 ATF_CHECK_EQ(0 + 0, 0); 717 ATF_CHECK_EQ(0 + 1, 1); 718 ATF_CHECK_EQ(1 + 0, 1); 719 720 ATF_CHECK_EQ(1 + 1, 2); 721 722 ATF_CHECK_EQ(100 + 200, 300); 723} 724 725ATF_TC(string_formatting); 726ATF_TC_HEAD(string_formatting, tc) 727{ 728 atf_tc_set_md_var(tc, "descr", 729 "Sample tests for the snprintf"); 730} 731ATF_TC_BODY(string_formatting, tc) 732{ 733 char buf[1024]; 734 snprintf(buf, sizeof(buf), "a %s", "string"); 735 ATF_CHECK_STREQ_MSG("a string", buf, "%s is not working"); 736} 737 738ATF_TC(open_failure); 739ATF_TC_HEAD(open_failure, tc) 740{ 741 atf_tc_set_md_var(tc, "descr", 742 "Sample tests for the open function"); 743} 744ATF_TC_BODY(open_failure, tc) 745{ 746 ATF_CHECK_ERRNO(ENOENT, open("non-existent", O_RDONLY) == -1); 747} 748 749ATF_TC(known_bug); 750ATF_TC_HEAD(known_bug, tc) 751{ 752 atf_tc_set_md_var(tc, "descr", 753 "Reproduces a known bug"); 754} 755ATF_TC_BODY(known_bug, tc) 756{ 757 atf_tc_expect_fail("See bug number foo/bar"); 758 ATF_CHECK_EQ(3, 1 + 1); 759 atf_tc_expect_pass(); 760 ATF_CHECK_EQ(3, 1 + 2); 761} 762 763ATF_TP_ADD_TCS(tp) 764{ 765 ATF_TP_ADD_TC(tp, addition); 766 ATF_TP_ADD_TC(tp, string_formatting); 767 ATF_TP_ADD_TC(tp, open_failure); 768 ATF_TP_ADD_TC(tp, known_bug); 769 770 return atf_no_error(); 771} 772.Ed 773.Sh SEE ALSO 774.Xr atf-test-program 1 , 775.Xr atf-test-case 4 , 776.Xr atf 7 777