tests: Start using the upstream C TAP harness
authorSimon Wilkinson <sxw@your-file-system.com>
Mon, 7 May 2012 20:52:16 +0000 (21:52 +0100)
committerDerrick Brashear <shadow@dementix.org>
Fri, 11 May 2012 23:36:44 +0000 (16:36 -0700)
Instead of bundling our own copies of Russ's C TAP Harness, start using
source pulled from his git repository using the src/external import
mechanism. Note that we are not currently building the floating
point (is_double) portion of the harness.

In the process of doing so, we also upgrade our test harness to the latest
upstream version, 1.11. This is somewhat problematic, as there have been
some significant code changes since the version bundled with OpenAFS.
Work around these by
   *) Referencing the basic.h header as <tests/tap/basic.h>, rather than
      just <tap/basic.h>, to match the new upstream layout
   *) Changing the include path so that the tests/ directory can be
      found within it.

Change-Id: I63efbb30248165e5729005b0a791e7eb7afb051d
Reviewed-on: http://gerrit.openafs.org/7374
Tested-by: BuildBot <buildbot@rampaginggeek.com>
Reviewed-by: Russ Allbery <rra@stanford.edu>
Reviewed-by: Derrick Brashear <shadow@dementix.org>

27 files changed:
tests/HOWTO [deleted file]
tests/Makefile.in
tests/README
tests/auth/Makefile.in
tests/auth/authcon-t.c
tests/auth/keys-t.c
tests/auth/realms-t.c
tests/auth/superuser-t.c
tests/cmd/Makefile.in
tests/cmd/command-t.c
tests/opr/Makefile.in
tests/opr/jhash-t.c
tests/opr/queues-t.c
tests/opr/rbtree-t.c
tests/runtests.c [deleted file]
tests/rx/Makefile.in
tests/rx/event-t.c
tests/tap/.gitignore [new file with mode: 0644]
tests/tap/Makefile.in
tests/tap/basic.c [deleted file]
tests/tap/basic.h [deleted file]
tests/tap/libtap.sh [deleted file]
tests/util/Makefile.in
tests/util/exec-alt-t.c
tests/util/ktime-t.c
tests/volser/Makefile.in
tests/volser/vos-t.c

diff --git a/tests/HOWTO b/tests/HOWTO
deleted file mode 100644 (file)
index 5d38748..0000000
+++ /dev/null
@@ -1,248 +0,0 @@
-                            Writing TAP Tests
-
-Introduction
-
-    This is a guide for users of the C TAP Harness package or similar
-    TAP-based test harnesses explaining how to write tests.  If your
-    package uses C TAP Harness as the test suite driver, you may want to
-    copy this document to an appropriate file name in your test suite as
-    documentation for contributors.
-
-About TAP
-
-    TAP is the Test Anything Protocol, a protocol for communication
-    between test cases and a test harness.  This is the protocol used by
-    Perl for its internal test suite and for nearly all Perl modules,
-    since it's the format used by the build tools for Perl modules to run
-    tests and report their results.
-
-    A TAP-based test suite works with a somewhat different set of
-    assumptions than an xUnit test suite.  In TAP, each test case is a
-    separate program.  That program, when run, must produce output in the
-    following format:
-
-        1..4
-        ok 1 - the first test
-        ok 2
-        # a diagnostic, ignored by the harness
-        not ok 3 - a failing test
-        ok 4 # skip a skipped test
-
-    The output should all go to standard output.  The first line specifies
-    the number of tests to be run, and then each test produces output that
-    looks like either "ok <n>" or "not ok <n>" depending on whether the
-    test succeeded or failed.  Additional information about the test can
-    be provided after the "ok <n>" or "not ok <n>", but is optional.
-    Additional diagnostics and information can be provided in lines
-    beginning with a "#".
-
-    Processing directives are supported after the "ok <n>" or "not ok <n>"
-    and start with a "#".  The main one of interest is "# skip" which says
-    that the test was skipped rather than successful and optionally gives
-    the reason.  Also supported is "# todo", which normally annotates a
-    failing test and indicates that test is expected to fail, optionally
-    providing a reason for why.
-
-    There are three more special cases.  First, the initial line stating
-    the number of tests to run, called the plan, may appear at the end of
-    the output instead of the beginning.  This can be useful if the number
-    of tests to run is not known in advance.  Second, a plan in the form:
-
-        1..0 # skip entire test case skipped
-
-    can be given instead, which indicates that this entire test case has
-    been skipped (generally because it depends on facilities or optional
-    configuration which is not present).  Finally, if the test case
-    encounters a fatal error, it should print the text:
-
-        Bail out!
-
-    on standard output, optionally followed by an error message, and then
-    exit.  This tells the harness that the test aborted unexpectedly.
-
-    The exit status of a successful test case should always be 0.  The
-    harness will report the test as "dubious" if all the tests appeared to
-    succeed but it exited with a non-zero status.
-
-Writing TAP Tests
-
-  Environment
-
-    One of the special features of C TAP Harness is the environment that
-    it sets up for your test cases.  If your test program is called under
-    the runtests driver, the environment variables SOURCE and BUILD will
-    be set to the top of the test directory in the source tree and the top
-    of the build tree, respectively.  You can use those environment
-    variables to locate additional test data, programs and libraries built
-    as part of your software build, and other supporting information
-    needed by tests.
-
-    The C and shell TAP libraries support a test_file_path() function,
-    which looks for a file under the build tree and then under the source
-    tree, using the BUILD and SOURCE environment variables, and return the
-    full path to the file.  This can be used to locate supporting data
-    files.
-
-  Perl
-
-    Since TAP is the native test framework for Perl, writing TAP tests in
-    Perl is very easy and extremely well-supported.  If you've never
-    written tests in Perl before, start by reading the documentation for
-    Test::Tutorial and Test::Simple, which walks you through the basics,
-    including the TAP output syntax.  Then, the best Perl module to use
-    for serious testing is Test::More, which provides a lot of additional
-    functions over Test::Simple including support for skipping tests,
-    bailing out, and not planning tests in advance.  See the documentation
-    of Test::More for all the details and lots of examples.
-
-    C TAP Harness can run Perl test scripts directly and interpret the
-    results correctly, and similarly the Perl Test::Harness module and
-    prove command can run TAP tests written in other languages using, for
-    example, the TAP library that comes with C TAP Harness.  You can, if
-    you wish, use the library that comes with C TAP Harness but use prove
-    instead of runtests for running the test suite.
-
-  C
-
-    C TAP Harness provides a basic TAP library that takes away most of the
-    pain of writing TAP test cases in C.  A C test case should start with
-    a call to plan(), passing in the number of tests to run.  Then, each
-    test should use is_int(), is_string(), is_double(), or is_hex() as
-    appropriate to compare expected and seen values, or ok() to do a
-    simpler boolean test.  The is_*() functions take expected and seen
-    values and then a printf-style format string explaining the test
-    (which may be NULL).  ok() takes a boolean and then the printf-style
-    string.
-
-    Here's a complete example test program that uses the C TAP library:
-
-        #include <stddef.h>
-        #include <tap/basic.h>
-
-        int
-        main(void)
-        {
-            plan(4);
-
-            ok(1, "the first test");
-            is_int(42, 42, NULL);
-            diag("a diagnostic, ignored by the harness");
-            ok(0, "a failing test");
-            skip("a skipped test");
-
-            return 0;
-        }
-
-    This test program produces the output shown above in the section on
-    TAP and demonstrates most of the functions.  The other functions of
-    interest are sysdiag() (like diag() but adds strerror() results),
-    bail() and sysbail() for fatal errors, skip_block() to skip a whole
-    block of tests, and skip_all() which is called instead of plan() to
-    skip an entire test case.
-
-    The C TAP library also provides plan_lazy(), which can be called
-    instead of plan().  If plan_lazy() is called, the library will keep
-    track of how many test results are reported and will print out the
-    plan at the end of execution of the program.  This should normally be
-    avoided since the test may appear to be successful even if it exits
-    prematurely, but it can make writing tests easier in some
-    circumstances.
-
-    Complete API documentation for the basic C TAP library that comes with
-    C TAP Harness is available at:
-
-        <http://www.eyrie.org/~eagle/software/c-tap-harness/>
-
-    It's common to need additional test functions and utility functions
-    for your C tests, particularly if you have to set up and tear down a
-    test environment for your test programs, and it's useful to have them
-    all in the libtap library so that you only have to link your test
-    programs with one library.  Rather than editing tap/basic.c and
-    tap/basic.h to add those additional functions, add additional *.c and
-    *.h files into the tap directory with the function implementations and
-    prototypes, and then add those additional objects to the library.
-    That way, you can update tap/basic.c and tap/basic.h from subsequent
-    releases of C TAP Harness without having to merge changes with your
-    own code.
-
-    Libraries of additional useful TAP test functions are available in
-    rra-c-util at:
-
-        <http://www.eyrie.org/~eagle/software/rra-c-util/>
-
-    Some of the code there is particularly useful when testing programs
-    that require Kerberos keys.
-
-    If you implement new test functions that compare an expected and seen
-    value, it's best to name them is_<something> and take the expected
-    value, the seen value, and then a printf-style format string and
-    possible arguments to match the calling convention of the functions
-    provided by C TAP Harness.
-
-  Shell
-
-    C TAP Harness provides a library of shell functions to make it easier
-    to write TAP tests in shell.  That library includes much of the same
-    functionality as the C TAP library, but takes its parameters in a
-    somewhat different order to make better use of shell features.
-
-    The libtap.sh file should be installed in a directory named tap in
-    your test suite area.  It can then be loaded by tests written in shell
-    using the environment set up by runtests with:
-
-        . "$SOURCE"/tap/libtap.sh
-
-    Here is a complete test case written in shell which produces the same
-    output as the TAP sample above:
-
-        #!/bin/sh
-
-        . "$SOURCE"/tap/libtap.sh
-        cd "$BUILD"
-
-        plan 4
-        ok 'the first test' true
-        ok '' [ 42 -eq 42 ]
-        diag a diagnostic, ignored by the harness
-        ok '' false
-        skip 'a skipped test'
-
-    The shell framework doesn't provide the is_* functions, so you'll use
-    the ok function more.  It takes a string describing the text and then
-    treats all of its remaining arguments as a condition, evaluated the
-    same way as the arguments to the "if" statement.  If that condition
-    evaluates to true, the test passes; otherwise, the test fails.
-
-    The plan, plan_lazy, diag, and bail functions work the same as with
-    the C library.  skip takes a string and skips the next test with that
-    explanation.  skip_block takes a count and a string and skips that
-    many tests with that explanation.  skip_all takes an optional reason
-    and skips the entire test case.
-
-    Since it's common for shell programs to want to test the output of
-    commands, there's an additional function ok_program provided by the
-    shell test library.  It takes the test description string, the
-    expected exit status, the expected program output, and then treats the
-    rest of its arguments as the program to run.  That program is run with
-    standard error and standard output combined, and then its exit status
-    and output are tested against the provided values.
-
-    A utility function, strip_colon_error, is provided that runs the
-    command given as its arguments and strips text following a colon and a
-    space from the output (unless there is no whitespace on the line
-    before the colon and the space, normally indicating a prefix of the
-    program name).  This function can be used to wrap commands that are
-    expected to fail with output that has a system- or locale-specific
-    error message appended, such as the output of strerror().
-
-License
-
-    This file is part of the documentation of C TAP Harness, which can be
-    found at <http://www.eyrie.org/~eagle/software/c-tap-harness/>.
-
-    Copyright 2010 Russ Allbery <rra@stanford.edu>
-
-    Copying and distribution of this file, with or without modification,
-    are permitted in any medium without royalty provided the copyright
-    notice and this notice are preserved.  This file is offered as-is,
-    without any warranty.
index cb0ad70..d6d221d 100644 (file)
@@ -1,6 +1,6 @@
 # Build rules for the OpenAFS test suite.
 
-srcdir=@srcdir@
+srcdir=@srcdir@/../src/external/c-tap-harness/tests
 abs_top_srcdir=@abs_top_srcdir@
 abs_top_builddir=@abs_top_builddir@
 include @TOP_OBJDIR@/src/config/Makefile.config
@@ -17,6 +17,9 @@ all: runtests
 runtests: runtests.o
        $(AFS_LDRULE) runtests.o
 
+runtests.o: $(srcdir)/runtests.c
+       $(AFS_CCRULE) $(srcdir)/runtests.c
+
 check test tests: runtests
        @for A in $(SUBDIRS); do cd $$A && $(MAKE) $@ && cd .. || exit 1; done
        ./libwrap @TOP_OBJDIR@/lib \
index 2b43b37..fbddf46 100644 (file)
@@ -3,7 +3,7 @@ intended to become the primary OpenAFS test suite.  The tests in this
 directory are run when "make check" is run at the top level of the OpenAFS
 tree.
 
-runtests.c is the test harness, and TESTS is the list of tests that it
+runtests is the test harness, and TESTS is the list of tests that it
 will run.  If you add a new test, add it to TESTS as well.  All tests must
 be executables (possibly shell scripts or Perl scripts) that end in either
 ".t" or "-t", but should be listed in TESTS without that suffix.
@@ -19,8 +19,9 @@ level.   The Makefile.in in this directory will also need to be modified
 to recurse into any new directories.  See util/Makefile.in for an example
 of how to write a Makefile.in for a new test directory.
 
-runtests.c, tap/basic.c, tap/basic.h, tap/libtap.sh, and HOWTO come from
-the C TAP Harness distribution at:
+The files comprising the test harness are sourced from the C TAP Harness 
+distribution using the src/external mechanism. The upstream site for that
+distribution is at:
 
     http://www.eyrie.org/~eagle/software/c-tap-harness/
 
@@ -28,5 +29,9 @@ but feel free to propose modifications directly through OpenAFS Gerrit.
 Russ Allbery will take care of merging modifications upstream.  However,
 OpenAFS-specific modifications should not be made to those files.  To add
 additional OpenAFS-specific code to the TAP library, add additional *.c
-and *.h (or *.sh) files to the tap directory rather than modifying
-basic.c, basic.h, or libtap.sh.
+and *.h (or *.sh) files to the tests/tap directory rather than modifying files
+in src/external.
+
+More information can be found in the HOWTO contained in
+src/external/c-tap-harness/HOWTO
+
index 82fcc34..2e9e3e3 100644 (file)
@@ -6,7 +6,7 @@ include @TOP_OBJDIR@/src/config/Makefile.pthread
 
 TESTS = authcon-t superuser-t keys-t realms-t
 
-MODULE_CFLAGS=-I$(srcdir)/.. -I$(srcdir)/../common/
+MODULE_CFLAGS=-I$(srcdir)/../.. -I$(srcdir)/../common/
 
 all check test tests: $(TESTS)
 
index c9e968e..359b3a3 100644 (file)
@@ -36,7 +36,7 @@
 #include <rx/rxkad.h>
 #include <afs/cellconfig.h>
 
-#include <tap/basic.h>
+#include <tests/tap/basic.h>
 #include "common.h"
 
 int
index 19ab98a..2f08e08 100644 (file)
@@ -36,7 +36,7 @@
 #include <afs/afsutil.h>
 #include <rx/rxkad.h>
 
-#include <tap/basic.h>
+#include <tests/tap/basic.h>
 
 #include "test.h"
 #include "common.h"
index 6ab9b46..cdd15da 100644 (file)
@@ -16,7 +16,7 @@
 #include <rx/rxkad.h>
 #include <afs/cellconfig.h>
 
-#include <tap/basic.h>
+#include <tests/tap/basic.h>
 #include "common.h"
 
 extern int _afsconf_Touch(struct afsconf_dir *adir);
index a8ff0f5..bb7141e 100644 (file)
@@ -41,7 +41,7 @@
 #include <rx/rxkad.h>
 #include <rx/rx_identity.h>
 
-#include <tap/basic.h>
+#include <tests/tap/basic.h>
 
 #include "test.h"
 #include "common.h"
index a0c82f9..41b550f 100644 (file)
@@ -5,7 +5,7 @@ abs_top_builddir=@abs_top_builddir@
 include @TOP_OBJDIR@/src/config/Makefile.config
 include @TOP_OBJDIR@/src/config/Makefile.pthread
 
-MODULE_CFLAGS = -I$(srcdir)/..
+MODULE_CFLAGS = -I$(srcdir)/../..
 
 LIBS = ../tap/libtap.a \
        $(abs_top_builddir)/lib/libcmd.a \
index 3322e1b..8237f3f 100644 (file)
@@ -33,7 +33,7 @@
 
 #include <afs/cmd.h>
 
-#include <tap/basic.h>
+#include <tests/tap/basic.h>
 
 enum cmdOptions {
    copt_flag = 0,
index 6ff8b2e..2e9e867 100644 (file)
@@ -3,7 +3,7 @@ abs_top_builddir=@abs_top_builddir@
 include @TOP_OBJDIR@/src/config/Makefile.config
 include @TOP_OBJDIR@/src/config/Makefile.lwp
 
-MODULE_CFLAGS = -I$(srcdir)/..
+MODULE_CFLAGS = -I$(srcdir)/../..
 
 LIBS=../tap/libtap.a $(abs_top_builddir)/lib/libopr.a
 
index 4fa518f..80bdf70 100644 (file)
@@ -26,7 +26,7 @@
 #include <afs/param.h>
 
 #include <roken.h>
-#include <tap/basic.h>
+#include <tests/tap/basic.h>
 
 #include <opr/jhash.h>
 
index b370b94..257e519 100644 (file)
@@ -3,7 +3,7 @@
 
 #include <stdlib.h>
 
-#include <tap/basic.h>
+#include <tests/tap/basic.h>
 
 #include <opr/queue.h>
 
index e058e97..ed1f924 100644 (file)
@@ -4,7 +4,7 @@
 #include <stdlib.h>
 #include <stdio.h>
 
-#include <tap/basic.h>
+#include <tests/tap/basic.h>
 
 #include <afs/opr.h>
 #include <opr/rbtree.h>
diff --git a/tests/runtests.c b/tests/runtests.c
deleted file mode 100644 (file)
index 1bcf051..0000000
+++ /dev/null
@@ -1,1172 +0,0 @@
-/*
- * Run a set of tests, reporting results.
- *
- * Usage:
- *
- *      runtests [-b <build-dir>] [-s <source-dir>] <test-list>
- *      runtests -o [-b <build-dir>] [-s <source-dir>] <test>
- *
- * In the first case, expects a list of executables located in the given file,
- * one line per executable.  For each one, runs it as part of a test suite,
- * reporting results.  Test output should start with a line containing the
- * number of tests (numbered from 1 to this number), optionally preceded by
- * "1..", although that line may be given anywhere in the output.  Each
- * additional line should be in the following format:
- *
- *      ok <number>
- *      not ok <number>
- *      ok <number> # skip
- *      not ok <number> # todo
- *
- * where <number> is the number of the test.  An optional comment is permitted
- * after the number if preceded by whitespace.  ok indicates success, not ok
- * indicates failure.  "# skip" and "# todo" are a special cases of a comment,
- * and must start with exactly that formatting.  They indicate the test was
- * skipped for some reason (maybe because it doesn't apply to this platform)
- * or is testing something known to currently fail.  The text following either
- * "# skip" or "# todo" and whitespace is the reason.
- *
- * As a special case, the first line of the output may be in the form:
- *
- *      1..0 # skip some reason
- *
- * which indicates that this entire test case should be skipped and gives a
- * reason.
- *
- * Any other lines are ignored, although for compliance with the TAP protocol
- * all lines other than the ones in the above format should be sent to
- * standard error rather than standard output and start with #.
- *
- * This is a subset of TAP as documented in Test::Harness::TAP or
- * TAP::Parser::Grammar, which comes with Perl.
- *
- * If the -o option is given, instead run a single test and display all of its
- * output.  This is intended for use with failing tests so that the person
- * running the test suite can get more details about what failed.
- *
- * If built with the C preprocessor symbols SOURCE and BUILD defined, C TAP
- * Harness will export those values in the environment so that tests can find
- * the source and build directory and will look for tests under both
- * directories.  These paths can also be set with the -b and -s command-line
- * options, which will override anything set at build time.
- *
- * Any bug reports, bug fixes, and improvements are very much welcome and
- * should be sent to the e-mail address below.  This program is part of C TAP
- * Harness <http://www.eyrie.org/~eagle/software/c-tap-harness/>.
- *
- * Copyright 2000, 2001, 2004, 2006, 2007, 2008, 2009, 2010, 2011
- *     Russ Allbery <rra@stanford.edu>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
-*/
-
-/* Required for fdopen(), getopt(), and putenv(). */
-#ifndef _XOPEN_SOURCE
-# define _XOPEN_SOURCE 500
-#endif
-
-#include <ctype.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <strings.h>
-#include <sys/stat.h>
-#include <sys/time.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <time.h>
-#include <unistd.h>
-
-/* sys/time.h must be included before sys/resource.h on some platforms. */
-#include <sys/resource.h>
-
-/* AIX doesn't have WCOREDUMP. */
-#ifndef WCOREDUMP
-# define WCOREDUMP(status)      ((unsigned)(status) & 0x80)
-#endif
-
-/*
- * The source and build versions of the tests directory.  This is used to set
- * the SOURCE and BUILD environment variables and find test programs, if set.
- * Normally, this should be set as part of the build process to the test
- * subdirectories of $(abs_top_srcdir) and $(abs_top_builddir) respectively.
- */
-#ifndef SOURCE
-# define SOURCE NULL
-#endif
-#ifndef BUILD
-# define BUILD NULL
-#endif
-
-/* Test status codes. */
-enum test_status {
-    TEST_FAIL,
-    TEST_PASS,
-    TEST_SKIP,
-    TEST_INVALID
-};
-
-/* Indicates the state of our plan. */
-enum plan_status {
-    PLAN_INIT,                  /* Nothing seen yet. */
-    PLAN_FIRST,                 /* Plan seen before any tests. */
-    PLAN_PENDING,               /* Test seen and no plan yet. */
-    PLAN_FINAL                  /* Plan seen after some tests. */
-};
-
-/* Error exit statuses for test processes. */
-#define CHILDERR_DUP    100     /* Couldn't redirect stderr or stdout. */
-#define CHILDERR_EXEC   101     /* Couldn't exec child process. */
-#define CHILDERR_STDERR 102     /* Couldn't open stderr file. */
-
-/* Structure to hold data for a set of tests. */
-struct testset {
-    char *file;                 /* The file name of the test. */
-    char *path;                 /* The path to the test program. */
-    enum plan_status plan;      /* The status of our plan. */
-    unsigned long count;        /* Expected count of tests. */
-    unsigned long current;      /* The last seen test number. */
-    unsigned int length;        /* The length of the last status message. */
-    unsigned long passed;       /* Count of passing tests. */
-    unsigned long failed;       /* Count of failing lists. */
-    unsigned long skipped;      /* Count of skipped tests (passed). */
-    unsigned long allocated;    /* The size of the results table. */
-    enum test_status *results;  /* Table of results by test number. */
-    unsigned int aborted;       /* Whether the set as aborted. */
-    int reported;               /* Whether the results were reported. */
-    int status;                 /* The exit status of the test. */
-    unsigned int all_skipped;   /* Whether all tests were skipped. */
-    char *reason;               /* Why all tests were skipped. */
-};
-
-/* Structure to hold a linked list of test sets. */
-struct testlist {
-    struct testset *ts;
-    struct testlist *next;
-};
-
-/*
- * Usage message.  Should be used as a printf format with two arguments: the
- * path to runtests, given twice.
- */
-static const char usage_message[] = "\
-Usage: %s [-b <build-dir>] [-s <source-dir>] <test-list>\n\
-       %s -o [-b <build-dir>] [-s <source-dir>] <test>\n\
-\n\
-Options:\n\
-    -b <build-dir>      Set the build directory to <build-dir>\n\
-    -o                  Run a single test rather than a list of tests\n\
-    -s <source-dir>     Set the source directory to <source-dir>\n\
-\n\
-runtests normally runs each test listed in a file whose path is given as\n\
-its command-line argument.  With the -o option, it instead runs a single\n\
-test and shows its complete output.\n";
-
-/*
- * Header used for test output.  %s is replaced by the file name of the list
- * of tests.
- */
-static const char banner[] = "\n\
-Running all tests listed in %s.  If any tests fail, run the failing\n\
-test program with runtests -o to see more details.\n\n";
-
-/* Header for reports of failed tests. */
-static const char header[] = "\n\
-Failed Set                 Fail/Total (%) Skip Stat  Failing Tests\n\
--------------------------- -------------- ---- ----  ------------------------";
-
-/* Include the file name and line number in malloc failures. */
-#define xmalloc(size)     x_malloc((size), __FILE__, __LINE__)
-#define xrealloc(p, size) x_realloc((p), (size), __FILE__, __LINE__)
-#define xstrdup(p)        x_strdup((p), __FILE__, __LINE__)
-
-
-/*
- * Report a fatal error, including the results of strerror, and exit.
- */
-static void
-sysdie(const char *format, ...)
-{
-    int oerrno;
-    va_list args;
-
-    oerrno = errno;
-    fflush(stdout);
-    fprintf(stderr, "runtests: ");
-    va_start(args, format);
-    vfprintf(stderr, format, args);
-    va_end(args);
-    fprintf(stderr, ": %s\n", strerror(oerrno));
-    exit(1);
-}
-
-
-/*
- * Allocate memory, reporting a fatal error and exiting on failure.
- */
-static void *
-x_malloc(size_t size, const char *file, int line)
-{
-    void *p;
-
-    p = malloc(size);
-    if (p == NULL)
-        sysdie("failed to malloc %lu bytes at %s line %d",
-               (unsigned long) size, file, line);
-    return p;
-}
-
-
-/*
- * Reallocate memory, reporting a fatal error and exiting on failure.
- */
-static void *
-x_realloc(void *p, size_t size, const char *file, int line)
-{
-    p = realloc(p, size);
-    if (p == NULL)
-        sysdie("failed to realloc %lu bytes at %s line %d",
-               (unsigned long) size, file, line);
-    return p;
-}
-
-
-/*
- * Copy a string, reporting a fatal error and exiting on failure.
- */
-static char *
-x_strdup(const char *s, const char *file, int line)
-{
-    char *p;
-    size_t len;
-
-    len = strlen(s) + 1;
-    p = malloc(len);
-    if (p == NULL)
-        sysdie("failed to strdup %lu bytes at %s line %d",
-               (unsigned long) len, file, line);
-    memcpy(p, s, len);
-    return p;
-}
-
-
-/*
- * Given a struct timeval, return the number of seconds it represents as a
- * double.  Use difftime() to convert a time_t to a double.
- */
-static double
-tv_seconds(const struct timeval *tv)
-{
-    return difftime(tv->tv_sec, 0) + tv->tv_usec * 1e-6;
-}
-
-
-/*
- * Given two struct timevals, return the difference in seconds.
- */
-static double
-tv_diff(const struct timeval *tv1, const struct timeval *tv0)
-{
-    return tv_seconds(tv1) - tv_seconds(tv0);
-}
-
-
-/*
- * Given two struct timevals, return the sum in seconds as a double.
- */
-static double
-tv_sum(const struct timeval *tv1, const struct timeval *tv2)
-{
-    return tv_seconds(tv1) + tv_seconds(tv2);
-}
-
-
-/*
- * Given a pointer to a string, skip any leading whitespace and return a
- * pointer to the first non-whitespace character.
- */
-static const char *
-skip_whitespace(const char *p)
-{
-    while (isspace((unsigned char)(*p)))
-        p++;
-    return p;
-}
-
-
-/*
- * Start a program, connecting its stdout to a pipe on our end and its stderr
- * to /dev/null, and storing the file descriptor to read from in the two
- * argument.  Returns the PID of the new process.  Errors are fatal.
- */
-static pid_t
-test_start(const char *path, int *fd)
-{
-    int fds[2], errfd;
-    pid_t child;
-
-    if (pipe(fds) == -1) {
-        puts("ABORTED");
-        fflush(stdout);
-        sysdie("can't create pipe");
-    }
-    child = fork();
-    if (child == (pid_t) -1) {
-        puts("ABORTED");
-        fflush(stdout);
-        sysdie("can't fork");
-    } else if (child == 0) {
-        /* In child.  Set up our stdout and stderr. */
-        errfd = open("/dev/null", O_WRONLY);
-        if (errfd < 0)
-            _exit(CHILDERR_STDERR);
-        if (dup2(errfd, 2) == -1)
-            _exit(CHILDERR_DUP);
-        close(fds[0]);
-        if (dup2(fds[1], 1) == -1)
-            _exit(CHILDERR_DUP);
-
-        /* Now, exec our process. */
-        if (execl(path, path, (char *) 0) == -1)
-            _exit(CHILDERR_EXEC);
-    } else {
-        /* In parent.  Close the extra file descriptor. */
-        close(fds[1]);
-    }
-    *fd = fds[0];
-    return child;
-}
-
-
-/*
- * Back up over the output saying what test we were executing.
- */
-static void
-test_backspace(struct testset *ts)
-{
-    unsigned int i;
-
-    if (!isatty(STDOUT_FILENO))
-        return;
-    for (i = 0; i < ts->length; i++)
-        putchar('\b');
-    for (i = 0; i < ts->length; i++)
-        putchar(' ');
-    for (i = 0; i < ts->length; i++)
-        putchar('\b');
-    ts->length = 0;
-}
-
-
-/*
- * Read the plan line of test output, which should contain the range of test
- * numbers.  We may initialize the testset structure here if we haven't yet
- * seen a test.  Return true if initialization succeeded and the test should
- * continue, false otherwise.
- */
-static int
-test_plan(const char *line, struct testset *ts)
-{
-    unsigned long i;
-    long n;
-
-    /*
-     * Accept a plan without the leading 1.. for compatibility with older
-     * versions of runtests.  This will only be allowed if we've not yet seen
-     * a test result.
-     */
-    line = skip_whitespace(line);
-    if (strncmp(line, "1..", 3) == 0)
-        line += 3;
-
-    /*
-     * Get the count, check it for validity, and initialize the struct.  If we
-     * have something of the form "1..0 # skip foo", the whole file was
-     * skipped; record that.  If we do skip the whole file, zero out all of
-     * our statistics, since they're no longer relevant.  strtol is called
-     * with a second argument to advance the line pointer past the count to
-     * make it simpler to detect the # skip case.
-     */
-    n = strtol(line, (char **) &line, 10);
-    if (n == 0) {
-        line = skip_whitespace(line);
-        if (*line == '#') {
-            line = skip_whitespace(line + 1);
-            if (strncasecmp(line, "skip", 4) == 0) {
-                line = skip_whitespace(line + 4);
-                if (*line != '\0') {
-                    ts->reason = xstrdup(line);
-                    ts->reason[strlen(ts->reason) - 1] = '\0';
-                }
-                ts->all_skipped = 1;
-                ts->aborted = 1;
-                ts->count = 0;
-                ts->passed = 0;
-                ts->skipped = 0;
-                ts->failed = 0;
-                return 0;
-            }
-        }
-    }
-    if (n <= 0) {
-        puts("ABORTED (invalid test count)");
-        ts->aborted = 1;
-        ts->reported = 1;
-        return 0;
-    }
-    if (ts->plan == PLAN_INIT && ts->allocated == 0) {
-        ts->count = n;
-        ts->allocated = n;
-        ts->plan = PLAN_FIRST;
-        ts->results = xmalloc(ts->count * sizeof(enum test_status));
-        for (i = 0; i < ts->count; i++)
-            ts->results[i] = TEST_INVALID;
-    } else if (ts->plan == PLAN_PENDING) {
-        if ((unsigned long) n < ts->count) {
-            printf("ABORTED (invalid test number %lu)\n", ts->count);
-            ts->aborted = 1;
-            ts->reported = 1;
-            return 0;
-        }
-        ts->count = n;
-        if ((unsigned long) n > ts->allocated) {
-            ts->results = xrealloc(ts->results, n * sizeof(enum test_status));
-            for (i = ts->allocated; i < ts->count; i++)
-                ts->results[i] = TEST_INVALID;
-            ts->allocated = n;
-        }
-        ts->plan = PLAN_FINAL;
-    }
-    return 1;
-}
-
-
-/*
- * Given a single line of output from a test, parse it and return the success
- * status of that test.  Anything printed to stdout not matching the form
- * /^(not )?ok \d+/ is ignored.  Sets ts->current to the test number that just
- * reported status.
- */
-static void
-test_checkline(const char *line, struct testset *ts)
-{
-    enum test_status status = TEST_PASS;
-    const char *bail;
-    char *end;
-    long number;
-    unsigned long i, current;
-    int outlen;
-
-    /* Before anything, check for a test abort. */
-    bail = strstr(line, "Bail out!");
-    if (bail != NULL) {
-        bail = skip_whitespace(bail + strlen("Bail out!"));
-        if (*bail != '\0') {
-            size_t length;
-
-            length = strlen(bail);
-            if (bail[length - 1] == '\n')
-                length--;
-            test_backspace(ts);
-            printf("ABORTED (%.*s)\n", (int) length, bail);
-            ts->reported = 1;
-        }
-        ts->aborted = 1;
-        return;
-    }
-
-    /*
-     * If the given line isn't newline-terminated, it was too big for an
-     * fgets(), which means ignore it.
-     */
-    if (line[strlen(line) - 1] != '\n')
-        return;
-
-    /* If the line begins with a hash mark, ignore it. */
-    if (line[0] == '#')
-        return;
-
-    /* If we haven't yet seen a plan, look for one. */
-    if (ts->plan == PLAN_INIT && isdigit((unsigned char)(*line))) {
-        if (!test_plan(line, ts))
-            return;
-    } else if (strncmp(line, "1..", 3) == 0) {
-        if (ts->plan == PLAN_PENDING) {
-            if (!test_plan(line, ts))
-                return;
-        } else {
-            puts("ABORTED (multiple plans)");
-            ts->aborted = 1;
-            ts->reported = 1;
-            return;
-        }
-    }
-
-    /* Parse the line, ignoring something we can't parse. */
-    if (strncmp(line, "not ", 4) == 0) {
-        status = TEST_FAIL;
-        line += 4;
-    }
-    if (strncmp(line, "ok", 2) != 0)
-        return;
-    line = skip_whitespace(line + 2);
-    errno = 0;
-    number = strtol(line, &end, 10);
-    if (errno != 0 || end == line)
-        number = ts->current + 1;
-    current = number;
-    if (number <= 0 || (current > ts->count && ts->plan == PLAN_FIRST)) {
-        test_backspace(ts);
-        printf("ABORTED (invalid test number %lu)\n", current);
-        ts->aborted = 1;
-        ts->reported = 1;
-        return;
-    }
-
-    /* We have a valid test result.  Tweak the results array if needed. */
-    if (ts->plan == PLAN_INIT || ts->plan == PLAN_PENDING) {
-        ts->plan = PLAN_PENDING;
-        if (current > ts->count)
-            ts->count = current;
-        if (current > ts->allocated) {
-            unsigned long n;
-
-            n = (ts->allocated == 0) ? 32 : ts->allocated * 2;
-            if (n < current)
-                n = current;
-            ts->results = xrealloc(ts->results, n * sizeof(enum test_status));
-            for (i = ts->allocated; i < n; i++)
-                ts->results[i] = TEST_INVALID;
-            ts->allocated = n;
-        }
-    }
-
-    /*
-     * Handle directives.  We should probably do something more interesting
-     * with unexpected passes of todo tests.
-     */
-    while (isdigit((unsigned char)(*line)))
-        line++;
-    line = skip_whitespace(line);
-    if (*line == '#') {
-        line = skip_whitespace(line + 1);
-        if (strncasecmp(line, "skip", 4) == 0)
-            status = TEST_SKIP;
-        if (strncasecmp(line, "todo", 4) == 0)
-            status = (status == TEST_FAIL) ? TEST_SKIP : TEST_FAIL;
-    }
-
-    /* Make sure that the test number is in range and not a duplicate. */
-    if (ts->results[current - 1] != TEST_INVALID) {
-        test_backspace(ts);
-        printf("ABORTED (duplicate test number %lu)\n", current);
-        ts->aborted = 1;
-        ts->reported = 1;
-        return;
-    }
-
-    /* Good results.  Increment our various counters. */
-    switch (status) {
-        case TEST_PASS: ts->passed++;   break;
-        case TEST_FAIL: ts->failed++;   break;
-        case TEST_SKIP: ts->skipped++;  break;
-        case TEST_INVALID:              break;
-    }
-    ts->current = current;
-    ts->results[current - 1] = status;
-    test_backspace(ts);
-    if (isatty(STDOUT_FILENO)) {
-        outlen = printf("%lu/%lu", current, ts->count);
-        ts->length = (outlen >= 0) ? outlen : 0;
-        fflush(stdout);
-    }
-}
-
-
-/*
- * Print out a range of test numbers, returning the number of characters it
- * took up.  Takes the first number, the last number, the number of characters
- * already printed on the line, and the limit of number of characters the line
- * can hold.  Add a comma and a space before the range if chars indicates that
- * something has already been printed on the line, and print ... instead if
- * chars plus the space needed would go over the limit (use a limit of 0 to
- * disable this).
- */
-static unsigned int
-test_print_range(unsigned long first, unsigned long last, unsigned int chars,
-                 unsigned int limit)
-{
-    unsigned int needed = 0;
-    unsigned long n;
-
-    for (n = first; n > 0; n /= 10)
-        needed++;
-    if (last > first) {
-        for (n = last; n > 0; n /= 10)
-            needed++;
-        needed++;
-    }
-    if (chars > 0)
-        needed += 2;
-    if (limit > 0 && chars + needed > limit) {
-        needed = 0;
-        if (chars <= limit) {
-            if (chars > 0) {
-                printf(", ");
-                needed += 2;
-            }
-            printf("...");
-            needed += 3;
-        }
-    } else {
-        if (chars > 0)
-            printf(", ");
-        if (last > first)
-            printf("%lu-", first);
-        printf("%lu", last);
-    }
-    return needed;
-}
-
-
-/*
- * Summarize a single test set.  The second argument is 0 if the set exited
- * cleanly, a positive integer representing the exit status if it exited
- * with a non-zero status, and a negative integer representing the signal
- * that terminated it if it was killed by a signal.
- */
-static void
-test_summarize(struct testset *ts, int status)
-{
-    unsigned long i;
-    unsigned long missing = 0;
-    unsigned long failed = 0;
-    unsigned long first = 0;
-    unsigned long last = 0;
-
-    if (ts->aborted) {
-        fputs("ABORTED", stdout);
-        if (ts->count > 0)
-            printf(" (passed %lu/%lu)", ts->passed, ts->count - ts->skipped);
-    } else {
-        for (i = 0; i < ts->count; i++) {
-            if (ts->results[i] == TEST_INVALID) {
-                if (missing == 0)
-                    fputs("MISSED ", stdout);
-                if (first && i == last)
-                    last = i + 1;
-                else {
-                    if (first)
-                        test_print_range(first, last, missing - 1, 0);
-                    missing++;
-                    first = i + 1;
-                    last = i + 1;
-                }
-            }
-        }
-        if (first)
-            test_print_range(first, last, missing - 1, 0);
-        first = 0;
-        last = 0;
-        for (i = 0; i < ts->count; i++) {
-            if (ts->results[i] == TEST_FAIL) {
-                if (missing && !failed)
-                    fputs("; ", stdout);
-                if (failed == 0)
-                    fputs("FAILED ", stdout);
-                if (first && i == last)
-                    last = i + 1;
-                else {
-                    if (first)
-                        test_print_range(first, last, failed - 1, 0);
-                    failed++;
-                    first = i + 1;
-                    last = i + 1;
-                }
-            }
-        }
-        if (first)
-            test_print_range(first, last, failed - 1, 0);
-        if (!missing && !failed) {
-            fputs(!status ? "ok" : "dubious", stdout);
-            if (ts->skipped > 0) {
-                if (ts->skipped == 1)
-                    printf(" (skipped %lu test)", ts->skipped);
-                else
-                    printf(" (skipped %lu tests)", ts->skipped);
-            }
-        }
-    }
-    if (status > 0)
-        printf(" (exit status %d)", status);
-    else if (status < 0)
-        printf(" (killed by signal %d%s)", -status,
-               WCOREDUMP(ts->status) ? ", core dumped" : "");
-    putchar('\n');
-}
-
-
-/*
- * Given a test set, analyze the results, classify the exit status, handle a
- * few special error messages, and then pass it along to test_summarize() for
- * the regular output.  Returns true if the test set ran successfully and all
- * tests passed or were skipped, false otherwise.
- */
-static int
-test_analyze(struct testset *ts)
-{
-    if (ts->reported)
-        return 0;
-    if (ts->all_skipped) {
-        if (ts->reason == NULL)
-            puts("skipped");
-        else
-            printf("skipped (%s)\n", ts->reason);
-        return 1;
-    } else if (WIFEXITED(ts->status) && WEXITSTATUS(ts->status) != 0) {
-        switch (WEXITSTATUS(ts->status)) {
-        case CHILDERR_DUP:
-            if (!ts->reported)
-                puts("ABORTED (can't dup file descriptors)");
-            break;
-        case CHILDERR_EXEC:
-            if (!ts->reported)
-                puts("ABORTED (execution failed -- not found?)");
-            break;
-        case CHILDERR_STDERR:
-            if (!ts->reported)
-                puts("ABORTED (can't open /dev/null)");
-            break;
-        default:
-            test_summarize(ts, WEXITSTATUS(ts->status));
-            break;
-        }
-        return 0;
-    } else if (WIFSIGNALED(ts->status)) {
-        test_summarize(ts, -WTERMSIG(ts->status));
-        return 0;
-    } else if (ts->plan != PLAN_FIRST && ts->plan != PLAN_FINAL) {
-        puts("ABORTED (no valid test plan)");
-        ts->aborted = 1;
-        return 0;
-    } else {
-        test_summarize(ts, 0);
-        return (ts->failed == 0);
-    }
-}
-
-
-/*
- * Runs a single test set, accumulating and then reporting the results.
- * Returns true if the test set was successfully run and all tests passed,
- * false otherwise.
- */
-static int
-test_run(struct testset *ts)
-{
-    pid_t testpid, child;
-    int outfd, status;
-    unsigned long i;
-    FILE *output;
-    char buffer[BUFSIZ];
-
-    /* Run the test program. */
-    testpid = test_start(ts->path, &outfd);
-    output = fdopen(outfd, "r");
-    if (!output) {
-        puts("ABORTED");
-        fflush(stdout);
-        sysdie("fdopen failed");
-    }
-
-    /* Pass each line of output to test_checkline(). */
-    while (!ts->aborted && fgets(buffer, sizeof(buffer), output))
-        test_checkline(buffer, ts);
-    if (ferror(output) || ts->plan == PLAN_INIT)
-        ts->aborted = 1;
-    test_backspace(ts);
-
-    /*
-     * Consume the rest of the test output, close the output descriptor,
-     * retrieve the exit status, and pass that information to test_analyze()
-     * for eventual output.
-     */
-    while (fgets(buffer, sizeof(buffer), output))
-        ;
-    fclose(output);
-    child = waitpid(testpid, &ts->status, 0);
-    if (child == (pid_t) -1) {
-        if (!ts->reported) {
-            puts("ABORTED");
-            fflush(stdout);
-        }
-        sysdie("waitpid for %u failed", (unsigned int) testpid);
-    }
-    if (ts->all_skipped)
-        ts->aborted = 0;
-    status = test_analyze(ts);
-
-    /* Convert missing tests to failed tests. */
-    for (i = 0; i < ts->count; i++) {
-        if (ts->results[i] == TEST_INVALID) {
-            ts->failed++;
-            ts->results[i] = TEST_FAIL;
-            status = 0;
-        }
-    }
-    return status;
-}
-
-
-/* Summarize a list of test failures. */
-static void
-test_fail_summary(const struct testlist *fails)
-{
-    struct testset *ts;
-    unsigned int chars;
-    unsigned long i, first, last, total;
-
-    puts(header);
-
-    /* Failed Set                 Fail/Total (%) Skip Stat  Failing (25)
-       -------------------------- -------------- ---- ----  -------------- */
-    for (; fails; fails = fails->next) {
-        ts = fails->ts;
-        total = ts->count - ts->skipped;
-        printf("%-26.26s %4lu/%-4lu %3.0f%% %4lu ", ts->file, ts->failed,
-               total, total ? (ts->failed * 100.0) / total : 0,
-               ts->skipped);
-        if (WIFEXITED(ts->status))
-            printf("%4d  ", WEXITSTATUS(ts->status));
-        else
-            printf("  --  ");
-        if (ts->aborted) {
-            puts("aborted");
-            continue;
-        }
-        chars = 0;
-        first = 0;
-        last = 0;
-        for (i = 0; i < ts->count; i++) {
-            if (ts->results[i] == TEST_FAIL) {
-                if (first != 0 && i == last)
-                    last = i + 1;
-                else {
-                    if (first != 0)
-                        chars += test_print_range(first, last, chars, 19);
-                    first = i + 1;
-                    last = i + 1;
-                }
-            }
-        }
-        if (first != 0)
-            test_print_range(first, last, chars, 19);
-        putchar('\n');
-        free(ts->file);
-        free(ts->path);
-        free(ts->results);
-        if (ts->reason != NULL)
-            free(ts->reason);
-        free(ts);
-    }
-}
-
-
-/*
- * Given the name of a test, a pointer to the testset struct, and the source
- * and build directories, find the test.  We try first relative to the current
- * directory, then in the build directory (if not NULL), then in the source
- * directory.  In each of those directories, we first try a "-t" extension and
- * then a ".t" extension.  When we find an executable program, we fill in the
- * path member of the testset struct.  If none of those paths are executable,
- * just fill in the name of the test with "-t" appended.
- *
- * The caller is responsible for freeing the path member of the testset
- * struct.
- */
-static void
-find_test(const char *name, struct testset *ts, const char *source,
-          const char *build)
-{
-    char *path;
-    const char *bases[4];
-    unsigned int i;
-
-    bases[0] = ".";
-    bases[1] = build;
-    bases[2] = source;
-    bases[3] = NULL;
-
-    for (i = 0; bases[i] != NULL; i++) {
-        path = xmalloc(strlen(bases[i]) + strlen(name) + 4);
-        sprintf(path, "%s/%s-t", bases[i], name);
-        if (access(path, X_OK) != 0)
-            path[strlen(path) - 2] = '.';
-        if (access(path, X_OK) == 0)
-            break;
-        free(path);
-        path = NULL;
-    }
-    if (path == NULL) {
-        path = xmalloc(strlen(name) + 3);
-        sprintf(path, "%s-t", name);
-    }
-    ts->path = path;
-}
-
-
-/*
- * Run a batch of tests from a given file listing each test on a line by
- * itself.  Takes two additional parameters: the root of the source directory
- * and the root of the build directory.  Test programs will be first searched
- * for in the current directory, then the build directory, then the source
- * directory.  The file must be rewindable.  Returns true iff all tests
- * passed.
- */
-static int
-test_batch(const char *testlist, const char *source, const char *build)
-{
-    FILE *tests;
-    unsigned int length, i;
-    unsigned int longest = 0;
-    char buffer[BUFSIZ];
-    unsigned int line;
-    struct testset ts, *tmp;
-    struct timeval start, end;
-    struct rusage stats;
-    struct testlist *failhead = NULL;
-    struct testlist *failtail = NULL;
-    struct testlist *next;
-    unsigned long total = 0;
-    unsigned long passed = 0;
-    unsigned long skipped = 0;
-    unsigned long failed = 0;
-    unsigned long aborted = 0;
-
-    /*
-     * Open our file of tests to run and scan it, checking for lines that
-     * are too long and searching for the longest line.
-     */
-    tests = fopen(testlist, "r");
-    if (!tests)
-        sysdie("can't open %s", testlist);
-    line = 0;
-    while (fgets(buffer, sizeof(buffer), tests)) {
-        line++;
-        length = strlen(buffer) - 1;
-        if (buffer[length] != '\n') {
-            fprintf(stderr, "%s:%u: line too long\n", testlist, line);
-            exit(1);
-        }
-        if (length > longest)
-            longest = length;
-    }
-    if (fseek(tests, 0, SEEK_SET) == -1)
-        sysdie("can't rewind %s", testlist);
-
-    /*
-     * Add two to longest and round up to the nearest tab stop.  This is how
-     * wide the column for printing the current test name will be.
-     */
-    longest += 2;
-    if (longest % 8)
-        longest += 8 - (longest % 8);
-
-    /* Start the wall clock timer. */
-    gettimeofday(&start, NULL);
-
-    /*
-     * Now, plow through our tests again, running each one.  Check line
-     * length again out of paranoia.
-     */
-    line = 0;
-    while (fgets(buffer, sizeof(buffer), tests)) {
-        line++;
-        length = strlen(buffer) - 1;
-        if (buffer[length] != '\n') {
-            fprintf(stderr, "%s:%u: line too long\n", testlist, line);
-            exit(1);
-        }
-        buffer[length] = '\0';
-        fputs(buffer, stdout);
-        for (i = length; i < longest; i++)
-            putchar('.');
-        if (isatty(STDOUT_FILENO))
-            fflush(stdout);
-        memset(&ts, 0, sizeof(ts));
-        ts.plan = PLAN_INIT;
-        ts.file = xstrdup(buffer);
-        find_test(buffer, &ts, source, build);
-        ts.reason = NULL;
-        if (test_run(&ts)) {
-            free(ts.file);
-            free(ts.path);
-            free(ts.results);
-            if (ts.reason != NULL)
-                free(ts.reason);
-        } else {
-            tmp = xmalloc(sizeof(struct testset));
-            memcpy(tmp, &ts, sizeof(struct testset));
-            if (!failhead) {
-                failhead = xmalloc(sizeof(struct testset));
-                failhead->ts = tmp;
-                failhead->next = NULL;
-                failtail = failhead;
-            } else {
-                failtail->next = xmalloc(sizeof(struct testset));
-                failtail = failtail->next;
-                failtail->ts = tmp;
-                failtail->next = NULL;
-            }
-        }
-        aborted += ts.aborted;
-        total += ts.count + ts.all_skipped;
-        passed += ts.passed;
-        skipped += ts.skipped + ts.all_skipped;
-        failed += ts.failed;
-    }
-    total -= skipped;
-
-    /* Stop the timer and get our child resource statistics. */
-    gettimeofday(&end, NULL);
-    getrusage(RUSAGE_CHILDREN, &stats);
-
-    /* Print out our final results. */
-    if (failhead != NULL) {
-        test_fail_summary(failhead);
-        while (failhead != NULL) {
-            next = failhead->next;
-            free(failhead);
-            failhead = next;
-        }
-    }
-    putchar('\n');
-    if (aborted != 0) {
-        if (aborted == 1)
-            printf("Aborted %lu test set", aborted);
-        else
-            printf("Aborted %lu test sets", aborted);
-        printf(", passed %lu/%lu tests", passed, total);
-    }
-    else if (failed == 0)
-        fputs("All tests successful", stdout);
-    else
-        printf("Failed %lu/%lu tests, %.2f%% okay", failed, total,
-               (total - failed) * 100.0 / total);
-    if (skipped != 0) {
-        if (skipped == 1)
-            printf(", %lu test skipped", skipped);
-        else
-            printf(", %lu tests skipped", skipped);
-    }
-    puts(".");
-    printf("Files=%u,  Tests=%lu", line, total);
-    printf(",  %.2f seconds", tv_diff(&end, &start));
-    printf(" (%.2f usr + %.2f sys = %.2f CPU)\n",
-           tv_seconds(&stats.ru_utime), tv_seconds(&stats.ru_stime),
-           tv_sum(&stats.ru_utime, &stats.ru_stime));
-    return (failed == 0 && aborted == 0);
-}
-
-
-/*
- * Run a single test case.  This involves just running the test program after
- * having done the environment setup and finding the test program.
- */
-static void
-test_single(const char *program, const char *source, const char *build)
-{
-    struct testset ts;
-
-    memset(&ts, 0, sizeof(ts));
-    find_test(program, &ts, source, build);
-    if (execl(ts.path, ts.path, (char *) 0) == -1)
-        sysdie("cannot exec %s", ts.path);
-}
-
-
-/*
- * Main routine.  Set the SOURCE and BUILD environment variables and then,
- * given a file listing tests, run each test listed.
- */
-int
-main(int argc, char *argv[])
-{
-    int option;
-    int single = 0;
-    char *setting;
-    const char *list;
-    const char *source = SOURCE;
-    const char *build = BUILD;
-
-    while ((option = getopt(argc, argv, "b:hos:")) != EOF) {
-        switch (option) {
-        case 'b':
-            build = optarg;
-            break;
-        case 'h':
-            printf(usage_message, argv[0], argv[0]);
-            exit(0);
-            break;
-        case 'o':
-            single = 1;
-            break;
-        case 's':
-            source = optarg;
-            break;
-        default:
-            exit(1);
-        }
-    }
-    if (argc - optind != 1) {
-        fprintf(stderr, usage_message, argv[0], argv[0]);
-        exit(1);
-    }
-    argc -= optind;
-    argv += optind;
-
-    if (source != NULL) {
-        setting = xmalloc(strlen("SOURCE=") + strlen(source) + 1);
-        sprintf(setting, "SOURCE=%s", source);
-        if (putenv(setting) != 0)
-            sysdie("cannot set SOURCE in the environment");
-    }
-    if (build != NULL) {
-        setting = xmalloc(strlen("BUILD=") + strlen(build) + 1);
-        sprintf(setting, "BUILD=%s", build);
-        if (putenv(setting) != 0)
-            sysdie("cannot set BUILD in the environment");
-    }
-
-    if (single) {
-        test_single(argv[0], source, build);
-        exit(0);
-    } else {
-        list = strrchr(argv[0], '/');
-        if (list == NULL)
-            list = argv[0];
-        else
-            list++;
-        printf(banner, list);
-        exit(test_batch(argv[0], source, build) ? 0 : 1);
-    }
-}
index d24c53c..17b510a 100644 (file)
@@ -5,7 +5,7 @@ abs_top_builddir=@abs_top_builddir@
 include @TOP_OBJDIR@/src/config/Makefile.config
 include @TOP_OBJDIR@/src/config/Makefile.pthread
 
-MODULE_CFLAGS = -I$(srcdir)/..
+MODULE_CFLAGS = -I$(srcdir)/../..
 
 LIBS = ../tap/libtap.a \
        $(abs_top_builddir)/lib/libafsrpc.a \
index c66ef71..885ad99 100644 (file)
@@ -6,7 +6,7 @@
 #include <roken.h>
 #include <pthread.h>
 
-#include <tap/basic.h>
+#include <tests/tap/basic.h>
 
 #include "rx/rx_event.h"
 #include "rx/rx_clock.h"
diff --git a/tests/tap/.gitignore b/tests/tap/.gitignore
new file mode 100644 (file)
index 0000000..3a25bc3
--- /dev/null
@@ -0,0 +1,3 @@
+/libtap.sh
+/basic.h
+/macros.h
index d74a13d..2f5f745 100644 (file)
@@ -1,15 +1,25 @@
 # Build rules for the OpenAFS test suite.
 
 srcdir=@srcdir@
+tapdir=$(srcdir)/../../src/external/c-tap-harness/tests/tap
 include @TOP_OBJDIR@/src/config/Makefile.config
 include @TOP_OBJDIR@/src/config/Makefile.pthread
 
 objects = basic.o
 
-all check test tests: libtap.a
+all check test tests: libtap.a basic.h macros.h libtap.sh
 
-basic.o: $(srcdir)/basic.c $(srcdir)/basic.h
-       $(CC) $(AFS_CFLAGS) -I$(srcdir)/.. -c $(srcdir)/basic.c
+basic.o: $(tapdir)/basic.c $(tapdir)/basic.h
+       $(CC) $(AFS_CFLAGS) @CFLAGS_NOERROR@ -I$(tapdir)/../.. -c $(tapdir)/basic.c
+
+basic.h: $(tapdir)/basic.h
+       cp $(tapdir)/basic.h basic.h
+
+macros.h: $(tapdir)/macros.h
+       cp $(tapdir)/macros.h macros.h
+
+libtap.sh: $(tapdir)/libtap.sh
+       cp $(tapdir)/libtap.sh libtap.sh
 
 libtap.a: $(objects)
        $(RM) -f libtap.a
@@ -19,4 +29,4 @@ libtap.a: $(objects)
 install:
 
 clean distclean:
-       $(RM) -f *.o *.a core
+       $(RM) -f *.o *.a core basic.h macros.h libtap.sh
diff --git a/tests/tap/basic.c b/tests/tap/basic.c
deleted file mode 100644 (file)
index 8027a31..0000000
+++ /dev/null
@@ -1,524 +0,0 @@
-/*
- * Some utility routines for writing tests.
- *
- * Here are a variety of utility routines for writing tests compatible with
- * the TAP protocol.  All routines of the form ok() or is*() take a test
- * number and some number of appropriate arguments, check to be sure the
- * results match the expected output using the arguments, and print out
- * something appropriate for that test number.  Other utility routines help in
- * constructing more complex tests, skipping tests, or setting up the TAP
- * output format.
- *
- * This file is part of C TAP Harness.  The current version plus supporting
- * documentation is at <http://www.eyrie.org/~eagle/software/c-tap-harness/>.
- *
- * Copyright 2009, 2010 Russ Allbery <rra@stanford.edu>
- * Copyright 2001, 2002, 2004, 2005, 2006, 2007, 2008
- *     The Board of Trustees of the Leland Stanford Junior University
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
-
-/* Required for isnan() and isinf(). */
-#ifndef _XOPEN_SOURCE
-# define _XOPEN_SOURCE 600
-#endif
-
-#include <errno.h>
-#include <math.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/time.h>
-#include <sys/wait.h>
-#include <unistd.h>
-
-#include <tap/basic.h>
-
-/*
- * The test count.  Always contains the number that will be used for the next
- * test status.
- */
-unsigned long testnum = 1;
-
-/*
- * Status information stored so that we can give a test summary at the end of
- * the test case.  We store the planned final test and the count of failures.
- * We can get the highest test count from testnum.
- *
- * We also store the PID of the process that called plan() and only summarize
- * results when that process exits, so as to not misreport results in forked
- * processes.
- *
- * If _lazy is true, we're doing lazy planning and will print out the plan
- * based on the last test number at the end of testing.
- */
-static unsigned long _planned = 0;
-static unsigned long _failed  = 0;
-static pid_t _process = 0;
-static int _lazy = 0;
-
-
-/*
- * Our exit handler.  Called on completion of the test to report a summary of
- * results provided we're still in the original process.
- */
-static void
-finish(void)
-{
-    unsigned long highest = testnum - 1;
-
-    if (_planned == 0 && !_lazy)
-        return;
-    fflush(stderr);
-    if (_process != 0 && getpid() == _process) {
-        if (_lazy) {
-            printf("1..%lu\n", highest);
-            _planned = highest;
-        }
-        if (_planned > highest)
-            printf("# Looks like you planned %lu test%s but only ran %lu\n",
-                   _planned, (_planned > 1 ? "s" : ""), highest);
-        else if (_planned < highest)
-            printf("# Looks like you planned %lu test%s but ran %lu extra\n",
-                   _planned, (_planned > 1 ? "s" : ""), highest - _planned);
-        else if (_failed > 0)
-            printf("# Looks like you failed %lu test%s of %lu\n", _failed,
-                   (_failed > 1 ? "s" : ""), _planned);
-        else if (_planned > 1)
-            printf("# All %lu tests successful or skipped\n", _planned);
-        else
-            printf("# %lu test successful or skipped\n", _planned);
-    }
-}
-
-
-/*
- * Initialize things.  Turns on line buffering on stdout and then prints out
- * the number of tests in the test suite.
- */
-void
-plan(unsigned long count)
-{
-    if (setvbuf(stdout, NULL, _IOLBF, BUFSIZ) != 0)
-        fprintf(stderr, "# cannot set stdout to line buffered: %s\n",
-                strerror(errno));
-    fflush(stderr);
-    printf("1..%lu\n", count);
-    testnum = 1;
-    _planned = count;
-    _process = getpid();
-    atexit(finish);
-}
-
-
-/*
- * Initialize things for lazy planning, where we'll automatically print out a
- * plan at the end of the program.  Turns on line buffering on stdout as well.
- */
-void
-plan_lazy(void)
-{
-    if (setvbuf(stdout, NULL, _IOLBF, BUFSIZ) != 0)
-        fprintf(stderr, "# cannot set stdout to line buffered: %s\n",
-                strerror(errno));
-    testnum = 1;
-    _process = getpid();
-    _lazy = 1;
-    atexit(finish);
-}
-
-
-/*
- * Skip the entire test suite and exits.  Should be called instead of plan(),
- * not after it, since it prints out a special plan line.
- */
-void
-skip_all(const char *format, ...)
-{
-    fflush(stderr);
-    printf("1..0 # skip");
-    if (format != NULL) {
-        va_list args;
-
-        putchar(' ');
-        va_start(args, format);
-        vprintf(format, args);
-        va_end(args);
-    }
-    putchar('\n');
-    exit(0);
-}
-
-
-/*
- * Print the test description.
- */
-static void
-print_desc(const char *format, va_list args)
-{
-    printf(" - ");
-    vprintf(format, args);
-}
-
-
-/*
- * Takes a boolean success value and assumes the test passes if that value
- * is true and fails if that value is false.
- */
-void
-ok(int success, const char *format, ...)
-{
-    fflush(stderr);
-    printf("%sok %lu", success ? "" : "not ", testnum++);
-    if (!success)
-        _failed++;
-    if (format != NULL) {
-        va_list args;
-
-        va_start(args, format);
-        print_desc(format, args);
-        va_end(args);
-    }
-    putchar('\n');
-}
-
-
-/*
- * Same as ok(), but takes the format arguments as a va_list.
- */
-void
-okv(int success, const char *format, va_list args)
-{
-    fflush(stderr);
-    printf("%sok %lu", success ? "" : "not ", testnum++);
-    if (!success)
-        _failed++;
-    if (format != NULL)
-        print_desc(format, args);
-    putchar('\n');
-}
-
-
-/*
- * Skip a test.
- */
-void
-skip(const char *reason, ...)
-{
-    fflush(stderr);
-    printf("ok %lu # skip", testnum++);
-    if (reason != NULL) {
-        va_list args;
-
-        va_start(args, reason);
-        putchar(' ');
-        vprintf(reason, args);
-        va_end(args);
-    }
-    putchar('\n');
-}
-
-
-/*
- * Report the same status on the next count tests.
- */
-void
-ok_block(unsigned long count, int status, const char *format, ...)
-{
-    unsigned long i;
-
-    fflush(stderr);
-    for (i = 0; i < count; i++) {
-        printf("%sok %lu", status ? "" : "not ", testnum++);
-        if (!status)
-            _failed++;
-        if (format != NULL) {
-            va_list args;
-
-            va_start(args, format);
-            print_desc(format, args);
-            va_end(args);
-        }
-        putchar('\n');
-    }
-}
-
-
-/*
- * Skip the next count tests.
- */
-void
-skip_block(unsigned long count, const char *reason, ...)
-{
-    unsigned long i;
-
-    fflush(stderr);
-    for (i = 0; i < count; i++) {
-        printf("ok %lu # skip", testnum++);
-        if (reason != NULL) {
-            va_list args;
-
-            va_start(args, reason);
-            putchar(' ');
-            vprintf(reason, args);
-            va_end(args);
-        }
-        putchar('\n');
-    }
-}
-
-
-/*
- * Takes an expected integer and a seen integer and assumes the test passes
- * if those two numbers match.
- */
-void
-is_int(long wanted, long seen, const char *format, ...)
-{
-    fflush(stderr);
-    if (wanted == seen)
-        printf("ok %lu", testnum++);
-    else {
-        printf("# wanted: %ld\n#   seen: %ld\n", wanted, seen);
-        printf("not ok %lu", testnum++);
-        _failed++;
-    }
-    if (format != NULL) {
-        va_list args;
-
-        va_start(args, format);
-        print_desc(format, args);
-        va_end(args);
-    }
-    putchar('\n');
-}
-
-
-/*
- * Takes a string and what the string should be, and assumes the test passes
- * if those strings match (using strcmp).
- */
-void
-is_string(const char *wanted, const char *seen, const char *format, ...)
-{
-    if (wanted == NULL)
-        wanted = "(null)";
-    if (seen == NULL)
-        seen = "(null)";
-    fflush(stderr);
-    if (strcmp(wanted, seen) == 0)
-        printf("ok %lu", testnum++);
-    else {
-        printf("# wanted: %s\n#   seen: %s\n", wanted, seen);
-        printf("not ok %lu", testnum++);
-        _failed++;
-    }
-    if (format != NULL) {
-        va_list args;
-
-        va_start(args, format);
-        print_desc(format, args);
-        va_end(args);
-    }
-    putchar('\n');
-}
-
-
-/*
- * Takes an expected double and a seen double and assumes the test passes if
- * those two numbers are within delta of each other.
- */
-void
-is_double(double wanted, double seen, double epsilon, const char *format, ...)
-{
-    fflush(stderr);
-    if ((isnan(wanted) && isnan(seen))
-        || (isinf(wanted) && isinf(seen) && wanted == seen)
-        || fabs(wanted - seen) <= epsilon)
-        printf("ok %lu", testnum++);
-    else {
-        printf("# wanted: %g\n#   seen: %g\n", wanted, seen);
-        printf("not ok %lu", testnum++);
-        _failed++;
-    }
-    if (format != NULL) {
-        va_list args;
-
-        va_start(args, format);
-        print_desc(format, args);
-        va_end(args);
-    }
-    putchar('\n');
-}
-
-
-/*
- * Takes an expected unsigned long and a seen unsigned long and assumes the
- * test passes if the two numbers match.  Otherwise, reports them in hex.
- */
-void
-is_hex(unsigned long wanted, unsigned long seen, const char *format, ...)
-{
-    fflush(stderr);
-    if (wanted == seen)
-        printf("ok %lu", testnum++);
-    else {
-        printf("# wanted: %lx\n#   seen: %lx\n", (unsigned long) wanted,
-               (unsigned long) seen);
-        printf("not ok %lu", testnum++);
-        _failed++;
-    }
-    if (format != NULL) {
-        va_list args;
-
-        va_start(args, format);
-        print_desc(format, args);
-        va_end(args);
-    }
-    putchar('\n');
-}
-
-
-/*
- * Bail out with an error.
- */
-void
-bail(const char *format, ...)
-{
-    va_list args;
-
-    fflush(stderr);
-    fflush(stdout);
-    printf("Bail out! ");
-    va_start(args, format);
-    vprintf(format, args);
-    va_end(args);
-    printf("\n");
-    exit(1);
-}
-
-
-/*
- * Bail out with an error, appending strerror(errno).
- */
-void
-sysbail(const char *format, ...)
-{
-    va_list args;
-    int oerrno = errno;
-
-    fflush(stderr);
-    fflush(stdout);
-    printf("Bail out! ");
-    va_start(args, format);
-    vprintf(format, args);
-    va_end(args);
-    printf(": %s\n", strerror(oerrno));
-    exit(1);
-}
-
-
-/*
- * Report a diagnostic to stderr.
- */
-void
-diag(const char *format, ...)
-{
-    va_list args;
-
-    fflush(stderr);
-    fflush(stdout);
-    printf("# ");
-    va_start(args, format);
-    vprintf(format, args);
-    va_end(args);
-    printf("\n");
-}
-
-
-/*
- * Report a diagnostic to stderr, appending strerror(errno).
- */
-void
-sysdiag(const char *format, ...)
-{
-    va_list args;
-    int oerrno = errno;
-
-    fflush(stderr);
-    fflush(stdout);
-    printf("# ");
-    va_start(args, format);
-    vprintf(format, args);
-    va_end(args);
-    printf(": %s\n", strerror(oerrno));
-}
-
-
-/*
- * Locate a test file.  Given the partial path to a file, look under BUILD and
- * then SOURCE for the file and return the full path to the file.  Returns
- * NULL if the file doesn't exist.  A non-NULL return should be freed with
- * test_file_path_free().
- *
- * This function uses sprintf because it attempts to be independent of all
- * other portability layers.  The use immediately after a memory allocation
- * should be safe without using snprintf or strlcpy/strlcat.
- */
-char *
-test_file_path(const char *file)
-{
-    char *base;
-    char *path = NULL;
-    size_t length;
-    const char *envs[] = { "BUILD", "SOURCE", NULL };
-    int i;
-
-    for (i = 0; envs[i] != NULL; i++) {
-        base = getenv(envs[i]);
-        if (base == NULL)
-            continue;
-        length = strlen(base) + 1 + strlen(file) + 1;
-        path = malloc(length);
-        if (path == NULL)
-            sysbail("cannot allocate memory");
-        sprintf(path, "%s/%s", base, file);
-        if (access(path, R_OK) == 0)
-            break;
-        free(path);
-        path = NULL;
-    }
-    return path;
-}
-
-
-/*
- * Free a path returned from test_file_path().  This function exists primarily
- * for Windows, where memory must be freed from the same library domain that
- * it was allocated from.
- */
-void
-test_file_path_free(char *path)
-{
-    if (path != NULL)
-        free(path);
-}
diff --git a/tests/tap/basic.h b/tests/tap/basic.h
deleted file mode 100644 (file)
index a3475d9..0000000
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * Basic utility routines for the TAP protocol.
- *
- * This file is part of C TAP Harness.  The current version plus supporting
- * documentation is at <http://www.eyrie.org/~eagle/software/c-tap-harness/>.
- *
- * Copyright 2009, 2010 Russ Allbery <rra@stanford.edu>
- * Copyright 2001, 2002, 2004, 2005, 2006, 2007, 2008
- *     The Board of Trustees of the Leland Stanford Junior University
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
-
-#ifndef TAP_BASIC_H
-#define TAP_BASIC_H 1
-
-#include <stdarg.h>             /* va_list */
-#include <sys/types.h>          /* pid_t */
-
-/*
- * __attribute__ is available in gcc 2.5 and later, but only with gcc 2.7
- * could you use the __format__ form of the attributes, which is what we use
- * (to avoid confusion with other macros).
- */
-#ifndef __attribute__
-# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 7)
-#  define __attribute__(spec)   /* empty */
-# endif
-#endif
-
-/*
- * BEGIN_DECLS is used at the beginning of declarations so that C++
- * compilers don't mangle their names.  END_DECLS is used at the end.
- */
-#undef BEGIN_DECLS
-#undef END_DECLS
-#ifdef __cplusplus
-# define BEGIN_DECLS    extern "C" {
-# define END_DECLS      }
-#else
-# define BEGIN_DECLS    /* empty */
-# define END_DECLS      /* empty */
-#endif
-
-/*
- * Used for iterating through arrays.  ARRAY_SIZE returns the number of
- * elements in the array (useful for a < upper bound in a for loop) and
- * ARRAY_END returns a pointer to the element past the end (ISO C99 makes it
- * legal to refer to such a pointer as long as it's never dereferenced).
- */
-#define ARRAY_SIZE(array)       (sizeof(array) / sizeof((array)[0]))
-#define ARRAY_END(array)        (&(array)[ARRAY_SIZE(array)])
-
-BEGIN_DECLS
-
-/*
- * The test count.  Always contains the number that will be used for the next
- * test status.
- */
-extern unsigned long testnum;
-
-/* Print out the number of tests and set standard output to line buffered. */
-void plan(unsigned long count);
-
-/*
- * Prepare for lazy planning, in which the plan will be  printed automatically
- * at the end of the test program.
- */
-void plan_lazy(void);
-
-/* Skip the entire test suite.  Call instead of plan. */
-void skip_all(const char *format, ...)
-    __attribute__((__noreturn__, __format__(printf, 1, 2)));
-
-/*
- * Basic reporting functions.  The okv() function is the same as ok() but
- * takes the test description as a va_list to make it easier to reuse the
- * reporting infrastructure when writing new tests.
- */
-void ok(int success, const char *format, ...)
-    __attribute__((__format__(printf, 2, 3)));
-void okv(int success, const char *format, va_list args);
-void skip(const char *reason, ...)
-    __attribute__((__format__(printf, 1, 2)));
-
-/* Report the same status on, or skip, the next count tests. */
-void ok_block(unsigned long count, int success, const char *format, ...)
-    __attribute__((__format__(printf, 3, 4)));
-void skip_block(unsigned long count, const char *reason, ...)
-    __attribute__((__format__(printf, 2, 3)));
-
-/* Check an expected value against a seen value. */
-void is_int(long wanted, long seen, const char *format, ...)
-    __attribute__((__format__(printf, 3, 4)));
-void is_double(double wanted, double seen, double epsilon,
-               const char *format, ...)
-    __attribute__((__format__(printf, 4, 5)));
-void is_string(const char *wanted, const char *seen, const char *format, ...)
-    __attribute__((__format__(printf, 3, 4)));
-void is_hex(unsigned long wanted, unsigned long seen, const char *format, ...)
-    __attribute__((__format__(printf, 3, 4)));
-
-/* Bail out with an error.  sysbail appends strerror(errno). */
-void bail(const char *format, ...)
-    __attribute__((__noreturn__, __nonnull__, __format__(printf, 1, 2)));
-void sysbail(const char *format, ...)
-    __attribute__((__noreturn__, __nonnull__, __format__(printf, 1, 2)));
-
-/* Report a diagnostic to stderr prefixed with #. */
-void diag(const char *format, ...)
-    __attribute__((__nonnull__, __format__(printf, 1, 2)));
-void sysdiag(const char *format, ...)
-    __attribute__((__nonnull__, __format__(printf, 1, 2)));
-
-/*
- * Find a test file under BUILD or SOURCE, returning the full path.  The
- * returned path should be freed with test_file_path_free().
- */
-char *test_file_path(const char *file)
-    __attribute__((__malloc__, __nonnull__));
-void test_file_path_free(char *path);
-
-END_DECLS
-
-#endif /* TAP_BASIC_H */
diff --git a/tests/tap/libtap.sh b/tests/tap/libtap.sh
deleted file mode 100644 (file)
index bf2d191..0000000
+++ /dev/null
@@ -1,222 +0,0 @@
-# Shell function library for test cases.
-#
-# This file provides a TAP-compatible shell function library useful for
-# writing test cases.  It is part of C TAP Harness, which can be found at
-# <http://www.eyrie.org/~eagle/software/c-tap-harness/>.
-#
-# Written by Russ Allbery <rra@stanford.edu>
-# Copyright 2009, 2010 Russ Allbery <rra@stanford.edu>
-# Copyright 2006, 2007, 2008
-#     The Board of Trustees of the Leland Stanford Junior University
-#
-# Permission is hereby granted, free of charge, to any person obtaining a copy
-# of this software and associated documentation files (the "Software"), to
-# deal in the Software without restriction, including without limitation the
-# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
-# sell copies of the Software, and to permit persons to whom the Software is
-# furnished to do so, subject to the following conditions:
-#
-# The above copyright notice and this permission notice shall be included in
-# all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
-# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
-# IN THE SOFTWARE.
-
-# Print out the number of test cases we expect to run.
-plan () {
-    count=1
-    planned="$1"
-    failed=0
-    echo "1..$1"
-    trap finish 0
-}
-
-# Prepare for lazy planning.
-plan_lazy () {
-    count=1
-    planned=0
-    failed=0
-    trap finish 0
-}
-
-# Report the test status on exit.
-finish () {
-    local highest looks
-    highest=`expr "$count" - 1`
-    if [ "$planned" = 0 ] ; then
-        echo "1..$highest"
-        planned="$highest"
-    fi
-    looks='# Looks like you'
-    if [ "$planned" -gt 0 ] ; then
-        if [ "$planned" -gt "$highest" ] ; then
-            if [ "$planned" -gt 1 ] ; then
-                echo "$looks planned $planned tests but only ran $highest"
-            else
-                echo "$looks planned $planned test but only ran $highest"
-            fi
-        elif [ "$planned" -lt "$highest" ] ; then
-            local extra
-            extra=`expr "$highest" - "$planned"`
-            if [ "$planned" -gt 1 ] ; then
-                echo "$looks planned $planned tests but ran $extra extra"
-            else
-                echo "$looks planned $planned test but ran $extra extra"
-            fi
-        elif [ "$failed" -gt 0 ] ; then
-            if [ "$failed" -gt 1 ] ; then
-                echo "$looks failed $failed tests of $planned"
-            else
-                echo "$looks failed $failed test of $planned"
-            fi
-        elif [ "$planned" -gt 1 ] ; then
-            echo "# All $planned tests successful or skipped"
-        else
-            echo "# $planned test successful or skipped"
-        fi
-    fi
-}
-
-# Skip the entire test suite.  Should be run instead of plan.
-skip_all () {
-    local desc
-    desc="$1"
-    if [ -n "$desc" ] ; then
-        echo "1..0 # skip $desc"
-    else
-        echo "1..0 # skip"
-    fi
-    exit 0
-}
-
-# ok takes a test description and a command to run and prints success if that
-# command is successful, false otherwise.  The count starts at 1 and is
-# updated each time ok is printed.
-ok () {
-    local desc
-    desc="$1"
-    if [ -n "$desc" ] ; then
-        desc=" - $desc"
-    fi
-    shift
-    if "$@" ; then
-        echo ok $count$desc
-    else
-        echo not ok $count$desc
-        failed=`expr $failed + 1`
-    fi
-    count=`expr $count + 1`
-}
-
-# Skip the next test.  Takes the reason why the test is skipped.
-skip () {
-    echo "ok $count # skip $*"
-    count=`expr $count + 1`
-}
-
-# Report the same status on a whole set of tests.  Takes the count of tests,
-# the description, and then the command to run to determine the status.
-ok_block () {
-    local end i desc
-    i=$count
-    end=`expr $count + $1`
-    shift
-    desc="$1"
-    shift
-    while [ "$i" -lt "$end" ] ; do
-        ok "$desc" "$@"
-        i=`expr $i + 1`
-    done
-}
-
-# Skip a whole set of tests.  Takes the count and then the reason for skipping
-# the test.
-skip_block () {
-    local i end
-    i=$count
-    end=`expr $count + $1`
-    shift
-    while [ "$i" -lt "$end" ] ; do
-        skip "$@"
-        i=`expr $i + 1`
-    done
-}
-
-# Portable variant of printf '%s\n' "$*".  In the majority of cases, this
-# function is slower than printf, because the latter is often implemented
-# as a builtin command.  The value of the variable IFS is ignored.
-puts () {
-    cat << EOH
-$@
-EOH
-}
-
-# Run a program expected to succeed, and print ok if it does and produces the
-# correct output.  Takes the description, expected exit status, the expected
-# output, the command to run, and then any arguments for that command.
-# Standard output and standard error are combined when analyzing the output of
-# the command.
-#
-# If the command may contain system-specific error messages in its output,
-# add strip_colon_error before the command to post-process its output.
-ok_program () {
-    local desc w_status w_output output status
-    desc="$1"
-    shift
-    w_status="$1"
-    shift
-    w_output="$1"
-    shift
-    output=`"$@" 2>&1`
-    status=$?
-    if [ $status = $w_status ] && [ x"$output" = x"$w_output" ] ; then
-        ok "$desc" true
-    else
-        echo "#  saw: ($status) $output"
-        echo "#  not: ($w_status) $w_output"
-        ok "$desc" false
-    fi
-}
-
-# Strip a colon and everything after it off the output of a command, as long
-# as that colon comes after at least one whitespace character.  (This is done
-# to avoid stripping the name of the program from the start of an error
-# message.)  This is used to remove system-specific error messages (coming
-# from strerror, for example).
-strip_colon_error() {
-    local output status
-    output=`"$@" 2>&1`
-    status=$?
-    output=`puts "$output" | sed 's/^\([^ ]* [^:]*\):.*/\1/'`
-    puts "$output"
-    return $status
-}
-
-# Bail out with an error message.
-bail () {
-    echo 'Bail out!' "$@"
-    exit 1
-}
-
-# Output a diagnostic on standard error, preceded by the required # mark.
-diag () {
-    echo '#' "$@"
-}
-
-# Search for the given file first in $BUILD and then in $SOURCE and echo the
-# path where the file was found, or the empty string if the file wasn't
-# found.
-test_file_path () {
-    if [ -n "$BUILD" ] && [ -f "$BUILD/$1" ] ; then
-        puts "$BUILD/$1"
-    elif [ -n "$SOURCE" ] && [ -f "$SOURCE/$1" ] ; then
-        puts "$SOURCE/$1"
-    else
-        echo ''
-    fi
-}
index f99a959..763ac89 100644 (file)
@@ -5,7 +5,7 @@ abs_top_builddir=@abs_top_builddir@
 include @TOP_OBJDIR@/src/config/Makefile.config
 include @TOP_OBJDIR@/src/config/Makefile.lwp
 
-MODULE_CFLAGS = -I$(srcdir)/..
+MODULE_CFLAGS = -I$(srcdir)/../..
 
 LIBS = ../tap/libtap.a \
        $(abs_top_builddir)/lib/util.a \
index f8921a0..69a41c0 100644 (file)
@@ -11,7 +11,7 @@
 #include <afs/param.h>
 
 #include <afs/afsutil.h>
-#include <tap/basic.h>
+#include <tests/tap/basic.h>
 
 #include <unistd.h>
 #include <sys/types.h>
index d9793bb..9609fbb 100644 (file)
@@ -19,7 +19,7 @@
 #include <afs/ktime.h>
 #include <afs/afsutil.h>
 #include <afs/afsutil_prototypes.h>
-#include <tap/basic.h>
+#include <tests/tap/basic.h>
 
 static struct testTime {
     char *time;
index 15f9def..ad11dda 100644 (file)
@@ -6,7 +6,7 @@ include @TOP_OBJDIR@/src/config/Makefile.pthread
 
 TESTS = vos-t
 
-MODULE_CFLAGS=-I$(srcdir)/.. -I$(srcdir)/../common/
+MODULE_CFLAGS=-I$(srcdir)/../.. -I$(srcdir)/../common/
 
 all check test tests: $(TESTS)
 
index 8eb32ea..dc8f64e 100644 (file)
@@ -12,7 +12,7 @@
 #include <afs/vldbint.h>
 #include <afs/cellconfig.h>
 
-#include <tap/basic.h>
+#include <tests/tap/basic.h>
 
 #include "common.h"