Merge branch 'master' of ozlabs.org:ccan
[ccan] / ccan / tap / tap.c
index 4bbd977bbfdd6f3312295afb67a3d9e5d7832206..7c01e140d5c206c475957f439b47eb3462fff994 100644 (file)
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  */
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  */
-#define _GNU_SOURCE
+#include "config.h"
 #include <ctype.h>
 #include <stdarg.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <ctype.h>
 #include <stdarg.h>
 #include <stdio.h>
 #include <stdlib.h>
+#include <unistd.h>
 
 #include "tap.h"
 
 
 #include "tap.h"
 
@@ -38,13 +39,19 @@ static unsigned int test_count = 0; /* Number of tests that have been run */
 static unsigned int e_tests = 0; /* Expected number of tests to run */
 static unsigned int failures = 0; /* Number of tests that failed */
 static char *todo_msg = NULL;
 static unsigned int e_tests = 0; /* Expected number of tests to run */
 static unsigned int failures = 0; /* Number of tests that failed */
 static char *todo_msg = NULL;
-static char *todo_msg_fixed = "libtap malloc issue";
+static const char *todo_msg_fixed = "libtap malloc issue";
 static int todo = 0;
 static int test_died = 0;
 static int todo = 0;
 static int test_died = 0;
+static int test_pid;
 
 /* Encapsulate the pthread code in a conditional.  In the absence of
 
 /* Encapsulate the pthread code in a conditional.  In the absence of
-   libpthread the code does nothing */
-#ifdef HAVE_LIBPTHREAD
+   libpthread the code does nothing.
+
+   If you have multiple threads calling ok() etc. at the same time you would
+   need this, but in that case your test numbers will be random and I'm not
+   sure it makes sense. --RR
+*/
+#ifdef WANT_PTHREAD
 #include <pthread.h>
 static pthread_mutex_t M = PTHREAD_MUTEX_INITIALIZER;
 # define LOCK pthread_mutex_lock(&M)
 #include <pthread.h>
 static pthread_mutex_t M = PTHREAD_MUTEX_INITIALIZER;
 # define LOCK pthread_mutex_lock(&M)
@@ -63,15 +70,15 @@ _expected_tests(unsigned int tests)
 }
 
 static void
 }
 
 static void
-diagv(char *fmt, va_list ap)
+diagv(const char *fmt, va_list ap)
 {
 {
-       fputs("# ", stderr);
-       vfprintf(stderr, fmt, ap);
-       fputs("\n", stderr);
+       fputs("# ", stdout);
+       vfprintf(stdout, fmt, ap);
+       fputs("\n", stdout);
 }
 
 static void
 }
 
 static void
-_diag(char *fmt, ...)
+_diag(const char *fmt, ...)
 {
        va_list ap;
        va_start(ap, fmt);
 {
        va_list ap;
        va_start(ap, fmt);
@@ -87,8 +94,8 @@ _diag(char *fmt, ...)
  * test_comment -- a comment to print afterwards, may be NULL
  */
 unsigned int
  * test_comment -- a comment to print afterwards, may be NULL
  */
 unsigned int
-_gen_result(int ok, const char *func, char *file, unsigned int line, 
-           char *test_name, ...)
+_gen_result(int ok, const char *func, const char *file, unsigned int line,
+           const char *test_name, ...)
 {
        va_list ap;
        char *local_test_name = NULL;
 {
        va_list ap;
        char *local_test_name = NULL;
@@ -103,7 +110,8 @@ _gen_result(int ok, const char *func, char *file, unsigned int line,
           expansions on it */
        if(test_name != NULL) {
                va_start(ap, test_name);
           expansions on it */
        if(test_name != NULL) {
                va_start(ap, test_name);
-               vasprintf(&local_test_name, test_name, ap);
+               if (vasprintf(&local_test_name, test_name, ap) < 0)
+                       local_test_name = NULL;
                va_end(ap);
 
                /* Make sure the test name contains more than digits
                va_end(ap);
 
                /* Make sure the test name contains more than digits
@@ -112,7 +120,8 @@ _gen_result(int ok, const char *func, char *file, unsigned int line,
                if(local_test_name) {
                        name_is_digits = 1;
                        for(c = local_test_name; *c != '\0'; c++) {
                if(local_test_name) {
                        name_is_digits = 1;
                        for(c = local_test_name; *c != '\0'; c++) {
-                               if(!isdigit(*c) && !isspace(*c)) {
+                               if(!isdigit((unsigned char)*c)
+                                  && !isspace((unsigned char)*c)) {
                                        name_is_digits = 0;
                                        break;
                                }
                                        name_is_digits = 0;
                                        break;
                                }
@@ -166,13 +175,16 @@ _gen_result(int ok, const char *func, char *file, unsigned int line,
        printf("\n");
 
        if(!ok)
        printf("\n");
 
        if(!ok)
-               _diag("    Failed %stest (%s:%s() at line %d)", 
+               _diag("    Failed %stest (%s:%s() at line %d)",
                      todo ? "(TODO) " : "", file, func, line);
 
        free(local_test_name);
 
        UNLOCK;
 
                      todo ? "(TODO) " : "", file, func, line);
 
        free(local_test_name);
 
        UNLOCK;
 
+       if (!ok && tap_fail_callback)
+               tap_fail_callback();
+
        /* We only care (when testing) that ok is positive, but here we
           specifically only want to return 1 or 0 */
        return ok ? 1 : 0;
        /* We only care (when testing) that ok is positive, but here we
           specifically only want to return 1 or 0 */
        return ok ? 1 : 0;
@@ -185,6 +197,9 @@ _gen_result(int ok, const char *func, char *file, unsigned int line,
 static void
 _cleanup(void)
 {
 static void
 _cleanup(void)
 {
+       /* If we forked, don't do cleanup in child! */
+       if (getpid() != test_pid)
+               return;
 
        LOCK;
 
 
        LOCK;
 
@@ -221,7 +236,7 @@ _cleanup(void)
                _diag("Looks like you planned %d tests but only ran %d.",
                      e_tests, test_count);
                if(failures) {
                _diag("Looks like you planned %d tests but only ran %d.",
                      e_tests, test_count);
                if(failures) {
-                       _diag("Looks like you failed %d tests of %d run.", 
+                       _diag("Looks like you failed %d tests of %d run.",
                              failures, test_count);
                }
                UNLOCK;
                              failures, test_count);
                }
                UNLOCK;
@@ -229,7 +244,7 @@ _cleanup(void)
        }
 
        if(failures)
        }
 
        if(failures)
-               _diag("Looks like you failed %d tests of %d.", 
+               _diag("Looks like you failed %d tests of %d.",
                      failures, test_count);
 
        UNLOCK;
                      failures, test_count);
 
        UNLOCK;
@@ -245,12 +260,13 @@ _tap_init(void)
        static int run_once = 0;
 
        if(!run_once) {
        static int run_once = 0;
 
        if(!run_once) {
+               test_pid = getpid();
                atexit(_cleanup);
 
                /* stdout needs to be unbuffered so that the output appears
                atexit(_cleanup);
 
                /* stdout needs to be unbuffered so that the output appears
-                  in the same place relative to stderr output as it does 
+                  in the same place relative to stderr output as it does
                   with Test::Harness */
                   with Test::Harness */
-               setbuf(stdout, 0);
+//             setbuf(stdout, 0);
                run_once = 1;
        }
 }
                run_once = 1;
        }
 }
@@ -283,7 +299,7 @@ plan_no_plan(void)
  * Note that the plan is to skip all tests
  */
 void
  * Note that the plan is to skip all tests
  */
 void
-plan_skip_all(char *reason)
+plan_skip_all(const char *reason)
 {
 
        LOCK;
 {
 
        LOCK;
@@ -335,7 +351,7 @@ plan_tests(unsigned int tests)
 }
 
 void
 }
 
 void
-diag(char *fmt, ...)
+diag(const char *fmt, ...)
 {
        va_list ap;
 
 {
        va_list ap;
 
@@ -349,7 +365,7 @@ diag(char *fmt, ...)
 }
 
 void
 }
 
 void
-skip(unsigned int n, char *fmt, ...)
+skip(unsigned int n, const char *fmt, ...)
 {
        va_list ap;
        char *skip_msg;
 {
        va_list ap;
        char *skip_msg;
@@ -357,13 +373,14 @@ skip(unsigned int n, char *fmt, ...)
        LOCK;
 
        va_start(ap, fmt);
        LOCK;
 
        va_start(ap, fmt);
-       vasprintf(&skip_msg, fmt, ap);
+       if (vasprintf(&skip_msg, fmt, ap) < 0)
+               skip_msg = NULL;
        va_end(ap);
 
        while(n-- > 0) {
                test_count++;
        va_end(ap);
 
        while(n-- > 0) {
                test_count++;
-               printf("ok %d # skip %s\n", test_count, 
-                      skip_msg != NULL ? 
+               printf("ok %d # skip %s\n", test_count,
+                      skip_msg != NULL ?
                       skip_msg : "libtap():malloc() failed");
        }
 
                       skip_msg : "libtap():malloc() failed");
        }
 
@@ -373,14 +390,15 @@ skip(unsigned int n, char *fmt, ...)
 }
 
 void
 }
 
 void
-todo_start(char *fmt, ...)
+todo_start(const char *fmt, ...)
 {
        va_list ap;
 
        LOCK;
 
        va_start(ap, fmt);
 {
        va_list ap;
 
        LOCK;
 
        va_start(ap, fmt);
-       vasprintf(&todo_msg, fmt, ap);
+       if (vasprintf(&todo_msg, fmt, ap) < 0)
+               todo_msg = NULL;
        va_end(ap);
 
        todo = 1;
        va_end(ap);
 
        todo = 1;
@@ -421,7 +439,7 @@ exit_status(void)
                return r;
        }
 
                return r;
        }
 
-       /* Return the number of tests that failed + the number of tests 
+       /* Return the number of tests that failed + the number of tests
           that weren't run */
        r = failures + e_tests - test_count;
        UNLOCK;
           that weren't run */
        r = failures + e_tests - test_count;
        UNLOCK;