Import of code from c-tap-harness
authorRuss Allbery <rra@stanford.edu>
Fri, 11 May 2012 20:16:22 +0000 (21:16 +0100)
committerDerrick Brashear <shadow@dementix.org>
Fri, 11 May 2012 23:36:06 +0000 (16:36 -0700)
This commit updates the code imported from c-tap-harness to
d3fc03606efc8e76ff34f04470e6133db25a3982 (release/1.12)

New files are:
LICENSE
NEWS
README
tests/runtests.c
tests/tap/basic.c
tests/tap/basic.h
tests/tap/float.c
tests/tap/float.h
tests/tap/libtap.sh
tests/tap/macros.h

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

src/external/c-tap-harness-last [new file with mode: 0644]
src/external/c-tap-harness/LICENSE [new file with mode: 0644]
src/external/c-tap-harness/NEWS [new file with mode: 0644]
src/external/c-tap-harness/README [new file with mode: 0644]
src/external/c-tap-harness/tests/runtests.c [new file with mode: 0644]
src/external/c-tap-harness/tests/tap/basic.c [new file with mode: 0644]
src/external/c-tap-harness/tests/tap/basic.h [new file with mode: 0644]
src/external/c-tap-harness/tests/tap/float.c [new file with mode: 0644]
src/external/c-tap-harness/tests/tap/float.h [new file with mode: 0644]
src/external/c-tap-harness/tests/tap/libtap.sh [new file with mode: 0644]
src/external/c-tap-harness/tests/tap/macros.h [new file with mode: 0644]

diff --git a/src/external/c-tap-harness-last b/src/external/c-tap-harness-last
new file mode 100644 (file)
index 0000000..3420957
--- /dev/null
@@ -0,0 +1 @@
+d3fc03606efc8e76ff34f04470e6133db25a3982
diff --git a/src/external/c-tap-harness/LICENSE b/src/external/c-tap-harness/LICENSE
new file mode 100644 (file)
index 0000000..5f95816
--- /dev/null
@@ -0,0 +1,138 @@
+The C TAP Harness package as a whole is:
+
+  Copyright 2000, 2001, 2004, 2006, 2007, 2008, 2009, 2010, 2011, 2012
+      Russ Allbery <rra@stanford.edu>
+  Copyright 2006, 2007, 2008, 2009, 2011, 2012
+      The Board of Trustees of the Leland Stanford Junior University
+
+and released under the following license:
+
+  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.
+
+All individual files without an explicit exception below are released
+under this license.  Some files may have additional copyright holders as
+noted in those files.
+
+Some files in this distribution are individually released under different
+licenses, all of which are compatible with the above general package
+license but which may require preservation of additional notices.  All
+required notices are preserved in this file.  Of the files intended to be
+copied into other packages, only docs/writing-tests has a different
+license notice, and its requirements are met by preserving the license
+section of that document in any derivative works.
+
+Collected copyright notices for the entire package:
+
+  Copyright 2000, 2001, 2004, 2006, 2007, 2008, 2009, 2010, 2011, 2012
+      Russ Allbery <rra@stanford.edu>
+  Copyright 2006, 2007, 2008, 2009, 2011, 2012
+      The Board of Trustees of the Leland Stanford Junior University
+  Copyright 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
+      2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
+      Free Software Foundation, Inc.
+  Copyright 1994 X Consortium
+
+The file docs/writing-tests is released under the following license:
+
+  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.
+
+The files Makefile.in and aclocal.m4 are generated by GNU Automake and
+released under the following copyright and license:
+
+  Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+  2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software
+  Foundation, Inc.  This file is free software; the Free Software
+  Foundation gives unlimited permission to copy and/or distribute it, with
+  or without modifications, as long as this notice is preserved.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+  even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+  PARTICULAR PURPOSE.
+
+The file configure is generated by GNU Autoconf and is released under the
+following copyright and license:
+
+  Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
+  2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software
+  Foundation, Inc.  This configure script is free software; the Free
+  Software Foundation gives unlimited permission to copy, distribute and
+  modify it.
+
+The files build-aux/compile, build-aux/depcomp, and build-aux/missing are
+taken from GNU Automake and are released under the following copyright and
+license:
+
+  Copyright (C) 1996, 1997, 1999, 2000, 2002, 2003, 2004, 2005, 2006,
+  2007, 2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc.
+
+  This program is free software; you can redistribute it and/or modify it
+  under the terms of the GNU General Public License as published by the
+  Free Software Foundation; either version 2, or (at your option) any
+  later version.
+
+  This program is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  General Public License for more details.
+
+  As a special exception to the GNU General Public License, if you
+  distribute this file as part of a program that contains a configuration
+  script generated by Autoconf, you may include it under the same
+  distribution terms that you use for the rest of that program.
+
+For the C TAP Harness distribution, the option described in the last
+paragraph has been accepted and these files are distributed under the same
+terms as the C TAP Harness package as a whole, as described at the top of
+this file.
+
+The file build-aux/install-sh is released under the following copyright
+and license:
+
+  Copyright (C) 1994 X Consortium
+
+  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 X CONSORTIUM 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.
+
+  Except as contained in this notice, the name of the X Consortium shall
+  not be used in advertising or otherwise to promote the sale, use or
+  other dealings in this Software without prior written authorization
+  from the X Consortium.
+
+  FSF changes to this file are in the public domain.
diff --git a/src/external/c-tap-harness/NEWS b/src/external/c-tap-harness/NEWS
new file mode 100644 (file)
index 0000000..be4aba8
--- /dev/null
@@ -0,0 +1,285 @@
+                    User-Visible C TAP Harness Changes
+
+C TAP Harness 1.12 (2012-05-11)
+
+    Fix additional uses of local in the shell TAP library for portability
+    to Solaris /bin/sh and document a bad interaction between backquotes
+    and double quotes for the puts, test_file_path, and test_tmpdir
+    functions.
+
+    In the C TAP library, if bail is called after plan_lazy but before any
+    tests are run, don't output the plan or the summary of test results.
+
+    Add the UNUSED macro (to mark possibly-usused variables for gcc) to
+    tests/tap/macros.h for use in the C TAP library.
+
+    Make the __attribute__ handling in tests/tap/macros.h more aware of
+    different versions and compilers.  All attributes are now suppressed
+    for GCC older than 2.96 (instead of 2.7), since __malloc__ became
+    available then.  __alloc_size__ is suppressed for GCC older than 4.3.
+    Warnings about unknown diagnostics are suppressed for LLVM and Clang,
+    which pretend to be GCC but don't support all the same attributes.
+
+C TAP Harness 1.11 (2012-04-25)
+
+    Reorganize the source package so that runtests.c is in the tests
+    directory and the C and shell TAP libraries are in tests/tap.  Change
+    the include directives in the C TAP library source files accordingly.
+    This is somewhat confusing for the standalone package, but means that
+    the files are located in the same locations here as they would be in
+    packages into which they're copied, which simplifies instructions and
+    the build system.  This also removes the need to build the C TAP
+    library with -I flags at the cost of requiring that it be located in a
+    tests subdirectory, allowing easier use of additional supporting
+    headers without requiring that all tests be built with a -I directive.
+
+    Do not attempt to use feature-test macros unless compiled with gcc's
+    -ansi flag or PEDANTIC is defined.  Defining _XOPEN_SOURCE 600 on
+    Solaris 10, which is required for isinf() if feature-test macros are
+    in use, causes compilation to fail unless the compiler is run in C99
+    mode due to an ABI change.  The basic TAP library doesn't care about
+    this distinction and doesn't want to force specific compiler flags, so
+    avoiding feature-test macros is a better fix.  Thanks to Bob
+    Friesenhahn for the bug report.
+
+    Do not use local in the shell TAP library.  Solaris /bin/sh doesn't
+    support it, and the shell library is otherwise portable to that shell.
+    Instead, use a prefix of tap_ on all non-public variables.
+
+    Move the __attribute__ and BEGIN_DECLS/END_DECLS macros from
+    tests/tap/basic.h to a new tests/tap/macros.h header file so that they
+    can be more easily reused by any other TAP add-on.  Be sure to copy
+    tests/tap/macros.h into your source package and add it to the source
+    files for the libtap library when upgrading.
+
+    Move the is_double C TAP test function into a separate source file.
+    Including this function may require linking with libm on some
+    platforms, which is undesireable if the package otherwise doesn't use
+    math functions.  The new tests/tap/float.c and tests/tap/float.h files
+    need only be included in a package that wants to do floating point
+    tests.  Users of is_double will now need to include tests/tap/float.h
+    in addition to tests/tap/basic.h (and link all clients of the libtap
+    library with -lm).
+
+C TAP Harness 1.10 (2012-02-29)
+
+    Add bstrndup to the basic C TAP library.  This is akin to strndup
+    (copying at most n characters of the string), but calls sysbail if
+    memory allocation fails.
+
+C TAP Harness 1.9 (2011-12-24)
+
+    Add test_tmpdir and test_tmpdir_free functions to the basic C TAP
+    library and a test_tmpdir function to the shell TAP library.  These
+    functions create a temporary directory under the build tests directory
+    for tests to use for transient files.
+
+    runtests now frees all allocated resources on exit so that it can be
+    used to run test cases with valgrind memory allocation checking
+    without adding false positives.
+
+C TAP Harness 1.8 (2011-09-02)
+
+    Add bmalloc, bcalloc, brealloc, and bstrdup functions to the basic C
+    TAP library.  These functions call sysbail if memory allocation fails.
+
+    If BUILD were not set when building runtests and the -b option was not
+    present, SOURCE and the -s option would be ignored when searching for
+    tests.  Fix runtests to still honor SOURCE and -s when searching for
+    tests even in that case.
+
+C TAP Harness 1.7 (2011-04-28)
+
+    Add a more complete usage message to runtests and add support for a -h
+    command-line flag to display the usage message.
+
+C TAP Harness 1.6 (2010-12-29)
+
+    is_double() now takes a third argument, an epsilon.  Two numbers are
+    considered equal if their absolute difference is less than epsilon.
+    is_double() also now treats wanted and seen values of NaN (not a
+    number) as equal.  Thanks to PICCA Frédéric-Emmanuel for the proposed
+    changes.
+
+    The ok_program function in the shell libtap.sh library no longer
+    strips text after a colon and a space from the program output if the
+    expected status is non-zero.  Instead, if program output may contain
+    system-specific error messages after a colon and a space, put the new
+    function strip_colon_error before the program to do this stripping.
+    Thanks to Carsten Hey for the idea.
+
+    strip_colon_error is now smarter about preserving an initial word
+    ending in a colon (which is generally the program name) while still
+    stripping error messages later in the line.
+
+    The test_file_path function in the shell libtap.sh library now always
+    returns the empty string, rather than possible absolute paths starting
+    at /, if $BUILD and $SOURCE are not set.
+
+    Flush standard error in the C TAP library before printing results for
+    more deterministic output.  Thanks to Carsten Hey for the idea.
+
+    All of C TAP Harness now compiles with gcc -ansi -pedantic and should
+    be fully C89-compatible.  Note that either C99 or SUSv3 is required to
+    build C TAP Harness.  (This should not be a problem on any modern
+    platform.)  Based on work by Carsten Hey.
+
+    Simplify and improve output formatting in the summary of failing tests
+    in some edge cases.
+
+    Add explicit license statements to the files meant to be copied into
+    other packages rather than referring to LICENSE.
+
+C TAP Harness 1.5 (2010-08-25)
+
+    In ok_program in the shell TAP library, strip error output after the
+    second colon, not after the first.  This code helps comparing error
+    output that includes system error messages, but needs to skip past the
+    first colon, since it separates the program name from the error
+    message.
+
+    runtests.c now builds without warnings with gcc -Wswitch-enum.
+
+C TAP Harness 1.4 (2010-07-07)
+
+    Add a test_file_path() function to the basic C and shell TAP
+    libraries, which searches the build and source directories for a
+    particular file and returns the full path.  This is a utility function
+    that can be used to find test data files.
+
+C TAP Harness 1.3 (2010-06-09)
+
+    Add API documentation for the functions provided by the basic TAP C
+    library.  The documentation is in POD and *roff format in docs/api and
+    installed as man pages in the (generally unused) case of make install.
+
+    Add docs/writing-tests, which provides some basic instructions for how
+    to write TAP tests in Perl, C, and shell using the facilities provided
+    by C TAP Harness.  This document is suitable for inclusion in packages
+    that use C TAP Harness as instructions for contributors.
+
+    Add an okv() function to the C TAP library.  This is the same as ok()
+    but takes the test description as a va_list to make it easier to reuse
+    the reporting infrastructure in other tests.
+
+C TAP Harness 1.2 (2010-04-13)
+
+    Support giving the plan at any point in the test output rather than
+    requiring it be first.  The TAP protocol permits giving the plan last
+    instead of first, but since it's just as easy to support providing the
+    plan in the middle of the test output, allow that as well.
+
+    Add support for lazy planning to the basic TAP library.  Instead of
+    calling plan at the start of the test, call plan_lazy instead, which
+    doesn't require specifying a test count.  Then, the plan will
+    automatically be printed based on the last test number at the end of
+    the program.  This is not the recommended approach for writing tests
+    since, should the test program exit in the middle for some reason,
+    everything will appear to succeed.  But it can save time in writing
+    tests quickly and allows for dynamic numbers of tests.
+
+    Add diag and sysdiag functions to the basic TAP library, which output
+    diagnostics to standard error preceded by the protocol-required #
+    character.
+
+    Clean up data types in the basic C TAP library.  Test numbers and
+    counts are now unsigned long, and ok_int compares longs.
+
+    Add the GCC nonnull attribute to the bail functions in the TAP
+    library.
+
+C TAP Harness 1.1 (2009-08-15)
+
+    Set an exit handler in libtap that prints a summary of the test
+    results at the end of a test script, similar to Perl's Test::More.
+
+    When looking for 0..1 # skip plan lines indicating the whole test case
+    should be skipped, correctly compare "skip" case-insensitively.  This
+    fixes interoperability with Perl's Test::More.
+
+    Consume all output from the test case before closing its file
+    descriptor, even if the case is aborted due to bailing out or sending
+    an invalid test number.  This prevents tests from spuriously dying
+    with SIGPIPE.
+
+    Enable Automake silent rules.  For a quieter build, pass the
+    --enable-silent-rules option to configure or build with make V=0.
+
+C TAP Harness 1.0 (2009-05-21)
+
+    Initial public release based on the version of runtests.c and the
+    libtest library that shipped with remctl 2.13.  The changes below are
+    relative to that version.
+
+    Set the SOURCE and BUILD environment variables when running tests to
+    the roots of the source and build test directories if set at compile
+    time or via the -s and -b command-line options to runtests.
+
+    Search for test programs first in the current directory and then in
+    the build and source directories, in that order, as specified by
+    SOURCE and BUILD or by the -s and -b options.  This allows some tests
+    to be compiled and some shipped with the package and merged together
+    at run time by runtests, even if the build directory is not the source
+    directory.
+
+    Support running a single test program with the -o command-line option.
+    This is mostly interesting to take advantage of the environment
+    variables and test searching algorithm described above.
+
+    Add support for 0..1 # skip <reason> plan lines, indicating that the
+    entire test case should be skipped.
+
+    Add support for aborting a test case with "Bail out!" and reporting
+    the reason given on that line.
+
+    Add support for omitting the test number from an "ok" or "not ok"
+    line, in which case the number is assumed to be one more than the
+    previous number.
+
+    Add support for todo tests, which are recorded as skipped if failing
+    and failed if they succeed unexpectedly.
+
+    Omitting the space after "ok" or "not ok" line is now supported, and a
+    test number of 0 now results in an error.
+
+    Recognize skip directives regardless of case.
+
+    Change the reporting of reasons to abort the test case to use ABORTED
+    and the abort reason in parentheses for more consistent output.
+
+    Rename test_init() to plan() and ok_int(), ok_double(), and
+    ok_string() to is_int(), is_double(), and is_string() in the C TAP
+    library to more closely match the function names in Perl's test
+    modules.
+
+    Add is_hex() C TAP library function to compare two unsigned longs and
+    print mismatches in hex.
+
+    Change all C library functions to take a test description
+    (printf-style) and to no longer take the test number.  Instead, keep a
+    static count of the current test number.
+
+    Add bail() and sysbail() C TAP library functions to bail out with the
+    right magic output string.
+
+    Add skip_all() C TAP library function to skip all tests and exit.
+
+    Stop exporting the printcount interface in the shell version of the
+    TAP library.  Instead, provide plan, skip_all, ok, skip, ok_block,
+    skip_block, ok_program, and bail shell functions, similar to the C
+    library interface, with the ok* functions taking a test description as
+    the first argument.
+
+    Show mismatch output from the is_*() functions before the "not ok"
+    line instead of after it.
+
+    Add the initial "1.." to plan() output for better TAP compliance.
+
+    Support either "-t" or ".t" as the ending of test cases.
+
+    Remove the dependency on both config.h and the general portability
+    framework and instead include the necessary C headers directly.  This
+    requires ANSI C.
+
+    Remove the functions from libtap that assume libutil from rra-c-util.
+    Those library functions will be provided by that package.
diff --git a/src/external/c-tap-harness/README b/src/external/c-tap-harness/README
new file mode 100644 (file)
index 0000000..ddcfc91
--- /dev/null
@@ -0,0 +1,228 @@
+                            C TAP Harness 1.12
+               (C harness for running TAP-compliant tests)
+
+                Written by Russ Allbery <rra@stanford.edu>
+
+  Copyright 2000, 2001, 2004, 2006, 2007, 2008, 2009, 2010, 2011, 2012
+  Russ Allbery <rra@stanford.edu>.  This software is distributed under a
+  BSD-style license.  Please see the file LICENSE in the distribution for
+  more information.
+
+BLURB
+
+  C TAP Harness is a pure-C implementation of TAP, the Test Anything
+  Protocol.  TAP is the text-based protocol used by Perl's test suite.
+  This package provides a harness similar to Perl's Test::Harness for
+  running tests, with some additional features useful for test suites in
+  packages that use Autoconf and Automake, and C and shell libraries to
+  make writing TAP-compliant test programs easier.
+
+DESCRIPTION
+
+  This package started as the runtests program I wrote for INN in 2000 to
+  serve as the basis for a new test suite using a test protocol similar to
+  that used for Perl modules.  When I started maintaining additional C
+  packages, I adopted runtests for the test suite driver of those as well,
+  resulting in further improvements but also separate copies of the same
+  program in different distributions.  The C TAP Harness distribution
+  merges all the various versions into a single code base that all my
+  packages can pull from.
+
+  C TAP Harness provides a full TAP specification (apart from a few
+  possible edge cases) and has additional special features for supporting
+  builds outside the source directory.  It's mostly useful for packages
+  using Autoconf and Automake and because it doesn't assume or require
+  Perl.
+
+  The runtests program can be built with knowledge of the source and build
+  directory and pass that knowledge on to test scripts, and will search
+  for test scripts in both the source and build directory.  This makes it
+  easier for packages using Autoconf and Automake and supporting
+  out-of-tree builds to build some test programs, ship others, and run
+  them all regardless of what tree they're in.  It also makes it easier
+  for test cases to find their supporting files when they run.
+
+  Also included in this package are C and shell libraries that provide
+  utility functions for writing test scripts that use TAP to report
+  exists.
+
+REQUIREMENTS
+
+  C TAP Harness requires a C compiler to build.  Any ISO C89 or later C
+  compiler on a system supporting the Single UNIX Specification, version 3
+  (SUSv3) should be sufficient.  This should not be a problem on any
+  modern system.  The test suite and shell library require a
+  Bourne-compatible shell.  Outside of the test suite, C TAP Harness has
+  no other prerequisites or requirements.
+
+  To run the test suite, you will need Perl plus the Perl modules
+  Test::More and Test::Pod.  Test::More comes with Perl 5.8 and later.
+  Test::Pod is available from CPAN and currently must be installed
+  separately, but the POD tests will be skipped without interfering with
+  the rest of the tests if it's not installed.
+
+  To check spelling in the POD documentation, Pod::Spell (available from
+  CPAN) and either aspell or ispell with the american dictionary are also
+  required.  The user's path is searched for aspell or ispell and aspell
+  is preferred.  Spelling tests are disabled by default since spelling
+  dictionaries differ too much between systems.  To enable those tests,
+  set RRA_MAINTAINER_TESTS to a true value.
+
+  To bootstrap from a Git checkout, or if you change the Automake files
+  and need to regenerate Makefile.in, you will need Automake 1.11 or
+  later.  For bootstrap or if you change configure.ac or any of the m4
+  files it includes and need to regenerate configure or config.h.in, you
+  will need Autoconf 2.64 or later.  Perl is also required to generate the
+  manual page from a fresh Git checkout.
+
+BUILDING AND TESTING
+
+  You can build C TAP Harness and run its internal test suite with:
+
+      ./configure
+      make
+      make check
+
+  While there is a configure script, it exists just to drive the build
+  system and do some path substitution and isn't doing portability
+  probes.  Pass --enable-silent-rules to configure for a quieter build
+  (similar to the Linux kernel).
+
+  Use make warnings instead of make to build with full GCC compiler
+  warnings (requires a relatively current version of GCC).
+
+  If a test fails, you can run a single test with verbose output via:
+
+      ./runtests -b `pwd`/tests -s `pwd`/tests -o <name-of-test>
+
+  Do this instead of running the test program directly since it will
+  ensure that necessary environment variables are set up.  You may need to
+  change the -s option if you build with a separate build directory from
+  the source directory.
+
+USING THE HARNESS
+
+  While there is an install target that installs runtests in the default
+  binary directory (/usr/local/bin by default) and installs the man pages,
+  one normally wouldn't install anything from this package.  Instead, the
+  code is intended to be copied into your package and refreshed from the
+  latest release of C TAP Harness for each release.
+
+  You can obviously copy the code and integrate it however works best for
+  your package and your build system.  Here's how I do it for my packages
+  as an example:
+
+  * Create a tests directory and copy tests/runtests.c into it.  Create a
+    tests/tap subdirectory and copy the portions of the TAP library (from
+    tests/tap) that I need for that package into it.  The TAP library is
+    designed to let you drop in additional source and header files for
+    additional utility functions that are useful in your package.
+
+  * Add code to my top-level Makefile.am (I always use a non-recursive
+    Makefile with subdir-objects set) to build runtests and the test
+    library:
+
+        check_PROGRAMS = tests/runtests
+        tests_runtests_CPPFLAGS = -DSOURCE='"$(abs_top_srcdir)/tests"' \
+                -DBUILD='"$(abs_top_builddir)/tests"'
+        check_LIBRARIES = tests/tap/libtap.a
+        tests_tap_libtap_a_CPPFLAGS = -I$(abs_top_srcdir)/tests
+        tests_tap_libtap_a_SOURCES = tests/tap/basic.c tests/tap/basic.h \
+                tests/tap/float.c tests/tap/float.h tests/tap/macros.h
+
+    Omit float.c and float.h from the last line if your package doesn't
+    need the is_double function.  Building the build and source
+    directories into runtests will let tests/runtests -o <test> to work
+    for users without requiring that they set any other variables, even if
+    they're doing an out-of-source build.
+
+    Add additional source files and headers that should go into the TAP
+    library if you added extra utility functions for your package.
+
+  * Add code to Makefile.am to run the test suite:
+
+        check-local: $(check_PROGRAMS)
+              cd tests && ./runtests $(abs_top_srcdir)/tests/TESTS
+
+    See the Makefile.am in this package for an example (although note that
+    it keeps runtests in an unusual location).
+
+  * List the test programs in the TESTS file.  This should have the name
+    of the test executable with the trailing "-t" or ".t" (you can use
+    either extension as you prefer) omitted.  For any test programs that
+    need to be compiled, add build rules for them in Makefile.am, simliar
+    to:
+
+        tests_libtap_c_basic_LDADD = tests/tap/libtap.a
+
+    and add them to check_PROGRAMS.  If you include the float.c add-on in
+    your libtap library, you will need to add -lm to the _LDADD setting
+    for all test programs linked against it.
+
+    A more complex example from the remctl package that needs additional
+    libraries:
+
+        tests_client_open_t_LDFLAGS = $(GSSAPI_LDFLAGS)
+        tests_client_open_t_LDADD = client/libremctl.la tests/tap/libtap.a \
+                util/libutil.la $(GSSAPI_LIBS)
+
+    If the test program doesn't need to be compiled, add it to EXTRA_DIST
+    so that it will be included in the distribution.
+
+  * If you have test programs written in shell, copy tests/tap/libtap.sh
+    the tap subdirectory of your tests directory and add it to EXTRA_DIST.
+    Shell programs should start with:
+
+        . "${SOURCE}/tap/libtap.sh"
+
+    and can then use the functions defined in the library.
+
+  * Optionally copy docs/writing-tests into your package somewhere, such
+    as tests/README, as instructions to contributors on how to write tests
+    for this framework.
+
+  If you have configuration files that the user must create to enable some
+  of the tests, conventionally they go into tests/config.
+
+  If you have data files that your test cases use, conventionally they go
+  into tests/data.  You can then find the data directory relative to the
+  SOURCE environment variable (set by runtests) in your test program.  If
+  you have data that's compiled or generated by Autoconf, it will be
+  relative to the BUILD environment variable.  Don't forget to add test
+  data to EXTRA_DIST as necessary.
+
+  For more TAP library add-ons, generally ones that rely on additional
+  portability code not shipped in this package or with narrower uses, see
+  the rra-c-util package:
+
+      http://www.eyrie.org/~eagle/software/rra-c-util/
+
+  There are several additional TAP library add-ons in the tests/tap
+  directory in that package.  It's also an example of how to use this test
+  harness in another package.
+
+HOMEPAGE AND SOURCE REPOSITORY
+
+  The C TAP Harness web page at:
+
+      http://www.eyrie.org/~eagle/software/c-tap-harness/
+
+  will always have the current version of this package, the current
+  documentation, and pointers to any additional resources.
+
+  C TAP Harness is maintained using Git.  You can access the current
+  source by cloning the repository at:
+
+      git://git.eyrie.org/devel/c-tap-harness.git
+
+  or view the repository via the web at:
+
+      http://git.eyrie.org/?p=devel/c-tap-harness.git
+
+  C TAP Harness is also available via github at:
+
+      http://github.com/rra/c-tap-harness
+
+  and the github wiki and issue tracker are available on an experimental
+  basis.  If you like using the github facilities, try filing issues or
+  adding supplemental documentation there.
diff --git a/src/external/c-tap-harness/tests/runtests.c b/src/external/c-tap-harness/tests/runtests.c
new file mode 100644 (file)
index 0000000..4249875
--- /dev/null
@@ -0,0 +1,1189 @@
+/*
+ * 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(). */
+#if defined(__STRICT_ANSI__) || defined(PEDANTIC)
+# ifndef _XOPEN_SOURCE
+#  define _XOPEN_SOURCE 500
+# endif
+#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; i < 3; i++) {
+        if (bases[i] == NULL)
+            continue;
+        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;
+    fclose(tests);
+
+    /* 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 status = 0;
+    int single = 0;
+    char *source_env = NULL;
+    char *build_env = NULL;
+    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) {
+        source_env = xmalloc(strlen("SOURCE=") + strlen(source) + 1);
+        sprintf(source_env, "SOURCE=%s", source);
+        if (putenv(source_env) != 0)
+            sysdie("cannot set SOURCE in the environment");
+    }
+    if (build != NULL) {
+        build_env = xmalloc(strlen("BUILD=") + strlen(build) + 1);
+        sprintf(build_env, "BUILD=%s", build);
+        if (putenv(build_env) != 0)
+            sysdie("cannot set BUILD in the environment");
+    }
+
+    if (single)
+        test_single(argv[0], source, build);
+    else {
+        list = strrchr(argv[0], '/');
+        if (list == NULL)
+            list = argv[0];
+        else
+            list++;
+        printf(banner, list);
+        status = test_batch(argv[0], source, build) ? 0 : 1;
+    }
+
+    /* For valgrind cleanliness. */
+    if (source_env != NULL) {
+        putenv((char *) "SOURCE=");
+        free(source_env);
+    }
+    if (build_env != NULL) {
+        putenv((char *) "BUILD=");
+        free(build_env);
+    }
+    exit(status);
+}
diff --git a/src/external/c-tap-harness/tests/tap/basic.c b/src/external/c-tap-harness/tests/tap/basic.c
new file mode 100644 (file)
index 0000000..e8196fc
--- /dev/null
@@ -0,0 +1,629 @@
+/*
+ * 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, reporting errors, setting
+ * up the TAP output format, or finding things in the test environment.
+ *
+ * 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, 2011, 2012 Russ Allbery <rra@stanford.edu>
+ * Copyright 2001, 2002, 2004, 2005, 2006, 2007, 2008, 2011, 2012
+ *     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.
+ */
+
+#include <errno.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#ifdef _WIN32
+# include <direct.h>
+#else
+# include <sys/stat.h>
+#endif
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <tests/tap/basic.h>
+
+/* Windows provides mkdir and rmdir under different names. */
+#ifdef _WIN32
+# define mkdir(p, m) _mkdir(p)
+# define rmdir(p)    _rmdir(p)
+#endif
+
+/*
+ * 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.  This also handles
+ * printing out the plan if we used plan_lazy(), although that's suppressed if
+ * we never ran a test (due to an early bail, for example).
+ */
+static void
+finish(void)
+{
+    unsigned long highest = testnum - 1;
+
+    if (_planned == 0 && !_lazy)
+        return;
+    fflush(stderr);
+    if (_process != 0 && getpid() == _process) {
+        if (_lazy && highest > 0) {
+            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 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));
+}
+
+
+/*
+ * Allocate cleared memory, reporting a fatal error with bail on failure.
+ */
+void *
+bcalloc(size_t n, size_t size)
+{
+    void *p;
+
+    p = calloc(n, size);
+    if (p == NULL)
+        sysbail("failed to calloc %lu", (unsigned long)(n * size));
+    return p;
+}
+
+
+/*
+ * Allocate memory, reporting a fatal error with bail on failure.
+ */
+void *
+bmalloc(size_t size)
+{
+    void *p;
+
+    p = malloc(size);
+    if (p == NULL)
+        sysbail("failed to malloc %lu", (unsigned long) size);
+    return p;
+}
+
+
+/*
+ * Reallocate memory, reporting a fatal error with bail on failure.
+ */
+void *
+brealloc(void *p, size_t size)
+{
+    p = realloc(p, size);
+    if (p == NULL)
+        sysbail("failed to realloc %lu bytes", (unsigned long) size);
+    return p;
+}
+
+
+/*
+ * Copy a string, reporting a fatal error with bail on failure.
+ */
+char *
+bstrdup(const char *s)
+{
+    char *p;
+    size_t len;
+
+    len = strlen(s) + 1;
+    p = malloc(len);
+    if (p == NULL)
+        sysbail("failed to strdup %lu bytes", (unsigned long) len);
+    memcpy(p, s, len);
+    return p;
+}
+
+
+/*
+ * Copy up to n characters of a string, reporting a fatal error with bail on
+ * failure.  Don't use the system strndup function, since it may not exist and
+ * the TAP library doesn't assume any portability support.
+ */
+char *
+bstrndup(const char *s, size_t n)
+{
+    const char *p;
+    char *copy;
+    size_t length;
+
+    /* Don't assume that the source string is nul-terminated. */
+    for (p = s; (size_t) (p - s) < n && *p != '\0'; p++)
+        ;
+    length = p - s;
+    copy = malloc(length + 1);
+    if (p == NULL)
+        sysbail("failed to strndup %lu bytes", (unsigned long) length);
+    memcpy(copy, s, length);
+    copy[length] = '\0';
+    return copy;
+}
+
+
+/*
+ * 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 = bmalloc(length);
+        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);
+}
+
+
+/*
+ * Create a temporary directory, tmp, under BUILD if set and the current
+ * directory if it does not.  Returns the path to the temporary directory in
+ * newly allocated memory, and calls bail on any failure.  The return value
+ * should be freed with test_tmpdir_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_tmpdir(void)
+{
+    const char *build;
+    char *path = NULL;
+    size_t length;
+
+    build = getenv("BUILD");
+    if (build == NULL)
+        build = ".";
+    length = strlen(build) + strlen("/tmp") + 1;
+    path = bmalloc(length);
+    sprintf(path, "%s/tmp", build);
+    if (access(path, X_OK) < 0)
+        if (mkdir(path, 0777) < 0)
+            sysbail("error creating temporary directory %s", path);
+    return path;
+}
+
+
+/*
+ * Free a path returned from test_tmpdir() and attempt to remove the
+ * directory.  If we can't delete the directory, don't worry; something else
+ * that hasn't yet cleaned up may still be using it.
+ */
+void
+test_tmpdir_free(char *path)
+{
+    rmdir(path);
+    if (path != NULL)
+        free(path);
+}
diff --git a/src/external/c-tap-harness/tests/tap/basic.h b/src/external/c-tap-harness/tests/tap/basic.h
new file mode 100644 (file)
index 0000000..fa4adaf
--- /dev/null
@@ -0,0 +1,134 @@
+/*
+ * 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, 2011, 2012 Russ Allbery <rra@stanford.edu>
+ * Copyright 2001, 2002, 2004, 2005, 2006, 2007, 2008, 2011, 2012
+ *     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 <tests/tap/macros.h>
+#include <stdarg.h>             /* va_list */
+#include <sys/types.h>          /* size_t */
+
+/*
+ * 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_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)));
+
+/* Allocate memory, reporting a fatal error with bail on failure. */
+void *bcalloc(size_t, size_t)
+    __attribute__((__alloc_size__(1, 2), __malloc__));
+void *bmalloc(size_t)
+    __attribute__((__alloc_size__(1), __malloc__));
+void *brealloc(void *, size_t)
+    __attribute__((__alloc_size__(2), __malloc__));
+char *bstrdup(const char *)
+    __attribute__((__malloc__, __nonnull__));
+char *bstrndup(const char *, size_t)
+    __attribute__((__malloc__, __nonnull__));
+
+/*
+ * 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);
+
+/*
+ * Create a temporary directory relative to BUILD and return the path.  The
+ * returned path should be freed with test_tmpdir_free.
+ */
+char *test_tmpdir(void)
+    __attribute__((__malloc__));
+void test_tmpdir_free(char *path);
+
+END_DECLS
+
+#endif /* TAP_BASIC_H */
diff --git a/src/external/c-tap-harness/tests/tap/float.c b/src/external/c-tap-harness/tests/tap/float.c
new file mode 100644 (file)
index 0000000..67dd555
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * Utility routines for writing floating point tests.
+ *
+ * Currently provides only one function, which checks whether a double is
+ * equal to an expected value within a given epsilon.  This is broken into a
+ * separate source file from the rest of the basic C TAP library because it
+ * may require linking with -lm on some platforms, and the package may not
+ * otherwise care about floating point.
+ *
+ * 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 2008, 2010, 2012 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 isnan() and isinf(). */
+#if defined(__STRICT_ANSI__) || defined(PEDANTIC)
+# ifndef _XOPEN_SOURCE
+#  define _XOPEN_SOURCE 600
+# endif
+#endif
+
+#include <math.h>
+#include <stdarg.h>
+#include <stdio.h>
+
+#include <tests/tap/basic.h>
+#include <tests/tap/float.h>
+
+/*
+ * 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, ...)
+{
+    va_list args;
+
+    va_start(args, format);
+    fflush(stderr);
+    if ((isnan(wanted) && isnan(seen))
+        || (isinf(wanted) && isinf(seen) && wanted == seen)
+        || fabs(wanted - seen) <= epsilon)
+        okv(1, format, args);
+    else {
+        printf("# wanted: %g\n#   seen: %g\n", wanted, seen);
+        okv(0, format, args);
+    }
+}
diff --git a/src/external/c-tap-harness/tests/tap/float.h b/src/external/c-tap-harness/tests/tap/float.h
new file mode 100644 (file)
index 0000000..7464535
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * Floating point check function 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 2008, 2010, 2012 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.
+ */
+
+#ifndef TAP_FLOAT_H
+#define TAP_FLOAT_H 1
+
+#include <tests/tap/macros.h>
+
+BEGIN_DECLS
+
+/* Check an expected value against a seen value within epsilon. */
+void is_double(double wanted, double seen, double epsilon,
+               const char *format, ...)
+    __attribute__((__format__(printf, 4, 5)));
+
+END_DECLS
+
+#endif /* TAP_FLOAT_H */
diff --git a/src/external/c-tap-harness/tests/tap/libtap.sh b/src/external/c-tap-harness/tests/tap/libtap.sh
new file mode 100644 (file)
index 0000000..f9347d8
--- /dev/null
@@ -0,0 +1,246 @@
+# Shell function library for test cases.
+#
+# Note that while many of the functions in this library could benefit from
+# using "local" to avoid possibly hammering global variables, Solaris /bin/sh
+# doesn't support local and this library aspires to be portable to Solaris
+# Bourne shell.  Instead, all private variables are prefixed with "tap_".
+#
+# 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, 2011, 2012 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 () {
+    tap_highest=`expr "$count" - 1`
+    if [ "$planned" = 0 ] ; then
+        echo "1..$tap_highest"
+        planned="$tap_highest"
+    fi
+    tap_looks='# Looks like you'
+    if [ "$planned" -gt 0 ] ; then
+        if [ "$planned" -gt "$tap_highest" ] ; then
+            if [ "$planned" -gt 1 ] ; then
+                echo "$tap_looks planned $planned tests but only ran" \
+                    "$tap_highest"
+            else
+                echo "$tap_looks planned $planned test but only ran" \
+                    "$tap_highest"
+            fi
+        elif [ "$planned" -lt "$tap_highest" ] ; then
+            tap_extra=`expr "$tap_highest" - "$planned"`
+            if [ "$planned" -gt 1 ] ; then
+                echo "$tap_looks planned $planned tests but ran" \
+                    "$tap_extra extra"
+            else
+                echo "$tap_looks planned $planned test but ran" \
+                    "$tap_extra extra"
+            fi
+        elif [ "$failed" -gt 0 ] ; then
+            if [ "$failed" -gt 1 ] ; then
+                echo "$tap_looks failed $failed tests of $planned"
+            else
+                echo "$tap_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 () {
+    tap_desc="$1"
+    if [ -n "$tap_desc" ] ; then
+        echo "1..0 # skip $tap_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 () {
+    tap_desc="$1"
+    if [ -n "$tap_desc" ] ; then
+        tap_desc=" - $tap_desc"
+    fi
+    shift
+    if "$@" ; then
+        echo ok "$count$tap_desc"
+    else
+        echo not ok "$count$tap_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 () {
+    tap_i=$count
+    tap_end=`expr $count + $1`
+    shift
+    while [ "$tap_i" -lt "$tap_end" ] ; do
+        ok "$@"
+        tap_i=`expr $tap_i + 1`
+    done
+}
+
+# Skip a whole set of tests.  Takes the count and then the reason for skipping
+# the test.
+skip_block () {
+    tap_i=$count
+    tap_end=`expr $count + $1`
+    shift
+    while [ "$tap_i" -lt "$tap_end" ] ; do
+        skip "$@"
+        tap_i=`expr $tap_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.
+#
+# This macro must not be called via backticks inside double quotes, since this
+# will result in bizarre escaping behavior and lots of extra backslashes on
+# Solaris.
+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 () {
+    tap_desc="$1"
+    shift
+    tap_w_status="$1"
+    shift
+    tap_w_output="$1"
+    shift
+    tap_output=`"$@" 2>&1`
+    tap_status=$?
+    if [ $tap_status = $tap_w_status ] \
+        && [ x"$tap_output" = x"$tap_w_output" ] ; then
+        ok "$tap_desc" true
+    else
+        echo "#  saw: ($tap_status) $tap_output"
+        echo "#  not: ($tap_w_status) $tap_w_output"
+        ok "$tap_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() {
+    tap_output=`"$@" 2>&1`
+    tap_status=$?
+    tap_output=`puts "$tap_output" | sed 's/^\([^ ]* [^:]*\):.*/\1/'`
+    puts "$tap_output"
+    return $tap_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.
+#
+# This macro uses puts, so don't run it using backticks inside double quotes
+# or bizarre quoting behavior will happen with Solaris sh.
+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
+}
+
+# Create $BUILD/tmp for use by tests for storing temporary files and return
+# the path (via standard output).
+#
+# This macro uses puts, so don't run it using backticks inside double quotes
+# or bizarre quoting behavior will happen with Solaris sh.
+test_tmpdir () {
+    if [ -z "$BUILD" ] ; then
+        tap_tmpdir="./tmp"
+    else
+        tap_tmpdir="$BUILD"/tmp
+    fi
+    if [ ! -d "$tap_tmpdir" ] ; then
+        mkdir "$tap_tmpdir" || bail "Error creating $tap_tmpdir"
+    fi
+    puts "$tap_tmpdir"
+}
diff --git a/src/external/c-tap-harness/tests/tap/macros.h b/src/external/c-tap-harness/tests/tap/macros.h
new file mode 100644 (file)
index 0000000..33fee42
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * Helpful macros for TAP header files.
+ *
+ * This is not, strictly speaking, related to TAP, but any TAP add-on is
+ * probably going to need these macros, so define them in one place so that
+ * everyone can pull them in.
+ *
+ * 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 2008, 2012 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.
+ */
+
+#ifndef TAP_MACROS_H
+#define TAP_MACROS_H 1
+
+/*
+ * __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), and only with gcc 2.96 can you use
+ * the attribute __malloc__.  2.96 is very old, so don't bother trying to get
+ * the other attributes to work with GCC versions between 2.7 and 2.96.
+ */
+#ifndef __attribute__
+# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 96)
+#  define __attribute__(spec)   /* empty */
+# endif
+#endif
+
+/*
+ * We use __alloc_size__, but it was only available in fairly recent versions
+ * of GCC.  Suppress warnings about the unknown attribute if GCC is too old.
+ * We know that we're GCC at this point, so we can use the GCC variadic macro
+ * extension, which will still work with versions of GCC too old to have C99
+ * variadic macro support.
+ */
+#if !defined(__attribute__) && !defined(__alloc_size__)
+# if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 3)
+#  define __alloc_size__(spec, args...) /* empty */
+# endif
+#endif
+
+/*
+ * LLVM and Clang pretend to be GCC but don't support all of the __attribute__
+ * settings that GCC does.  For them, suppress warnings about unknown
+ * attributes on declarations.  This unfortunately will affect the entire
+ * compilation context, but there's no push and pop available.
+ */
+#if !defined(__attribute__) && (defined(__llvm__) || defined(__clang__))
+# pragma GCC diagnostic ignored "-Wattributes"
+#endif
+
+/* Used for unused parameters to silence gcc warnings. */
+#define UNUSED __attribute__((__unused__))
+
+/*
+ * 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
+
+#endif /* TAP_MACROS_H */