Browse Source

Turned libtap into a proper ccan package.
Fixed up ccan_tools dir, not other package's tests.

Rusty Russell 17 years ago
parent
commit
ee4a263c10
10 changed files with 425 additions and 89 deletions
  1. 1 5
      ccan_tools/Makefile
  2. 0 80
      ccan_tools/libtap/src/tap.h
  3. 3 3
      ccan_tools/run_tests.c
  4. 0 0
      tap/Makefile.am
  5. 0 0
      tap/Makefile.in
  6. 58 0
      tap/_info.c
  7. 0 0
      tap/tap.3
  8. 1 1
      tap/tap.c
  9. 246 0
      tap/tap.h
  10. 116 0
      tap/test/run.c

+ 1 - 5
ccan_tools/Makefile

@@ -1,10 +1,7 @@
-ccan_tools/run_tests: ccan_tools/run_tests.o ccan_tools/libtap/src/tap.o ccan_tools/talloc/talloc.o 
+ccan_tools/run_tests: ccan_tools/run_tests.o tap/tap.o ccan_tools/talloc/talloc.o 
 
 ccan_tools/doc_extract: ccan_tools/doc_extract.c ccan_tools/talloc/talloc.o
 
-ccan_tools/libtap/src/tap.o:
-	cd ccan_tools/libtap && ./configure && make
-
 ccan_tools/talloc/talloc.o:
 	cd ccan_tools/talloc && ./configure && make
 
@@ -12,5 +9,4 @@ ccan_tools/namespacize: ccan_tools/namespacize.c ccan_tools/talloc/talloc.o
 
 ccan_tools-clean:
 	rm -f run_tests doc_extract
-	@cd ccan_tools/libtap && make clean
 	@cd ccan_tools/talloc && make clean

+ 0 - 80
ccan_tools/libtap/src/tap.h

@@ -1,80 +0,0 @@
-/*-
- * Copyright (c) 2004 Nik Clayton
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#if (!defined(__STDC_VERSION__) || __STDC_VERSION__ < 199901L) && !defined(__GNUC__)
-# error "Needs gcc or C99 compiler for variadic macros."
-#else
-
-# define ok(e, ...) ((e) ?						\
-		     _gen_result(1, __func__, __FILE__, __LINE__,	\
-				 __VA_ARGS__) :				\
-		     _gen_result(0, __func__, __FILE__, __LINE__,	\
-				 __VA_ARGS__))
-
-# define ok1(e) ((e) ?							\
-		 _gen_result(1, __func__, __FILE__, __LINE__, "%s", #e) : \
-		 _gen_result(0, __func__, __FILE__, __LINE__, "%s", #e))
-
-# define pass(...) ok(1, __VA_ARGS__)
-# define fail(...) ok(0, __VA_ARGS__)
-
-# define skip_if(cond, n, ...)				\
-	if (cond) skip((n), __VA_ARGS__);		\
-	else
-
-# define skip_start(test, n, ...)			\
-	do {						\
-		if((test)) {				\
-			skip(n,  __VA_ARGS__);		\
-			continue;			\
-		}
-
-# define skip_end } while(0)
-
-#ifndef PRINTF_ATTRIBUTE
-#ifdef __GNUC__
-#define PRINTF_ATTRIBUTE(a1, a2) __attribute__ ((format (__printf__, a1, a2)))
-#else
-#define PRINTF_ATTRIBUTE(a1, a2)
-#endif
-#endif
-
-unsigned int _gen_result(int, const char *, char *, unsigned int, char *, ...)
-	PRINTF_ATTRIBUTE(5, 6);
-
-void plan_no_plan(void);
-void plan_skip_all(char *);
-void plan_tests(unsigned int);
-
-void diag(char *, ...) PRINTF_ATTRIBUTE(1, 2);
-
-void skip(unsigned int, char *, ...) PRINTF_ATTRIBUTE(2, 3);
-
-void todo_start(char *, ...) PRINTF_ATTRIBUTE(1, 2);
-void todo_end(void);
-
-int exit_status(void);
-#endif /* C99 or gcc */

+ 3 - 3
ccan_tools/run_tests.c

@@ -4,11 +4,11 @@
 #include <dirent.h>
 #include <assert.h>
 #include <unistd.h>
-#include "libtap/src/tap.h"
+#include "tap/tap.h"
 #include "talloc/talloc.h"
 #include "../string/string.h"
 
-#define CFLAGS "-O3 -Wall -Wundef -Wstrict-prototypes -Wold-style-definition -Wmissing-prototypes -Wmissing-declarations -Werror -I. -Iccan_tools/libtap/src/"
+#define CFLAGS "-O3 -Wall -Wundef -Wstrict-prototypes -Wold-style-definition -Wmissing-prototypes -Wmissing-declarations -Werror -I."
 
 /* FIXME: Use build bug later. */
 #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
@@ -56,7 +56,7 @@ static char *obj_list(void)
 		list = talloc_asprintf_append(list, "%s ", i->name);
 
 	/* FIXME */
-	list = talloc_asprintf_append(list, "ccan_tools/libtap/src/tap.o");
+	list = talloc_asprintf_append(list, "tap/tap.o");
 	return list;
 }
 

+ 0 - 0
ccan_tools/libtap/src/Makefile.am → tap/Makefile.am


+ 0 - 0
ccan_tools/libtap/src/Makefile.in → tap/Makefile.in


+ 58 - 0
tap/_info.c

@@ -0,0 +1,58 @@
+#include <stdio.h>
+#include <string.h>
+#include "config.h"
+
+/**
+ * tap - Test Anything Protocol
+ *
+ * The tap package produces simple-to-parse mainly-human-readable test
+ * output to assist in the writing of test cases.  It is based on the
+ * (now-defunct) libtap, which is based on Perl's CPAN TAP module.  Its
+ * output can be parsed by a harness such as CPAN's Prove.
+ *
+ * CCAN testcases are expected to output the TAP format, usually using
+ * this package.
+ *
+ * For more information about TAP, see:
+ *	http://en.wikipedia.org/wiki/Test_Anything_Protocol
+ *
+ * Based on the original libtap, Copyright (c) 2004 Nik Clayton.
+ *
+ * Example:
+ *	#include <string.h>
+ *	#include "tap/tap.h"
+ *
+ *	// Run some simple (but overly chatty) tests on strcmp().
+ *	int main(int argc, char *argv[])
+ *	{
+ *		const char a[] = "a", another_a[] = "a";
+ *		const char b[] = "b";
+ *		const char ab[] = "ab";
+ *
+ *		plan_tests(4);
+ *		diag("Testing different pointers (%p/%p) with same contents",
+ *		     a, another_a);
+ *		ok1(strcmp(a, another_a) == 0);
+ *
+ *		diag("'a' comes before 'b'");
+ *		ok1(strcmp(a, b) < 0);
+ *		ok1(strcmp(b, a) > 0);
+ *
+ *		diag("'ab' comes after 'a'");
+ *		ok1(strcmp(ab, a) > 0);
+ *		return exit_status();
+ *	}
+ */
+int main(int argc, char *argv[])
+{
+	if (argc != 2)
+		return 1;
+
+	if (strcmp(argv[1], "depends") == 0)
+		return 0;
+
+	if (strcmp(argv[1], "license") == 0)
+		return "BSD";
+
+	return 1;
+}

+ 0 - 0
ccan_tools/libtap/src/tap.3 → tap/tap.3


+ 1 - 1
ccan_tools/libtap/src/tap.c → tap/tap.c

@@ -357,7 +357,7 @@ skip(unsigned int n, char *fmt, ...)
 	LOCK;
 
 	va_start(ap, fmt);
-	asprintf(&skip_msg, fmt, ap);
+	vasprintf(&skip_msg, fmt, ap);
 	va_end(ap);
 
 	while(n-- > 0) {

+ 246 - 0
tap/tap.h

@@ -0,0 +1,246 @@
+/*-
+ * Copyright (c) 2004 Nik Clayton
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/**
+ * plan_tests - announce the number of tests you plan to run
+ * @tests: the number of tests
+ *
+ * This should be the first call in your test program: it allows tracing
+ * of failures which mean that not all tests are run.
+ *
+ * If you don't know how many tests will actually be run, assume all of them
+ * and use skip() if you don't actually run some tests.
+ *
+ * Example:
+ *	plan_tests(13);
+ */
+void plan_tests(unsigned int tests);
+
+#if (!defined(__STDC_VERSION__) || __STDC_VERSION__ < 199901L) && !defined(__GNUC__)
+# error "Needs gcc or C99 compiler for variadic macros."
+#else
+
+/**
+ * ok1 - Simple conditional test
+ * @e: the expression which we expect to be true.
+ *
+ * This is the simplest kind of test: if the expression is true, the
+ * test passes.  The name of the test which is printed will simply be
+ * file name, line number, and the expression itself.
+ *
+ * Example:
+ *	ok1(init_subsystem() == 1);
+ */
+# define ok1(e) ((e) ?							\
+		 _gen_result(1, __func__, __FILE__, __LINE__, "%s", #e) : \
+		 _gen_result(0, __func__, __FILE__, __LINE__, "%s", #e))
+
+/**
+ * ok - Conditional test with a name
+ * @e: the expression which we expect to be true.
+ * @...: the printf-style name of the test.
+ *
+ * If the expression is true, the test passes.  The name of the test will be
+ * the filename, line number, and the printf-style string.  This can be clearer
+ * than simply the expression itself.
+ *
+ * Example:
+ *	ok1(init_subsystem() == 1);
+ *	ok(init_subsystem() == 0, "Second initialization should fail");
+ */
+# define ok(e, ...) ((e) ?						\
+		     _gen_result(1, __func__, __FILE__, __LINE__,	\
+				 __VA_ARGS__) :				\
+		     _gen_result(0, __func__, __FILE__, __LINE__,	\
+				 __VA_ARGS__))
+
+/**
+ * pass - Note that a test passed
+ * @...: the printf-style name of the test.
+ *
+ * For complicated code paths, it can be easiest to simply call pass() in one
+ * branch and fail() in another.
+ *
+ * Example:
+ *	x = do_something();
+ *	if (!checkable(x) || check_value(x))
+ *		pass("do_something() returned a valid value");
+ *	else		
+ *		fail("do_something() returned an invalid value");
+ */
+# define pass(...) ok(1, __VA_ARGS__)
+
+/**
+ * fail - Note that a test failed
+ * @...: the printf-style name of the test.
+ *
+ * For complicated code paths, it can be easiest to simply call pass() in one
+ * branch and fail() in another.
+ */
+# define fail(...) ok(0, __VA_ARGS__)
+
+/* I don't find these to be useful. */
+# define skip_if(cond, n, ...)				\
+	if (cond) skip((n), __VA_ARGS__);		\
+	else
+
+# define skip_start(test, n, ...)			\
+	do {						\
+		if((test)) {				\
+			skip(n,  __VA_ARGS__);		\
+			continue;			\
+		}
+
+# define skip_end } while(0)
+
+#ifndef PRINTF_ATTRIBUTE
+#ifdef __GNUC__
+#define PRINTF_ATTRIBUTE(a1, a2) __attribute__ ((format (__printf__, a1, a2)))
+#else
+#define PRINTF_ATTRIBUTE(a1, a2)
+#endif
+#endif
+
+unsigned int _gen_result(int, const char *, char *, unsigned int, char *, ...)
+	PRINTF_ATTRIBUTE(5, 6);
+
+/**
+ * diag - print a diagnostic message (use instead of printf/fprintf)
+ * @fmt: the format of the printf-style message
+ *
+ * diag ensures that the output will not be considered to be a test
+ * result by the TAP test harness.  It will append '\n' for you.
+ *
+ * Example:
+ *	diag("Now running complex tests");
+ */
+void diag(char *fmt, ...) PRINTF_ATTRIBUTE(1, 2);
+
+/**
+ * skip - print a diagnostic message (use instead of printf/fprintf)
+ * @n: number of tests you're skipping.
+ * @fmt: the format of the reason you're skipping the tests.
+ *
+ * Sometimes tests cannot be run because the test system lacks some feature:
+ * you should explicitly document that you're skipping tests using skip().
+ *
+ * From the Test::More documentation:
+ *   If it's something the user might not be able to do, use SKIP.  This
+ *   includes optional modules that aren't installed, running under an OS that
+ *   doesn't have some feature (like fork() or symlinks), or maybe you need an
+ *   Internet connection and one isn't available.
+ *
+ * Example:
+ *	#ifdef HAVE_SOME_FEATURE
+ *	ok1(test_some_feature());
+ *	#else
+ *	skip(1, "Don't have SOME_FEATURE");
+ *	#endif
+ */
+void skip(unsigned int n, char *fmt, ...) PRINTF_ATTRIBUTE(2, 3);
+
+/**
+ * todo_start - mark tests that you expect to fail.
+ * @fmt: the reason they currently fail.
+ *
+ * It's extremely useful to write tests before you implement the matching fix
+ * or features: surround these tests by todo_start()/todo_end().  These tests
+ * will still be run, but with additional output that indicates that they are
+ * expected to fail.
+ *
+ * This way, should a test start to succeed unexpectedly, tools like prove(1)
+ * will indicate this and you can move the test out of the todo block.  This
+ * is much more useful than simply commenting out (or '#if 0') the tests.
+ * 
+ * From the Test::More documentation:
+ *   If it's something the programmer hasn't done yet, use TODO.  This is for
+ *   any code you haven't written yet, or bugs you have yet to fix, but want to
+ *   put tests in your testing script (always a good idea).
+ *
+ * Example:
+ *	todo_start("dwim() not returning true yet");
+ *	ok(dwim(), "Did what the user wanted");
+ *	todo_end();
+ */
+void todo_start(char *fmt, ...) PRINTF_ATTRIBUTE(1, 2);
+
+/**
+ * todo_end - end of tests you expect to fail.
+ *
+ * See todo_start().
+ */
+void todo_end(void);
+
+/**
+ * exit_status - the value that main should return.
+ *
+ * For maximum compatability your test program should return a particular exit
+ * code (ie. 0 if all tests were run, and every test which was expected to
+ * succeed succeeded).
+ *
+ * Example:
+ *	exit(exit_status());
+ */
+int exit_status(void);
+
+/**
+ * plan_no_plan - I have no idea how many tests I'm going to run.
+ *
+ * In some situations you may not know how many tests you will be running, or
+ * you are developing your test program, and do not want to update the
+ * plan_tests() call every time you make a change.  For those situations use
+ * plan_no_plan() instead of plan_tests().  It indicates to the test harness
+ * that an indeterminate number of tests will be run.
+ *
+ * Remember, if you fail to plan, you plan to fail.
+ *
+ * Example:
+ *	plan_no_plan();
+ *	while (random() % 2)
+ *		ok1(some_test());
+ *	exit(exit_status());
+ */
+void plan_no_plan(void);
+
+/**
+ * plan_skip_all - Indicate that you will skip all tests.
+ * @reason: the string indicating why you can't run any tests.
+ *
+ * If your test program detects at run time that some required functionality
+ * is missing (for example, it relies on a database connection which is not
+ * present, or a particular configuration option that has not been included
+ * in the running kernel) use plan_skip_all() instead of plan_tests().
+ *
+ * Example:
+ *	if (!have_some_feature) {
+ *		plan_skip_all("Need some_feature support");
+ *		exit(exit_status());
+ *	}
+ *	plan_tests(13);
+ */
+void plan_skip_all(char *reason);
+
+#endif /* C99 or gcc */

+ 116 - 0
tap/test/run.c

@@ -0,0 +1,116 @@
+/* We use the fact that pipes have a buffer greater than the size of
+ * any output, and change stdout and stderr to use that.
+ *
+ * Since we don't use libtap for output, this looks like one big test. */
+#include "tap/tap.h"
+#include <stdio.h>
+#include <unistd.h>
+#include <stdarg.h>
+#include <err.h>
+#include <string.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <stdbool.h>
+
+/* We dup stderr to here. */
+static int stderrfd;
+
+/* Simple replacement for err() */
+static void failmsg(const char *fmt, ...)
+{
+ 	char buf[1024];
+	va_list ap;
+
+	/* Write into buffer. */
+	va_start(ap, fmt);
+	vsprintf(buf, fmt, ap);
+	va_end(ap);
+
+	write(stderrfd, "# ", 2);
+	write(stderrfd, buf, strlen(buf));
+	write(stderrfd, "\n", 1);
+	_exit(1);
+}
+
+static void expect(int fd, const char *str)
+{
+ 	char buffer[PIPE_BUF];
+	int r;
+
+	r = read(fd, buffer, sizeof(buffer));
+	if (r < 0)
+		failmsg("reading from pipe");
+
+	if (strlen(str) != r || strncmp(str, buffer, r) != 0)
+		failmsg("Expected '%s' got '%.*s'",
+			str, r, buffer);
+}
+
+int main(int argc, char *argv[])
+{
+	int p[2];
+	int stdoutfd;
+
+	printf("1..1\n");
+	stderrfd = dup(STDERR_FILENO);
+	if (stderrfd < 0)
+		err(1, "dup of stderr failed");
+
+	stdoutfd = dup(STDOUT_FILENO);
+	if (stdoutfd < 0)
+		err(1, "dup of stdout failed");
+
+	if (pipe(p) != 0)
+		failmsg("pipe failed");
+
+	if (dup2(p[1], STDERR_FILENO) < 0 || dup2(p[1], STDOUT_FILENO) < 0)
+		failmsg("Duplicating file descriptor");
+
+	plan_tests(10);
+	expect(p[0], "1..10\n");
+
+	ok(1, "msg1");
+	expect(p[0], "ok 1 - msg1\n");
+
+	ok(0, "msg2");
+	expect(p[0], "not ok 2 - msg2\n"
+	       "#     Failed test (tap/test/run.c:main() at line 75)\n");
+
+	ok1(true);
+	expect(p[0], "ok 3 - true\n");
+
+	ok1(false);
+ 	expect(p[0], "not ok 4 - false\n"
+	       "#     Failed test (tap/test/run.c:main() at line 82)\n");
+
+	pass("passed");
+ 	expect(p[0], "ok 5 - passed\n");
+
+	fail("failed");
+ 	expect(p[0], "not ok 6 - failed\n"
+	       "#     Failed test (tap/test/run.c:main() at line 89)\n");
+
+	skip(2, "skipping %s", "test");
+ 	expect(p[0], "ok 7 # skip skipping test\n"
+	       "ok 8 # skip skipping test\n");
+
+	todo_start("todo");
+	ok1(false);
+	expect(p[0], "not ok 9 - false # TODO todo\n"
+	       "#     Failed (TODO) test (tap/test/run.c:main() at line 98)\n");
+	ok1(true);
+	expect(p[0], "ok 10 - true # TODO todo\n");
+	todo_end();
+
+	if (exit_status() != 3)
+		failmsg("Expected exit status 3, not %i", exit_status());
+
+#if 0
+	/* Manually run the atexit command. */
+	_cleanup();
+	expect(p[0], "# Looks like you failed 2 tests of 9.\n");
+#endif
+
+	write(stdoutfd, "ok 1 - All passed\n", strlen("ok 1 - All passed\n"));
+	_exit(0);
+}