Having done the initial work to get most of FreeBSD's regression testing
infrastructure producing Test::Harness TAP compatible output, I've started
putting together a C library that makes it easier to write tests in C.

This is a few hours work at the moment, but it's functional, and I'd
appreciate comments.  The code's at:

    http://jc.ngo.org.uk/trac-bin/trac.cgi/browser/nik/libtap/trunk/src/

I realise that's not the easiest way to download it, I'll make a tarball
available soon.  On the plus side, it's only a handful of files...

There are still a few things to do before it's a 1.0 candidate, listed at

    http://jc.ngo.org.uk/trac-bin/trac.cgi/report/9

Here's the README:

Usage:

    #include "tap.h", and link against libtap.so

Start by calling one of the plan_* functions:

    plan_no_plan()               /* you have no test plan, or */
    plan_skip_all("Because...")  /* all tests will be skipped, or */
    plan_tests(42);              /* you will run 42 tests */

Then you have one of ok() or ok2() at your disposal.  ok()'s first parameter
is the code to test.  The second parameter is the test name.  This is a 
printf()like format string, and the third and subsequent parameters should
fill out any values in the string.

    ok(a_func() == 0, "test name");
    ok(some_func(i), "some_func(%d)", i);

ok2() is for situations where the code to test is sufficiently 
self-documenting that you don't need to provide a test name.

    ok2(code to test); /* test name is automatically the same as the code */

E.g.,

    ok(1 == 1, "1 equals one"); /* PRINT: ok 1 - 1 equals 1 */
    ok2(1 == 2);                /* PRINT: not ok 2 - 1 == 2 */

Sets of tests can be skipped.  Ordinarily you would do this because
the test can't be run in this particular testing environment.

For example, suppose some tests should be run as root.  If the test is
not being run as root then the tests should be skipped.  In this 
implementation, skipped tests are flagged as being ok, with a special
message indicating that they were skipped.

    skip(n, msg, ...);

will produce output for 'n' lines of skipped tests.  The output message
is 'msg', and is printf()like.  It is your responsibility to ensure that
'n' is correct for the number of tests to skip.

This is normally implemented with a "do { ... } while(0);" loop, with a 
"continue;" immediately after the skip() call.  This ensures that there
are no additional side effects from the skipped tests.

    do {
        if(getuid() != 0) {
            skip(1, "Test only makes sense as root");
            continue;
        }

        ok(do_something_as_root() == 0, "do_something_as_root() worked");
    } while(0);

Two macros, SKIP_START and SKIP_END can handle some of this for you.  The
above example could be re-written:

    SKIP_START(getuid() != 0, 1, "Test only makes sense as root");

    ok(do_something_as_root() == 0, "do_something_as_root() worked");

    SKIP_END;

You also have diag(), which takes a printf() style format string and related
arguments, and sends the output to stderr as a test comment.  diag() adds
the necessary trailing "\n" for you.

    diag("Expected return code 0, got return code %d", rcode);

Finally, there's exit_status(), which returns an int suitable for use
when return'ing from main(), or calling exit().  You should always do one
of:

    return exit_status();
    exit(exit_status());

As appropriate.
-- 
1        1         2         3         4         5         6         7    7
         0         0         0         0         0         0         0    5
                                                    -- The 75 column-ometer
Not speaking on behalf of my employer.                              </bush>

Reply via email to