INN commit: trunk (58 files)

INN Commit rra at isc.org
Wed Sep 3 17:18:23 UTC 2014


    Date: Wednesday, September 3, 2014 @ 10:18:22
  Author: iulius
Revision: 9669

sync the test suite driver with latest C TAP Harness 3.1

The latest version of the C TAP Harness package is now integrated into
INN.  The README file shipped with the test suite driver is included
in the tests directory.  Also keep the same name as upstream for file
names in the news tests/tap directory.
Update paths to header files, and keep the INN specificities for legacy
tests (not yet updated to the new syntax).

The math library is now linked only with the test that needs it.

Added:
  trunk/tests/README
  trunk/tests/tap/
  trunk/tests/tap/basic.c
    (from rev 9649, trunk/tests/libtest.c)
  trunk/tests/tap/basic.h
    (from rev 9649, trunk/tests/libtest.h)
  trunk/tests/tap/float.c
  trunk/tests/tap/float.h
  trunk/tests/tap/libtap.sh
    (from rev 9649, trunk/tests/libtest.sh)
  trunk/tests/tap/macros.h
Modified:
  trunk/MANIFEST
  trunk/doc/pod/hacking.pod
  trunk/tests/Makefile
  trunk/tests/authprogs/ident-t.c
  trunk/tests/innd/artparse-t.c
  trunk/tests/innd/chan-t.c
  trunk/tests/lib/asprintf-t.c
  trunk/tests/lib/buffer-t.c
  trunk/tests/lib/concat-t.c
  trunk/tests/lib/conffile-t.c
  trunk/tests/lib/confparse-t.c
  trunk/tests/lib/date-t.c
  trunk/tests/lib/dispatch-t.c
  trunk/tests/lib/getaddrinfo-t.c
  trunk/tests/lib/getnameinfo-t.c
  trunk/tests/lib/hash-t.c
  trunk/tests/lib/hashtab-t.c
  trunk/tests/lib/hex-t.c
  trunk/tests/lib/inet_aton-t.c
  trunk/tests/lib/inet_ntoa-t.c
  trunk/tests/lib/inet_ntop-t.c
  trunk/tests/lib/innconf-t.c
  trunk/tests/lib/list-t.c
  trunk/tests/lib/md5-t.c
  trunk/tests/lib/memcmp-t.c
  trunk/tests/lib/messages-t.c
  trunk/tests/lib/mkstemp-t.c
  trunk/tests/lib/network-t.c
  trunk/tests/lib/pread-t.c
  trunk/tests/lib/pwrite-t.c
  trunk/tests/lib/qio-t.c
  trunk/tests/lib/setenv-t.c
  trunk/tests/lib/snprintf-t.c
  trunk/tests/lib/strlcat-t.c
  trunk/tests/lib/strlcpy-t.c
  trunk/tests/lib/tst-t.c
  trunk/tests/lib/uwildmat-t.c
  trunk/tests/lib/vector-t.c
  trunk/tests/lib/wire-t.c
  trunk/tests/lib/xmalloc.t
  trunk/tests/lib/xwrite-t.c
  trunk/tests/nnrpd/auth-ext-t.c
  trunk/tests/overview/api-t.c
  trunk/tests/overview/overview-t.c
  trunk/tests/overview/xref-t.c
  trunk/tests/runtests.c
  trunk/tests/util/innbind-t.c
Deleted:
  trunk/tests/libtest.c
  trunk/tests/libtest.h
  trunk/tests/libtest.sh

-----------------------------+
 MANIFEST                    |   13 
 doc/pod/hacking.pod         |   26 -
 tests/Makefile              |  174 +++----
 tests/README                |  248 ++++++++++
 tests/authprogs/ident-t.c   |    2 
 tests/innd/artparse-t.c     |    2 
 tests/innd/chan-t.c         |    2 
 tests/lib/asprintf-t.c      |    2 
 tests/lib/buffer-t.c        |    2 
 tests/lib/concat-t.c        |    2 
 tests/lib/conffile-t.c      |    2 
 tests/lib/confparse-t.c     |    3 
 tests/lib/date-t.c          |    2 
 tests/lib/dispatch-t.c      |    2 
 tests/lib/getaddrinfo-t.c   |    2 
 tests/lib/getnameinfo-t.c   |    2 
 tests/lib/hash-t.c          |    2 
 tests/lib/hashtab-t.c       |    2 
 tests/lib/hex-t.c           |    2 
 tests/lib/inet_aton-t.c     |    2 
 tests/lib/inet_ntoa-t.c     |    2 
 tests/lib/inet_ntop-t.c     |    2 
 tests/lib/innconf-t.c       |    2 
 tests/lib/list-t.c          |    2 
 tests/lib/md5-t.c           |    2 
 tests/lib/memcmp-t.c        |    2 
 tests/lib/messages-t.c      |    2 
 tests/lib/mkstemp-t.c       |    2 
 tests/lib/network-t.c       |    2 
 tests/lib/pread-t.c         |    2 
 tests/lib/pwrite-t.c        |    2 
 tests/lib/qio-t.c           |    2 
 tests/lib/setenv-t.c        |    2 
 tests/lib/snprintf-t.c      |    2 
 tests/lib/strlcat-t.c       |    2 
 tests/lib/strlcpy-t.c       |    2 
 tests/lib/tst-t.c           |    2 
 tests/lib/uwildmat-t.c      |    2 
 tests/lib/vector-t.c        |    2 
 tests/lib/wire-t.c          |    2 
 tests/lib/xmalloc.t         |    2 
 tests/lib/xwrite-t.c        |    2 
 tests/libtest.c             |  640 --------------------------
 tests/libtest.h             |  177 -------
 tests/libtest.sh            |  224 ---------
 tests/nnrpd/auth-ext-t.c    |    2 
 tests/overview/api-t.c      |    2 
 tests/overview/overview-t.c |    2 
 tests/overview/xref-t.c     |    2 
 tests/runtests.c            |  729 +++++++++++++++++++++---------
 tests/tap/basic.c           | 1020 ++++++++++++++++++++++++++++++++++++++++++
 tests/tap/basic.h           |  205 ++++++++
 tests/tap/float.c           |   82 +++
 tests/tap/float.h           |   47 +
 tests/tap/libtap.sh         |  248 ++++++++++
 tests/tap/macros.h          |   96 +++
 tests/util/innbind-t.c      |    2 
 57 files changed, 2622 insertions(+), 1394 deletions(-)

Modified: MANIFEST
===================================================================
--- MANIFEST	2014-08-30 12:13:46 UTC (rev 9668)
+++ MANIFEST	2014-09-03 17:18:22 UTC (rev 9669)
@@ -773,6 +773,7 @@
 support/mkversion                     Generate <inn/version.h> with INN version
 tests                                 Test suite for INN (Directory)
 tests/Makefile                        Makefile for test suite
+tests/README                          Guide to write TAP tests
 tests/TESTS                           List of tests to run
 tests/authprogs                       Test suite for auth programs (Directory)
 tests/authprogs/ckpasswd.t            Tests for authprogs/ckpasswd
@@ -898,10 +899,7 @@
 tests/lib/xmalloc.c                   Helper program for xmalloc tests
 tests/lib/xmalloc.t                   Tests for lib/xmalloc.c
 tests/lib/xwrite-t.c                  Tests for lib/xwrite.c
-tests/libtest.c                       Helper C library for writing tests
-tests/libtest.h                       Interface to libtest
-tests/libtest.sh                      Helper shell library for writing tests
-tests/nnrpd                           test suite for nnrpd (Directory)
+tests/nnrpd                           Test suite for nnrpd (Directory)
 tests/nnrpd/auth-ext-t.c              Tests for auth_external in nnrpd
 tests/nnrpd/auth-test                 Helper program for external auth tests
 tests/overview                        Test suite for overview (Directory)
@@ -914,6 +912,13 @@
 tests/storage/archive.t               Tests for backends/archive
 tests/storage/makehistory.t           Tests for expire/makehistory
 tests/storage/sm.t                    Tests for frontends/sm
+tests/tap                             Helper scripts for TAP (Directory)
+tests/tap/basic.c                     Helper C library for writing tests
+tests/tap/basic.h                     Header file for basic testing routines
+tests/tap/float.c                     Helper C library for floating point tests
+tests/tap/float.h                     Header file for floating point routines
+tests/tap/libtap.sh                   Helper shell library for writing tests
+tests/tap/macros.h                    Helpful macros for TAP header files
 tests/util                            Test suite for utilities (Directory)
 tests/util/convdate.t                 Tests for expire/convdate
 tests/util/innbind-t.c                Tests for backends/innbind

Modified: doc/pod/hacking.pod
===================================================================
--- doc/pod/hacking.pod	2014-08-30 12:13:46 UTC (rev 9668)
+++ doc/pod/hacking.pod	2014-09-03 17:18:22 UTC (rev 9669)
@@ -222,7 +222,7 @@
 
 The test suite for INN is located in the F<tests> directory and is just
 getting started.  The test suite consists of a set of programs listed in
-F<tests/TESTS> and the scaffolding in the F<runtests> program.
+F<tests/TESTS> and the scaffolding in the B<runtests> program.
 
 Adding new tests is very straightforward and very flexible.  Just write a
 program that tests some part of INN, put it in a directory under F<tests>
@@ -236,10 +236,11 @@
 subdirectories) and make sure it creates an executable ending in F<.t>.
 Then add the name of the test to F<tests/TESTS>, without the F<.t> ending.
 
-For C tests, you probably want to use the functions in F<libtest.c>
-(prototypes in F<libtest.h>) to handle all of the output.  For shell script
-tests, F<libtest.sh> contains helpful shell functions.  See the existing tests
-for some hints about how to write new tests.
+For C tests, you probably want to use the functions in
+F<tests/tap/basic.c> (prototypes in F<tests/tap/basic.h>) to handle
+all of the output.  For shell script tests, F<tests/tap/libtap.sh>
+contains helpful shell functions.  See the existing tests for some
+hints about how to write new tests, as well as the F<tests/README> guide.
 
 One naming convention:  to distinguish more easily between for example
 F<lib/error.c> (the implementation) and F<tests/lib/error-t.c> (the test
@@ -658,19 +659,18 @@
 
 =item *
 
-Make sure that the latest version of C TAP Harness is used for the test
-suite.  It is available from
+Make sure that the latest upstream version of the C TAP Harness package
+is used for the test suite driver.  It is available from
 L<http://www.eyrie.org/~eagle/software/c-tap-harness/>.  The file
-F<runtests.c> should be updated.  F<libtest.c>, F<libtest.h> and
-F<libtest.sh> come from F<tap/basic.c>, F<tap/basic.h> and
-F<tap/libtap.sh> respectively.  Parts specific to INN should be kept
-during an update (especially sections relative to LIBTEST_NEW_FORMAT
-because the test suite has not yet been updated to use the new format of C
+F<tests/runtests.c> should be updated, as well as the files in the
+F<tests/tap> directory.  Parts specific to INN should be kept during
+an update (especially sections relative to LIBTEST_NEW_FORMAT because
+the test suite has not yet been updated to use the new format of C
 TAP Harness).
 
 =item *
 
-Make sure that the latest version of the files maintained in the
+Make sure that the latest upstream version of the files maintained in the
 rra-c-util package that INN uses are in sync with upstream.  These files
 are available at L<http://www.eyrie.org/~eagle/software/rra-c-util/>
 and can be easily synchronized with the script F<support/getrra-c-util>;

Modified: tests/Makefile
===================================================================
--- tests/Makefile	2014-08-30 12:13:46 UTC (rev 9668)
+++ tests/Makefile	2014-09-03 17:18:22 UTC (rev 9669)
@@ -31,7 +31,7 @@
 EXTRA	= runtests clients/server-list lib/xmalloc
 
 all check test tests: $(TESTS) $(EXTRA)
-	./runtests TESTS
+	./runtests -l TESTS
 
 build: $(TESTS) $(EXTRA)
 
@@ -49,7 +49,7 @@
 .c.o: $*.c
 	$(CC) $(CFLAGS) -c -o $@ $*.c
 
-LINK		= $(LIBTOOLLD) $(CC) $(LDFLAGS) $(LIBM_LDFLAGS) $(BDB_LDFLAGS) $(SSL_LDFLAGS) $(SASL_LDFLAGS) $(KRB5_LDFLAGS) -o $@
+LINK		= $(LIBTOOLLD) $(CC) $(LDFLAGS) $(BDB_LDFLAGS) $(SSL_LDFLAGS) $(SASL_LDFLAGS) $(KRB5_LDFLAGS) -o $@
 STORAGEDEPS	= $(LIBSTORAGE) $(LIBHIST) $(LIBINN)
 STORAGELIBS	= $(STORAGEDEPS) $(STORAGE_LIBS)
 
@@ -70,95 +70,95 @@
 clients/server-list: clients/server-list.in $(FIXSCRIPT)
 	$(FIXSCRIPT) -i clients/server-list.in
 
-authprogs/ident.t: authprogs/ident-t.o libtest.o $(LIBINN)
-	$(LINK) authprogs/ident-t.o libtest.o $(LIBINN) $(LIBS)
+authprogs/ident.t: authprogs/ident-t.o tap/basic.o $(LIBINN)
+	$(LINK) authprogs/ident-t.o tap/basic.o $(LIBINN) $(LIBS)
 
-innd/artparse.t: innd/artparse-t.o innd/fakeinnd.o libtest.o $(INNOBJS)
-	$(LINK) innd/artparse-t.o innd/fakeinnd.o libtest.o $(INNOBJS) \
+innd/artparse.t: innd/artparse-t.o innd/fakeinnd.o tap/basic.o $(INNOBJS)
+	$(LINK) innd/artparse-t.o innd/fakeinnd.o tap/basic.o $(INNOBJS) \
 	    $(INNDLIBS)
 
-innd/chan.t: innd/chan-t.o innd/fakeinnd.o libtest.o $(INNOBJS)
-	$(LINK) innd/chan-t.o innd/fakeinnd.o libtest.o $(INNOBJS) $(INNDLIBS)
+innd/chan.t: innd/chan-t.o innd/fakeinnd.o tap/basic.o $(INNOBJS)
+	$(LINK) innd/chan-t.o innd/fakeinnd.o tap/basic.o $(INNOBJS) $(INNDLIBS)
 
 lib/asprintf.o: ../lib/asprintf.c
 	$(CC) $(CFLAGS) -DTESTING -c -o $@ ../lib/asprintf.c
 
-lib/asprintf.t: lib/asprintf.o lib/asprintf-t.o libtest.o $(LIBINN)
-	$(LINK) lib/asprintf.o lib/asprintf-t.o libtest.o $(LIBINN) $(LIBS)
+lib/asprintf.t: lib/asprintf.o lib/asprintf-t.o tap/basic.o $(LIBINN)
+	$(LINK) lib/asprintf.o lib/asprintf-t.o tap/basic.o $(LIBINN) $(LIBS)
 
-lib/buffer.t: lib/buffer-t.o libtest.o $(LIBINN)
-	$(LINK) lib/buffer-t.o libtest.o $(LIBINN)
+lib/buffer.t: lib/buffer-t.o tap/basic.o $(LIBINN)
+	$(LINK) lib/buffer-t.o tap/basic.o $(LIBINN)
 
-lib/concat.t: lib/concat-t.o libtest.o $(LIBINN)
-	$(LINK) lib/concat-t.o libtest.o $(LIBINN)
+lib/concat.t: lib/concat-t.o tap/basic.o $(LIBINN)
+	$(LINK) lib/concat-t.o tap/basic.o $(LIBINN)
 
-lib/conffile.t: lib/conffile-t.o libtest.o $(LIBINN)
-	$(LINK) lib/conffile-t.o libtest.o $(LIBINN)
+lib/conffile.t: lib/conffile-t.o tap/basic.o $(LIBINN)
+	$(LINK) lib/conffile-t.o tap/basic.o $(LIBINN)
 
-lib/confparse.t: lib/confparse-t.o libtest.o $(LIBINN)
-	$(LINK) lib/confparse-t.o libtest.o $(LIBINN)
+lib/confparse.t: lib/confparse-t.o tap/basic.o tap/float.o $(LIBINN)
+	$(LINK) $(LIBM_LDFLAGS) lib/confparse-t.o tap/basic.o tap/float.o $(LIBINN)
 
-lib/date.t: lib/date-t.o libtest.o $(LIBINN)
-	$(LINK) lib/date-t.o libtest.o $(LIBINN)
+lib/date.t: lib/date-t.o tap/basic.o $(LIBINN)
+	$(LINK) lib/date-t.o tap/basic.o $(LIBINN)
 
-lib/dispatch.t: lib/dispatch-t.o libtest.o $(LIBINN)
-	$(LINK) lib/dispatch-t.o libtest.o $(LIBINN)
+lib/dispatch.t: lib/dispatch-t.o tap/basic.o $(LIBINN)
+	$(LINK) lib/dispatch-t.o tap/basic.o $(LIBINN)
 
 lib/getaddrinfo.o: ../lib/getaddrinfo.c
 	$(CC) $(CFLAGS) -DTESTING -c -o $@ ../lib/getaddrinfo.c
 
-lib/getaddrinfo.t: lib/getaddrinfo.o lib/getaddrinfo-t.o libtest.o $(LIBINN)
-	$(LINK) lib/getaddrinfo.o lib/getaddrinfo-t.o libtest.o \
+lib/getaddrinfo.t: lib/getaddrinfo.o lib/getaddrinfo-t.o tap/basic.o $(LIBINN)
+	$(LINK) lib/getaddrinfo.o lib/getaddrinfo-t.o tap/basic.o \
 	    $(LIBINN) $(LIBS)
 
 lib/getnameinfo.o: ../lib/getnameinfo.c
 	$(CC) $(CFLAGS) -DTESTING -c -o $@ ../lib/getnameinfo.c
 
-lib/getnameinfo.t: lib/getnameinfo.o lib/getnameinfo-t.o libtest.o $(LIBINN)
-	$(LINK) lib/getnameinfo.o lib/getnameinfo-t.o libtest.o \
+lib/getnameinfo.t: lib/getnameinfo.o lib/getnameinfo-t.o tap/basic.o $(LIBINN)
+	$(LINK) lib/getnameinfo.o lib/getnameinfo-t.o tap/basic.o \
 	    $(LIBINN) $(LIBS)
 
-lib/hash.t: lib/hash-t.o libtest.o $(LIBINN)
-	$(LINK) lib/hash-t.o libtest.o $(LIBINN)
+lib/hash.t: lib/hash-t.o tap/basic.o $(LIBINN)
+	$(LINK) lib/hash-t.o tap/basic.o $(LIBINN)
 
-lib/hashtab.t: lib/hashtab-t.o libtest.o $(LIBINN)
-	$(LINK) lib/hashtab-t.o libtest.o $(LIBINN)
+lib/hashtab.t: lib/hashtab-t.o tap/basic.o $(LIBINN)
+	$(LINK) lib/hashtab-t.o tap/basic.o $(LIBINN)
 
-lib/hex.t: lib/hex-t.o libtest.o $(LIBINN)
-	$(LINK) lib/hex-t.o libtest.o $(LIBINN) $(LIBS)
+lib/hex.t: lib/hex-t.o tap/basic.o $(LIBINN)
+	$(LINK) lib/hex-t.o tap/basic.o $(LIBINN) $(LIBS)
 
 lib/inet_aton.o: ../lib/inet_aton.c
 	$(CC) $(CFLAGS) -DTESTING -c -o $@ ../lib/inet_aton.c
 
-lib/inet_aton.t: lib/inet_aton.o lib/inet_aton-t.o libtest.o $(LIBINN)
-	$(LINK) lib/inet_aton.o lib/inet_aton-t.o libtest.o $(LIBINN)
+lib/inet_aton.t: lib/inet_aton.o lib/inet_aton-t.o tap/basic.o $(LIBINN)
+	$(LINK) lib/inet_aton.o lib/inet_aton-t.o tap/basic.o $(LIBINN)
 
 lib/inet_ntoa.o: ../lib/inet_ntoa.c
 	$(CC) $(CFLAGS) -DTESTING -c -o $@ ../lib/inet_ntoa.c
 
-lib/inet_ntoa.t: lib/inet_ntoa.o lib/inet_ntoa-t.o libtest.o $(LIBINN)
-	$(LINK) lib/inet_ntoa.o lib/inet_ntoa-t.o libtest.o $(LIBINN)
+lib/inet_ntoa.t: lib/inet_ntoa.o lib/inet_ntoa-t.o tap/basic.o $(LIBINN)
+	$(LINK) lib/inet_ntoa.o lib/inet_ntoa-t.o tap/basic.o $(LIBINN)
 
 lib/inet_ntop.o: ../lib/inet_ntop.c
 	$(CC) $(CFLAGS) -DTESTING -c -o $@ ../lib/inet_ntop.c
 
-lib/inet_ntop.t: lib/inet_ntop.o lib/inet_ntop-t.o libtest.o $(LIBINN)
-	$(LINK) lib/inet_ntop.o lib/inet_ntop-t.o libtest.o $(LIBINN)
+lib/inet_ntop.t: lib/inet_ntop.o lib/inet_ntop-t.o tap/basic.o $(LIBINN)
+	$(LINK) lib/inet_ntop.o lib/inet_ntop-t.o tap/basic.o $(LIBINN)
 
-lib/innconf.t: lib/innconf-t.o libtest.o $(LIBINN)
-	$(LINK) lib/innconf-t.o libtest.o $(LIBINN) $(LIBS)
+lib/innconf.t: lib/innconf-t.o tap/basic.o $(LIBINN)
+	$(LINK) lib/innconf-t.o tap/basic.o $(LIBINN) $(LIBS)
 
-lib/list.t: lib/list-t.o libtest.o $(LIBINN)
-	$(LINK) lib/list-t.o libtest.o $(LIBINN) $(LIBS)
+lib/list.t: lib/list-t.o tap/basic.o $(LIBINN)
+	$(LINK) lib/list-t.o tap/basic.o $(LIBINN) $(LIBS)
 
-lib/md5.t: lib/md5-t.o libtest.o $(LIBINN)
-	$(LINK) lib/md5-t.o libtest.o $(LIBINN)
+lib/md5.t: lib/md5-t.o tap/basic.o $(LIBINN)
+	$(LINK) lib/md5-t.o tap/basic.o $(LIBINN)
 
 lib/memcmp.o: ../lib/memcmp.c
 	$(CC) $(CFLAGS) -DTESTING -c -o $@ ../lib/memcmp.c
 
-lib/memcmp.t: lib/memcmp.o lib/memcmp-t.o libtest.o
-	$(LINK) lib/memcmp.o lib/memcmp-t.o libtest.o $(LIBINN)
+lib/memcmp.t: lib/memcmp.o lib/memcmp-t.o tap/basic.o
+	$(LINK) lib/memcmp.o lib/memcmp-t.o tap/basic.o $(LIBINN)
 
 lib/messages.o: ../lib/messages.c
 	$(CC) $(CFLAGS) -DDEBUG -c -o $@ ../lib/messages.c
@@ -166,68 +166,68 @@
 lib/messages-t.o: lib/messages-t.c
 	$(CC) $(CFLAGS) -DDEBUG -c -o $@ lib/messages-t.c
 
-lib/messages.t: lib/messages.o lib/messages-t.o libtest.o $(LIBINN)
-	$(LINK) lib/messages-t.o lib/messages.o libtest.o $(LIBINN)
+lib/messages.t: lib/messages.o lib/messages-t.o tap/basic.o $(LIBINN)
+	$(LINK) lib/messages-t.o lib/messages.o tap/basic.o $(LIBINN)
 
 lib/mkstemp.o: ../lib/mkstemp.c
 	$(CC) $(CFLAGS) -DTESTING -c -o $@ ../lib/mkstemp.c
 
-lib/mkstemp.t: lib/mkstemp.o lib/mkstemp-t.o libtest.o
-	$(LINK) lib/mkstemp.o lib/mkstemp-t.o libtest.o $(LIBINN)
+lib/mkstemp.t: lib/mkstemp.o lib/mkstemp-t.o tap/basic.o
+	$(LINK) lib/mkstemp.o lib/mkstemp-t.o tap/basic.o $(LIBINN)
 
-lib/network.t: lib/network-t.o libtest.o $(LIBINN)
-	$(LINK) lib/network-t.o libtest.o $(LIBINN) $(LIBS)
+lib/network.t: lib/network-t.o tap/basic.o $(LIBINN)
+	$(LINK) lib/network-t.o tap/basic.o $(LIBINN) $(LIBS)
 
 lib/pread.o: ../lib/pread.c
 	$(CC) $(CFLAGS) -DTESTING -c -o $@ ../lib/pread.c
 
-lib/pread.t: lib/pread.o lib/pread-t.o libtest.o $(LIBINN)
-	$(LINK) lib/pread.o lib/pread-t.o libtest.o $(LIBINN)
+lib/pread.t: lib/pread.o lib/pread-t.o tap/basic.o $(LIBINN)
+	$(LINK) lib/pread.o lib/pread-t.o tap/basic.o $(LIBINN)
 
 lib/pwrite.o: ../lib/pwrite.c
 	$(CC) $(CFLAGS) -DTESTING -c -o $@ ../lib/pwrite.c
 
-lib/pwrite.t: lib/pwrite.o lib/pwrite-t.o libtest.o $(LIBINN)
-	$(LINK) lib/pwrite.o lib/pwrite-t.o libtest.o $(LIBINN)
+lib/pwrite.t: lib/pwrite.o lib/pwrite-t.o tap/basic.o $(LIBINN)
+	$(LINK) lib/pwrite.o lib/pwrite-t.o tap/basic.o $(LIBINN)
 
-lib/qio.t: lib/qio-t.o libtest.o $(LIBINN)
-	$(LINK) lib/qio-t.o libtest.o $(LIBINN)
+lib/qio.t: lib/qio-t.o tap/basic.o $(LIBINN)
+	$(LINK) lib/qio-t.o tap/basic.o $(LIBINN)
 
 lib/setenv.o: ../lib/setenv.c
 	$(CC) $(CFLAGS) -DTESTING -c -o $@ ../lib/setenv.c
 
-lib/setenv.t: lib/setenv.o lib/setenv-t.o libtest.o $(LIBINN)
-	$(LINK) lib/setenv.o lib/setenv-t.o libtest.o $(LIBINN)
+lib/setenv.t: lib/setenv.o lib/setenv-t.o tap/basic.o $(LIBINN)
+	$(LINK) lib/setenv.o lib/setenv-t.o tap/basic.o $(LIBINN)
 
 lib/snprintf.o: ../lib/snprintf.c
 	$(CC) $(CFLAGS) -DTESTING -c -o $@ ../lib/snprintf.c
 
-lib/snprintf.t: lib/snprintf.o lib/snprintf-t.o libtest.o $(LIBINN)
-	$(LINK) lib/snprintf.o lib/snprintf-t.o libtest.o $(LIBINN)
+lib/snprintf.t: lib/snprintf.o lib/snprintf-t.o tap/basic.o $(LIBINN)
+	$(LINK) lib/snprintf.o lib/snprintf-t.o tap/basic.o $(LIBINN)
 
 lib/strlcat.o: ../lib/strlcat.c
 	$(CC) $(CFLAGS) -DTESTING -c -o $@ ../lib/strlcat.c
 
-lib/strlcat.t: lib/strlcat.o lib/strlcat-t.o libtest.o $(LIBINN)
-	$(LINK) lib/strlcat.o lib/strlcat-t.o libtest.o $(LIBINN)
+lib/strlcat.t: lib/strlcat.o lib/strlcat-t.o tap/basic.o $(LIBINN)
+	$(LINK) lib/strlcat.o lib/strlcat-t.o tap/basic.o $(LIBINN)
 
 lib/strlcpy.o: ../lib/strlcpy.c
 	$(CC) $(CFLAGS) -DTESTING -c -o $@ ../lib/strlcpy.c
 
-lib/strlcpy.t: lib/strlcpy.o lib/strlcpy-t.o libtest.o $(LIBINN)
-	$(LINK) lib/strlcpy.o lib/strlcpy-t.o libtest.o $(LIBINN)
+lib/strlcpy.t: lib/strlcpy.o lib/strlcpy-t.o tap/basic.o $(LIBINN)
+	$(LINK) lib/strlcpy.o lib/strlcpy-t.o tap/basic.o $(LIBINN)
 
-lib/tst.t: lib/tst-t.o libtest.o $(LIBINN)
-	$(LINK) lib/tst-t.o libtest.o $(LIBINN)
+lib/tst.t: lib/tst-t.o tap/basic.o $(LIBINN)
+	$(LINK) lib/tst-t.o tap/basic.o $(LIBINN)
 
-lib/uwildmat.t: lib/uwildmat-t.o libtest.o $(LIBINN)
-	$(LINK) lib/uwildmat-t.o libtest.o $(LIBINN)
+lib/uwildmat.t: lib/uwildmat-t.o tap/basic.o $(LIBINN)
+	$(LINK) lib/uwildmat-t.o tap/basic.o $(LIBINN)
 
-lib/vector.t: lib/vector-t.o libtest.o $(LIBINN)
-	$(LINK) lib/vector-t.o libtest.o $(LIBINN)
+lib/vector.t: lib/vector-t.o tap/basic.o $(LIBINN)
+	$(LINK) lib/vector-t.o tap/basic.o $(LIBINN)
 
-lib/wire.t: lib/wire-t.o libtest.o $(LIBINN)
-	$(LINK) lib/wire-t.o libtest.o $(LIBINN)
+lib/wire.t: lib/wire-t.o tap/basic.o $(LIBINN)
+	$(LINK) lib/wire-t.o tap/basic.o $(LIBINN)
 
 lib/xmalloc: lib/xmalloc.o $(LIBINN)
 	$(LINK) lib/xmalloc.o $(LIBINN)
@@ -235,29 +235,29 @@
 lib/xwrite.o: ../lib/xwrite.c
 	$(CC) $(CFLAGS) -DTESTING -c -o $@ ../lib/xwrite.c
 
-lib/xwrite.t: lib/xwrite-t.o lib/xwrite.o lib/fakewrite.o libtest.o $(LIBINN)
-	$(LINK) lib/xwrite-t.o lib/xwrite.o lib/fakewrite.o libtest.o $(LIBINN)
+lib/xwrite.t: lib/xwrite-t.o lib/xwrite.o lib/fakewrite.o tap/basic.o $(LIBINN)
+	$(LINK) lib/xwrite-t.o lib/xwrite.o lib/fakewrite.o tap/basic.o $(LIBINN)
 
 nnrpd/auth-ext.t: nnrpd/auth-ext-t.o ../nnrpd/auth-ext.o $(LIBINN)
-	$(LINK) nnrpd/auth-ext-t.o ../nnrpd/auth-ext.o libtest.o $(LIBINN)
+	$(LINK) nnrpd/auth-ext-t.o ../nnrpd/auth-ext.o tap/basic.o $(LIBINN)
 
-overview/api.t: overview/api-t.o libtest.o $(STORAGEDEPS)
-	$(LINK) overview/api-t.o libtest.o $(STORAGELIBS) $(LIBS)
+overview/api.t: overview/api-t.o tap/basic.o $(STORAGEDEPS)
+	$(LINK) overview/api-t.o tap/basic.o $(STORAGELIBS) $(LIBS)
 
 overview/buffindexed-t.o: overview/overview-t.c
 	$(CC) $(CFLAGS) -DOVTYPE=buffindexed -c -o $@ overview/overview-t.c
 
-overview/buffindexed.t: overview/buffindexed-t.o libtest.o $(STORAGEDEPS)
-	$(LINK) overview/buffindexed-t.o libtest.o $(STORAGELIBS) $(LIBS)
+overview/buffindexed.t: overview/buffindexed-t.o tap/basic.o $(STORAGEDEPS)
+	$(LINK) overview/buffindexed-t.o tap/basic.o $(STORAGELIBS) $(LIBS)
 
 overview/tradindexed-t.o: overview/overview-t.c
 	$(CC) $(CFLAGS) -DOVTYPE=tradindexed -c -o $@ overview/overview-t.c
 
-overview/tradindexed.t: overview/tradindexed-t.o libtest.o $(STORAGEDEPS)
-	$(LINK) overview/tradindexed-t.o libtest.o $(STORAGELIBS) $(LIBS)
+overview/tradindexed.t: overview/tradindexed-t.o tap/basic.o $(STORAGEDEPS)
+	$(LINK) overview/tradindexed-t.o tap/basic.o $(STORAGELIBS) $(LIBS)
 
-overview/xref.t: overview/xref-t.o libtest.o $(STORAGEDEPS)
-	$(LINK) overview/xref-t.o libtest.o $(STORAGELIBS) $(LIBS)
+overview/xref.t: overview/xref-t.o tap/basic.o $(STORAGEDEPS)
+	$(LINK) overview/xref-t.o tap/basic.o $(STORAGELIBS) $(LIBS)
 
-util/innbind.t: util/innbind-t.o libtest.o $(LIBINN)
-	$(LINK) util/innbind-t.o libtest.o $(LIBINN) $(LIBS)
+util/innbind.t: util/innbind-t.o tap/basic.o $(LIBINN)
+	$(LINK) util/innbind-t.o tap/basic.o $(LIBINN) $(LIBS)

Added: tests/README
===================================================================
--- tests/README	                        (rev 0)
+++ tests/README	2014-09-03 17:18:22 UTC (rev 9669)
@@ -0,0 +1,248 @@
+                            Writing TAP Tests
+
+Introduction
+
+    This is a guide for users of the C TAP Harness package or similar
+    TAP-based test harnesses explaining how to write tests.  If your
+    package uses C TAP Harness as the test suite driver, you may want to
+    copy this document to an appropriate file name in your test suite as
+    documentation for contributors.
+
+About TAP
+
+    TAP is the Test Anything Protocol, a protocol for communication
+    between test cases and a test harness.  This is the protocol used by
+    Perl for its internal test suite and for nearly all Perl modules,
+    since it's the format used by the build tools for Perl modules to run
+    tests and report their results.
+
+    A TAP-based test suite works with a somewhat different set of
+    assumptions than an xUnit test suite.  In TAP, each test case is a
+    separate program.  That program, when run, must produce output in the
+    following format:
+
+        1..4
+        ok 1 - the first test
+        ok 2
+        # a diagnostic, ignored by the harness
+        not ok 3 - a failing test
+        ok 4 # skip a skipped test
+
+    The output should all go to standard output.  The first line specifies
+    the number of tests to be run, and then each test produces output that
+    looks like either "ok <n>" or "not ok <n>" depending on whether the
+    test succeeded or failed.  Additional information about the test can
+    be provided after the "ok <n>" or "not ok <n>", but is optional.
+    Additional diagnostics and information can be provided in lines
+    beginning with a "#".
+
+    Processing directives are supported after the "ok <n>" or "not ok <n>"
+    and start with a "#".  The main one of interest is "# skip" which says
+    that the test was skipped rather than successful and optionally gives
+    the reason.  Also supported is "# todo", which normally annotates a
+    failing test and indicates that test is expected to fail, optionally
+    providing a reason for why.
+
+    There are three more special cases.  First, the initial line stating
+    the number of tests to run, called the plan, may appear at the end of
+    the output instead of the beginning.  This can be useful if the number
+    of tests to run is not known in advance.  Second, a plan in the form:
+
+        1..0 # skip entire test case skipped
+
+    can be given instead, which indicates that this entire test case has
+    been skipped (generally because it depends on facilities or optional
+    configuration which is not present).  Finally, if the test case
+    encounters a fatal error, it should print the text:
+
+        Bail out!
+
+    on standard output, optionally followed by an error message, and then
+    exit.  This tells the harness that the test aborted unexpectedly.
+
+    The exit status of a successful test case should always be 0.  The
+    harness will report the test as "dubious" if all the tests appeared to
+    succeed but it exited with a non-zero status.
+
+Writing TAP Tests
+
+  Environment
+
+    One of the special features of C TAP Harness is the environment that
+    it sets up for your test cases.  If your test program is called under
+    the runtests driver, the environment variables SOURCE and BUILD will
+    be set to the top of the test directory in the source tree and the top
+    of the build tree, respectively.  You can use those environment
+    variables to locate additional test data, programs and libraries built
+    as part of your software build, and other supporting information
+    needed by tests.
+
+    The C and shell TAP libraries support a test_file_path() function,
+    which looks for a file under the build tree and then under the source
+    tree, using the BUILD and SOURCE environment variables, and return the
+    full path to the file.  This can be used to locate supporting data
+    files.
+
+  Perl
+
+    Since TAP is the native test framework for Perl, writing TAP tests in
+    Perl is very easy and extremely well-supported.  If you've never
+    written tests in Perl before, start by reading the documentation for
+    Test::Tutorial and Test::Simple, which walks you through the basics,
+    including the TAP output syntax.  Then, the best Perl module to use
+    for serious testing is Test::More, which provides a lot of additional
+    functions over Test::Simple including support for skipping tests,
+    bailing out, and not planning tests in advance.  See the documentation
+    of Test::More for all the details and lots of examples.
+
+    C TAP Harness can run Perl test scripts directly and interpret the
+    results correctly, and similarly the Perl Test::Harness module and
+    prove command can run TAP tests written in other languages using, for
+    example, the TAP library that comes with C TAP Harness.  You can, if
+    you wish, use the library that comes with C TAP Harness but use prove
+    instead of runtests for running the test suite.
+
+  C
+
+    C TAP Harness provides a basic TAP library that takes away most of the
+    pain of writing TAP test cases in C.  A C test case should start with
+    a call to plan(), passing in the number of tests to run.  Then, each
+    test should use is_int(), is_string(), is_double(), or is_hex() as
+    appropriate to compare expected and seen values, or ok() to do a
+    simpler boolean test.  The is_*() functions take expected and seen
+    values and then a printf-style format string explaining the test
+    (which may be NULL).  ok() takes a boolean and then the printf-style
+    string.
+
+    Here's a complete example test program that uses the C TAP library:
+
+        #include <stddef.h>
+        #include <tap/basic.h>
+
+        int
+        main(void)
+        {
+            plan(4);
+
+            ok(1, "the first test");
+            is_int(42, 42, NULL);
+            diag("a diagnostic, ignored by the harness");
+            ok(0, "a failing test");
+            skip("a skipped test");
+
+            return 0;
+        }
+
+    This test program produces the output shown above in the section on
+    TAP and demonstrates most of the functions.  The other functions of
+    interest are sysdiag() (like diag() but adds strerror() results),
+    bail() and sysbail() for fatal errors, skip_block() to skip a whole
+    block of tests, and skip_all() which is called instead of plan() to
+    skip an entire test case.
+
+    The C TAP library also provides plan_lazy(), which can be called
+    instead of plan().  If plan_lazy() is called, the library will keep
+    track of how many test results are reported and will print out the
+    plan at the end of execution of the program.  This should normally be
+    avoided since the test may appear to be successful even if it exits
+    prematurely, but it can make writing tests easier in some
+    circumstances.
+
+    Complete API documentation for the basic C TAP library that comes with
+    C TAP Harness is available at:
+
+        <http://www.eyrie.org/~eagle/software/c-tap-harness/>
+
+    It's common to need additional test functions and utility functions
+    for your C tests, particularly if you have to set up and tear down a
+    test environment for your test programs, and it's useful to have them
+    all in the libtap library so that you only have to link your test
+    programs with one library.  Rather than editing tap/basic.c and
+    tap/basic.h to add those additional functions, add additional *.c and
+    *.h files into the tap directory with the function implementations and
+    prototypes, and then add those additional objects to the library.
+    That way, you can update tap/basic.c and tap/basic.h from subsequent
+    releases of C TAP Harness without having to merge changes with your
+    own code.
+
+    Libraries of additional useful TAP test functions are available in
+    rra-c-util at:
+
+        <http://www.eyrie.org/~eagle/software/rra-c-util/>
+
+    Some of the code there is particularly useful when testing programs
+    that require Kerberos keys.
+
+    If you implement new test functions that compare an expected and seen
+    value, it's best to name them is_<something> and take the expected
+    value, the seen value, and then a printf-style format string and
+    possible arguments to match the calling convention of the functions
+    provided by C TAP Harness.
+
+  Shell
+
+    C TAP Harness provides a library of shell functions to make it easier
+    to write TAP tests in shell.  That library includes much of the same
+    functionality as the C TAP library, but takes its parameters in a
+    somewhat different order to make better use of shell features.
+
+    The libtap.sh file should be installed in a directory named tap in
+    your test suite area.  It can then be loaded by tests written in shell
+    using the environment set up by runtests with:
+
+        . "$SOURCE"/tap/libtap.sh
+
+    Here is a complete test case written in shell which produces the same
+    output as the TAP sample above:
+
+        #!/bin/sh
+
+        . "$SOURCE"/tap/libtap.sh
+        cd "$BUILD"
+
+        plan 4
+        ok 'the first test' true
+        ok '' [ 42 -eq 42 ]
+        diag a diagnostic, ignored by the harness
+        ok '' false
+        skip 'a skipped test'
+
+    The shell framework doesn't provide the is_* functions, so you'll use
+    the ok function more.  It takes a string describing the text and then
+    treats all of its remaining arguments as a condition, evaluated the
+    same way as the arguments to the "if" statement.  If that condition
+    evaluates to true, the test passes; otherwise, the test fails.
+
+    The plan, plan_lazy, diag, and bail functions work the same as with
+    the C library.  skip takes a string and skips the next test with that
+    explanation.  skip_block takes a count and a string and skips that
+    many tests with that explanation.  skip_all takes an optional reason
+    and skips the entire test case.
+
+    Since it's common for shell programs to want to test the output of
+    commands, there's an additional function ok_program provided by the
+    shell test library.  It takes the test description string, the
+    expected exit status, the expected program output, and then treats the
+    rest of its arguments as the program to run.  That program is run with
+    standard error and standard output combined, and then its exit status
+    and output are tested against the provided values.
+
+    A utility function, strip_colon_error, is provided that runs the
+    command given as its arguments and strips text following a colon and a
+    space from the output (unless there is no whitespace on the line
+    before the colon and the space, normally indicating a prefix of the
+    program name).  This function can be used to wrap commands that are
+    expected to fail with output that has a system- or locale-specific
+    error message appended, such as the output of strerror().
+
+License
+
+    This file is part of the documentation of C TAP Harness, which can be
+    found at <http://www.eyrie.org/~eagle/software/c-tap-harness/>.
+
+    Copyright 2010 Russ Allbery <eagle at eyrie.org>
+
+    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.


Property changes on: trunk/tests/README
___________________________________________________________________
Added: svn:eol-style
   + native

Modified: tests/authprogs/ident-t.c
===================================================================
--- tests/authprogs/ident-t.c	2014-08-30 12:13:46 UTC (rev 9668)
+++ tests/authprogs/ident-t.c	2014-09-03 17:18:22 UTC (rev 9669)
@@ -9,7 +9,7 @@
 
 #include "inn/messages.h"
 #include "inn/network.h"
-#include "libtest.h"
+#include "tap/basic.h"
 
 /* The path to the uninstalled ident resolver. */
 static const char ident[] = "../../authprogs/ident";

Modified: tests/innd/artparse-t.c
===================================================================
--- tests/innd/artparse-t.c	2014-08-30 12:13:46 UTC (rev 9668)
+++ tests/innd/artparse-t.c	2014-09-03 17:18:22 UTC (rev 9669)
@@ -10,7 +10,7 @@
 #include "inn/vector.h"
 #include "inn/wire.h"
 #include "inn/libinn.h"
-#include "libtest.h"
+#include "tap/basic.h"
 
 #include "../../innd/innd.h"
 

Modified: tests/innd/chan-t.c
===================================================================
--- tests/innd/chan-t.c	2014-08-30 12:13:46 UTC (rev 9668)
+++ tests/innd/chan-t.c	2014-09-03 17:18:22 UTC (rev 9669)
@@ -9,7 +9,7 @@
 #include "inn/buffer.h"
 #include "inn/innconf.h"
 #include "inn/libinn.h"
-#include "libtest.h"
+#include "tap/basic.h"
 
 #include "../../innd/innd.h"
 

Modified: tests/lib/asprintf-t.c
===================================================================
--- tests/lib/asprintf-t.c	2014-08-30 12:13:46 UTC (rev 9668)
+++ tests/lib/asprintf-t.c	2014-09-03 17:18:22 UTC (rev 9669)
@@ -22,7 +22,7 @@
 #include "config.h"
 #include "clibrary.h"
 
-#include "libtest.h"
+#include "tap/basic.h"
 
 int test_asprintf(char **, const char *, ...)
     __attribute__((__format__(printf, 2, 3)));

Modified: tests/lib/buffer-t.c
===================================================================
--- tests/lib/buffer-t.c	2014-08-30 12:13:46 UTC (rev 9668)
+++ tests/lib/buffer-t.c	2014-09-03 17:18:22 UTC (rev 9669)
@@ -26,7 +26,7 @@
 #include "inn/buffer.h"
 #include "inn/messages.h"
 #include "inn/libinn.h"
-#include "libtest.h"
+#include "tap/basic.h"
 
 static const char test_string1[] = "This is a test";
 static const char test_string2[] = " of the buffer system";

Modified: tests/lib/concat-t.c
===================================================================
--- tests/lib/concat-t.c	2014-08-30 12:13:46 UTC (rev 9668)
+++ tests/lib/concat-t.c	2014-09-03 17:18:22 UTC (rev 9669)
@@ -23,7 +23,7 @@
 #include <string.h>
 
 #include "inn/libinn.h"
-#include "libtest.h"
+#include "tap/basic.h"
 
 #define END (char *) 0
 

Modified: tests/lib/conffile-t.c
===================================================================
--- tests/lib/conffile-t.c	2014-08-30 12:13:46 UTC (rev 9668)
+++ tests/lib/conffile-t.c	2014-09-03 17:18:22 UTC (rev 9669)
@@ -8,7 +8,7 @@
 
 #include "conffile.h"
 #include "inn/messages.h"
-#include "libtest.h"
+#include "tap/basic.h"
 
 /* Test valid configuration file. */
 static const char valid[] = "test \"test #te\nst\\\"\" {\n  #foo\n test\n\n}";

Modified: tests/lib/confparse-t.c
===================================================================
--- tests/lib/confparse-t.c	2014-08-30 12:13:46 UTC (rev 9668)
+++ tests/lib/confparse-t.c	2014-09-03 17:18:22 UTC (rev 9669)
@@ -8,7 +8,8 @@
 #include "inn/messages.h"
 #include "inn/vector.h"
 #include "inn/libinn.h"
-#include "libtest.h"
+#include "tap/basic.h"
+#include "tap/float.h"
 
 /* Given a FILE *, read from that file, putting the results into a newly
    allocated buffer, until encountering a line consisting solely of "===".

Modified: tests/lib/date-t.c
===================================================================
--- tests/lib/date-t.c	2014-08-30 12:13:46 UTC (rev 9668)
+++ tests/lib/date-t.c	2014-09-03 17:18:22 UTC (rev 9669)
@@ -6,7 +6,7 @@
 #include <time.h>
 
 #include "inn/libinn.h"
-#include "libtest.h"
+#include "tap/basic.h"
 
 static const time_t test_times[] = {
     28800UL,                    /* Thu,  1 Jan 1970 00:00:00 -0800 (PST) */

Modified: tests/lib/dispatch-t.c
===================================================================
--- tests/lib/dispatch-t.c	2014-08-30 12:13:46 UTC (rev 9668)
+++ tests/lib/dispatch-t.c	2014-09-03 17:18:22 UTC (rev 9669)
@@ -6,7 +6,7 @@
 
 #include "inn/dispatch.h"
 #include "inn/vector.h"
-#include "libtest.h"
+#include "tap/basic.h"
 
 /* Prototypes for command callbacks. */
 static void command_0(struct cvector *, void *);

Modified: tests/lib/getaddrinfo-t.c
===================================================================
--- tests/lib/getaddrinfo-t.c	2014-08-30 12:13:46 UTC (rev 9668)
+++ tests/lib/getaddrinfo-t.c	2014-09-03 17:18:22 UTC (rev 9669)
@@ -24,7 +24,7 @@
 #include "portable/socket.h"
 
 #include "inn/messages.h"
-#include "libtest.h"
+#include "tap/basic.h"
 
 /*
  * If the native platform doesn't support AI_NUMERICSERV or AI_NUMERICHOST,

Modified: tests/lib/getnameinfo-t.c
===================================================================
--- tests/lib/getnameinfo-t.c	2014-08-30 12:13:46 UTC (rev 9668)
+++ tests/lib/getnameinfo-t.c	2014-09-03 17:18:22 UTC (rev 9669)
@@ -25,7 +25,7 @@
 
 #include "inn/messages.h"
 #include "inn/libinn.h"
-#include "libtest.h"
+#include "tap/basic.h"
 
 int test_getnameinfo(const struct sockaddr *, socklen_t, char *, socklen_t,
                      char *, socklen_t, int);

Modified: tests/lib/hash-t.c
===================================================================
--- tests/lib/hash-t.c	2014-08-30 12:13:46 UTC (rev 9668)
+++ tests/lib/hash-t.c	2014-09-03 17:18:22 UTC (rev 9669)
@@ -5,7 +5,7 @@
 #include "clibrary.h"
 
 #include "inn/libinn.h"
-#include "libtest.h"
+#include "tap/basic.h"
 
 int
 main(void)

Modified: tests/lib/hashtab-t.c
===================================================================
--- tests/lib/hashtab-t.c	2014-08-30 12:13:46 UTC (rev 9668)
+++ tests/lib/hashtab-t.c	2014-09-03 17:18:22 UTC (rev 9669)
@@ -8,7 +8,7 @@
 #include "inn/hashtab.h"
 #include "inn/messages.h"
 #include "inn/libinn.h"
-#include "libtest.h"
+#include "tap/basic.h"
 
 struct wordref {
     const char *word;

Modified: tests/lib/hex-t.c
===================================================================
--- tests/lib/hex-t.c	2014-08-30 12:13:46 UTC (rev 9668)
+++ tests/lib/hex-t.c	2014-09-03 17:18:22 UTC (rev 9669)
@@ -5,7 +5,7 @@
 #include "clibrary.h"
 
 #include "inn/utility.h"
-#include "libtest.h"
+#include "tap/basic.h"
 
 int
 main(void)

Modified: tests/lib/inet_aton-t.c
===================================================================
--- tests/lib/inet_aton-t.c	2014-08-30 12:13:46 UTC (rev 9668)
+++ tests/lib/inet_aton-t.c	2014-09-03 17:18:22 UTC (rev 9669)
@@ -23,7 +23,7 @@
 #include "clibrary.h"
 #include <netinet/in.h>
 
-#include "libtest.h"
+#include "tap/basic.h"
 
 int test_inet_aton(const char *, struct in_addr *);
 

Modified: tests/lib/inet_ntoa-t.c
===================================================================
--- tests/lib/inet_ntoa-t.c	2014-08-30 12:13:46 UTC (rev 9668)
+++ tests/lib/inet_ntoa-t.c	2014-09-03 17:18:22 UTC (rev 9669)
@@ -23,7 +23,7 @@
 #include "clibrary.h"
 #include <netinet/in.h>
 
-#include "libtest.h"
+#include "tap/basic.h"
 
 const char *test_inet_ntoa(const struct in_addr);
 

Modified: tests/lib/inet_ntop-t.c
===================================================================
--- tests/lib/inet_ntop-t.c	2014-08-30 12:13:46 UTC (rev 9668)
+++ tests/lib/inet_ntop-t.c	2014-09-03 17:18:22 UTC (rev 9669)
@@ -24,7 +24,7 @@
 #include "portable/socket.h"
 #include <errno.h>
 
-#include "libtest.h"
+#include "tap/basic.h"
 
 /* Some systems too old to have inet_ntop don't have EAFNOSUPPORT. */
 #ifndef EAFNOSUPPORT

Modified: tests/lib/innconf-t.c
===================================================================
--- tests/lib/innconf-t.c	2014-08-30 12:13:46 UTC (rev 9668)
+++ tests/lib/innconf-t.c	2014-09-03 17:18:22 UTC (rev 9669)
@@ -6,7 +6,7 @@
 
 #include "inn/innconf.h"
 #include "inn/messages.h"
-#include "libtest.h"
+#include "tap/basic.h"
 
 /* We will have strings, integers, bools and lists. */
 static const char grep[] =

Modified: tests/lib/list-t.c
===================================================================
--- tests/lib/list-t.c	2014-08-30 12:13:46 UTC (rev 9668)
+++ tests/lib/list-t.c	2014-09-03 17:18:22 UTC (rev 9669)
@@ -7,7 +7,7 @@
 #include "inn/messages.h"
 #include "inn/list.h"
 #include "inn/libinn.h"
-#include "libtest.h"
+#include "tap/basic.h"
 
 int
 main(void)

Modified: tests/lib/md5-t.c
===================================================================
--- tests/lib/md5-t.c	2014-08-30 12:13:46 UTC (rev 9668)
+++ tests/lib/md5-t.c	2014-09-03 17:18:22 UTC (rev 9669)
@@ -5,7 +5,7 @@
 #include "clibrary.h"
 #include "inn/md5.h"
 #include "inn/libinn.h"
-#include "libtest.h"
+#include "tap/basic.h"
 
 /* Used to initialize strings of unsigned characters. */
 #define U       (const unsigned char *)

Modified: tests/lib/memcmp-t.c
===================================================================
--- tests/lib/memcmp-t.c	2014-08-30 12:13:46 UTC (rev 9668)
+++ tests/lib/memcmp-t.c	2014-09-03 17:18:22 UTC (rev 9669)
@@ -5,7 +5,7 @@
 #include <stdio.h>
 #include <sys/types.h>
 
-#include "libtest.h"
+#include "tap/basic.h"
 
 int test_memcmp(const void *, const void *, size_t);
 

Modified: tests/lib/messages-t.c
===================================================================
--- tests/lib/messages-t.c	2014-08-30 12:13:46 UTC (rev 9668)
+++ tests/lib/messages-t.c	2014-09-03 17:18:22 UTC (rev 9669)
@@ -41,7 +41,7 @@
 
 #include "inn/messages.h"
 #include "inn/libinn.h"
-#include "libtest.h"
+#include "tap/basic.h"
 
 typedef void (*test_function_type)(void);
 void is_function_output(test_function_type, int status, const char *output,

Modified: tests/lib/mkstemp-t.c
===================================================================
--- tests/lib/mkstemp-t.c	2014-08-30 12:13:46 UTC (rev 9668)
+++ tests/lib/mkstemp-t.c	2014-09-03 17:18:22 UTC (rev 9669)
@@ -24,7 +24,7 @@
 #include <errno.h>
 #include <sys/stat.h>
 
-#include "libtest.h"
+#include "tap/basic.h"
 
 int test_mkstemp(char *template);
 

Modified: tests/lib/network-t.c
===================================================================
--- tests/lib/network-t.c	2014-08-30 12:13:46 UTC (rev 9668)
+++ tests/lib/network-t.c	2014-09-03 17:18:22 UTC (rev 9669)
@@ -43,7 +43,7 @@
 #include "inn/messages.h"
 #include "inn/network.h"
 #include "inn/libinn.h"
-#include "libtest.h"
+#include "tap/basic.h"
 
 /* Set this globally to 0 if IPv6 is available but doesn't work. */
 static int ipv6 = 1;

Modified: tests/lib/pread-t.c
===================================================================
--- tests/lib/pread-t.c	2014-08-30 12:13:46 UTC (rev 9668)
+++ tests/lib/pread-t.c	2014-09-03 17:18:22 UTC (rev 9669)
@@ -9,7 +9,7 @@
 
 #include "inn/messages.h"
 #include "inn/libinn.h"
-#include "libtest.h"
+#include "tap/basic.h"
 
 ssize_t test_pread(int fd, void *buf, size_t nbyte, off_t offset);
 

Modified: tests/lib/pwrite-t.c
===================================================================
--- tests/lib/pwrite-t.c	2014-08-30 12:13:46 UTC (rev 9668)
+++ tests/lib/pwrite-t.c	2014-09-03 17:18:22 UTC (rev 9669)
@@ -8,7 +8,7 @@
 #include <sys/stat.h>
 
 #include "inn/messages.h"
-#include "libtest.h"
+#include "tap/basic.h"
 
 ssize_t test_pwrite(int fd, const void *buf, size_t nbyte, off_t offset);
 

Modified: tests/lib/qio-t.c
===================================================================
--- tests/lib/qio-t.c	2014-08-30 12:13:46 UTC (rev 9668)
+++ tests/lib/qio-t.c	2014-09-03 17:18:22 UTC (rev 9669)
@@ -10,7 +10,7 @@
 #include "inn/messages.h"
 #include "inn/qio.h"
 #include "inn/libinn.h"
-#include "libtest.h"
+#include "tap/basic.h"
 
 static void
 output(int fd, const void *data, size_t size)

Modified: tests/lib/setenv-t.c
===================================================================
--- tests/lib/setenv-t.c	2014-08-30 12:13:46 UTC (rev 9668)
+++ tests/lib/setenv-t.c	2014-09-03 17:18:22 UTC (rev 9669)
@@ -25,7 +25,7 @@
 
 #include "inn/messages.h"
 #include "inn/libinn.h"
-#include "libtest.h"
+#include "tap/basic.h"
 
 int test_setenv(const char *name, const char *value, int overwrite);
 

Modified: tests/lib/snprintf-t.c
===================================================================
--- tests/lib/snprintf-t.c	2014-08-30 12:13:46 UTC (rev 9668)
+++ tests/lib/snprintf-t.c	2014-09-03 17:18:22 UTC (rev 9669)
@@ -24,7 +24,7 @@
 #include "config.h"
 #include "clibrary.h"
 
-#include "libtest.h"
+#include "tap/basic.h"
 
 /*
  * Disable the requirement that format strings be literals.  We need variable

Modified: tests/lib/strlcat-t.c
===================================================================
--- tests/lib/strlcat-t.c	2014-08-30 12:13:46 UTC (rev 9668)
+++ tests/lib/strlcat-t.c	2014-09-03 17:18:22 UTC (rev 9669)
@@ -22,7 +22,7 @@
 #include "config.h"
 #include "clibrary.h"
 
-#include "libtest.h"
+#include "tap/basic.h"
 
 size_t test_strlcat(char *, const char *, size_t);
 

Modified: tests/lib/strlcpy-t.c
===================================================================
--- tests/lib/strlcpy-t.c	2014-08-30 12:13:46 UTC (rev 9668)
+++ tests/lib/strlcpy-t.c	2014-09-03 17:18:22 UTC (rev 9669)
@@ -22,7 +22,7 @@
 #include "config.h"
 #include "clibrary.h"
 
-#include "libtest.h"
+#include "tap/basic.h"
 
 size_t test_strlcpy(char *, const char *, size_t);
 

Modified: tests/lib/tst-t.c
===================================================================
--- tests/lib/tst-t.c	2014-08-30 12:13:46 UTC (rev 9668)
+++ tests/lib/tst-t.c	2014-09-03 17:18:22 UTC (rev 9669)
@@ -7,7 +7,7 @@
 #include "inn/messages.h"
 #include "inn/tst.h"
 #include "inn/libinn.h"
-#include "libtest.h"
+#include "tap/basic.h"
 
 /* Used for strings of unsigned characters. */
 #define U (const unsigned char *)

Modified: tests/lib/uwildmat-t.c
===================================================================
--- tests/lib/uwildmat-t.c	2014-08-30 12:13:46 UTC (rev 9668)
+++ tests/lib/uwildmat-t.c	2014-09-03 17:18:22 UTC (rev 9669)
@@ -8,7 +8,7 @@
 
 #include "clibrary.h"
 #include "inn/libinn.h"
-#include "libtest.h"
+#include "tap/basic.h"
 
 static void
 test_r(int n, const char *text, const char *pattern, bool matches)

Modified: tests/lib/vector-t.c
===================================================================
--- tests/lib/vector-t.c	2014-08-30 12:13:46 UTC (rev 9668)
+++ tests/lib/vector-t.c	2014-09-03 17:18:22 UTC (rev 9669)
@@ -26,7 +26,7 @@
 #include "inn/messages.h"
 #include "inn/vector.h"
 #include "inn/libinn.h"
-#include "libtest.h"
+#include "tap/basic.h"
 
 int
 main(void)

Modified: tests/lib/wire-t.c
===================================================================
--- tests/lib/wire-t.c	2014-08-30 12:13:46 UTC (rev 9668)
+++ tests/lib/wire-t.c	2014-09-03 17:18:22 UTC (rev 9669)
@@ -9,7 +9,7 @@
 #include "inn/messages.h"
 #include "inn/wire.h"
 #include "inn/libinn.h"
-#include "libtest.h"
+#include "tap/basic.h"
 
 /* Read in a file and return the contents in newly allocated memory.  Fills in
    the provided stat buffer. */

Modified: tests/lib/xmalloc.t
===================================================================
--- tests/lib/xmalloc.t	2014-08-30 12:13:46 UTC (rev 9668)
+++ tests/lib/xmalloc.t	2014-09-03 17:18:22 UTC (rev 9669)
@@ -30,7 +30,7 @@
 # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 # DEALINGS IN THE SOFTWARE.
 
-. "$SOURCE/libtest.sh"
+. "$SOURCE/tap/libtap.sh"
 cd "$BUILD/lib"
 
 # Run an xmalloc test.  Takes the description, the expectd exit status, the

Modified: tests/lib/xwrite-t.c
===================================================================
--- tests/lib/xwrite-t.c	2014-08-30 12:13:46 UTC (rev 9668)
+++ tests/lib/xwrite-t.c	2014-09-03 17:18:22 UTC (rev 9669)
@@ -36,7 +36,7 @@
 #include <sys/uio.h>
 
 #include "inn/libinn.h"
-#include "libtest.h"
+#include "tap/basic.h"
 
 /* The data array we'll use to do testing. */
 char data[256];

Deleted: tests/libtest.c
===================================================================
--- tests/libtest.c	2014-08-30 12:13:46 UTC (rev 9668)
+++ tests/libtest.c	2014-09-03 17:18:22 UTC (rev 9669)
@@ -1,640 +0,0 @@
-/* $Id$
- *
- * Some utility routines for writing tests.
- *
- * Here are a variety of utility routines for writing tests compatible with
- * the TAP protocol.  All routines of the form ok() or is*() take a test
- * number and some number of appropriate arguments, check to be sure the
- * results match the expected output using the arguments, and print out
- * something appropriate for that test number.  Other utility routines help in
- * constructing more complex tests, skipping tests, or setting up the TAP
- * output format.
- *
- * This file is part of C TAP Harness.  The current version plus supporting
- * documentation is at <http://www.eyrie.org/~eagle/software/c-tap-harness/>.
- *
- * Copyright 2009, 2010 Russ Allbery <rra at stanford.edu>
- * Copyright 2001, 2002, 2004, 2005, 2006, 2007, 2008
- *     The Board of Trustees of the Leland Stanford Junior University
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
-
-/* Required for isnan() and isinf(). */
-#ifndef _XOPEN_SOURCE
-# define _XOPEN_SOURCE 600
-#endif
-
-#include <errno.h>
-#include <math.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/time.h>
-#include <sys/wait.h>
-#include <unistd.h>
-
-#include "libtest.h"
-
-/* Specific to the integration of C TAP Harness in INN. */
-#ifndef LIBTEST_NEW_FORMAT
-# include "inn/messages.h"
-# include "inn/libinn.h"
-#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.
- */
-static void
-finish(void)
-{
-    unsigned long highest = testnum - 1;
-
-    if (_planned == 0 && !_lazy)
-        return;
-    fflush(stderr);
-    if (_process != 0 && getpid() == _process) {
-        if (_lazy) {
-            printf("1..%lu\n", highest);
-            _planned = highest;
-        }
-        if (_planned > highest)
-            printf("# Looks like you planned %lu test%s but only ran %lu\n",
-                   _planned, (_planned > 1 ? "s" : ""), highest);
-        else if (_planned < highest)
-            printf("# Looks like you planned %lu test%s but ran %lu extra\n",
-                   _planned, (_planned > 1 ? "s" : ""), highest - _planned);
-        else if (_failed > 0)
-            printf("# Looks like you failed %lu test%s of %lu\n", _failed,
-                   (_failed > 1 ? "s" : ""), _planned);
-        else if (_planned > 1)
-            printf("# All %lu tests successful or skipped\n", _planned);
-        else
-            printf("# %lu test successful or skipped\n", _planned);
-    }
-}
-
-
-/*
- * Initialize things.  Turns on line buffering on stdout and then prints out
- * the number of tests in the test suite.
- */
-#ifndef LIBTEST_NEW_FORMAT
-void
-test_init(int count)
-{
-    plan(count);
-}
-#endif
-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.
- */
-#ifndef LIBTEST_NEW_FORMAT
-void
-ok(int n UNUSED, int success) {
-    new_ok(success, NULL);
-}
-#endif
-void
-new_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.
- */
-#ifndef LIBTEST_NEW_FORMAT
-void
-skip(int n UNUSED, const char *reason) {
-    new_skip(reason);
-}
-#endif
-void
-new_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.
- */
-#ifndef LIBTEST_NEW_FORMAT
-void
-ok_block(int n UNUSED, int count, int success) {
-    new_ok_block(count, success, NULL);
-}
-#endif
-void
-new_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.
- */
-#ifndef LIBTEST_NEW_FORMAT
-void
-skip_block(int n UNUSED, int count, const char *reason) {
-    new_skip_block(count, reason);
-}
-#endif
-void
-new_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.
- */
-#ifndef LIBTEST_NEW_FORMAT
-void
-ok_int(int n UNUSED, int wanted, int seen)
-{
-    is_int(wanted, seen, NULL);
-}
-#endif
-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).
- */
-#ifndef LIBTEST_NEW_FORMAT
-void
-ok_string(int n UNUSED, const char *wanted, const char *seen)
-{
-    is_string(wanted, seen, NULL);
-}
-#endif
-void
-is_string(const char *wanted, const char *seen, const char *format, ...)
-{
-    if (wanted == NULL)
-        wanted = "(null)";
-    if (seen == NULL)
-        seen = "(null)";
-    fflush(stderr);
-    if (strcmp(wanted, seen) == 0)
-        printf("ok %lu", testnum++);
-    else {
-        printf("# wanted: %s\n#   seen: %s\n", wanted, seen);
-        printf("not ok %lu", testnum++);
-        _failed++;
-    }
-    if (format != NULL) {
-        va_list args;
-
-        va_start(args, format);
-        print_desc(format, args);
-        va_end(args);
-    }
-    putchar('\n');
-}
-
-
-/*
- * Takes an expected double and a seen double and assumes the test passes if
- * those two numbers are within delta of each other.
- */
-#ifndef LIBTEST_NEW_FORMAT
-void
-ok_double(int n UNUSED, double wanted, double seen)
-{
-    is_double(wanted, seen, 0.01, NULL);
-}
-#endif
-void
-is_double(double wanted, double seen, double epsilon, const char *format, ...)
-{
-    fflush(stderr);
-    if ((isnan(wanted) && isnan(seen))
-        || (isinf(wanted) && isinf(seen) && wanted == seen)
-        || fabs(wanted - seen) <= epsilon)
-        printf("ok %lu", testnum++);
-    else {
-        printf("# wanted: %g\n#   seen: %g\n", wanted, seen);
-        printf("not ok %lu", testnum++);
-        _failed++;
-    }
-    if (format != NULL) {
-        va_list args;
-
-        va_start(args, format);
-        print_desc(format, args);
-        va_end(args);
-    }
-    putchar('\n');
-}
-
-
-/*
- * Takes an expected unsigned long and a seen unsigned long and assumes the
- * test passes if the two numbers match.  Otherwise, reports them in hex.
- */
-void
-is_hex(unsigned long wanted, unsigned long seen, const char *format, ...)
-{
-    fflush(stderr);
-    if (wanted == seen)
-        printf("ok %lu", testnum++);
-    else {
-        printf("# wanted: %lx\n#   seen: %lx\n", (unsigned long) wanted,
-               (unsigned long) seen);
-        printf("not ok %lu", testnum++);
-        _failed++;
-    }
-    if (format != NULL) {
-        va_list args;
-
-        va_start(args, format);
-        print_desc(format, args);
-        va_end(args);
-    }
-    putchar('\n');
-}
-
-
-/*
- * Bail out with an error.
- */
-void
-bail(const char *format, ...)
-{
-    va_list args;
-
-    fflush(stderr);
-    fflush(stdout);
-    printf("Bail out! ");
-    va_start(args, format);
-    vprintf(format, args);
-    va_end(args);
-    printf("\n");
-    exit(1);
-}
-
-
-/*
- * Bail out with an error, appending strerror(errno).
- */
-void
-sysbail(const char *format, ...)
-{
-    va_list args;
-    int oerrno = errno;
-
-    fflush(stderr);
-    fflush(stdout);
-    printf("Bail out! ");
-    va_start(args, format);
-    vprintf(format, args);
-    va_end(args);
-    printf(": %s\n", strerror(oerrno));
-    exit(1);
-}
-
-
-/*
- * Report a diagnostic to stderr.
- */
-void
-diag(const char *format, ...)
-{
-    va_list args;
-
-    fflush(stderr);
-    fflush(stdout);
-    printf("# ");
-    va_start(args, format);
-    vprintf(format, args);
-    va_end(args);
-    printf("\n");
-}
-
-
-/*
- * Report a diagnostic to stderr, appending strerror(errno).
- */
-void
-sysdiag(const char *format, ...)
-{
-    va_list args;
-    int oerrno = errno;
-
-    fflush(stderr);
-    fflush(stdout);
-    printf("# ");
-    va_start(args, format);
-    vprintf(format, args);
-    va_end(args);
-    printf(": %s\n", strerror(oerrno));
-}
-
-
-/*
- * Locate a test file.  Given the partial path to a file, look under BUILD and
- * then SOURCE for the file and return the full path to the file.  Returns
- * NULL if the file doesn't exist.  A non-NULL return should be freed with
- * test_file_path_free().
- *
- * This function uses sprintf because it attempts to be independent of all
- * other portability layers.  The use immediately after a memory allocation
- * should be safe without using snprintf or strlcpy/strlcat.
- */
-char *
-test_file_path(const char *file)
-{
-    char *base;
-    char *path = NULL;
-    size_t length;
-    const char *envs[] = { "BUILD", "SOURCE", NULL };
-    int i;
-
-    for (i = 0; envs[i] != NULL; i++) {
-        base = getenv(envs[i]);
-        if (base == NULL)
-            continue;
-        length = strlen(base) + 1 + strlen(file) + 1;
-        path = malloc(length);
-        if (path == NULL)
-            sysbail("cannot allocate memory");
-        sprintf(path, "%s/%s", base, file);
-        if (access(path, R_OK) == 0)
-            break;
-        free(path);
-        path = NULL;
-    }
-    return path;
-}
-
-
-/*
- * Free a path returned from test_file_path().  This function exists primarily
- * for Windows, where memory must be freed from the same library domain that
- * it was allocated from.
- */
-void
-test_file_path_free(char *path)
-{
-    if (path != NULL)
-        free(path);
-}
-
-
-#ifndef LIBTEST_NEW_FORMAT
-/* A global buffer into which message_log_buffer stores error messages. */
-char *errors = NULL;
-
-/*
- *  An error handler that appends all errors to the errors global.  Used by
- *  error_capture.
- */
-static void
-message_log_buffer(int len, const char *fmt, va_list args, int error UNUSED)
-{
-    char *message;
-
-    message = xmalloc(len + 1);
-    vsnprintf(message, len + 1, fmt, args);
-    if (errors == NULL) {
-        errors = concat(message, "\n", (char *) 0);
-    } else {
-        char *new_errors;
-
-        new_errors = concat(errors, message, "\n", (char *) 0);
-        free(errors);
-        errors = new_errors;
-    }
-    free(message);
-}
-
-
-/*
- *  Turn on the capturing of errors.  Errors will be stored in the global
- *  errors variable where they can be checked by the test suite.  Capturing is
- *  turned off with errors_uncapture.
- */
-void
-errors_capture(void)
-{
-    if (errors != NULL) {
-        free(errors);
-        errors = NULL;
-    }
-    message_handlers_warn(1, message_log_buffer);
-    message_handlers_notice(1, message_log_buffer);
-}
-
-
-/*
- *  Turn off the capturing of errors again.
- */
-void
-errors_uncapture(void)
-{
-    message_handlers_warn(1, message_log_stderr);
-    message_handlers_notice(1, message_log_stdout);
-}
-#endif

Deleted: tests/libtest.h
===================================================================
--- tests/libtest.h	2014-08-30 12:13:46 UTC (rev 9668)
+++ tests/libtest.h	2014-09-03 17:18:22 UTC (rev 9669)
@@ -1,177 +0,0 @@
-/* $Id$
- *
- * Basic utility routines for the TAP protocol.
- *
- * This file is part of C TAP Harness.  The current version plus supporting
- * documentation is at <http://www.eyrie.org/~eagle/software/c-tap-harness/>.
- *
- * Copyright 2009, 2010 Russ Allbery <rra at stanford.edu>
- * Copyright 2001, 2002, 2004, 2005, 2006, 2007, 2008
- *     The Board of Trustees of the Leland Stanford Junior University
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
-
-#ifndef TAP_BASIC_H
-#define TAP_BASIC_H 1
-
-#include <stdarg.h>             /* va_list */
-#include <sys/types.h>          /* pid_t */
-
-/*
- * __attribute__ is available in gcc 2.5 and later, but only with gcc 2.7
- * could you use the __format__ form of the attributes, which is what we use
- * (to avoid confusion with other macros).
- */
-#ifndef __attribute__
-# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 7)
-#  define __attribute__(spec)   /* empty */
-# endif
-#endif
-
-/*
- * BEGIN_DECLS is used at the beginning of declarations so that C++
- * compilers don't mangle their names.  END_DECLS is used at the end.
- */
-#undef BEGIN_DECLS
-#undef END_DECLS
-#ifdef __cplusplus
-# define BEGIN_DECLS    extern "C" {
-# define END_DECLS      }
-#else
-# define BEGIN_DECLS    /* empty */
-# define END_DECLS      /* empty */
-#endif
-
-/*
- * Used for iterating through arrays.  ARRAY_SIZE returns the number of
- * elements in the array (useful for a < upper bound in a for loop) and
- * ARRAY_END returns a pointer to the element past the end (ISO C99 makes it
- * legal to refer to such a pointer as long as it's never dereferenced).
- */
-#define ARRAY_SIZE(array)       (sizeof(array) / sizeof((array)[0]))
-#define ARRAY_END(array)        (&(array)[ARRAY_SIZE(array)])
-
-BEGIN_DECLS
-
-/*
- * The test count.  Always contains the number that will be used for the next
- * test status.
- */
-extern unsigned long testnum;
-
-/* Print out the number of tests and set standard output to line buffered. */
-void plan(unsigned long count);
-
-/*
- * Prepare for lazy planning, in which the plan will be  printed automatically
- * at the end of the test program.
- */
-void plan_lazy(void);
-
-/* Skip the entire test suite.  Call instead of plan. */
-void skip_all(const char *format, ...)
-    __attribute__((__noreturn__, __format__(printf, 1, 2)));
-
-/*
- * Basic reporting functions.  The okv() function is the same as ok() but
- * takes the test description as a va_list to make it easier to reuse the
- * reporting infrastructure when writing new tests.
- */
-#ifndef LIBTEST_NEW_FORMAT
-void ok(int n, int success);
-void new_ok(int success, const char *format, ...)
-        __attribute__((__format__(printf, 2, 3)));
-void ok_int(int n, int wanted, int seen);
-void ok_double(int n, double wanted, double seen);
-void ok_string(int n, const char *wanted, const char *seen);
-void skip(int n, const char *reason);
-void new_skip(const char *reason, ...)
-        __attribute__((__format__(printf, 1, 2)));
-void ok_block(int n, int count, int success);
-void new_ok_block(unsigned long count, int success, const char *format, ...)
-        __attribute__((__format__(printf, 3, 4)));
-void skip_block(int n, int count, const char *reason);
-void new_skip_block(unsigned long count, const char *reason, ...)
-        __attribute__((__format__(printf, 2, 3)));
-
-void test_init(int count);
-
-/* A global buffer into which errors_capture stores errors. */
-extern char *errors;
-
-/* Turn on capturing of errors with errors_capture.  Errors reported by warn
- * will be stored in the global errors variable.  Turn this off again with
- * errors_uncapture.  Caller is responsible for freeing errors when done.
- */
-void errors_capture(void);
-void errors_uncapture(void);
-#else
-# define ok new_ok
-# define skip new_skip
-# define ok_block new_ok_block
-# define skip_block new_skip_block
-void ok(int success, const char *format, ...)
-    __attribute__((__format__(printf, 2, 3)));
-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)));
-#endif
-
-void okv(int success, const char *format, va_list args);
-
-/* Check an expected value against a seen value. */
-void is_int(long wanted, long seen, const char *format, ...)
-    __attribute__((__format__(printf, 3, 4)));
-void is_double(double wanted, double seen, double epsilon,
-               const char *format, ...)
-    __attribute__((__format__(printf, 4, 5)));
-void is_string(const char *wanted, const char *seen, const char *format, ...)
-    __attribute__((__format__(printf, 3, 4)));
-void is_hex(unsigned long wanted, unsigned long seen, const char *format, ...)
-    __attribute__((__format__(printf, 3, 4)));
-
-/* Bail out with an error.  sysbail appends strerror(errno). */
-void bail(const char *format, ...)
-    __attribute__((__noreturn__, __nonnull__, __format__(printf, 1, 2)));
-void sysbail(const char *format, ...)
-    __attribute__((__noreturn__, __nonnull__, __format__(printf, 1, 2)));
-
-/* Report a diagnostic to stderr prefixed with #. */
-void diag(const char *format, ...)
-    __attribute__((__nonnull__, __format__(printf, 1, 2)));
-void sysdiag(const char *format, ...)
-    __attribute__((__nonnull__, __format__(printf, 1, 2)));
-
-/*
- * Find a test file under BUILD or SOURCE, returning the full path.  The
- * returned path should be freed with test_file_path_free().
- */
-char *test_file_path(const char *file)
-    __attribute__((__malloc__, __nonnull__));
-void test_file_path_free(char *path);
-
-END_DECLS
-
-#endif /* TAP_BASIC_H */

Deleted: tests/libtest.sh
===================================================================
--- tests/libtest.sh	2014-08-30 12:13:46 UTC (rev 9668)
+++ tests/libtest.sh	2014-09-03 17:18:22 UTC (rev 9669)
@@ -1,224 +0,0 @@
-# $Id$
-#
-# Shell function library for test cases.
-#
-# This file provides a TAP-compatible shell function library useful for
-# writing test cases.  It is part of C TAP Harness, which can be found at
-# <http://www.eyrie.org/~eagle/software/c-tap-harness/>.
-#
-# Written by Russ Allbery <rra at stanford.edu>
-# Copyright 2009, 2010 Russ Allbery <rra at stanford.edu>
-# Copyright 2006, 2007, 2008
-#     The Board of Trustees of the Leland Stanford Junior University
-#
-# Permission is hereby granted, free of charge, to any person obtaining a copy
-# of this software and associated documentation files (the "Software"), to
-# deal in the Software without restriction, including without limitation the
-# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
-# sell copies of the Software, and to permit persons to whom the Software is
-# furnished to do so, subject to the following conditions:
-#
-# The above copyright notice and this permission notice shall be included in
-# all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
-# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
-# IN THE SOFTWARE.
-
-# Print out the number of test cases we expect to run.
-plan () {
-    count=1
-    planned="$1"
-    failed=0
-    echo "1..$1"
-    trap finish 0
-}
-
-# Prepare for lazy planning.
-plan_lazy () {
-    count=1
-    planned=0
-    failed=0
-    trap finish 0
-}
-
-# Report the test status on exit.
-finish () {
-    local highest looks
-    highest=`expr "$count" - 1`
-    if [ "$planned" = 0 ] ; then
-        echo "1..$highest"
-        planned="$highest"
-    fi
-    looks='# Looks like you'
-    if [ "$planned" -gt 0 ] ; then
-        if [ "$planned" -gt "$highest" ] ; then
-            if [ "$planned" -gt 1 ] ; then
-                echo "$looks planned $planned tests but only ran $highest"
-            else
-                echo "$looks planned $planned test but only ran $highest"
-            fi
-        elif [ "$planned" -lt "$highest" ] ; then
-            local extra
-            extra=`expr "$highest" - "$planned"`
-            if [ "$planned" -gt 1 ] ; then
-                echo "$looks planned $planned tests but ran $extra extra"
-            else
-                echo "$looks planned $planned test but ran $extra extra"
-            fi
-        elif [ "$failed" -gt 0 ] ; then
-            if [ "$failed" -gt 1 ] ; then
-                echo "$looks failed $failed tests of $planned"
-            else
-                echo "$looks failed $failed test of $planned"
-            fi
-        elif [ "$planned" -gt 1 ] ; then
-            echo "# All $planned tests successful or skipped"
-        else
-            echo "# $planned test successful or skipped"
-        fi
-    fi
-}
-
-# Skip the entire test suite.  Should be run instead of plan.
-skip_all () {
-    local desc
-    desc="$1"
-    if [ -n "$desc" ] ; then
-        echo "1..0 # skip $desc"
-    else
-        echo "1..0 # skip"
-    fi
-    exit 0
-}
-
-# ok takes a test description and a command to run and prints success if that
-# command is successful, false otherwise.  The count starts at 1 and is
-# updated each time ok is printed.
-ok () {
-    local desc
-    desc="$1"
-    if [ -n "$desc" ] ; then
-        desc=" - $desc"
-    fi
-    shift
-    if "$@" ; then
-        echo ok $count$desc
-    else
-        echo not ok $count$desc
-        failed=`expr $failed + 1`
-    fi
-    count=`expr $count + 1`
-}
-
-# Skip the next test.  Takes the reason why the test is skipped.
-skip () {
-    echo "ok $count # skip $*"
-    count=`expr $count + 1`
-}
-
-# Report the same status on a whole set of tests.  Takes the count of tests,
-# the description, and then the command to run to determine the status.
-ok_block () {
-    local end i desc
-    i=$count
-    end=`expr $count + $1`
-    shift
-    desc="$1"
-    shift
-    while [ "$i" -lt "$end" ] ; do
-        ok "$desc" "$@"
-        i=`expr $i + 1`
-    done
-}
-
-# Skip a whole set of tests.  Takes the count and then the reason for skipping
-# the test.
-skip_block () {
-    local i end
-    i=$count
-    end=`expr $count + $1`
-    shift
-    while [ "$i" -lt "$end" ] ; do
-        skip "$@"
-        i=`expr $i + 1`
-    done
-}
-
-# Portable variant of printf '%s\n' "$*".  In the majority of cases, this
-# function is slower than printf, because the latter is often implemented
-# as a builtin command.  The value of the variable IFS is ignored.
-puts () {
-    cat << EOH
-$@
-EOH
-}
-
-# Run a program expected to succeed, and print ok if it does and produces the
-# correct output.  Takes the description, expected exit status, the expected
-# output, the command to run, and then any arguments for that command.
-# Standard output and standard error are combined when analyzing the output of
-# the command.
-#
-# If the command may contain system-specific error messages in its output,
-# add strip_colon_error before the command to post-process its output.
-ok_program () {
-    local desc w_status w_output output status
-    desc="$1"
-    shift
-    w_status="$1"
-    shift
-    w_output="$1"
-    shift
-    output=`"$@" 2>&1`
-    status=$?
-    if [ $status = $w_status ] && [ x"$output" = x"$w_output" ] ; then
-        ok "$desc" true
-    else
-        echo "#  saw: ($status) $output"
-        echo "#  not: ($w_status) $w_output"
-        ok "$desc" false
-    fi
-}
-
-# Strip a colon and everything after it off the output of a command, as long
-# as that colon comes after at least one whitespace character.  (This is done
-# to avoid stripping the name of the program from the start of an error
-# message.)  This is used to remove system-specific error messages (coming
-# from strerror, for example).
-strip_colon_error() {
-    local output status
-    output=`"$@" 2>&1`
-    status=$?
-    output=`puts "$output" | sed 's/^\([^ ]* [^:]*\):.*/\1/'`
-    puts "$output"
-    return $status
-}
-
-# Bail out with an error message.
-bail () {
-    echo 'Bail out!' "$@"
-    exit 1
-}
-
-# Output a diagnostic on standard error, preceded by the required # mark.
-diag () {
-    echo '#' "$@"
-}
-
-# Search for the given file first in $BUILD and then in $SOURCE and echo the
-# path where the file was found, or the empty string if the file wasn't
-# found.
-test_file_path () {
-    if [ -n "$BUILD" ] && [ -f "$BUILD/$1" ] ; then
-        puts "$BUILD/$1"
-    elif [ -n "$SOURCE" ] && [ -f "$SOURCE/$1" ] ; then
-        puts "$SOURCE/$1"
-    else
-        echo ''
-    fi
-}

Modified: tests/nnrpd/auth-ext-t.c
===================================================================
--- tests/nnrpd/auth-ext-t.c	2014-08-30 12:13:46 UTC (rev 9668)
+++ tests/nnrpd/auth-ext-t.c	2014-09-03 17:18:22 UTC (rev 9669)
@@ -5,7 +5,7 @@
 #include "clibrary.h"
 
 #include "inn/messages.h"
-#include "libtest.h"
+#include "tap/basic.h"
 
 #include "../../nnrpd/nnrpd.h"
 

Modified: tests/overview/api-t.c
===================================================================
--- tests/overview/api-t.c	2014-08-30 12:13:46 UTC (rev 9668)
+++ tests/overview/api-t.c	2014-09-03 17:18:22 UTC (rev 9669)
@@ -13,7 +13,7 @@
 #include "inn/overview.h"
 #include "inn/vector.h"
 #include "inn/libinn.h"
-#include "libtest.h"
+#include "tap/basic.h"
 #include "inn/storage.h"
 
 /* Used as the artificial token for all articles inserted into overview. */

Modified: tests/overview/overview-t.c
===================================================================
--- tests/overview/overview-t.c	2014-08-30 12:13:46 UTC (rev 9668)
+++ tests/overview/overview-t.c	2014-09-03 17:18:22 UTC (rev 9669)
@@ -16,7 +16,7 @@
 #include "inn/messages.h"
 #include "inn/vector.h"
 #include "inn/libinn.h"
-#include "libtest.h"
+#include "tap/basic.h"
 #include "inn/ov.h"
 #include "inn/storage.h"
 

Modified: tests/overview/xref-t.c
===================================================================
--- tests/overview/xref-t.c	2014-08-30 12:13:46 UTC (rev 9668)
+++ tests/overview/xref-t.c	2014-09-03 17:18:22 UTC (rev 9669)
@@ -13,7 +13,7 @@
 #include "inn/wire.h"
 #include "inn/vector.h"
 #include "inn/libinn.h"
-#include "libtest.h"
+#include "tap/basic.h"
 #include "inn/storage.h"
 
 /* Used as the artificial token for all articles inserted into overview. */

Modified: tests/runtests.c
===================================================================
--- tests/runtests.c	2014-08-30 12:13:46 UTC (rev 9668)
+++ tests/runtests.c	2014-09-03 17:18:22 UTC (rev 9669)
@@ -2,13 +2,6 @@
  *
  * Run a set of tests, reporting results.
  *
- * Please note that this file is maintained separately from INN by the above
- * author (which is why the coding style is slightly different).  Any fixes
- * added to the INN tree should also be reported to the above author if
- * necessary.
- *
- * Based on C TAP Harness 1.7 (2011-04-28).
- *
  * Usage:
  *
  *      runtests [-b <build-dir>] [-s <source-dir>] <test-list>
@@ -62,8 +55,8 @@
  * 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 at stanford.edu>
+ * Copyright 2000, 2001, 2004, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013,
+ *     2014 Russ Allbery <eagle at eyrie.org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -85,14 +78,18 @@
 */
 
 /* Required for fdopen(), getopt(), and putenv(). */
-#ifndef _XOPEN_SOURCE
-# define _XOPEN_SOURCE 500
+#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 <limits.h>
 #include <stdarg.h>
+#include <stddef.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -107,12 +104,29 @@
 /* sys/time.h must be included before sys/resource.h on some platforms. */
 #include <sys/resource.h>
 
-/* AIX doesn't have WCOREDUMP. */
+/* AIX 6.1 (and possibly later) doesn't have WCOREDUMP. */
 #ifndef WCOREDUMP
-# define WCOREDUMP(status)      ((unsigned)(status) & 0x80)
+# define WCOREDUMP(status) ((unsigned)(status) & 0x80)
 #endif
 
 /*
+ * POSIX requires that these be defined in <unistd.h>, but they're not always
+ * available.  If one of them has been defined, all the rest almost certainly
+ * have.
+ */
+#ifndef STDIN_FILENO
+# define STDIN_FILENO  0
+# define STDOUT_FILENO 1
+# define STDERR_FILENO 2
+#endif
+
+/*
+ * Used for iterating through arrays.  Returns the number of elements in the
+ * array (useful for a < upper bound in a for loop).
+ */
+#define ARRAY_SIZE(array) (sizeof(array) / sizeof((array)[0]))
+
+/*
  * 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
@@ -144,7 +158,8 @@
 /* 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. */
+#define CHILDERR_STDIN  102     /* Couldn't open stdin file. */
+#define CHILDERR_STDERR 103     /* Couldn't open stderr file. */
 
 /* Structure to hold data for a set of tests. */
 struct testset {
@@ -159,7 +174,7 @@
     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. */
+    unsigned int aborted;       /* Whether the set was 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. */
@@ -173,21 +188,25 @@
 };
 
 /*
- * Usage message.  Should be used as a printf format with two arguments: the
- * path to runtests, given twice.
+ * Usage message.  Should be used as a printf format with four arguments: the
+ * path to runtests, given three times, and the usage_description.  This is
+ * split into variables to satisfy the pedantic ISO C90 limit on strings.
  */
 static const char usage_message[] = "\
-Usage: %s [-b <build-dir>] [-s <source-dir>] <test-list>\n\
+Usage: %s [-b <build-dir>] [-s <source-dir>] <test> ...\n\
+       %s [-b <build-dir>] [-s <source-dir>] -l <test-list>\n\
        %s -o [-b <build-dir>] [-s <source-dir>] <test>\n\
-\n\
+\n%s";
+static const char usage_extra[] = "\
 Options:\n\
     -b <build-dir>      Set the build directory to <build-dir>\n\
+    -l <list>           Take the list of tests to run from <test-list>\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";
+runtests normally runs each test listed on the command line.  With the -l\n\
+option, it instead runs every test listed in a file.  With the -o option,\n\
+it instead runs a single test and shows its complete output.\n";
 
 /*
  * Header used for test output.  %s is replaced by the file name of the list
@@ -203,12 +222,60 @@
 -------------------------- -------------- ---- ----  ------------------------";
 
 /* 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__)
+#define xcalloc(n, size)      x_calloc((n), (size), __FILE__, __LINE__)
+#define xmalloc(size)         x_malloc((size), __FILE__, __LINE__)
+#define xstrdup(p)            x_strdup((p), __FILE__, __LINE__)
+#define xreallocarray(p, n, size) \
+    x_reallocarray((p), (n), (size), __FILE__, __LINE__)
 
+/*
+ * __attribute__ is available in gcc 2.5 and later, but only with gcc 2.7
+ * could you use the __format__ form of the attributes, which is what we use
+ * (to avoid confusion with other macros).
+ */
+#ifndef __attribute__
+# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 7)
+#  define __attribute__(spec)   /* empty */
+# endif
+#endif
 
 /*
+ * 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
+
+/* Declare internal functions that benefit from compiler attributes. */
+static void sysdie(const char *, ...)
+    __attribute__((__nonnull__, __noreturn__, __format__(printf, 1, 2)));
+static void *x_calloc(size_t, size_t, const char *, int)
+    __attribute__((__alloc_size__(1, 2), __malloc__, __nonnull__));
+static void *x_malloc(size_t, const char *, int)
+    __attribute__((__alloc_size__(1), __malloc__, __nonnull__));
+static void *x_reallocarray(void *, size_t, size_t, const char *, int)
+    __attribute__((__alloc_size__(2, 3), __malloc__, __nonnull__(4)));
+static char *x_strdup(const char *, const char *, int)
+    __attribute__((__malloc__, __nonnull__));
+
+
+/*
  * Report a fatal error, including the results of strerror, and exit.
  */
 static void
@@ -229,6 +296,24 @@
 
 
 /*
+ * Allocate zeroed memory, reporting a fatal error and exiting on failure.
+ */
+static void *
+x_calloc(size_t n, size_t size, const char *file, int line)
+{
+    void *p;
+
+    n = (n > 0) ? n : 1;
+    size = (size > 0) ? size : 1;
+    p = calloc(n, size);
+    if (p == NULL)
+        sysdie("failed to calloc %lu bytes at %s line %d",
+               (unsigned long) size, file, line);
+    return p;
+}
+
+
+/*
  * Allocate memory, reporting a fatal error and exiting on failure.
  */
 static void *
@@ -246,14 +331,26 @@
 
 /*
  * Reallocate memory, reporting a fatal error and exiting on failure.
+ *
+ * We should technically use SIZE_MAX here for the overflow check, but
+ * SIZE_MAX is C99 and we're only assuming C89 + SUSv3, which does not
+ * guarantee that it exists.  They do guarantee that UINT_MAX exists, and we
+ * can assume that UINT_MAX <= SIZE_MAX.  And we should not be allocating
+ * anything anywhere near that large.
+ *
+ * (In theory, C89 and C99 permit size_t to be smaller than unsigned int, but
+ * I disbelieve in the existence of such systems and they will have to cope
+ * without overflow checks.)
  */
 static void *
-x_realloc(void *p, size_t size, const char *file, int line)
+x_reallocarray(void *p, size_t n, size_t size, const char *file, int line)
 {
-    p = realloc(p, size);
+    if (n > 0 && UINT_MAX / n <= size)
+        sysdie("realloc too large at %s line %d", file, line);
+    p = realloc(p, n * size);
     if (p == NULL)
         sysdie("failed to realloc %lu bytes at %s line %d",
-               (unsigned long) size, file, line);
+               (unsigned long) (n * size), file, line);
     return p;
 }
 
@@ -278,6 +375,55 @@
 
 
 /*
+ * Form a new string by concatenating multiple strings.  The arguments must be
+ * terminated by (const char *) 0.
+ *
+ * This function only exists because we can't assume asprintf.  We can't
+ * simulate asprintf with snprintf because we're only assuming SUSv3, which
+ * does not require that snprintf with a NULL buffer return the required
+ * length.  When those constraints are relaxed, this should be ripped out and
+ * replaced with asprintf or a more trivial replacement with snprintf.
+ */
+static char *
+concat(const char *first, ...)
+{
+    va_list args;
+    char *result;
+    const char *string;
+    size_t offset;
+    size_t length = 0;
+
+    /*
+     * Find the total memory required.  Ensure we don't overflow length.  We
+     * aren't guaranteed to have SIZE_MAX, so use UINT_MAX as an acceptable
+     * substitute (see the x_nrealloc comments).
+     */
+    va_start(args, first);
+    for (string = first; string != NULL; string = va_arg(args, const char *)) {
+        if (length >= UINT_MAX - strlen(string)) {
+            errno = EINVAL;
+            sysdie("strings too long in concat");
+        }
+        length += strlen(string);
+    }
+    va_end(args);
+    length++;
+
+    /* Create the string. */
+    result = xmalloc(length);
+    va_start(args, first);
+    offset = 0;
+    for (string = first; string != NULL; string = va_arg(args, const char *)) {
+        memcpy(result + offset, string, strlen(string));
+        offset += strlen(string);
+    }
+    va_end(args);
+    result[offset] = '\0';
+    return result;
+}
+
+
+/*
  * Given a struct timeval, return the number of seconds it represents as a
  * double.  Use difftime() to convert a time_t to a double.
  */
@@ -329,36 +475,62 @@
 static pid_t
 test_start(const char *path, int *fd)
 {
-    int fds[2], errfd;
+    int fds[2], infd, errfd;
     pid_t child;
 
+    /* Create a pipe used to capture the output from the test program. */
     if (pipe(fds) == -1) {
         puts("ABORTED");
         fflush(stdout);
         sysdie("can't create pipe");
     }
+
+    /* Fork a child process, massage the file descriptors, and exec. */
     child = fork();
-    if (child == (pid_t) -1) {
+    switch (child) {
+    case -1:
         puts("ABORTED");
         fflush(stdout);
         sysdie("can't fork");
-    } else if (child == 0) {
-        /* In child.  Set up our stdout and stderr. */
+
+    /* In the child.  Set up our standard output. */
+    case 0:
+        close(fds[0]);
+        close(STDOUT_FILENO);
+        if (dup2(fds[1], STDOUT_FILENO) < 0)
+            _exit(CHILDERR_DUP);
+        close(fds[1]);
+
+        /* Point standard input at /dev/null. */
+        close(STDIN_FILENO);
+        infd = open("/dev/null", O_RDONLY);
+        if (infd < 0)
+            _exit(CHILDERR_STDIN);
+        if (infd != STDIN_FILENO) {
+            if (dup2(infd, STDIN_FILENO) < 0)
+                _exit(CHILDERR_DUP);
+            close(infd);
+        }
+
+        /* Point standard error at /dev/null. */
+        close(STDERR_FILENO);
         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);
+        if (errfd != STDERR_FILENO) {
+            if (dup2(errfd, STDERR_FILENO) < 0)
+                _exit(CHILDERR_DUP);
+            close(errfd);
+        }
 
         /* Now, exec our process. */
         if (execl(path, path, (char *) 0) == -1)
             _exit(CHILDERR_EXEC);
-    } else {
-        /* In parent.  Close the extra file descriptor. */
+
+    /* In parent.  Close the extra file descriptor. */
+    default:
         close(fds[1]);
+        break;
     }
     *fd = fds[0];
     return child;
@@ -386,6 +558,40 @@
 
 
 /*
+ * Allocate or resize the array of test results to be large enough to contain
+ * the test number in.
+ */
+static void
+resize_results(struct testset *ts, unsigned long n)
+{
+    unsigned long i;
+    size_t s;
+
+    /* If there's already enough space, return quickly. */
+    if (n <= ts->allocated)
+        return;
+
+    /*
+     * If no space has been allocated, do the initial allocation.  Otherwise,
+     * resize.  Start with 32 test cases and then add 1024 with each resize to
+     * try to reduce the number of reallocations.
+     */
+    if (ts->allocated == 0) {
+        s = (n > 32) ? n : 32;
+        ts->results = xcalloc(s, sizeof(enum test_status));
+    } else {
+        s = (n > ts->allocated + 1024) ? n : ts->allocated + 1024;
+        ts->results = xreallocarray(ts->results, s, sizeof(enum test_status));
+    }
+
+    /* Set the results for the newly-allocated test array. */
+    for (i = ts->allocated; i < s; i++)
+        ts->results[i] = TEST_INVALID;
+    ts->allocated = s;
+}
+
+
+/*
  * 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
@@ -394,7 +600,6 @@
 static int
 test_plan(const char *line, struct testset *ts)
 {
-    unsigned long i;
     long n;
 
     /*
@@ -407,12 +612,14 @@
         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
+     * Get the count and check it for validity.
+     *
+     * 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.
+     * 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) {
@@ -441,29 +648,30 @@
         ts->reported = 1;
         return 0;
     }
-    if (ts->plan == PLAN_INIT && ts->allocated == 0) {
-        ts->count = n;
-        ts->allocated = n;
+
+    /*
+     * If we are doing lazy planning, check the plan against the largest test
+     * number that we saw and fail now if we saw a check outside the plan
+     * range.
+     */
+    if (ts->plan == PLAN_PENDING && (unsigned long) n < ts->count) {
+        test_backspace(ts);
+        printf("ABORTED (invalid test number %lu)\n", ts->count);
+        ts->aborted = 1;
+        ts->reported = 1;
+        return 0;
+    }
+
+    /*
+     * Otherwise, allocated or resize the results if needed and update count,
+     * and then record that we've seen a plan.
+     */
+    resize_results(ts, n);
+    ts->count = n;
+    if (ts->plan == PLAN_INIT)
         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;
-        }
+    else if (ts->plan == PLAN_PENDING)
         ts->plan = PLAN_FINAL;
-    }
     return 1;
 }
 
@@ -481,7 +689,7 @@
     const char *bail;
     char *end;
     long number;
-    unsigned long i, current;
+    unsigned long current;
     int outlen;
 
     /* Before anything, check for a test abort. */
@@ -522,6 +730,7 @@
             if (!test_plan(line, ts))
                 return;
         } else {
+            test_backspace(ts);
             puts("ABORTED (multiple plans)");
             ts->aborted = 1;
             ts->reported = 1;
@@ -553,19 +762,9 @@
     /* 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;
+        resize_results(ts, current);
         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;
-        }
     }
 
     /*
@@ -601,9 +800,12 @@
     }
     ts->current = current;
     ts->results[current - 1] = status;
-    test_backspace(ts);
     if (isatty(STDOUT_FILENO)) {
-        outlen = printf("%lu/%lu", current, ts->count);
+        test_backspace(ts);
+        if (ts->plan == PLAN_PENDING)
+            outlen = printf("%lu/?", current);
+        else
+            outlen = printf("%lu/%lu", current, ts->count);
         ts->length = (outlen >= 0) ? outlen : 0;
         fflush(stdout);
     }
@@ -760,6 +962,7 @@
             if (!ts->reported)
                 puts("ABORTED (execution failed -- not found?)");
             break;
+        case CHILDERR_STDIN:
         case CHILDERR_STDERR:
             if (!ts->reported)
                 puts("ABORTED (can't open /dev/null)");
@@ -889,107 +1092,203 @@
         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);
     }
 }
 
 
 /*
+ * Check whether a given file path is a valid test.  Currently, this checks
+ * whether it is executable and is a regular file.  Returns true or false.
+ */
+static int
+is_valid_test(const char *path)
+{
+    struct stat st;
+
+    if (access(path, X_OK) < 0)
+        return 0;
+    if (stat(path, &st) < 0)
+        return 0;
+    if (!S_ISREG(st.st_mode))
+        return 0;
+    return 1;
+}
+
+
+/*
  * 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.
+ * then a ".t" extension.  When we find an executable program, we return the
+ * path to that program.  If none of those paths are executable, just fill in
+ * the name of the test as is.
  *
  * 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)
+static char *
+find_test(const char *name, const char *source, const char *build)
 {
     char *path;
-    const char *bases[4];
-    unsigned int i;
+    const char *bases[3], *suffix, *base;
+    unsigned int i, j;
+    const char *suffixes[3] = { "-t", ".t", "" };
 
+    /* Possible base directories. */
     bases[0] = ".";
     bases[1] = build;
     bases[2] = source;
-    bases[3] = NULL;
 
-    for (i = 0; bases[i] != NULL; i++) {
-        path = xmalloc(strlen(bases[i]) + strlen(name) + 4);
-        sprintf(path, "%s/%s-t", bases[i], name);
-        if (access(path, X_OK) != 0)
-            path[strlen(path) - 2] = '.';
-        if (access(path, X_OK) == 0)
-            break;
-        free(path);
-        path = NULL;
+    /* Try each suffix with each base. */
+    for (i = 0; i < ARRAY_SIZE(suffixes); i++) {
+        suffix = suffixes[i];
+        for (j = 0; j < ARRAY_SIZE(bases); j++) {
+            base = bases[j];
+            if (base == NULL)
+                continue;
+            path = concat(base, "/", name, suffix, (const char *) 0);
+            if (is_valid_test(path))
+                return path;
+            free(path);
+            path = NULL;
+        }
     }
-    if (path == NULL) {
-        path = xmalloc(strlen(name) + 3);
-        sprintf(path, "%s-t", name);
+    if (path == NULL)
+        path = xstrdup(name);
+    return path;
+}
+
+
+/*
+ * Read a list of tests from a file, returning the list of tests as a struct
+ * testlist.  Reports an error to standard error and exits if the list of
+ * tests cannot be read.
+ */
+static struct testlist *
+read_test_list(const char *filename)
+{
+    FILE *file;
+    unsigned int line;
+    size_t length;
+    char buffer[BUFSIZ];
+    struct testlist *listhead, *current;
+
+    /* Create the initial container list that will hold our results. */
+    listhead = xcalloc(1, sizeof(struct testlist));
+    current = NULL;
+
+    /*
+     * Open our file of tests to run and read it line by line, creating a new
+     * struct testlist and struct testset for each line.
+     */
+    file = fopen(filename, "r");
+    if (file == NULL)
+        sysdie("can't open %s", filename);
+    line = 0;
+    while (fgets(buffer, sizeof(buffer), file)) {
+        line++;
+        length = strlen(buffer) - 1;
+        if (buffer[length] != '\n') {
+            fprintf(stderr, "%s:%u: line too long\n", filename, line);
+            exit(1);
+        }
+        buffer[length] = '\0';
+        if (current == NULL)
+            current = listhead;
+        else {
+            current->next = xcalloc(1, sizeof(struct testlist));
+            current = current->next;
+        }
+        current->ts = xcalloc(1, sizeof(struct testset));
+        current->ts->plan = PLAN_INIT;
+        current->ts->file = xstrdup(buffer);
     }
-    ts->path = path;
+    fclose(file);
+
+    /* Return the results. */
+    return listhead;
 }
 
 
 /*
- * 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.
+ * Build a list of tests from command line arguments.  Takes the argv and argc
+ * representing the command line arguments and returns a newly allocated test
+ * list.  The caller is responsible for freeing.
  */
+static struct testlist *
+build_test_list(char *argv[], int argc)
+{
+    int i;
+    struct testlist *listhead, *current;
+
+    /* Create the initial container list that will hold our results. */
+    listhead = xcalloc(1, sizeof(struct testlist));
+    current = NULL;
+
+    /* Walk the list of arguments and create test sets for them. */
+    for (i = 0; i < argc; i++) {
+        if (current == NULL)
+            current = listhead;
+        else {
+            current->next = xcalloc(1, sizeof(struct testlist));
+            current = current->next;
+        }
+        current->ts = xcalloc(1, sizeof(struct testset));
+        current->ts->plan = PLAN_INIT;
+        current->ts->file = xstrdup(argv[i]);
+    }
+
+    /* Return the results. */
+    return listhead;
+}
+
+
+/* Free a struct testset. */
+static void
+free_testset(struct testset *ts)
+{
+    free(ts->file);
+    free(ts->path);
+    free(ts->results);
+    free(ts->reason);
+    free(ts);
+}
+
+
+/*
+ * Run a batch of tests.  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.  Returns true iff all tests passed, and always
+ * frees the test list that's passed in.
+ */
 static int
-test_batch(const char *testlist, const char *source, const char *build)
+test_batch(struct testlist *tests, const char *source, const char *build)
 {
-    FILE *tests;
-    unsigned int length, i;
+    size_t length;
+    unsigned int i;
     unsigned int longest = 0;
-    char buffer[BUFSIZ];
-    unsigned int line;
-    struct testset ts, *tmp;
+    unsigned int count = 0;
+    struct testset *ts;
     struct timeval start, end;
     struct rusage stats;
     struct testlist *failhead = NULL;
     struct testlist *failtail = NULL;
-    struct testlist *next;
+    struct testlist *current, *next;
+    int succeeded;
     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);
-        }
+    /* Walk the list of tests to find the longest name. */
+    for (current = tests; current != NULL; current = current->next) {
+        length = strlen(current->ts->file);
         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
@@ -1002,55 +1301,42 @@
     /* 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++)
+    /* Now, plow through our tests again, running each one. */
+    for (current = tests; current != NULL; current = current->next) {
+        ts = current->ts;
+
+        /* Print out the name of the test file. */
+        fputs(ts->file, stdout);
+        for (i = strlen(ts->file); 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) {
+
+        /* Run the test. */
+        ts->path = find_test(ts->file, source, build);
+        succeeded = test_run(ts);
+        fflush(stdout);
+
+        /* Record cumulative statistics. */
+        aborted += ts->aborted;
+        total += ts->count + ts->all_skipped;
+        passed += ts->passed;
+        skipped += ts->skipped + ts->all_skipped;
+        failed += ts->failed;
+        count++;
+
+        /* If the test fails, we shuffle it over to the fail list. */
+        if (!succeeded) {
+            if (failhead == NULL) {
                 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;
             }
+            failtail->ts = ts;
+            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;
 
@@ -1058,7 +1344,7 @@
     gettimeofday(&end, NULL);
     getrusage(RUSAGE_CHILDREN, &stats);
 
-    /* Print out our final results. */
+    /* Summarize the failures and free the failure list. */
     if (failhead != NULL) {
         test_fail_summary(failhead);
         while (failhead != NULL) {
@@ -1067,6 +1353,16 @@
             failhead = next;
         }
     }
+
+    /* Free the memory used by the test lists. */
+    while (tests != NULL) {
+        next = tests->next;
+        free_testset(tests->ts);
+        free(tests);
+        tests = next;
+    }
+
+    /* Print out the final test summary. */
     putchar('\n');
     if (aborted != 0) {
         if (aborted == 1)
@@ -1087,7 +1383,7 @@
             printf(", %lu tests skipped", skipped);
     }
     puts(".");
-    printf("Files=%u,  Tests=%lu", line, total);
+    printf("Files=%u,  Tests=%lu", count, 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),
@@ -1103,12 +1399,11 @@
 static void
 test_single(const char *program, const char *source, const char *build)
 {
-    struct testset ts;
+    char *path;
 
-    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);
+    path = find_test(program, source, build);
+    if (execl(path, path, (char *) 0) == -1)
+        sysdie("cannot exec %s", path);
 }
 
 
@@ -1120,21 +1415,28 @@
 main(int argc, char *argv[])
 {
     int option;
+    int status = 0;
     int single = 0;
-    char *setting;
-    const char *list;
+    char *source_env = NULL;
+    char *build_env = NULL;
+    const char *shortlist;
+    const char *list = NULL;
     const char *source = SOURCE;
     const char *build = BUILD;
+    struct testlist *tests;
 
-    while ((option = getopt(argc, argv, "b:hos:")) != EOF) {
+    while ((option = getopt(argc, argv, "b:hl:os:")) != EOF) {
         switch (option) {
         case 'b':
             build = optarg;
             break;
         case 'h':
-            printf(usage_message, argv[0], argv[0]);
+            printf(usage_message, argv[0], argv[0], argv[0], usage_extra);
             exit(0);
             break;
+        case 'l':
+            list = optarg;
+            break;
         case 'o':
             single = 1;
             break;
@@ -1145,35 +1447,50 @@
             exit(1);
         }
     }
-    if (argc - optind != 1) {
-        fprintf(stderr, usage_message, argv[0], argv[0]);
+    argv += optind;
+    argc -= optind;
+    if ((list == NULL && argc < 1) || (list != NULL && argc > 0)) {
+        fprintf(stderr, usage_message, argv[0], argv[0], argv[0], usage_extra);
         exit(1);
     }
-    argv += optind;
 
+    /* Set SOURCE and BUILD environment variables. */
     if (source != NULL) {
-        setting = xmalloc(strlen("SOURCE=") + strlen(source) + 1);
-        sprintf(setting, "SOURCE=%s", source);
-        if (putenv(setting) != 0)
+        source_env = concat("SOURCE=", source, (const char *) 0);
+        if (putenv(source_env) != 0)
             sysdie("cannot set SOURCE in the environment");
     }
     if (build != NULL) {
-        setting = xmalloc(strlen("BUILD=") + strlen(build) + 1);
-        sprintf(setting, "BUILD=%s", build);
-        if (putenv(setting) != 0)
+        build_env = concat("BUILD=", build, (const char *) 0);
+        if (putenv(build_env) != 0)
             sysdie("cannot set BUILD in the environment");
     }
 
-    if (single) {
+    /* Run the tests as instructed. */
+    if (single)
         test_single(argv[0], source, build);
-        exit(0);
+    else if (list != NULL) {
+        shortlist = strrchr(list, '/');
+        if (shortlist == NULL)
+            shortlist = list;
+        else
+            shortlist++;
+        printf(banner, shortlist);
+        tests = read_test_list(list);
+        status = test_batch(tests, source, build) ? 0 : 1;
     } else {
-        list = strrchr(argv[0], '/');
-        if (list == NULL)
-            list = argv[0];
-        else
-            list++;
-        printf(banner, list);
-        exit(test_batch(argv[0], source, build) ? 0 : 1);
+        tests = build_test_list(argv, argc);
+        status = test_batch(tests, source, build) ? 0 : 1;
     }
+
+    /* For valgrind cleanliness, free all our memory. */
+    if (source_env != NULL) {
+        putenv((char *) "SOURCE=");
+        free(source_env);
+    }
+    if (build_env != NULL) {
+        putenv((char *) "BUILD=");
+        free(build_env);
+    }
+    exit(status);
 }

Copied: trunk/tests/tap/basic.c (from rev 9649, trunk/tests/libtest.c)
===================================================================
--- tests/tap/basic.c	                        (rev 0)
+++ tests/tap/basic.c	2014-09-03 17:18:22 UTC (rev 9669)
@@ -0,0 +1,1020 @@
+/* $Id$
+ *
+ * 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, 2013, 2014 Russ Allbery <eagle at eyrie.org>
+ * Copyright 2001, 2002, 2004, 2005, 2006, 2007, 2008, 2011, 2012, 2013, 2014
+ *     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 <limits.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 <tap/basic.h>
+
+/* Specific to the integration of C TAP Harness in INN. */
+#ifndef LIBTEST_NEW_FORMAT
+# include "inn/messages.h"
+# include "inn/libinn.h"
+
+void
+test_init(int count)
+{
+    plan(count);
+}
+
+void
+ok(int n UNUSED, int success)
+{
+    new_ok(success, NULL);
+}
+
+void
+skip(int n UNUSED, const char *reason)
+{
+    new_skip(reason);
+}
+
+void
+ok_block(int n UNUSED, int count, int success)
+{
+    new_ok_block(count, success, NULL);
+}
+
+void
+skip_block(int n UNUSED, int count, const char *reason)
+{
+    new_skip_block(count, reason);
+}
+
+void
+ok_int(int n UNUSED, int wanted, int seen)
+{
+    is_int(wanted, seen, NULL);
+}
+
+void
+ok_string(int n UNUSED, const char *wanted, const char *seen)
+{
+    is_string(wanted, seen, NULL);
+}
+
+/* A global buffer into which message_log_buffer stores error messages. */
+char *errors = NULL;
+
+/*
+ *  An error handler that appends all errors to the errors global.  Used by
+ *  error_capture.
+ */
+static void
+message_log_buffer(int len, const char *fmt, va_list args, int error UNUSED)
+{
+    char *message;
+
+    message = xmalloc(len + 1);
+    vsnprintf(message, len + 1, fmt, args);
+    if (errors == NULL) {
+        errors = concat(message, "\n", (char *) 0);
+    } else {
+        char *new_errors;
+
+        new_errors = concat(errors, message, "\n", (char *) 0);
+        free(errors);
+        errors = new_errors;
+    }
+    free(message);
+}
+
+/*
+ *  Turn on the capturing of errors.  Errors will be stored in the global
+ *  errors variable where they can be checked by the test suite.  Capturing is
+ *  turned off with errors_uncapture.
+ */
+void
+errors_capture(void)
+{
+    if (errors != NULL) {
+        free(errors);
+        errors = NULL;
+    }
+    message_handlers_warn(1, message_log_buffer);
+    message_handlers_notice(1, message_log_buffer);
+}
+
+/*
+ *  Turn off the capturing of errors again.
+ */
+void
+errors_uncapture(void)
+{
+    message_handlers_warn(1, message_log_stderr);
+    message_handlers_notice(1, message_log_stdout);
+}
+#endif
+
+/* 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.  This is exported to callers of the library.
+ */
+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.
+ */
+static unsigned long _planned = 0;
+static unsigned long _failed  = 0;
+
+/*
+ * 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.
+ */
+static pid_t _process = 0;
+
+/*
+ * If true, we're doing lazy planning and will print out the plan based on the
+ * last test number at the end of testing.
+ */
+static int _lazy = 0;
+
+/*
+ * If true, the test was aborted by calling bail().  Currently, this is only
+ * used to ensure that we pass a false value to any cleanup functions even if
+ * all tests to that point have passed.
+ */
+static int _aborted = 0;
+
+/*
+ * Registered cleanup functions.  These are stored as a linked list and run in
+ * registered order by finish when the test program exits.  Each function is
+ * passed a boolean value indicating whether all tests were successful.
+ */
+struct cleanup_func {
+    test_cleanup_func func;
+    struct cleanup_func *next;
+};
+static struct cleanup_func *cleanup_funcs = NULL;
+
+/*
+ * Registered diag files.  Any output found in these files will be printed out
+ * as if it were passed to diag() before any other output we do.  This allows
+ * background processes to log to a file and have that output interleved with
+ * the test output.
+ */
+struct diag_file {
+    char *name;
+    FILE *file;
+    char *buffer;
+    size_t bufsize;
+    struct diag_file *next;
+};
+static struct diag_file *diag_files = NULL;
+
+/*
+ * Print a specified prefix and then the test description.  Handles turning
+ * the argument list into a va_args structure suitable for passing to
+ * print_desc, which has to be done in a macro.  Assumes that format is the
+ * argument immediately before the variadic arguments.
+ */
+#define PRINT_DESC(prefix, format)              \
+    do {                                        \
+        if (format != NULL) {                   \
+            va_list args;                       \
+            if (prefix != NULL)                 \
+                printf("%s", prefix);           \
+            va_start(args, format);             \
+            vprintf(format, args);              \
+            va_end(args);                       \
+        }                                       \
+    } while (0)
+
+
+/*
+ * Form a new string by concatenating multiple strings.  The arguments must be
+ * terminated by (const char *) 0.
+ *
+ * This function only exists because we can't assume asprintf.  We can't
+ * simulate asprintf with snprintf because we're only assuming SUSv3, which
+ * does not require that snprintf with a NULL buffer return the required
+ * length.  When those constraints are relaxed, this should be ripped out and
+ * replaced with asprintf or a more trivial replacement with snprintf.
+ */
+#ifndef LIBINN_H
+static char *
+concat(const char *first, ...)
+{
+    va_list args;
+    char *result;
+    const char *string;
+    size_t offset;
+    size_t length = 0;
+
+    /*
+     * Find the total memory required.  Ensure we don't overflow length.  See
+     * the comment for breallocarray for why we're using UINT_MAX here.
+     */
+    va_start(args, first);
+    for (string = first; string != NULL; string = va_arg(args, const char *)) {
+        if (length >= UINT_MAX - strlen(string))
+            bail("strings too long in concat");
+        length += strlen(string);
+    }
+    va_end(args);
+    length++;
+
+    /* Create the string. */
+    result = bmalloc(length);
+    va_start(args, first);
+    offset = 0;
+    for (string = first; string != NULL; string = va_arg(args, const char *)) {
+        memcpy(result + offset, string, strlen(string));
+        offset += strlen(string);
+    }
+    va_end(args);
+    result[offset] = '\0';
+    return result;
+}
+#endif
+
+
+/*
+ * Check all registered diag_files for any output.  We only print out the
+ * output if we see a complete line; otherwise, we wait for the next newline.
+ */
+static void
+check_diag_files(void)
+{
+    struct diag_file *file;
+    fpos_t where;
+    size_t length;
+    int incomplete;
+
+    /*
+     * Walk through each file and read each line of output available.  The
+     * general scheme here used is as follows: try to read a line of output at
+     * a time.  If we get NULL, check for EOF; on EOF, advance to the next
+     * file.
+     *
+     * If we get some data, see if it ends in a newline.  If it doesn't end in
+     * a newline, we have one of two cases: our buffer isn't large enough, in
+     * which case we resize it and try again, or we have incomplete data in
+     * the file, in which case we rewind the file and will try again next
+     * time.
+     */
+    for (file = diag_files; file != NULL; file = file->next) {
+        clearerr(file->file);
+
+        /* Store the current position in case we have to rewind. */
+        if (fgetpos(file->file, &where) < 0)
+            sysbail("cannot get position in %s", file->name);
+
+        /* Continue until we get EOF or an incomplete line of data. */
+        incomplete = 0;
+        while (!feof(file->file) && !incomplete) {
+            if (fgets(file->buffer, file->bufsize, file->file) == NULL) {
+                if (ferror(file->file))
+                    sysbail("cannot read from %s", file->name);
+                continue;
+            }
+
+            /*
+             * See if the line ends in a newline.  If not, see which error
+             * case we have.  Use UINT_MAX as a substitute for SIZE_MAX (see
+             * the comment for breallocarray).
+             */
+            length = strlen(file->buffer);
+            if (file->buffer[length - 1] != '\n') {
+                if (length < file->bufsize - 1)
+                    incomplete = 1;
+                else {
+                    if (file->bufsize >= UINT_MAX - BUFSIZ)
+                        sysbail("line too long in %s", file->name);
+                    file->bufsize += BUFSIZ;
+                    file->buffer = brealloc(file->buffer, file->bufsize);
+                }
+
+                /*
+                 * On either incomplete lines or too small of a buffer, rewind
+                 * and read the file again (on the next pass, if incomplete).
+                 * It's simpler than trying to double-buffer the file.
+                 */
+                if (fsetpos(file->file, &where) < 0)
+                    sysbail("cannot set position in %s", file->name);
+                continue;
+            }
+
+            /* We saw a complete line.  Print it out. */
+            printf("# %s", file->buffer);
+        }
+    }
+}
+
+
+/*
+ * 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), and running any
+ * registered cleanup functions.
+ */
+static void
+finish(void)
+{
+    int success, primary;
+    struct cleanup_func *current;
+    unsigned long highest = testnum - 1;
+    struct diag_file *file, *tmp;
+
+    /* Check for pending diag_file output. */
+    check_diag_files();
+
+    /* Free the diag_files. */
+    file = diag_files;
+    while (file != NULL) {
+        tmp = file;
+        file = file->next;
+        fclose(tmp->file);
+        free(tmp->name);
+        free(tmp->buffer);
+        free(tmp);
+    }
+    diag_files = NULL;
+
+    /*
+     * Determine whether all tests were successful, which is needed before
+     * calling cleanup functions since we pass that fact to the functions.
+     */
+    if (_planned == 0 && _lazy)
+        _planned = highest;
+    success = (!_aborted && _planned == highest && _failed == 0);
+
+    /*
+     * If there are any registered cleanup functions, we run those first.  We
+     * always run them, even if we didn't run a test.  Don't do anything
+     * except free the diag_files and call cleanup functions if we aren't the
+     * primary process (the process in which plan or plan_lazy was called),
+     * and tell the cleanup functions that fact.
+     */
+    primary = (_process == 0 || getpid() == _process);
+    while (cleanup_funcs != NULL) {
+        cleanup_funcs->func(success, primary);
+        current = cleanup_funcs;
+        cleanup_funcs = cleanup_funcs->next;
+        free(current);
+    }
+    if (!primary)
+        return;
+
+    /* Don't do anything further if we never planned a test. */
+    if (_planned == 0)
+        return;
+
+    /* If we're aborting due to bail, don't print summaries. */
+    if (_aborted)
+        return;
+
+    /* Print out the lazy plan if needed. */
+    fflush(stderr);
+    if (_lazy && _planned > 0)
+        printf("1..%lu\n", _planned);
+
+    /* Print out a summary of the results. */
+    if (_planned > highest)
+        diag("Looks like you planned %lu test%s but only ran %lu", _planned,
+             (_planned > 1 ? "s" : ""), highest);
+    else if (_planned < highest)
+        diag("Looks like you planned %lu test%s but ran %lu extra", _planned,
+             (_planned > 1 ? "s" : ""), highest - _planned);
+    else if (_failed > 0)
+        diag("Looks like you failed %lu test%s of %lu", _failed,
+             (_failed > 1 ? "s" : ""), _planned);
+    else if (_planned != 1)
+        diag("All %lu tests successful or skipped", _planned);
+    else
+        diag("%lu test successful or skipped", _planned);
+}
+
+
+/*
+ * Initialize things.  Turns on line buffering on stdout and then prints out
+ * the number of tests in the test suite.  We intentionally don't check for
+ * pending diag_file output here, since it should really come after the plan.
+ */
+void
+plan(unsigned long count)
+{
+    if (setvbuf(stdout, NULL, _IOLBF, BUFSIZ) != 0)
+        sysdiag("cannot set stdout to line buffered");
+    fflush(stderr);
+    printf("1..%lu\n", count);
+    testnum = 1;
+    _planned = count;
+    _process = getpid();
+    if (atexit(finish) != 0) {
+        sysdiag("cannot register exit handler");
+        diag("cleanups will not be run");
+    }
+}
+
+
+/*
+ * 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)
+        sysdiag("cannot set stdout to line buffered");
+    testnum = 1;
+    _process = getpid();
+    _lazy = 1;
+    if (atexit(finish) != 0)
+        sysbail("cannot register exit handler to display plan");
+}
+
+
+/*
+ * Skip the entire test suite and exits.  Should be called instead of plan(),
+ * not after it, since it prints out a special plan line.  Ignore diag_file
+ * output here, since it's not clear if it's allowed before the plan.
+ */
+void
+skip_all(const char *format, ...)
+{
+    fflush(stderr);
+    printf("1..0 # skip");
+    PRINT_DESC(" ", format);
+    putchar('\n');
+    exit(0);
+}
+
+
+/*
+ * Takes a boolean success value and assumes the test passes if that value
+ * is true and fails if that value is false.
+ */
+int
+new_ok(int success, const char *format, ...)
+{
+    fflush(stderr);
+    check_diag_files();
+    printf("%sok %lu", success ? "" : "not ", testnum++);
+    if (!success)
+        _failed++;
+    PRINT_DESC(" - ", format);
+    putchar('\n');
+    return success;
+}
+
+
+/*
+ * Same as ok(), but takes the format arguments as a va_list.
+ */
+int
+okv(int success, const char *format, va_list args)
+{
+    fflush(stderr);
+    check_diag_files();
+    printf("%sok %lu", success ? "" : "not ", testnum++);
+    if (!success)
+        _failed++;
+    if (format != NULL) {
+        printf(" - ");
+        vprintf(format, args);
+    }
+    putchar('\n');
+    return success;
+}
+
+
+/*
+ * Skip a test.
+ */
+void
+new_skip(const char *reason, ...)
+{
+    fflush(stderr);
+    check_diag_files();
+    printf("ok %lu # skip", testnum++);
+    PRINT_DESC(" ", reason);
+    putchar('\n');
+}
+
+
+/*
+ * Report the same status on the next count tests.
+ */
+int
+new_ok_block(unsigned long count, int success, const char *format, ...)
+{
+    unsigned long i;
+
+    fflush(stderr);
+    check_diag_files();
+    for (i = 0; i < count; i++) {
+        printf("%sok %lu", success ? "" : "not ", testnum++);
+        if (!success)
+            _failed++;
+        PRINT_DESC(" - ", format);
+        putchar('\n');
+    }
+    return success;
+}
+
+
+/*
+ * Skip the next count tests.
+ */
+void
+new_skip_block(unsigned long count, const char *reason, ...)
+{
+    unsigned long i;
+
+    fflush(stderr);
+    check_diag_files();
+    for (i = 0; i < count; i++) {
+        printf("ok %lu # skip", testnum++);
+        PRINT_DESC(" ", reason);
+        putchar('\n');
+    }
+}
+
+
+/*
+ * Takes an expected integer and a seen integer and assumes the test passes
+ * if those two numbers match.
+ */
+int
+is_int(long wanted, long seen, const char *format, ...)
+{
+    int success;
+
+    fflush(stderr);
+    check_diag_files();
+    success = (wanted == seen);
+    if (success)
+        printf("ok %lu", testnum++);
+    else {
+        diag("wanted: %ld", wanted);
+        diag("  seen: %ld", seen);
+        printf("not ok %lu", testnum++);
+        _failed++;
+    }
+    PRINT_DESC(" - ", format);
+    putchar('\n');
+    return success;
+}
+
+
+/*
+ * Takes a string and what the string should be, and assumes the test passes
+ * if those strings match (using strcmp).
+ */
+int
+is_string(const char *wanted, const char *seen, const char *format, ...)
+{
+    int success;
+
+    if (wanted == NULL)
+        wanted = "(null)";
+    if (seen == NULL)
+        seen = "(null)";
+    fflush(stderr);
+    check_diag_files();
+    success = (strcmp(wanted, seen) == 0);
+    if (success)
+        printf("ok %lu", testnum++);
+    else {
+        diag("wanted: %s", wanted);
+        diag("  seen: %s", seen);
+        printf("not ok %lu", testnum++);
+        _failed++;
+    }
+    PRINT_DESC(" - ", format);
+    putchar('\n');
+    return success;
+}
+
+
+/*
+ * 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.
+ */
+int
+is_hex(unsigned long wanted, unsigned long seen, const char *format, ...)
+{
+    int success;
+
+    fflush(stderr);
+    check_diag_files();
+    success = (wanted == seen);
+    if (success)
+        printf("ok %lu", testnum++);
+    else {
+        diag("wanted: %lx", (unsigned long) wanted);
+        diag("  seen: %lx", (unsigned long) seen);
+        printf("not ok %lu", testnum++);
+        _failed++;
+    }
+    PRINT_DESC(" - ", format);
+    putchar('\n');
+    return success;
+}
+
+
+/*
+ * Bail out with an error.
+ */
+void
+bail(const char *format, ...)
+{
+    va_list args;
+
+    _aborted = 1;
+    fflush(stderr);
+    check_diag_files();
+    fflush(stdout);
+    printf("Bail out! ");
+    va_start(args, format);
+    vprintf(format, args);
+    va_end(args);
+    printf("\n");
+    exit(255);
+}
+
+
+/*
+ * Bail out with an error, appending strerror(errno).
+ */
+void
+sysbail(const char *format, ...)
+{
+    va_list args;
+    int oerrno = errno;
+
+    _aborted = 1;
+    fflush(stderr);
+    check_diag_files();
+    fflush(stdout);
+    printf("Bail out! ");
+    va_start(args, format);
+    vprintf(format, args);
+    va_end(args);
+    printf(": %s\n", strerror(oerrno));
+    exit(255);
+}
+
+
+/*
+ * Report a diagnostic to stderr.  Always returns 1 to allow embedding in
+ * compound statements.
+ */
+int
+diag(const char *format, ...)
+{
+    va_list args;
+
+    fflush(stderr);
+    check_diag_files();
+    fflush(stdout);
+    printf("# ");
+    va_start(args, format);
+    vprintf(format, args);
+    va_end(args);
+    printf("\n");
+    return 1;
+}
+
+
+/*
+ * Report a diagnostic to stderr, appending strerror(errno).  Always returns 1
+ * to allow embedding in compound statements.
+ */
+int
+sysdiag(const char *format, ...)
+{
+    va_list args;
+    int oerrno = errno;
+
+    fflush(stderr);
+    check_diag_files();
+    fflush(stdout);
+    printf("# ");
+    va_start(args, format);
+    vprintf(format, args);
+    va_end(args);
+    printf(": %s\n", strerror(oerrno));
+    return 1;
+}
+
+
+/*
+ * Register a new file for diag_file processing.
+ */
+void
+diag_file_add(const char *name)
+{
+    struct diag_file *file, *prev;
+
+    file = bcalloc(1, sizeof(struct diag_file));
+    file->name = bstrdup(name);
+    file->file = fopen(file->name, "r");
+    if (file->file == NULL)
+        sysbail("cannot open %s", name);
+    file->buffer = bmalloc(BUFSIZ);
+    file->bufsize = BUFSIZ;
+    if (diag_files == NULL)
+        diag_files = file;
+    else {
+        for (prev = diag_files; prev->next != NULL; prev = prev->next)
+            ;
+        prev->next = file;
+    }
+}
+
+
+/*
+ * Remove a file from diag_file processing.  If the file is not found, do
+ * nothing, since there are some situations where it can be removed twice
+ * (such as if it's removed from a cleanup function, since cleanup functions
+ * are called after freeing all the diag_files).
+ */
+void
+diag_file_remove(const char *name)
+{
+    struct diag_file *file;
+    struct diag_file **prev = &diag_files;
+
+    for (file = diag_files; file != NULL; file = file->next) {
+        if (strcmp(file->name, name) == 0) {
+            *prev = file->next;
+            fclose(file->file);
+            free(file->name);
+            free(file->buffer);
+            free(file);
+            return;
+        }
+        prev = &file->next;
+    }
+}
+
+
+/*
+ * 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;
+}
+
+
+/*
+ * The same as brealloc, but determine the size by multiplying an element
+ * count by a size, similar to calloc.  The multiplication is checked for
+ * integer overflow.
+ *
+ * We should technically use SIZE_MAX here for the overflow check, but
+ * SIZE_MAX is C99 and we're only assuming C89 + SUSv3, which does not
+ * guarantee that it exists.  They do guarantee that UINT_MAX exists, and we
+ * can assume that UINT_MAX <= SIZE_MAX.
+ *
+ * (In theory, C89 and C99 permit size_t to be smaller than unsigned int, but
+ * I disbelieve in the existence of such systems and they will have to cope
+ * without overflow checks.)
+ */
+void *
+breallocarray(void *p, size_t n, size_t size)
+{
+    if (n > 0 && UINT_MAX / n <= size)
+        bail("reallocarray too large");
+    p = realloc(p, n * size);
+    if (p == NULL)
+        sysbail("failed to realloc %lu bytes", (unsigned long) (n * 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().
+ */
+char *
+test_file_path(const char *file)
+{
+    char *base;
+    char *path = NULL;
+    const char *envs[] = { "BUILD", "SOURCE", NULL };
+    int i;
+
+    for (i = 0; envs[i] != NULL; i++) {
+        base = getenv(envs[i]);
+        if (base == NULL)
+            continue;
+        path = concat(base, "/", file, (const char *) 0);
+        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)
+{
+    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;
+
+    build = getenv("BUILD");
+    if (build == NULL)
+        build = ".";
+    path = concat(build, "/tmp", (const char *) 0);
+    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)
+{
+    if (path != NULL)
+        rmdir(path);
+    free(path);
+}
+
+
+/*
+ * Register a cleanup function that is called when testing ends.  All such
+ * registered functions will be run by finish.
+ */
+void
+test_cleanup_register(test_cleanup_func func)
+{
+    struct cleanup_func *cleanup, **last;
+
+    cleanup = bmalloc(sizeof(struct cleanup_func));
+    cleanup->func = func;
+    cleanup->next = NULL;
+    last = &cleanup_funcs;
+    while (*last != NULL)
+        last = &(*last)->next;
+    *last = cleanup;
+}

Copied: trunk/tests/tap/basic.h (from rev 9649, trunk/tests/libtest.h)
===================================================================
--- tests/tap/basic.h	                        (rev 0)
+++ tests/tap/basic.h	2014-09-03 17:18:22 UTC (rev 9669)
@@ -0,0 +1,205 @@
+/* $Id$
+ *
+ * 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, 2013, 2014 Russ Allbery <eagle at eyrie.org>
+ * Copyright 2001, 2002, 2004, 2005, 2006, 2007, 2008, 2011, 2012, 2014
+ *     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 <tap/macros.h>
+#include <stdarg.h>             /* va_list */
+#include <stddef.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.  ok() and okv() return the
+ * value of the success argument.
+ */
+#ifndef LIBTEST_NEW_FORMAT
+/* Specific to the integration of C TAP Harness in INN. */
+void ok(int n, int success);
+int new_ok(int success, const char *format, ...)
+        __attribute__((__format__(printf, 2, 3)));
+void ok_int(int n, int wanted, int seen);
+void ok_string(int n, const char *wanted, const char *seen);
+int okv(int success, const char *format, va_list args);
+void skip(int n, const char *reason);
+void new_skip(const char *reason, ...)
+        __attribute__((__format__(printf, 1, 2)));
+void ok_block(int n, int count, int success);
+int new_ok_block(unsigned long count, int success, const char *format, ...)
+        __attribute__((__format__(printf, 3, 4)));
+void skip_block(int n, int count, const char *reason);
+void new_skip_block(unsigned long count, const char *reason, ...)
+        __attribute__((__format__(printf, 2, 3)));
+
+void test_init(int count);
+
+/* A global buffer into which errors_capture stores errors. */
+extern char *errors;
+
+/* Turn on capturing of errors with errors_capture.  Errors reported by warn
+ * will be stored in the global errors variable.  Turn this off again with
+ * errors_uncapture.  Caller is responsible for freeing errors when done.
+ */
+void errors_capture(void);
+void errors_uncapture(void);
+#else
+# define ok new_ok
+# define skip new_skip
+# define ok_block new_ok_block
+# define skip_block new_skip_block
+int ok(int success, const char *format, ...)
+    __attribute__((__format__(printf, 2, 3)));
+int 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.  ok_block()
+ * returns the value of the success argument.
+ */
+int 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)));
+#endif
+
+/*
+ * Check an expected value against a seen value.  Returns true if the test
+ * passes and false if it fails.
+ */
+int is_int(long wanted, long seen, const char *format, ...)
+    __attribute__((__format__(printf, 3, 4)));
+int is_string(const char *wanted, const char *seen, const char *format, ...)
+    __attribute__((__format__(printf, 3, 4)));
+int 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 #. */
+int diag(const char *format, ...)
+    __attribute__((__nonnull__, __format__(printf, 1, 2)));
+int sysdiag(const char *format, ...)
+    __attribute__((__nonnull__, __format__(printf, 1, 2)));
+
+/*
+ * Register or unregister a file that contains supplementary diagnostics.
+ * Before any other output, all registered files will be read, line by line,
+ * and each line will be reported as a diagnostic as if it were passed to
+ * diag().  Nul characters are not supported in these files and will result in
+ * truncated output.
+ */
+void diag_file_add(const char *file)
+    __attribute__((__nonnull__));
+void diag_file_remove(const char *file)
+    __attribute__((__nonnull__));
+
+/* Allocate memory, reporting a fatal error with bail on failure. */
+void *bcalloc(size_t, size_t)
+    __attribute__((__alloc_size__(1, 2), __malloc__, __warn_unused_result__));
+void *bmalloc(size_t)
+    __attribute__((__alloc_size__(1), __malloc__, __warn_unused_result__));
+void *breallocarray(void *, size_t, size_t)
+    __attribute__((__alloc_size__(2, 3), __malloc__, __warn_unused_result__));
+void *brealloc(void *, size_t)
+    __attribute__((__alloc_size__(2), __malloc__, __warn_unused_result__));
+char *bstrdup(const char *)
+    __attribute__((__malloc__, __nonnull__, __warn_unused_result__));
+char *bstrndup(const char *, size_t)
+    __attribute__((__malloc__, __nonnull__, __warn_unused_result__));
+
+/*
+ * 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__, __warn_unused_result__));
+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__, __warn_unused_result__));
+void test_tmpdir_free(char *path);
+
+/*
+ * Register a cleanup function that is called when testing ends.  All such
+ * registered functions will be run during atexit handling (and are therefore
+ * subject to all the same constraints and caveats as atexit functions).
+ *
+ * The function must return void and will be passed two argument, an int that
+ * will be true if the test completed successfully and false otherwise, and an
+ * int that will be true if the cleanup function is run in the primary process
+ * (the one that called plan or plan_lazy) and false otherwise.
+ */
+typedef void (*test_cleanup_func)(int, int);
+void test_cleanup_register(test_cleanup_func)
+    __attribute__((__nonnull__));
+
+END_DECLS
+
+#endif /* TAP_BASIC_H */

Added: tests/tap/float.c
===================================================================
--- tests/tap/float.c	                        (rev 0)
+++ tests/tap/float.c	2014-09-03 17:18:22 UTC (rev 9669)
@@ -0,0 +1,82 @@
+/* $Id$
+ *
+ * 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, 2013, 2014 Russ Allbery <eagle at eyrie.org>
+ *
+ * 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 <tap/basic.h>
+#include <tap/float.h>
+
+#ifndef LIBTEST_NEW_FORMAT
+/* Specific to the integration of C TAP Harness in INN. */
+void
+ok_double(int n UNUSED, double wanted, double seen)
+{
+    is_double(wanted, seen, 0.01, NULL);
+}
+#endif
+
+/*
+ * Takes an expected double and a seen double and assumes the test passes if
+ * those two numbers are within delta of each other.
+ */
+int
+is_double(double wanted, double seen, double epsilon, const char *format, ...)
+{
+    va_list args;
+    int success;
+
+    va_start(args, format);
+    fflush(stderr);
+    if ((isnan(wanted) && isnan(seen))
+        || (isinf(wanted) && isinf(seen) && wanted == seen)
+        || fabs(wanted - seen) <= epsilon) {
+        success = 1;
+        okv(1, format, args);
+    } else {
+        success = 0;
+        diag("wanted: %g", wanted);
+        diag("  seen: %g", seen);
+        okv(0, format, args);
+    }
+    return success;
+}


Property changes on: trunk/tests/tap/float.c
___________________________________________________________________
Added: svn:eol-style
   + native
Added: svn:keywords
   + Author Date Id Revision

Added: tests/tap/float.h
===================================================================
--- tests/tap/float.h	                        (rev 0)
+++ tests/tap/float.h	2014-09-03 17:18:22 UTC (rev 9669)
@@ -0,0 +1,47 @@
+/* $Id$
+ *
+ * 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, 2014 Russ Allbery <eagle at eyrie.org>
+ *
+ * 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 <tap/macros.h>
+
+BEGIN_DECLS
+
+/* Check an expected value against a seen value within epsilon. */
+#ifndef LIBTEST_NEW_FORMAT
+/* Specific to the integration of C TAP Harness in INN. */
+void ok_double(int n, double wanted, double seen);
+#endif
+int is_double(double wanted, double seen, double epsilon,
+               const char *format, ...)
+    __attribute__((__format__(printf, 4, 5)));
+
+END_DECLS
+
+#endif /* TAP_FLOAT_H */


Property changes on: trunk/tests/tap/float.h
___________________________________________________________________
Added: svn:keywords
   + Author Date Id Revision
Added: svn:eol-style
   + native

Copied: trunk/tests/tap/libtap.sh (from rev 9649, trunk/tests/libtest.sh)
===================================================================
--- tests/tap/libtap.sh	                        (rev 0)
+++ tests/tap/libtap.sh	2014-09-03 17:18:22 UTC (rev 9669)
@@ -0,0 +1,248 @@
+# $Id$
+#
+# 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 <eagle at eyrie.org>
+# Copyright 2009, 2010, 2011, 2012 Russ Allbery <eagle at eyrie.org>
+# Copyright 2006, 2007, 2008, 2013
+#     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 255
+}
+
+# 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"
+}

Added: tests/tap/macros.h
===================================================================
--- tests/tap/macros.h	                        (rev 0)
+++ tests/tap/macros.h	2014-09-03 17:18:22 UTC (rev 9669)
@@ -0,0 +1,96 @@
+/* $Id$
+ *
+ * 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, 2013 Russ Allbery <eagle at eyrie.org>
+ *
+ * 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
+
+/* Suppress __warn_unused_result__ if gcc is too old. */
+#if !defined(__attribute__) && !defined(__warn_unused_result__)
+# if __GNUC__ < 3 || (__GNUC__ == 3 && __GNUC_MINOR__ < 4)
+#  define __warn_unused_result__ /* 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 */


Property changes on: trunk/tests/tap/macros.h
___________________________________________________________________
Added: svn:eol-style
   + native
Added: svn:keywords
   + Author Date Id Revision

Modified: tests/util/innbind-t.c
===================================================================
--- tests/util/innbind-t.c	2014-08-30 12:13:46 UTC (rev 9668)
+++ tests/util/innbind-t.c	2014-09-03 17:18:22 UTC (rev 9669)
@@ -11,7 +11,7 @@
 #endif
 
 #include "inn/messages.h"
-#include "libtest.h"
+#include "tap/basic.h"
 
 /* If SO_REUSEADDR isn't available, make calls to set_reuseaddr go away. */
 #ifndef SO_REUSEADDR



More information about the inn-committers mailing list