Annotation of wikisrc/tutorials/atf.mdwn, revision 1.5

1.5     ! jmmv        1: [[!meta title="Creating atf-based tests for NetBSD src"]]
        !             2: [[!toc ]]
        !             3: 
1.1       jmmv        4: # Creating atf-based tests for NetBSD src
                      5: 
                      6: This quick tutorial is an attempt to workaround the lack of proper documentation
                      7: in atf.  The tutorial provides a guideline on how to start creating new test
                      8: programs and/or test cases, how these tests are tied to the NetBSD source tree
                      9: and a short reference of the most commonly used functions.
                     10: 
                     11: You should start by reading the
                     12: [tests(7)](http://netbsd.gw.com/cgi-bin/man-cgi?tests++NetBSD-current) manual
                     13: page, which is probably the only sane document in the whole documentation.  Any
                     14: other attempts at reading the atf-* manual pages are probably doomed unless you
                     15: are already familiar with atf itself and its internals.  Still, you may be able
                     16: to get some useful information out of
                     17: [atf-run(1)](http://netbsd.gw.com/cgi-bin/man-cgi?atf-run++NetBSD-current),
                     18: [atf-report(1)](http://netbsd.gw.com/cgi-bin/man-cgi?atf-report++NetBSD-current),
                     19: [atf-test-program(1)](http://netbsd.gw.com/cgi-bin/man-cgi?atf-test-program++NetBSD-current),
                     20: [atf-c-api(3)](http://netbsd.gw.com/cgi-bin/man-cgi?atf-c-api++NetBSD-current)
                     21: and
                     22: [atf-sh-api(3)](http://netbsd.gw.com/cgi-bin/man-cgi?atf-sh-api++NetBSD-current).
                     23: 
                     24: **IMPORTANT: Do not take anything for granted, SPECIALLY if you have previously
                     25: worked with and/or have seen src/regress/.  Your assumptions are most likely
1.2       jmmv       26: incorrect.**
1.1       jmmv       27: 
1.5     ! jmmv       28: # Test programs vs. test cases
1.1       jmmv       29: 
                     30: So, what is what and how do you organize your tests?
                     31: 
                     32: A **test case** is a piece of code that exercises a particular functionality of
                     33: another piece of code.  Commonly, test cases validate the outcome of a
                     34: particular source function or class method, the validity of the execution of a
                     35: command with a particular combination of flags/arguments, etc.  Test cases are
                     36: supposed to be very concise, in the sense that they should just be testing *one
                     37: behavior*.
                     38: 
                     39: A **test program** is a binary that collects and exposes a group of test cases.
                     40: Typically, these test programs expose conceptually-related tests or all the
                     41: tests for a particular source file.
                     42: 
                     43: In general, having many test programs with **just one test case** in them is
                     44: **wrong** and smells from the previous layout of src/regress/.  Think about some
                     45: other organization.  And don't blame atf for this separation: this is extremely
                     46: common in (almost?) all other test frameworks and, when used wisely, becomes an
                     47: invaluable classification.
                     48: 
                     49: For example, suppose you have the following fictitious source files for the ls
                     50: tool:
                     51: 
                     52: * bin/ls/fs.c: Provides the list_files() and stat_files() functions.
                     53: 
                     54: * bin/ls/ui.c: Provides the format_columns() function.
                     55: 
                     56: * bin/ls/main.c: The main method for ls.
                     57: 
                     58: Then, you could define the following test programs and test cases:
                     59: 
                     60: * bin/ls/fs_test.c: Provides test cases for list_files and stat_files.  These
                     61:   would be named list_files__empty_directory, list_files__one_file,
                     62:   list_files__multiple_files, stat_files__directory, stat_files__symlink, etc.
                     63: 
                     64: * bin/ls/ui_test.c: Provides test cases for the format_columns function.  These
                     65:   would be named format_columns__no_files, format_columns__multiple_files, etc.
                     66: 
                     67: * bin/ls/integration_test.sh: Provides "black box" test cases for the binary
                     68:   itself.  These would be named lflag, lflag_and_Fflag, no_flags, no_files, etc.
                     69: 
1.2       jmmv       70: Try to keep your test case names as descriptive as possible so that they do not
                     71: require comments to explain what they intend to test.
                     72: 
1.5     ! jmmv       73: # Test case parts
1.3       jmmv       74: 
                     75: A test case is composed by three parts: the *head*, the *body* and the
                     76: *cleanup*.  Only the body is required; the other two routines are optional.
                     77: 
1.5     ! jmmv       78: ## The head
1.3       jmmv       79: 
                     80: The *head* is used **for the sole purpose** to define meta-data properties for
                     81: the test case.  (Eventually, this would not be specified programmatically, but
                     82: is how we deal with the information right now.)
                     83: 
                     84: The following properties are commonly useful:
                     85: 
                     86: * descr: A textual description of the purpose of the test case.
                     87: 
                     88: * require.user: Set to 'root' to mark the test case as root-specific.  It is
                     89:   nice not to abuse this; see puffs and rump.
                     90: 
                     91: * use.fs: Set to 'true' if the test case creates temporary files in the "current
                     92:   directory".  Otherwise the atf runtime will isolate the test case in such a
                     93:   way to forbid this, which will misteriously make your test to fail.
                     94: 
1.5     ! jmmv       95: ## The body
1.3       jmmv       96: 
                     97: The *body* is the actual meat of the test case.  This is just a regular function
                     98: that executes any code you want and calls special atf functions to report
                     99: failures; see below.
                    100: 
                    101: In particular, be aware that the atf run-time **isolates** the execution of
                    102: every test case to prevent side-effects (such as temporary file leftovers,
                    103: in-memory data corruption, etc.).  In particular:
                    104: 
                    105: * A test case is **always executed as a subprocess** that is separate from the
                    106:   head and the cleanup.
                    107: 
                    108: * The current working directory of a test case is changed to a temporary
                    109:   location that gets cleaned up later on automatically.  (Set the use.fs
                    110:   property to true in the head if you need to write to this temporary
                    111:   directory.)
                    112: 
                    113: * The environment of the test case is "sanitized" to get rid of variables that
                    114:   can cause side-effects; e.g. LC_ALL, TZ, etc.
                    115: 
1.5     ! jmmv      116: # Installation of test programs: the why and the where
1.2       jmmv      117: 
                    118: Test programs get installed into the /usr/tests/ hierarchy.  The main reason for
                    119: doing that is to allow *any* user to test his system and to be able to convince
                    120: himself that everything is working correctly.
                    121: 
                    122: Imagine that you install NetBSD-current on a public-facing machine that has some
                    123: particular hardware only supported in the bleeding-edge source tree.  In this
                    124: scenario, you, as the administrator, could just go into /usr/tests/, run the
                    125: tests and know immediately if everything is working correctly in your
                    126: software+hardware combination or not.  No need to rely on promises from the
                    127: vendor, no need to deal with a source tree, no need to have a compiler
                    128: installed...
                    129: 
                    130: So, that's the theory.  Now, how does this map to our source tree?
                    131: 
                    132: At the moment, the source test programs are located somewhere under src/tests/.
                    133: Say, for example, that you have the src/tests/bin/ls/ui_test.c source file.
                    134: This Makefile in src/tests/bin/ls/ will take this source file and generate a
                    135: ui_test binary.  The Makefile will also generate an Atffile.  Both files (the
                    136: ui_test binary and the Atffile) will later be installed to /usr/tests/bin/ls/
1.1       jmmv      137: 
1.5     ! jmmv      138: # Adding a new test
1.1       jmmv      139: 
                    140: To add a new *test case* to the source tree, look for any test program in
                    141: src/tests/ that can assimilate it.  If you find such a program, just add the
1.2       jmmv      142: test case to it: no other changes are required so your life is easy.  Otherwise,
                    143: you will have to create a new test program.
1.1       jmmv      144: 
                    145: To add a new *test program* to the source tree:
                    146: 
                    147: 1. Locate the appropriate subdirectory in which to put your test program.  It is
                    148: OK (and **expected**) to have multiple test programs into the same directory.
                    149: **Restrain yourself from creating one directory per test program.**
                    150: 
                    151: If the subdirectory exists:
                    152: 
                    153: 1. Choose a sane name for the test program; the name must not be so specific
                    154:    that it restricts the addition of future test cases into it.
                    155: 
                    156: 1. Create the test program source file using one of the templates below.
                    157:    E.g. src/tests/tutorial/sample_test.c.
                    158: 
                    159: 1. Add the new test program to the Makefile.
                    160: 
                    161: If the subdirectory does not exist:
                    162: 
                    163: 1. Do the same as above.
                    164: 
                    165: 1. Create the Makefile for the directory using the templates below.
                    166: 
                    167: 1. Edit the parent Makefile to recurse into the new subdirectory.
                    168: 
                    169: 1. Edit src/etc/mtree/NetBSD.base.dist to register the new subdirectory.  Your
                    170:    test will be installed under /usr/tests/.
                    171: 
                    172: 1. Edit src/distrib/sets/lists/tests/mi to register the new test program.  Do
                    173:    not forget to add .debug entries if your test program is a C/C++ binary.
                    174: 
1.5     ! jmmv      175: ## Makefile template
1.1       jmmv      176: 
1.5     ! jmmv      177:     # $NetBSD: atf.mdwn,v 1.4 2010/09/03 14:53:05 jmmv Exp $
1.1       jmmv      178: 
                    179:     .include <bsd.own.mk>
                    180: 
                    181:     # This must always be defined.
                    182:     TESTSDIR= ${TESTSBASE}/bin/ls
                    183: 
                    184:     # Define only the variables you actually need for the directory.
                    185:     TESTS_C+= c1_test c2_test  # Correspond to c1_test.c and c2_test.c.
                    186:     TESTS_SH+= sh1_test sh2_test  # Correspond to sh1_test.c and sh2_test.c
                    187: 
                    188:     # Define only if your tests need any data files.
                    189:     FILESDIR= ${TESTSDIR}
                    190:     FILES= testdata1.txt testdata2.bin  # Any necessary data files.
                    191: 
                    192:     .include <bsd.test.mk>
                    193: 
1.5     ! jmmv      194: ## Atffile template
1.2       jmmv      195: 
                    196: What is an Atffile?  An Atffile is the atf-run counterpart of a "Makefile".
                    197: Given that atf tests *do not rely on a toolchain*, they cannot use make(1) to
                    198: script their execution as the old tests in src/regress/ did.
                    199: 
                    200: The Atffiles, in general, just provide a list of test programs in a particular
                    201: directory and the list of the subdirectories to descend into.
                    202: 
                    203: Atffiles are automatically generated by bsd.test.mk, so in general you will not
                    204: have to deal with them.  However, if you have to provide one explicitly, they
                    205: follow the following format:
                    206: 
                    207:     Content-Type: application/X-atf-atffile; version="1"
                    208: 
                    209:     prop: test-suite = NetBSD
                    210: 
                    211:     tp: first_test
                    212:     tp: second_test
                    213:     tp-glob: optional_*_test
                    214:     tp: subdir1
                    215:     tp: subdir2
                    216: 
1.5     ! jmmv      217: # C test programs
1.1       jmmv      218: 
1.5     ! jmmv      219: ## Template
1.1       jmmv      220: 
1.2       jmmv      221: The following code snippet provides a C test program with two test cases:
                    222: 
1.1       jmmv      223:     #include <atf-c.h>
                    224: 
                    225:     ATF_TC(tc, my_test_case);
                    226:     ATF_TC_HEAD(tc, my_test_case)
                    227:     {
                    228:         atf_tc_set_md_var(tc, "descr", "This test case ensures that...");
                    229:     }
                    230:     ATF_TC_BODY(tc, my_test_case)
                    231:     {
                    232:         ATF_CHECK(returns_a_boolean()); /* Non-fatal test. */
                    233:         ATF_REQUIRE(returns_a_boolean()); /* Non-fatal test. */
                    234: 
                    235:         ATF_CHECK_EQ(4, 2 + 2); /* Non-fatal test. */
                    236:         ATF_REQUIRE_EQ(4, 2 + 2); /* Fatal test. */
                    237: 
                    238:         if (!condition)
                    239:             atf_tc_fail("Condition not met!"); /* Explicit failure. */
                    240:     }
                    241: 
1.2       jmmv      242:     ATF_TC_WITHOUT_HEAD(tc, another_test_case);
                    243:     ATF_TC_BODY(tc, another_test_case)
                    244:     {
                    245:         /* Do more tests here... */
                    246:     }
                    247: 
1.1       jmmv      248:     ATF_TP_ADD_TCS(tp)
                    249:     {
                    250:         ATF_TP_ADD_TC(tp, my_test_case);
1.2       jmmv      251:         ATF_TP_ADD_TC(tp, another_test_case);
1.1       jmmv      252:     }
                    253: 
1.2       jmmv      254: This program needs to be linked against libatf-c as described below.  Once
                    255: linked, the program automatically gains a main() method that provides a
                    256: consistent user interface to all test programs.  You are simply not inteded to
                    257: provide your own main method, nor to deal with the command-line of the
                    258: invocation.
                    259: 
1.5     ! jmmv      260: ## How to build
1.1       jmmv      261: 
                    262: To build a C test program, append the name of the test program (without the .c
                    263: extension) to the TESTS_C variable in the Makefile.
                    264: 
                    265: For example:
                    266: 
                    267:     .include <bsd.own.mk>
                    268: 
                    269:     TESTSDIR= ${TESTSBASE}/bin/ls
                    270: 
                    271:     TESTS_C+= fs_test ui_test
                    272: 
                    273:     .include <bsd.test.mk>
                    274: 
1.5     ! jmmv      275: ## Common functions
1.3       jmmv      276: 
                    277: The following functions are commonly used from within a test case body:
                    278: 
                    279: * ATF_CHECK(boolean_expression): Checks if the given boolean expression is true
                    280:   and, if not, records a failure for the test case but *execution continues*.
                    281:   Using ATF_REQUIRE aborts execution immediately after a failure.
                    282: 
                    283: * ATF_CHECK_EQ(expected_expression, actual_expression): Checks if the two
                    284:   expressions match and, if not, records a failure.  Similarly, ATF_REQUIRE_EQ
                    285:   aborts immediately if the check fails.
                    286: 
                    287: * ATF_CHECK_STREQ(expected_string, actual_string): Same as ATF_CHECK_EQ but
                    288:   performs string comparisons with strcmp.
                    289: 
                    290: * atf_tc_skip(const char *format, ...): Marks the test case as skipped with the
                    291:   provided reason and exits.
                    292: 
                    293: * atf_tc_fail(const char *format, ...): Marks the test case as failed with the
                    294:   provided reason and exits.
                    295: 
                    296: * atf_tc_pass(void): Explicitly marks the test case as passed.  This is
                    297:   *implied* when the test case function ends, so you should not use this in
                    298:   general.
                    299: 
                    300: * atf_expect_fail(const char *format, ...): Tells the atf runtime that the code
                    301:   following this call is expected to raise one or more failures (be it with
                    302:   atf_tc_fail, ATF_CHECK_*, etc.).  Use this to mark a block of code that is
                    303:   known to be broken (e.g. a test that reproduces a known bug).  Use the string
                    304:   parameter to provide an explanation about why the code is broken; if possible,
                    305:   provide a PR number.  Lastly, to terminate the "expected failure" code block
                    306:   and reset the runtime to the default functionality, use the atf_expect_pass()
                    307:   function.
                    308: 
                    309: * atf_expect_death(const char *format, ...): Same as atf_expect_fail but expects
                    310:   an abrupt termination of the test case, be it due to a call to exit() or to
                    311:   the reception of a signal.
                    312: 
                    313: * atf_expect_exit(int exitcode, const char *fomat, ...): Same as atf_expect_fail
                    314:   but expects the test case to exit with a specific exitcode.  Provide -1 to
                    315:   indicate any exit code.
                    316: 
                    317: * atf_expect_signal(int signo, const char *fomat, ...): Same as atf_expect_fail
                    318:   but expects the test case to receive a specific signal.  Provide -1 to
                    319:   indicate any signal.
                    320: 
                    321: * atf_expect_timeout(const char *reason, ...): Same as atf_expect_fail but
                    322:   expects the test case to get stuck and time out.
                    323: 
1.5     ! jmmv      324: # Shell test programs
1.1       jmmv      325: 
1.5     ! jmmv      326: ## Template
1.1       jmmv      327: 
1.2       jmmv      328: The following code snippet provides a shell test program with two test cases:
                    329: 
1.1       jmmv      330:     atf_test_case my_test_case
                    331:     my_test_case_head() {
                    332:         atf_set "descr" "This test case ensures that..."
                    333:     }
                    334:     my_test_case_body() {
                    335:         touch file1 file2
                    336: 
                    337:         cat >expout <<EOF
                    338:     file1
                    339:     file2
                    340:     EOF
                    341:         atf_check -s eq:0 -o file:expout -e empty 'ls'
                    342: 
                    343:         atf_check_equal 4 $((2 + 2))
                    344: 
                    345:         if [ 'a' != 'b' ]; then
                    346:             atf_fail "Condition not met!"  # Explicit failure.
                    347:         fi
                    348:     }
                    349: 
1.2       jmmv      350:     atf_test_case another_test_case
                    351:     another_test_case_body() {
                    352:         # Do more tests...
                    353:     }
                    354: 
1.1       jmmv      355:     atf_init_test_cases() {
                    356:         atf_add_test_case my_test_case
1.2       jmmv      357:         atf_add_test_case another_test_case
1.1       jmmv      358:     }
                    359: 
1.2       jmmv      360: This program needs to be be executed with the atf-sh(1) interpreter as described
                    361: below.  The program automatically gains an entry point that provides a
                    362: consistent user interface to all test programs.  You are simply not inteded to
                    363: provide your own "main method", nor to deal with the command-line of the
                    364: invocation.
                    365: 
1.5     ! jmmv      366: ## How to build
1.1       jmmv      367: 
                    368: To build a shell test program, append the name of the test program (without the
                    369: .sh extension) to the TESTS_SH variable in the Makefile.
                    370: 
                    371: For example:
                    372: 
                    373:     .include <bsd.own.mk>
                    374: 
                    375:     TESTSDIR= ${TESTSBASE}/bin/ls
                    376: 
                    377:     TESTS_SH+= integration_test something_else_test
                    378: 
                    379:     .include <bsd.test.mk>
                    380: 
                    381: If you want to run the test program yourself, you should know that shell-based
                    382: test programs are processed with the atf-sh interpreter.  atf-sh is just a thin
                    383: wrapper over /bin/sh that loads the shared atf code and then delegates execution
                    384: to your source file.
                    385: 
1.5     ! jmmv      386: ## Common functions
1.3       jmmv      387: 
                    388: The following functions are commonly used from within a test case body:
                    389: 
                    390: * atf_check: This is probably the most useful function for shell-based tests.
                    391:   It may need some experience to get it right, but it allows, in one line, to
                    392:   check the execution of a command.  Where check means: validate exit code,
                    393:   stdout and stderr.  This is just a wrapper over atf-check, so please refer to
                    394:   [atf-check(1)](http://netbsd.gw.com/cgi-bin/man-cgi?atf-check++NetBSD-current)
                    395:   for more details.
                    396: 
                    397: * atf_check_equal value1 value2: Check that the two values are equal and, if
                    398:   not, abort execution.
                    399: 
                    400: * atf_expect_*: Same as their C counterparts; see above.
                    401: 
                    402: * atf_fail reason: Explicitly marks the test case as failed and aborts it.
                    403: 
                    404: * atf_skip reason: Explicitly marks the test case as skipped and exits.
                    405: 
                    406: * atf_pass: Explicitly markts the test case as passed and exits.
                    407: 
                    408: * atf_get_srcdir: Prints the path to the directory where the test case lives.
                    409:   Use as $(atf_get_srcdir)/my-static-data-file.
                    410: 
1.5     ! jmmv      411: # FAQ
1.1       jmmv      412: 
1.5     ! jmmv      413: ## How do I atfify a plain test program?
1.1       jmmv      414: 
                    415: Let's suppose you have a program to exercise a particular piece of code.
                    416: Conceptually this implements a test but it does not use atf at all.  For
                    417: example:
                    418: 
                    419:     #include <err.h>
                    420:     #include <stdio.h>
                    421:     #include <stdlib.h>
                    422:     #include <string.h>
                    423: 
                    424:     /* This test program exercises the snprintf function. */
                    425: 
                    426:     int main(void)
                    427:     {
                    428:         char buf[1024];
                    429: 
                    430:         printf("Testing integers");
                    431:         snprintf(buf, sizeof(buf), "%d", 3);
                    432:         if (strcmp(buf, "3") != 0)
                    433:             errx(EXIT_FAILURE, "%d failed");
                    434:         snprintf(buf, sizeof(buf), "a %d b", 5);
                    435:         if (strcmp(buf, "a 5 b") != 0)
                    436:             errx(EXIT_FAILURE, "%d failed");
                    437: 
                    438:         printf("Testing strings");
                    439:         snprintf(buf, sizeof(buf), "%s", "foo");
                    440:         if (strcmp(buf, "foo") != 0)
                    441:             errx(EXIT_FAILURE, "%s failed");
                    442:         snprintf(buf, sizeof(buf), "a %s b", "bar");
                    443:         if (strcmp(buf, "a bar b") != 0)
                    444:             errx(EXIT_FAILURE, "%s failed");
                    445: 
                    446:         return EXIT_SUCCESS;
                    447:     }
                    448: 
                    449: To convert this program into an atf test program, use the template above and
                    450: keep this in mind:
                    451: 
                    452: * Split the whole main function into separate test cases.  In this scenario, the
                    453:   calls to printf(3) delimit a good granularity for the test cases: one for the
                    454:   integer formatter, one for the string formatter, etc.
                    455: 
                    456: * Use the ATF_CHECK* and/or atf_tc_fail functions to do the comparisons and
                    457:   report errors.  errx should not be used.
                    458: 
                    459: The result would look like:
                    460: 
                    461:     #include <atf-c.h>
                    462:     #include <stdio.h>
                    463: 
                    464:     ATF_TC(tc, integer_formatter);
                    465:     ATF_TC_HEAD(tc, integer_formatter)
                    466:     {
                    467:         atf_tc_set_md_var(tc, "descr", "Validates the %d formatter");
                    468:     }
                    469:     ATF_TC_BODY(tc, integer_formatter)
                    470:     {
                    471:         char buf[1024];
                    472: 
                    473:         snprintf(buf, sizeof(1024), "%d", 3);
                    474:         ATF_CHECK_STREQ("3", buf);
                    475: 
                    476:         snprintf(buf, sizeof(1024), "a %d b", 5);
                    477:         ATF_CHECK_STREQ("a 5 b", buf);
                    478:     }
                    479: 
                    480:     ATF_TC(tc, string_formatter);
                    481:     ATF_TC_HEAD(tc, string_formatter)
                    482:     {
                    483:         atf_tc_set_md_var(tc, "descr", "Validates the %s formatter");
                    484:     }
                    485:     ATF_TC_BODY(tc, string_formatter)
                    486:     {
                    487:         char buf[1024];
                    488: 
                    489:         snprintf(buf, sizeof(1024), "%s", "foo");
                    490:         ATF_CHECK_STREQ("foo", buf);
                    491: 
                    492:         snprintf(buf, sizeof(1024), "a %s b", "bar");
                    493:         ATF_CHECK_STREQ("a bar b", buf);
                    494:     }
                    495: 
                    496:     ATF_TP_ADD_TCS(tp)
                    497:     {
                    498:         ATF_TP_ADD_TC(tp, integer_formatter);
                    499:         ATF_TP_ADD_TC(tp, string_formatter);
                    500:     }
                    501: 
                    502: Which can later be invoked as any of:
                    503: 
                    504:     $ ./snprintf_test integer_formatter
                    505:     $ ./snprintf_test string_formatter
                    506:     $ atf-run snprintf_test | atf-report
                    507: 
1.5     ! jmmv      508: ## How do I write a test case for an unfixed PR?
1.3       jmmv      509: 
                    510: Use the "expectations" mechanism to define part of the test case as faulty,
                    511: crashy, etc.  For example, suppose we have PR 1 that reports a condition in
                    512: which snprintf() does the wrong formatting when using %s, and PR 2 that mentions
                    513: that another snprintf() call using %d with number 5 causes a segfault.  We could
                    514: do:
                    515: 
                    516:     #include <atf-c.h>
                    517:     #include <signal.h>
                    518:     #include <stdio.h>
                    519: 
                    520:     ATF_TC_WITHOUT_HEAD(tc, integer_formatter);
                    521:     ATF_TC_BODY(tc, integer_formatter)
                    522:     {
                    523:         char buf[1024];
                    524: 
                    525:         snprintf(buf, sizeof(buf), "Hello %d\n", 1);
                    526:         ATF_CHECK_STREQ("Hello 1", buf);
                    527: 
                    528:         atf_tc_expect_signal(SIGSEGV, "PR 2: %%d with 5 causes a crash");
                    529:         snprintf(buf, sizeof(buf), "Hello %d\n", 5);
                    530:         atf_tc_expect_pass();
                    531:         ATF_CHECK_STREQ("Hello 5", buf);
                    532:     }
                    533: 
                    534:     ATF_TC_WITHOUT_HEAD(tc, string_formatter);
                    535:     ATF_TC_BODY(tc, string_formatter)
                    536:     {
                    537:         char buf[1024];
                    538: 
                    539:         snprintf(buf, sizeof(buf), "Hello %s\n", "world!");
                    540:         atf_tc_expect_failure("PR 1: %%s does not work");
                    541:         ATF_CHECK_STREQ("Hello world!", buf);
                    542:         atf_tc_expect_pass();
                    543:     }
                    544: 
                    545:     ATF_TP_ADD_TCS(tp)
                    546:     {
                    547:         ATF_TP_ADD_TC(tp, integer_formatter);
                    548:         ATF_TP_ADD_TC(tp, string_formatter);
                    549:     }
                    550: 
1.5     ! jmmv      551: ## Do I need to remove temporary files?
1.1       jmmv      552: 
                    553: No.  atf-run does this automatically for you, because it runs every test program
                    554: in its own temporary subdirectory.

CVSweb for NetBSD wikisrc <wikimaster@NetBSD.org> software: FreeBSD-CVSweb