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