summaryrefslogtreecommitdiff
path: root/tests/tap
diff options
context:
space:
mode:
Diffstat (limited to 'tests/tap')
-rw-r--r--tests/tap/basic.c196
-rw-r--r--tests/tap/basic.h41
-rw-r--r--tests/tap/kerberos.c31
-rw-r--r--tests/tap/kerberos.sh17
-rw-r--r--tests/tap/libtap.sh32
-rw-r--r--tests/tap/remctl.sh18
6 files changed, 239 insertions, 96 deletions
diff --git a/tests/tap/basic.c b/tests/tap/basic.c
index 5ca9ff4..829f91a 100644
--- a/tests/tap/basic.c
+++ b/tests/tap/basic.c
@@ -2,12 +2,13 @@
* Some utility routines for writing tests.
*
* Herein are a variety of utility routines for writing tests. All routines
- * of the form ok*() take a test number and some number of appropriate
+ * 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.
+ * utility routines help in constructing more complex tests, skipping tests,
+ * or setting up the TAP output format.
*
- * Copyright 2009 Russ Allbery <rra@stanford.edu>
+ * Copyright 2009, 2010 Russ Allbery <rra@stanford.edu>
* Copyright 2006, 2007, 2008
* Board of Trustees, Leland Stanford Jr. University
* Copyright (c) 2004, 2005, 2006
@@ -34,7 +35,7 @@
* The test count. Always contains the number that will be used for the next
* test status.
*/
-int testnum = 1;
+unsigned long testnum = 1;
/*
* Status information stored so that we can give a test summary at the end of
@@ -44,10 +45,14 @@ int testnum = 1;
* 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 int _planned = 0;
-static int _failed = 0;
+static unsigned long _planned = 0;
+static unsigned long _failed = 0;
static pid_t _process = 0;
+static int _lazy = 0;
/*
@@ -57,22 +62,28 @@ static pid_t _process = 0;
static void
finish(void)
{
- int highest = testnum - 1;
-
- if (_process != 0 && getpid() == _process && _planned > 0) {
+ unsigned long highest = testnum - 1;
+
+ if (_planned == 0 && !_lazy)
+ return;
+ if (_process != 0 && getpid() == _process) {
+ if (_lazy) {
+ printf("1..%lu\n", highest);
+ _planned = highest;
+ }
if (_planned > highest)
- printf("# Looks like you planned %d test%s but only ran %d\n",
+ 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 %d test%s but ran %d extra\n",
+ 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 %d test%s of %d\n", _failed,
+ printf("# Looks like you failed %lu test%s of %lu\n", _failed,
(_failed > 1 ? "s" : ""), _planned);
else if (_planned > 1)
- printf("# All %d tests successful or skipped\n", _planned);
+ printf("# All %lu tests successful or skipped\n", _planned);
else
- printf("# %d test successful or skipped\n", _planned);
+ printf("# %lu test successful or skipped\n", _planned);
}
}
@@ -82,12 +93,12 @@ finish(void)
* the number of tests in the test suite.
*/
void
-plan(int count)
+plan(unsigned long count)
{
if (setvbuf(stdout, NULL, _IOLBF, BUFSIZ) != 0)
fprintf(stderr, "# cannot set stdout to line buffered: %s\n",
strerror(errno));
- printf("1..%d\n", count);
+ printf("1..%lu\n", count);
testnum = 1;
_planned = count;
_process = getpid();
@@ -96,6 +107,23 @@ plan(int count)
/*
+ * 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.
*/
@@ -134,7 +162,7 @@ print_desc(const char *format, va_list args)
void
ok(int success, const char *format, ...)
{
- printf("%sok %d", success ? "" : "not ", testnum++);
+ printf("%sok %lu", success ? "" : "not ", testnum++);
if (!success)
_failed++;
if (format != NULL) {
@@ -149,12 +177,27 @@ ok(int success, const char *format, ...)
/*
+ * Same as ok(), but takes the format arguments as a va_list.
+ */
+void
+okv(int success, const char *format, va_list args)
+{
+ 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, ...)
{
- printf("ok %d # skip", testnum++);
+ printf("ok %lu # skip", testnum++);
if (reason != NULL) {
va_list args;
@@ -171,12 +214,12 @@ skip(const char *reason, ...)
* Report the same status on the next count tests.
*/
void
-ok_block(int count, int status, const char *format, ...)
+ok_block(unsigned long count, int status, const char *format, ...)
{
- int i;
+ unsigned long i;
for (i = 0; i < count; i++) {
- printf("%sok %d", status ? "" : "not ", testnum++);
+ printf("%sok %lu", status ? "" : "not ", testnum++);
if (!status)
_failed++;
if (format != NULL) {
@@ -195,12 +238,12 @@ ok_block(int count, int status, const char *format, ...)
* Skip the next count tests.
*/
void
-skip_block(int count, const char *reason, ...)
+skip_block(unsigned long count, const char *reason, ...)
{
- int i;
+ unsigned long i;
for (i = 0; i < count; i++) {
- printf("ok %d # skip", testnum++);
+ printf("ok %lu # skip", testnum++);
if (reason != NULL) {
va_list args;
@@ -219,13 +262,13 @@ skip_block(int count, const char *reason, ...)
* if those two numbers match.
*/
void
-is_int(int wanted, int seen, const char *format, ...)
+is_int(long wanted, long seen, const char *format, ...)
{
if (wanted == seen)
- printf("ok %d", testnum++);
+ printf("ok %lu", testnum++);
else {
- printf("# wanted: %d\n# seen: %d\n", wanted, seen);
- printf("not ok %d", testnum++);
+ printf("# wanted: %ld\n# seen: %ld\n", wanted, seen);
+ printf("not ok %lu", testnum++);
_failed++;
}
if (format != NULL) {
@@ -251,10 +294,10 @@ is_string(const char *wanted, const char *seen, const char *format, ...)
if (seen == NULL)
seen = "(null)";
if (strcmp(wanted, seen) == 0)
- printf("ok %d", testnum++);
+ printf("ok %lu", testnum++);
else {
printf("# wanted: %s\n# seen: %s\n", wanted, seen);
- printf("not ok %d", testnum++);
+ printf("not ok %lu", testnum++);
_failed++;
}
if (format != NULL) {
@@ -276,10 +319,10 @@ void
is_double(double wanted, double seen, const char *format, ...)
{
if (wanted == seen)
- printf("ok %d", testnum++);
+ printf("ok %lu", testnum++);
else {
printf("# wanted: %g\n# seen: %g\n", wanted, seen);
- printf("not ok %d", testnum++);
+ printf("not ok %lu", testnum++);
_failed++;
}
if (format != NULL) {
@@ -301,11 +344,11 @@ void
is_hex(unsigned long wanted, unsigned long seen, const char *format, ...)
{
if (wanted == seen)
- printf("ok %d", testnum++);
+ printf("ok %lu", testnum++);
else {
printf("# wanted: %lx\n# seen: %lx\n", (unsigned long) wanted,
(unsigned long) seen);
- printf("not ok %d", testnum++);
+ printf("not ok %lu", testnum++);
_failed++;
}
if (format != NULL) {
@@ -354,3 +397,88 @@ sysbail(const char *format, ...)
printf(": %s\n", strerror(oerrno));
exit(1);
}
+
+
+/*
+ * Report a diagnostic to stderr.
+ */
+void
+diag(const char *format, ...)
+{
+ va_list args;
+
+ 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(stdout);
+ printf("# ");
+ va_start(args, format);
+ vprintf(format, args);
+ va_end(args);
+ printf(": %s\n", strerror(oerrno));
+}
+
+
+/*
+ * Locate a test file. Given the partial path to a file, look under BUILD and
+ * then SOURCE for the file and return the full path to the file. Returns
+ * NULL if the file doesn't exist. A non-NULL return should be freed with
+ * test_file_path_free().
+ *
+ * This function uses sprintf because it attempts to be independent of all
+ * other portability layers. The use immediately after a memory allocation
+ * should be safe without using snprintf or strlcpy/strlcat.
+ */
+char *
+test_file_path(const char *file)
+{
+ char *base;
+ char *path = NULL;
+ size_t length;
+ const char *envs[] = { "BUILD", "SOURCE", NULL };
+ int i;
+
+ for (i = 0; envs[i] != NULL; i++) {
+ base = getenv(envs[i]);
+ if (base == NULL)
+ continue;
+ length = strlen(base) + 1 + strlen(file) + 1;
+ path = malloc(length);
+ if (path == NULL)
+ sysbail("cannot allocate memory");
+ sprintf(path, "%s/%s", base, file);
+ if (access(path, R_OK) == 0)
+ break;
+ free(path);
+ path = NULL;
+ }
+ return path;
+}
+
+
+/*
+ * Free a path returned from test_file_path(). This function exists primarily
+ * for Windows, where memory must be freed from the same library domain that
+ * it was allocated from.
+ */
+void
+test_file_path_free(char *path)
+{
+ if (path != NULL)
+ free(path);
+}
diff --git a/tests/tap/basic.h b/tests/tap/basic.h
index efe94ba..9602db4 100644
--- a/tests/tap/basic.h
+++ b/tests/tap/basic.h
@@ -1,6 +1,7 @@
/*
* Basic utility routines for the TAP protocol.
*
+ * Copyright 2009, 2010 Russ Allbery <rra@stanford.edu>
* Copyright 2006, 2007, 2008
* Board of Trustees, Leland Stanford Jr. University
* Copyright (c) 2004, 2005, 2006
@@ -14,6 +15,7 @@
#ifndef TAP_BASIC_H
#define TAP_BASIC_H 1
+#include <stdarg.h> /* va_list */
#include <sys/types.h> /* pid_t */
/*
@@ -56,29 +58,40 @@ BEGIN_DECLS
* The test count. Always contains the number that will be used for the next
* test status.
*/
-extern int testnum;
+extern unsigned long testnum;
/* Print out the number of tests and set standard output to line buffered. */
-void plan(int count);
+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. */
+/*
+ * 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(int count, int success, const char *format, ...)
+void ok_block(unsigned long count, int success, const char *format, ...)
__attribute__((__format__(printf, 3, 4)));
-void skip_block(int count, const char *reason, ...)
+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(int wanted, int seen, const char *format, ...)
+void is_int(long wanted, long seen, const char *format, ...)
__attribute__((__format__(printf, 3, 4)));
void is_double(double wanted, double seen, const char *format, ...)
__attribute__((__format__(printf, 3, 4)));
@@ -93,6 +106,20 @@ void bail(const char *format, ...)
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 /* LIBTEST_H */
+#endif /* TAP_BASIC_H */
diff --git a/tests/tap/kerberos.c b/tests/tap/kerberos.c
index 700212e..a17d980 100644
--- a/tests/tap/kerberos.c
+++ b/tests/tap/kerberos.c
@@ -23,33 +23,6 @@
/*
- * Given the partial path to a file, look under BUILD and then SOURCE for the
- * file and return the full path to the file in newly-allocated memory.
- * Returns NULL if the file doesn't exist.
- */
-static char *
-find_file(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 = concatpath(base, file);
- if (access(path, R_OK) == 0)
- break;
- free(path);
- path = NULL;
- }
- return path;
-}
-
-
-/*
* Obtain Kerberos tickets for the principal specified in test.principal using
* the keytab specified in test.keytab, both of which are presumed to be in
* tests/data in either the build or the source tree.
@@ -78,7 +51,7 @@ kerberos_setup(void)
krb5_creds creds;
/* Read the principal name and find the keytab file. */
- path = find_file("data/test.principal");
+ path = test_file_path("data/test.principal");
if (path == NULL)
return NULL;
file = fopen(path, "r");
@@ -95,7 +68,7 @@ kerberos_setup(void)
bail("no newline in %s", path);
free(path);
principal[strlen(principal) - 1] = '\0';
- path = find_file("data/test.keytab");
+ path = test_file_path("data/test.keytab");
if (path == NULL)
return NULL;
diff --git a/tests/tap/kerberos.sh b/tests/tap/kerberos.sh
index fbeaaba..904cae5 100644
--- a/tests/tap/kerberos.sh
+++ b/tests/tap/kerberos.sh
@@ -1,4 +1,4 @@
-# Shell function library for Kerberos test support.
+# Shell function library to initialize Kerberos credentials
#
# Written by Russ Allbery <rra@stanford.edu>
# Copyright 2009, 2010 Board of Trustees, Leland Stanford Jr. University
@@ -10,18 +10,9 @@
# configured. Sets the global principal variable to the principal to use.
kerberos_setup () {
local keytab
- keytab=''
- for f in "$BUILD/data/test.keytab" "$SOURCE/data/test.keytab" ; do
- if [ -r "$f" ] ; then
- keytab="$f"
- fi
- done
- principal=''
- for f in "$BUILD/data/test.principal" "$SOURCE/data/test.principal" ; do
- if [ -r "$f" ] ; then
- principal=`cat "$BUILD/data/test.principal"`
- fi
- done
+ keytab=`test_file_path data/test.keytab`
+ principal=`test_file_path data/test.principal`
+ principal=`cat "$principal" 2>/dev/null`
if [ -z "$keytab" ] || [ -z "$principal" ] ; then
return 1
fi
diff --git a/tests/tap/libtap.sh b/tests/tap/libtap.sh
index 1846840..a9b46d4 100644
--- a/tests/tap/libtap.sh
+++ b/tests/tap/libtap.sh
@@ -1,7 +1,7 @@
# Shell function library for test cases.
#
# Written by Russ Allbery <rra@stanford.edu>
-# Copyright 2009 Russ Allbery <rra@stanford.edu>
+# Copyright 2009, 2010 Russ Allbery <rra@stanford.edu>
# Copyright 2006, 2007, 2008 Board of Trustees, Leland Stanford Jr. University
#
# See LICENSE for licensing terms.
@@ -15,10 +15,22 @@ plan () {
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
@@ -146,3 +158,21 @@ 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 [ -f "$BUILD/$1" ] ; then
+ echo "$BUILD/$1"
+ elif [ -f "$SOURCE/$1" ] ; then
+ echo "$SOURCE/$1"
+ else
+ echo ''
+ fi
+}
diff --git a/tests/tap/remctl.sh b/tests/tap/remctl.sh
index b9667ef..9e01bcf 100644
--- a/tests/tap/remctl.sh
+++ b/tests/tap/remctl.sh
@@ -10,18 +10,12 @@
remctld_start () {
local keytab principal
rm -f "$BUILD/data/remctld.pid"
- keytab=''
- for f in "$BUILD/data/test.keytab" "$SOURCE/data/test.keytab" ; do
- if [ -r "$f" ] ; then
- keytab="$f"
- fi
- done
- principal=''
- for f in "$BUILD/data/test.principal" "$SOURCE/data/test.principal" ; do
- if [ -r "$f" ] ; then
- principal=`cat "$BUILD/data/test.principal"`
- fi
- done
+ keytab=`test_file_path data/test.keytab`
+ principal=`test_file_path data/test.principal`
+ principal=`cat "$principal" 2>/dev/null`
+ if [ -z "$keytab" ] || [ -z "$principal" ] ; then
+ return 1
+ fi
if [ -n "$VALGRIND" ] ; then
( "$VALGRIND" --log-file=valgrind.%p --leak-check=full "$1" -m \
-p 14373 -s "$principal" -P "$BUILD/data/remctld.pid" -f "$2" -d \