]> git.ipfire.org Git - thirdparty/libarchive.git/commitdiff
Rewrite a lot of the test assertion framework.
authorTim Kientzle <kientzle@gmail.com>
Sun, 23 Aug 2009 03:18:13 +0000 (23:18 -0400)
committerTim Kientzle <kientzle@gmail.com>
Sun, 23 Aug 2009 03:18:13 +0000 (23:18 -0400)
Mostly, this was done just to simplify the code, but it also brings
the file/line reporting into one place where it can be adjusted to
suit different environments (e.g., Visual Studio expects "file.c(89):
message" instead of "file.c:89: message").

SVN-Revision: 1380

cpio/test/main.c
cpio/test/test.h
libarchive/config_freebsd.h
libarchive/test/main.c
libarchive/test/test.h
libarchive/test/test_acl_freebsd.c
libarchive/test/test_extattr_freebsd.c
tar/test/main.c
tar/test/test.h

index 7c480f1aca5207cc8e8cfd38c805f55bcd2b97b0..3d9992854226cf86d445b60447834cc0805e1144 100644 (file)
@@ -90,12 +90,6 @@ __FBSDID("$FreeBSD: src/usr.bin/cpio/test/main.c,v 1.3 2008/08/24 04:58:22 kient
 #define        DEFINE_TEST(name) void name(void);
 #include "list.h"
 
-/* Interix doesn't define these in a standard header. */
-#if __INTERIX__
-extern char *optarg;
-extern int optind;
-#endif
-
 /* Enable core dump on failure. */
 static int dump_on_failure = 0;
 /* Default is to remove temp dirs for successful tests. */
@@ -140,7 +134,8 @@ invalid_parameter_handler(const wchar_t * expression,
  *          printed if the following assertion fails, good for
  *          explaining subtle tests.
  */
-static char msg[4096];
+static char msgbuff[4096];
+static const char *msg, *nextmsg;
 
 /*
  * For each test source file, we remember how many times each
@@ -148,10 +143,9 @@ static char msg[4096];
  */
 static const char *failed_filename = NULL;
 static struct line {
-       int line;
        int count;
-       int critical;
-}  failed_lines[1000];
+       int skip;
+}  failed_lines[10000];
 
 /*
  * Called at the beginning of each assert() function.
@@ -162,40 +156,61 @@ count_assertion(const char *file, int line)
        (void)file; /* UNUSED */
        (void)line; /* UNUSED */
        ++assertions;
+       msg = nextmsg;
+       nextmsg = NULL;
        /* Uncomment to print file:line after every assertion.
         * Verbose, but occasionally useful in tracking down crashes. */
        /* printf("Checked %s:%d\n", file, line); */
 }
 
 /*
- * Count this failure; return the number of previous failures.
+ * Count this failure; return true if this failure is being reported.
  */
 static int
-previous_failures(const char *filename, int line, int critical)
+report_failure(const char *filename, int line, const char *fmt, ...)
 {
-       unsigned int i;
-       int count;
+       ++failures;
 
+       /* If this is a new file, clear the counts. */
        if (failed_filename == NULL || strcmp(failed_filename, filename) != 0)
                memset(failed_lines, 0, sizeof(failed_lines));
        failed_filename = filename;
 
-       for (i = 0; i < sizeof(failed_lines)/sizeof(failed_lines[0]); i++) {
-               if (failed_lines[i].line == line) {
-                       count = failed_lines[i].count;
-                       failed_lines[i].count++;
-                       return (count);
-               }
-               if (failed_lines[i].line == 0) {
-                       failed_lines[i].line = line;
-                       failed_lines[i].count = 1;
-                       failed_lines[i].critical = critical;
-                       return (0);
-               }
+       /* Report first hit always, every hit if verbose. */
+       if (failed_lines[line].count++ == 0 || verbose) {
+               va_list ap;
+               va_start(ap, fmt);
+               fprintf(stderr, "%s:%d: ", filename, line);
+               vfprintf(stderr, fmt, ap);
+               va_end(ap);
+               fprintf(stderr, "\n");
+               return (1);
        }
        return (0);
 }
 
+/* Complete reporting of failed tests. */
+static void
+finish_failure(void *extra)
+{
+       if (msg != NULL && msg[0] != '\0')
+               fprintf(stderr, "   Description: %s\n", msg);
+
+#ifdef EXTRA_DUMP
+       if (extra != NULL)
+               fprintf(stderr, "   detail: %s\n", EXTRA_DUMP(extra));
+#else
+       (void)extra; /* UNUSED */
+#endif
+
+       if (dump_on_failure) {
+               fprintf(stderr,
+                   " *** forcing core dump so failure can be debugged ***\n");
+               *(char *)(NULL) = 0;
+               exit(1);
+       }
+}
+
 /*
  * Copy arguments into file-local variables.
  */
@@ -216,39 +231,17 @@ test_skipping(const char *fmt, ...)
 {
        va_list ap;
 
-       if (previous_failures(test_filename, test_line, 0))
-               return;
-
-       va_start(ap, fmt);
-       fprintf(stderr, " *** SKIPPING: ");
-       vfprintf(stderr, fmt, ap);
-       fprintf(stderr, "\n");
-       va_end(ap);
-       ++skips;
-}
-
-/* Common handling of failed tests. */
-static void
-report_failure(void *extra)
-{
-       if (msg[0] != '\0') {
-               fprintf(stderr, "   Description: %s\n", msg);
-               msg[0] = '\0';
-       }
-
-#ifdef EXTRA_DUMP
-       if (extra != NULL)
-               fprintf(stderr, "   detail: %s\n", EXTRA_DUMP(extra));
-#else
-       (void)extra; /* UNUSED */
-#endif
-
-       if (dump_on_failure) {
-               fprintf(stderr,
-                   " *** forcing core dump so failure can be debugged ***\n");
-               *(char *)(NULL) = 0;
-               exit(1);
+       if (report_failure(test_filename, test_line, "SKIPPING" )) {
+               va_start(ap,fmt);
+               fprintf(stderr, "      Reason: ");
+               vfprintf(stderr, fmt, ap);
+               fprintf(stderr, "\n");
+               /* Don't finish_failure() here. */
        }
+       /* Mark as skip, so doesn't count as failed test. */
+       failed_lines[test_line].skip = 1;
+       ++skips;
+       --failures;
 }
 
 /*
@@ -256,33 +249,17 @@ report_failure(void *extra)
  * The reports above suppress multiple failures from the same source
  * line; this reports on any tests that did fail multiple times.
  */
-static int
-summarize_comparator(const void *a0, const void *b0)
-{
-       const struct line *a = a0, *b = b0;
-       if (a->line == 0 && b->line == 0)
-               return (0);
-       if (a->line == 0)
-               return (1);
-       if (b->line == 0)
-               return (-1);
-       return (a->line - b->line);
-}
-
 static void
 summarize(void)
 {
        unsigned int i;
 
-       qsort(failed_lines, sizeof(failed_lines)/sizeof(failed_lines[0]),
-           sizeof(failed_lines[0]), summarize_comparator);
        for (i = 0; i < sizeof(failed_lines)/sizeof(failed_lines[0]); i++) {
-               if (failed_lines[i].line == 0)
+               if (failed_lines[i].count == 0)
                        break;
-               if (failed_lines[i].count > 1 && failed_lines[i].critical)
+               if (failed_lines[i].count > 1 && !failed_lines[i].skip)
                        fprintf(stderr, "%s:%d: Failed %d times\n",
-                           failed_filename, failed_lines[i].line,
-                           failed_lines[i].count);
+                           failed_filename, i, failed_lines[i].count);
        }
        /* Clear the failure history for the next file. */
        memset(failed_lines, 0, sizeof(failed_lines));
@@ -294,25 +271,22 @@ failure(const char *fmt, ...)
 {
        va_list ap;
        va_start(ap, fmt);
-       vsprintf(msg, fmt, ap);
+       vsprintf(msgbuff, fmt, ap);
        va_end(ap);
+       nextmsg = msgbuff;
 }
 
 /* Generic assert() just displays the failed condition. */
 int
-test_assert(const char *file, int line, int value, const char *condition, void *extra)
+test_assert(const char *file, int line, int value,
+    const char *condition, void *extra)
 {
        count_assertion(file, line);
-       if (value) {
-               msg[0] = '\0';
+       if (value)
                return (value);
+       if (report_failure(file, line, "Assertion failed: %s", condition)) {
+               finish_failure(extra);
        }
-       ++failures;
-       if (!verbose && previous_failures(file, line, 1))
-               return (value);
-       fprintf(stderr, "%s:%d: Assertion failed\n", file, line);
-       fprintf(stderr, "   Condition: %s\n", condition);
-       report_failure(extra);
        return (value);
 }
 
@@ -322,11 +296,9 @@ test_assert_chdir(const char *file, int line, const char *pathname)
        count_assertion(file, line);
        if (chdir(pathname) == 0)
                return (1);
-       ++failures;
-       if (!verbose && previous_failures(file, line, 1))
-               return (0);
-       fprintf(stderr, "%s:%d: chdir(\"%s\") failed\n",
-               file, line, pathname);
+       if (report_failure(file, line, "chdir(\"%s\")", pathname)) {
+               finish_failure(NULL);
+       }
        return (0);
 
 }
@@ -337,23 +309,19 @@ test_assert_equal_int(const char *file, int line,
     long long v1, const char *e1, long long v2, const char *e2, void *extra)
 {
        count_assertion(file, line);
-       if (v1 == v2) {
-               msg[0] = '\0';
+       if (v1 == v2)
                return (1);
+       if (report_failure(file, line, "Ints not equal")) {
+               fprintf(stderr, "      %s=%lld\n", e1, v1);
+               fprintf(stderr, "      %s=%lld\n", e2, v2);
+               finish_failure(extra);
        }
-       ++failures;
-       if (!verbose && previous_failures(file, line, 1))
-               return (0);
-       fprintf(stderr, "%s:%d: Assertion failed: Ints not equal\n",
-           file, line);
-       fprintf(stderr, "      %s=%lld\n", e1, v1);
-       fprintf(stderr, "      %s=%lld\n", e2, v2);
-       report_failure(extra);
        return (0);
 }
 
-static void strdump(const char *p)
+static void strdump(const char *e, const char *p)
 {
+       fprintf(stderr, "      %s = ", e);
        if (p == NULL) {
                fprintf(stderr, "(null)");
                return;
@@ -374,6 +342,7 @@ static void strdump(const char *p)
                }
        }
        fprintf(stderr, "\"");
+       fprintf(stderr, " (length %d)\n", p == NULL ? 0 : (int)strlen(p));
 }
 
 /* assertEqualString() displays the values of the two strings. */
@@ -384,32 +353,21 @@ test_assert_equal_string(const char *file, int line,
     void *extra)
 {
        count_assertion(file, line);
-       if (v1 == NULL || v2 == NULL) {
-               if (v1 == v2) {
-                       msg[0] = '\0';
-                       return (1);
-               }
-       } else if (strcmp(v1, v2) == 0) {
-               msg[0] = '\0';
+       if (v1 == v2)
+               return (1);
+       else if (strcmp(v1, v2) == 0)
                return (1);
+       if (report_failure(file, line, "Strings not equal")) {
+               strdump(e1, v1);
+               strdump(e2, v2);
+               finish_failure(extra);
        }
-       ++failures;
-       if (!verbose && previous_failures(file, line, 1))
-               return (0);
-       fprintf(stderr, "%s:%d: Assertion failed: Strings not equal\n",
-           file, line);
-       fprintf(stderr, "      %s = ", e1);
-       strdump(v1);
-       fprintf(stderr, " (length %d)\n", v1 == NULL ? 0 : (int)strlen(v1));
-       fprintf(stderr, "      %s = ", e2);
-       strdump(v2);
-       fprintf(stderr, " (length %d)\n", v2 == NULL ? 0 : (int)strlen(v2));
-       report_failure(extra);
        return (0);
 }
 
-static void wcsdump(const wchar_t *w)
+static void wcsdump(const char *e, const wchar_t *w)
 {
+       fprintf(stderr, "      %s = ", e);
        if (w == NULL) {
                fprintf(stderr, "(null)");
                return;
@@ -426,7 +384,7 @@ static void wcsdump(const wchar_t *w)
                else
                        fprintf(stderr, "\\U%08X", c);
        }
-       fprintf(stderr, "\"");
+       fprintf(stderr, "\"\n");
 }
 
 /* assertEqualWString() displays the values of the two strings. */
@@ -437,32 +395,15 @@ test_assert_equal_wstring(const char *file, int line,
     void *extra)
 {
        count_assertion(file, line);
-       if (v1 == NULL) {
-               if (v2 == NULL) {
-                       msg[0] = '\0';
-                       return (1);
-               }
-       } else if (v2 == NULL) {
-               if (v1 == NULL) {
-                       msg[0] = '\0';
-                       return (1);
-               }
-       } else if (wcscmp(v1, v2) == 0) {
-               msg[0] = '\0';
+       if (v1 == v2)
+               return (1);
+       else if (wcscmp(v1, v2) == 0)
                return (1);
+       if (report_failure(file, line, "Unicode strings not equal")) {
+               wcsdump(e1, v1);
+               wcsdump(e2, v2);
+               finish_failure(extra);
        }
-       ++failures;
-       if (!verbose && previous_failures(file, line, 1))
-               return (0);
-       fprintf(stderr, "%s:%d: Assertion failed: Unicode strings not equal\n",
-           file, line);
-       fprintf(stderr, "      %s = ", e1);
-       wcsdump(v1);
-       fprintf(stderr, "\n");
-       fprintf(stderr, "      %s = ", e2);
-       wcsdump(v2);
-       fprintf(stderr, "\n");
-       report_failure(extra);
        return (0);
 }
 
@@ -515,37 +456,29 @@ test_assert_equal_mem(const char *file, int line,
        size_t offset;
 
        count_assertion(file, line);
-       if (v1 == NULL || v2 == NULL) {
-               if (v1 == v2) {
-                       msg[0] = '\0';
-                       return (1);
-               }
-       } else if (memcmp(v1, v2, l) == 0) {
-               msg[0] = '\0';
+       if (v1 == v2)
+               return (1);
+       else if (memcmp(v1, v2, l) == 0)
                return (1);
+       if (report_failure(file, line, "Memory not equal")) {
+               fprintf(stderr, "      size %s = %d\n", ld, (int)l);
+               /* Dump 48 bytes (3 lines) so that the first difference is
+                * in the second line. */
+               offset = 0;
+               while (l > 64 && memcmp(v1, v2, 32) == 0) {
+                       /* Two lines agree, so step forward one line. */
+                       v1 += 16;
+                       v2 += 16;
+                       l -= 16;
+                       offset += 16;
+               }
+               fprintf(stderr, "      Dump of %s\n", e1);
+               hexdump(v1, v2, l < 64 ? l : 64, offset);
+               fprintf(stderr, "      Dump of %s\n", e2);
+               hexdump(v2, v1, l < 64 ? l : 64, offset);
+               fprintf(stderr, "\n");
+               finish_failure(extra);
        }
-       ++failures;
-       if (!verbose && previous_failures(file, line, 1))
-               return (0);
-       fprintf(stderr, "%s:%d: Assertion failed: memory not equal\n",
-           file, line);
-       fprintf(stderr, "      size %s = %d\n", ld, (int)l);
-       /* Dump 48 bytes (3 lines) so that the first difference is
-        * in the second line. */
-       offset = 0;
-       while (l > 64 && memcmp(v1, v2, 32) == 0) {
-               /* The first two lines agree, so step forward one line. */
-               v1 += 16;
-               v2 += 16;
-               l -= 16;
-               offset += 16;
-       }
-       fprintf(stderr, "      Dump of %s\n", e1);
-       hexdump(v1, v2, l < 64 ? l : 64, offset);
-       fprintf(stderr, "      Dump of %s\n", e2);
-       hexdump(v2, v1, l < 64 ? l : 64, offset);
-       fprintf(stderr, "\n");
-       report_failure(extra);
        return (0);
 }
 
@@ -559,37 +492,35 @@ test_assert_empty_file(const char *f1fmt, ...)
        ssize_t s;
        FILE *f;
 
-
+       count_assertion(test_filename, test_line);
        va_start(ap, f1fmt);
        vsprintf(f1, f1fmt, ap);
        va_end(ap);
 
        if (stat(f1, &st) != 0) {
-               fprintf(stderr, "%s:%d: Could not stat: %s\n", test_filename, test_line, f1);
-               report_failure(NULL);
+               if (report_failure(test_filename, test_line, "Stat failed: %s", f1)) {
+                       finish_failure(NULL);
+               }
                return (0);
        }
        if (st.st_size == 0)
                return (1);
 
-       ++failures;
-       if (!verbose && previous_failures(test_filename, test_line, 1))
-               return (0);
-
-       fprintf(stderr, "%s:%d: File not empty: %s\n", test_filename, test_line, f1);
-       fprintf(stderr, "    File size: %d\n", (int)st.st_size);
-       fprintf(stderr, "    Contents:\n");
-       f = fopen(f1, "rb");
-       if (f == NULL) {
-               fprintf(stderr, "    Unable to open %s\n", f1);
-       } else {
-               s = ((off_t)sizeof(buff) < st.st_size) ?
-                   (ssize_t)sizeof(buff) : (ssize_t)st.st_size;
-               s = fread(buff, 1, s, f);
-               hexdump(buff, NULL, s, 0);
-               fclose(f);
+       if (report_failure(test_filename, test_line, "%s not empty", f1)) {
+               fprintf(stderr, "    File size: %d\n", (int)st.st_size);
+               fprintf(stderr, "    Contents:\n");
+               f = fopen(f1, "rb");
+               if (f == NULL) {
+                       fprintf(stderr, "    Unable to open %s\n", f1);
+               } else {
+                       s = ((off_t)sizeof(buff) < st.st_size) ?
+                           (ssize_t)sizeof(buff) : (ssize_t)st.st_size;
+                       s = fread(buff, 1, s, f);
+                       hexdump(buff, NULL, s, 0);
+                       fclose(f);
+               }
+               finish_failure(NULL);
        }
-       report_failure(NULL);
        return (0);
 }
 
@@ -600,28 +531,20 @@ test_assert_non_empty_file(const char *f1fmt, ...)
        struct stat st;
        va_list ap;
 
-
+       count_assertion(test_filename, test_line);
        va_start(ap, f1fmt);
        vsprintf(f1, f1fmt, ap);
        va_end(ap);
 
        if (stat(f1, &st) != 0) {
-               fprintf(stderr, "%s:%d: Could not stat: %s\n",
-                   test_filename, test_line, f1);
-               report_failure(NULL);
-               ++failures;
+               if (report_failure(test_filename, test_line, "Stat failed: %s", f1))
+                       finish_failure(NULL);
                return (0);
        }
        if (st.st_size != 0)
                return (1);
-
-       ++failures;
-       if (!verbose && previous_failures(test_filename, test_line, 1))
-               return (0);
-
-       fprintf(stderr, "%s:%d: File empty: %s\n",
-           test_filename, test_line, f1);
-       report_failure(NULL);
+       if (report_failure(test_filename, test_line, "File empty: %s", f1))
+               finish_failure(NULL);
        return (0);
 }
 
@@ -637,6 +560,7 @@ test_assert_equal_file(const char *fn1, const char *f2pattern, ...)
        FILE *f1, *f2;
        int n1, n2;
 
+       count_assertion(test_filename, test_line);
        va_start(ap, f2pattern);
        vsprintf(fn2, f2pattern, ap);
        va_end(ap);
@@ -658,14 +582,11 @@ test_assert_equal_file(const char *fn1, const char *f2pattern, ...)
        }
        fclose(f1);
        fclose(f2);
-       ++failures;
-       if (!verbose && previous_failures(test_filename, test_line, 1))
-               return (0);
-       fprintf(stderr, "%s:%d: Files are not identical\n",
-           test_filename, test_line);
-       fprintf(stderr, "  file1=\"%s\"\n", fn1);
-       fprintf(stderr, "  file2=\"%s\"\n", fn2);
-       report_failure(test_extra);
+       if (report_failure(test_filename, test_line, "Files not identical")) {
+               fprintf(stderr, "  file1=\"%s\"\n", fn1);
+               fprintf(stderr, "  file2=\"%s\"\n", fn2);
+               finish_failure(test_extra);
+       }
        return (0);
 }
 
@@ -687,12 +608,9 @@ test_assert_file_exists(const char *fpattern, ...)
        if (!access(f, F_OK))
                return (1);
 #endif
-       ++failures;
-       if (!previous_failures(test_filename, test_line, 1)) {
-               fprintf(stderr, "%s:%d: File doesn't exist\n",
-                   test_filename, test_line);
+       if (report_failure(test_filename, test_line, "File doesn't exist")) {
                fprintf(stderr, "  file=\"%s\"\n", f);
-               report_failure(test_extra);
+               finish_failure(test_extra);
        }
        return (0);
 }
@@ -715,12 +633,9 @@ test_assert_file_not_exists(const char *fpattern, ...)
        if (access(f, F_OK))
                return (1);
 #endif
-       ++failures;
-       if (!previous_failures(test_filename, test_line, 1)) {
-               fprintf(stderr, "%s:%d: File exists and shouldn't\n",
-                   test_filename, test_line);
+       if (report_failure(test_filename, test_line, "File exists")) {
                fprintf(stderr, "  file=\"%s\"\n", f);
-               report_failure(test_extra);
+               finish_failure(test_extra);
        }
        return (0);
 }
@@ -742,11 +657,8 @@ test_assert_file_contents(const void *buff, int s, const char *fpattern, ...)
 
        f = fopen(fn, "rb");
        if (f == NULL) {
-               ++failures;
-               if (!previous_failures(test_filename, test_line, 1)) {
-                       fprintf(stderr, "%s:%d: File doesn't exist: %s\n",
-                           test_filename, test_line, fn);
-                       report_failure(test_extra);
+               if (report_failure(test_filename, test_line, "File doesn't exist: %s", fn)) {
+                       finish_failure(test_extra);
                }
                return (0);
        }
@@ -757,10 +669,7 @@ test_assert_file_contents(const void *buff, int s, const char *fpattern, ...)
                free(contents);
                return (1);
        }
-       ++failures;
-       if (!previous_failures(test_filename, test_line, 1)) {
-               fprintf(stderr, "%s:%d: File contents don't match\n",
-                   test_filename, test_line);
+       if (report_failure(test_filename, test_line, "File contents don't match")) {
                fprintf(stderr, "  file=\"%s\"\n", fn);
                if (n > 0)
                        hexdump(contents, buff, n > 512 ? 512 : 0, 0);
@@ -768,7 +677,7 @@ test_assert_file_contents(const void *buff, int s, const char *fpattern, ...)
                        fprintf(stderr, "  File empty, contents should be:\n");
                        hexdump(buff, NULL, s > 512 ? 512 : 0, 0);
                }
-               report_failure(test_extra);
+               finish_failure(test_extra);
        }
        free(contents);
        return (0);
@@ -810,13 +719,9 @@ test_assert_text_file_contents(const char *buff, const char *fn)
        }
        if (*btxt == '\0' && *ftxt == '\0') {
                free(contents);
-               msg[0] = '\0';
                return (1);
        }
-       ++failures;
-       if (!previous_failures(test_filename, test_line, 1)) {
-               fprintf(stderr, "%s:%d: File contents don't match\n",
-                   test_filename, test_line);
+       if (report_failure(test_filename, test_line, "Contents don't match")) {
                fprintf(stderr, "  file=\"%s\"\n", fn);
                if (n > 0)
                        hexdump(contents, buff, n, 0);
@@ -824,10 +729,9 @@ test_assert_text_file_contents(const char *buff, const char *fn)
                        fprintf(stderr, "  File empty, contents should be:\n");
                        hexdump(buff, NULL, s, 0);
                }
-               report_failure(test_extra);
+               finish_failure(test_extra);
        }
        free(contents);
-       msg[0] = '\0';
        return (0);
 }
 
@@ -841,28 +745,20 @@ test_assert_file_hardlinks(const char *file, int line,
        count_assertion(file, line);
        r = lstat(path1, &st1);
        if (r != 0) {
-               ++failures;
-               if (!previous_failures(file, line, 1))
-                       fprintf(stderr, "%s:%d: File ``%s'' should exist\n",
-                           file, line, path1);
+               if (report_failure(file, line, "File %s should exist", path1))
+                       finish_failure(NULL);
                return (0);
        }
        r = lstat(path2, &st2);
        if (r != 0) {
-               ++failures;
-               if (!previous_failures(file, line, 1))
-                       fprintf(stderr, "%s:%d: File ``%s'' should exist\n",
-                           file, line, path2);
+               if (report_failure(file, line, "File %s should exist", path2))
+                       finish_failure(NULL);
                return (0);
        }
        if (st1.st_ino != st2.st_ino || st1.st_dev != st2.st_dev) {
-               ++failures;
-               if (!previous_failures(file, line, 1)) {
-                       fprintf(stderr,
-                               "%s:%d: Files ``%s'' and ``%s'' are not hardlinked\n",
-                           file, line, path1, path2);
-                       report_failure(NULL);
-               }
+               if (report_failure(file, line,
+                       "Files %s and %s are not hardlinked", path1, path2))
+                       finish_failure(NULL);
                return (0);
        }
        return (1);
@@ -879,12 +775,9 @@ test_assert_file_nlinks(const char *file, int line,
        r = lstat(pathname, &st);
        if (r == 0 && st.st_nlink == nlinks)
                        return (1);
-       ++failures;
-       if (!previous_failures(file, line, 1)) {
-               fprintf(stderr, "%s:%d: File ``%s'' has %d links, expected %d\n",
-                   file, line, pathname, st.st_nlink, nlinks);
-               report_failure(NULL);
-       }
+       if (report_failure(file, line, "File %s has %d links, expected %d",
+               pathname, st.st_nlink, nlinks))
+               finish_failure(NULL);
        return (0);
 }
 
@@ -899,12 +792,9 @@ test_assert_file_size(const char *file, int line,
        r = lstat(pathname, &st);
        if (r == 0 && st.st_size == size)
                        return (1);
-       ++failures;
-       if (!previous_failures(file, line, 1)) {
-               fprintf(stderr, "%s:%d: File ``%s'' has size %ld, expected %ld\n",
-                   file, line, pathname, (long)st.st_size, (long)size);
-               report_failure(NULL);
-       }
+       if (report_failure(file, line, "File %s has size %ld, expected %ld",
+               pathname, (long)st.st_size, (long)size))
+               finish_failure(NULL);
        return (0);
 }
 
@@ -917,39 +807,25 @@ test_assert_is_dir(const char *file, int line, const char *pathname, int mode)
        count_assertion(file, line);
        r = lstat(pathname, &st);
        if (r != 0) {
-               ++failures;
-               if (!previous_failures(file, line, 1)) {
-                       fprintf(stderr, "%s:%d: Dir ``%s'' doesn't exist\n",
-                           file, line, pathname);
-                       report_failure(NULL);
-               }
+               if (report_failure(file, line, "Dir %s doesn't exist", pathname))
+                       finish_failure(NULL);
                return (0);
        }
        if (!S_ISDIR(st.st_mode)) {
-               ++failures;
-               if (!previous_failures(file, line, 1)) {
-                       fprintf(stderr, "%s:%d: ``%s'' is not a dir\n",
-                           file, line, pathname);
-                       report_failure(NULL);
-               }
+               if (report_failure(file, line, "%s is not a dir", pathname))
+                       finish_failure(NULL);
                return (0);
        }
-       if (mode < 0) {
-               msg[0] = '\0';
+       if (mode < 0)
                return (1);
-       }
        if (mode != (st.st_mode & 07777)) {
-               ++failures;
-               if (!previous_failures(file, line, 1)) {
-                       fprintf(stderr, "%s:%d: Dir ``%s'' has wrong mode\n",
-                           file, line, pathname);
+               if (report_failure(file, line, "Dir %s has wrong mode", pathname)) {
                        fprintf(stderr, "  Expected: 0%3o\n", mode);
                        fprintf(stderr, "  Found: 0%3o\n", st.st_mode & 07777);
-                       report_failure(NULL);
+                       finish_failure(NULL);
                }
                return (0);
        }
-       msg[0] = '\0';
        return (1);
 }
 
@@ -958,13 +834,10 @@ test_assert_is_symlink(const char *file, int line,
     const char *pathname, const char *contents)
 {
 #if defined(_WIN32) && !defined(__CYGWIN__)
+       count_assertion(file, line);
        // TODO: Vista supports symlinks
-       ++failures;
-       if (!previous_failures(file, line, 1)) {
-               fprintf(stderr, "%s:%d: Symlink ``%s'' not supported\n",
-                       file, line, pathname);
-               report_failure(NULL);
-       }
+       if (report_failure(file, line, "Symlink %s not supported", pathname))
+               finish_failure(NULL);
        return (0);
 #else
        char buff[300];
@@ -975,44 +848,29 @@ test_assert_is_symlink(const char *file, int line,
        count_assertion(file, line);
        r = lstat(pathname, &st);
        if (r != 0) {
-               ++failures;
-               if (!previous_failures(file, line, 1)) {
-                       fprintf(stderr, "%s:%d: Symlink ``%s'' doesn't exist\n",
-                           file, line, pathname);
-                       report_failure(NULL);
-               }
+               if (report_failure(file, line, "Symlink %s doesn't exist", pathname))
+                       finish_failure(NULL);
                return (0);
        }
        if (!S_ISLNK(st.st_mode)) {
-               ++failures;
-               if (!previous_failures(file, line, 1)) {
-                       fprintf(stderr, "%s:%d:  ``%s'' should be a symlink\n",
-                           file, line, pathname);
-                       report_failure(NULL);
-               }
+               if (report_failure(file, line, "%s should be a symlink", pathname))
+                       finish_failure(NULL);
                return (0);
        }
        if (contents == NULL)
                return (1);
        linklen = readlink(pathname, buff, sizeof(buff));
        if (linklen < 0) {
-               ++failures;
-               if (!previous_failures(file, line, 1)) {
-                       fprintf(stderr, "%s:%d: symlink ``%s'' can't be read\n",
-                           file, line, pathname);
-                       report_failure(NULL);
-               }
+               if (report_failure(file, line, "Can't read symlink %s", pathname))
+                       finish_failure(NULL);
                return (0);
        }
        buff[linklen] = '\0';
        if (strcmp(buff, contents) != 0) {
-               ++failures;
-               if (!previous_failures(file, line, 1)) {
-                       fprintf(stderr, "%s:%d: Wrong symlink ``%s''\n",
-                           file, line, pathname);
+               if (report_failure(file, line, "Wrong symlink %s", pathname)) {
                        fprintf(stderr, "   Expected: %s\n", contents);
                        fprintf(stderr, "   Found: %s\n", buff);
-                       report_failure(NULL);
+                       finish_failure(NULL);
                }
                return (0);
        }
@@ -1029,24 +887,17 @@ test_assert_is_reg(const char *file, int line, const char *pathname, int mode)
        count_assertion(file, line);
        r = lstat(pathname, &st);
        if (r != 0 || !S_ISREG(st.st_mode)) {
-               ++failures;
-               if (!previous_failures(file, line, 1)) {
-                       fprintf(stderr, "%s:%d: File ``%s'' doesn't exist\n",
-                           file, line, pathname);
-                       report_failure(NULL);
-               }
+               if (report_failure(file, line, "File %s doesn't exist", pathname))
+                       finish_failure(NULL);
                return (0);
        }
        if (mode < 0)
                return (1);
        if (mode != (st.st_mode & 07777)) {
-               ++failures;
-               if (!previous_failures(file, line, 1)) {
-                       fprintf(stderr, "%s:%d: File ``%s'' has wrong mode\n",
-                           file, line, pathname);
+               if (report_failure(file, line, "File %s has wrong mode", pathname)) {
                        fprintf(stderr, "  Expected: 0%3o\n", mode);
                        fprintf(stderr, "  Found: 0%3o\n", st.st_mode & 07777);
-                       report_failure(NULL);
+                       finish_failure(NULL);
                }
                return (0);
        }
@@ -1056,24 +907,16 @@ test_assert_is_reg(const char *file, int line, const char *pathname, int mode)
 int
 test_assert_make_dir(const char *file, int line, const char *dirname, int mode)
 {
-       int r;
-
        count_assertion(file, line);
 #if defined(_WIN32) && !defined(__CYGWIN__)
-       r = _mkdir(dirname);
+       if (0 == _mkdir(dirname))
+               return (1);
 #else
-       r = mkdir(dirname, mode);
-#endif
-       if (r == 0) {
-               msg[0] = '\0';
+       if (0 == mkdir(dirname, mode))
                return (1);
-       }
-       ++failures;
-       if (!verbose && previous_failures(file, line, 1))
-               return (0);
-       fprintf(stderr, "%s:%d: Could not create directory\n",
-               file, line);
-       fprintf(stderr, "     Dirname: %s\n", dirname);
+#endif
+       if (report_failure(file, line, "Could not create directory %s", dirname))
+               finish_failure(NULL);
        return(0);
 }
 
@@ -1084,56 +927,43 @@ test_assert_make_file(const char *file, int line,
 #if defined(_WIN32) && !defined(__CYGWIN__)
        /* TODO: Rework this to set file mode as well. */
        FILE *f;
+       count_assertion(file, line);
        f = fopen(path, "wb");
        if (f == NULL) {
-               ++failures;
-               if (!verbose && previous_failures(file, line, 1))
-                       return (0);
-               fprintf(stderr, "%s:%d: Could not create file ``%s''\n",
-                   file, line, path);
+               if (report_failure(file, line, "Could not create file %s", path))
+                       finish_failure(NULL);
                return (0);
        }
        if (contents != NULL) {
                if (strlen(contents)
                    != fwrite(contents, 1, strlen(contents), f)) {
                        fclose(f);
-                       ++failures;
-                       if (!verbose && previous_failures(file, line, 1))
-                               return (0);
-                       fprintf(stderr, "%s:%d: Could not write file ``%s''\n",
-                           file, line, path);
+                       if (report_failure(file, line, "Could not write file %s", path))
+                               finish_failure(NULL);
                        return (0);
                }
        }
        fclose(f);
-       msg[0] = '\0';
        return (1);
 #else
        int fd;
        count_assertion(file, line);
        fd = open(path, O_CREAT | O_WRONLY, mode >= 0 ? mode : 0644);
        if (fd < 0) {
-               ++failures;
-               if (!verbose && previous_failures(file, line, 1))
-                       return (0);
-               fprintf(stderr, "%s:%d: Could not create file ``%s''\n",
-                   file, line, path);
+               if (report_failure(file, line, "Could not create %s", path))
+                       finish_failure(NULL);
                return (0);
        }
        if (contents != NULL) {
                if ((ssize_t)strlen(contents)
                    != write(fd, contents, strlen(contents))) {
                        close(fd);
-                       ++failures;
-                       if (!verbose && previous_failures(file, line, 1))
-                               return (0);
-                       fprintf(stderr, "%s:%d: Could not write file ``%s''\n",
-                           file, line, path);
+                       if (report_failure(file, line, "Could not write to %s", path))
+                               finish_failure(NULL);
                        return (0);
                }
        }
        close(fd);
-       msg[0] = '\0';
        return (1);
 #endif
 }
@@ -1152,16 +982,12 @@ test_assert_make_hardlink(const char *file, int line,
 #else
        succeeded = 0;
 #endif
-       if (succeeded) {
-               msg[0] = '\0';
+       if (succeeded)
                return (1);
-       }
-       ++failures;
-       if (verbose || !previous_failures(file, line, 1)) {
-               fprintf(stderr, "%s:%d: Could not create new hardlink\n",
-                       file, line);
+       if (report_failure(file, line, "Could not create hardlink")) {
                fprintf(stderr, "   New link: %s\n", newpath);
                fprintf(stderr, "   Old name: %s\n", linkto);
+               finish_failure(NULL);
        }
        return(0);
 }
@@ -1171,28 +997,20 @@ int
 test_assert_make_symlink(const char *file, int line,
     const char *newpath, const char *linkto)
 {
-       int succeeded;
-
 #if HAVE_CREATESYMBOLICLINK
        int targetIsDir = 0; /* TODO: Fix this. */
        count_assertion(file, line);
-       succeeded = CreateSymbolicLink(newpath, linkto, targetIsDir);
+       if (CreateSymbolicLink(newpath, linkto, targetIsDir))
+               return (1);
 #elif HAVE_SYMLINK
        count_assertion(file, line);
-       succeeded = !symlink(linkto, newpath);
-#else
-       succeeded = 0;
-#endif
-       if (succeeded) {
-               msg[0] = '\0';
+       if (0 == symlink(linkto, newpath))
                return (1);
-       }
-       ++failures;
-       if (verbose || !previous_failures(file, line, 1)) {
-               fprintf(stderr, "%s:%d: Could not create new symlink\n",
-                       file, line);
+#endif
+       if (report_failure(file, line, "Could not create symlink")) {
                fprintf(stderr, "   New link: %s\n", newpath);
                fprintf(stderr, "   Old name: %s\n", linkto);
+               finish_failure(NULL);
        }
        return(0);
 }
@@ -1207,6 +1025,17 @@ test_assert_umask(const char *file, int line, int mask)
        return (1);
 }
 
+void
+sleepUntilAfter(time_t t)
+{
+       while (t >= time(NULL))
+#if defined(_WIN32) && !defined(__CYGWIN__)
+               Sleep(500);
+#else
+               sleep(1);
+#endif
+}
+
 /*
  * Call standard system() call, but build up the command line using
  * sprintf() conventions.
@@ -1755,16 +1584,3 @@ int main(int argc, char **argv)
 
        return (tests_failed);
 }
-
-void
-sleepUntilAfter(time_t t)
-{
-       /* If utime() is supported above, there's no sleep here which
-        * makes the test faster. */
-       while (t >= time(NULL))
-#if defined(_WIN32) && !defined(__CYGWIN__)
-               Sleep(500);
-#else
-               sleep(1);
-#endif
-}
index ad504770ce5031f6c51c05e0d03c8691fae85aa6..a3dddc89d914e13f3f5652ca2f98895fc1013540 100644 (file)
 #endif
 #endif
 
+#ifndef O_BINARY
+#define        O_BINARY 0
+#endif
+
 /*
  * Redefine DEFINE_TEST for use in defining the test functions.
  */
index 37c80660525536dee1811f7c9b2639147f46e325..2ebfe209148b0744d28620768d461ce3bf7ff382 100644 (file)
  * $FreeBSD: src/lib/libarchive/config_freebsd.h,v 1.15 2008/09/30 03:53:03 kientzle Exp $
  */
 
-#ifndef __LIBARCHIVE_BUILD
-#error This header is only to be used internally to libarchive.
-#endif
-
 /* FreeBSD 5.0 and later have ACL and extattr support. */
 #if __FreeBSD__ > 4
 #define        HAVE_ACL_CREATE_ENTRY 1
@@ -57,6 +53,7 @@
 #define        HAVE_DECL_STRERROR_R 1
 #define        HAVE_DECL_UINT32_MAX 1
 #define        HAVE_DECL_UINT64_MAX 1
+#define        HAVE_DIRENT_H 1
 #define        HAVE_EFTYPE 1
 #define        HAVE_EILSEQ 1
 #define        HAVE_ERRNO_H 1
index 3357b565dcd527337c9c7dec3118ebf818c8b4c0..c3b48af4e9779a898b687ea5b57dceda4063db85 100644 (file)
@@ -39,6 +39,7 @@
 #endif
 #include <io.h>
 #include <windows.h>
+#include <winbase.h>
 #ifndef F_OK
 #define F_OK (0)
 #endif
 #define umask _umask
 #endif
 
-#if defined(_WIN32) && !defined(__CYGWIN__)
-void *GetFunctionKernel32(const char *name)
-{
-       static HINSTANCE lib;
-       static int set;
-       if (!set) {
-               set = 1;
-               lib = LoadLibrary("kernel32.dll");
-       }
-       if (lib == NULL) {
-               fprintf(stderr, "Can't load kernel32.dll?!\n");
-               return NULL;
-       }
-       return (void *)GetProcAddress(lib, name);
-}
-
-int __CreateSymbolicLinkA(const char *linkname, const char *target, int flags)
-{
-       static BOOLEAN (*f)(LPCSTR, LPCSTR, DWORD);
-       static int set;
-       if (!set) {
-               set = 1;
-               f = GetFunctionKernel32("CreateSymbolicLinkA");
-       }
-       return f == NULL ? 0 : (*f)(linkname, target, flags);
-}
-
-int __CreateHardLinkA(const char *linkname, const char *target)
-{
-       static BOOLEAN (*f)(LPCSTR, LPCSTR, LPSECURITY_ATTRIBUTES);
-       static int set;
-       if (!set) {
-               set = 1;
-               f = GetFunctionKernel32("CreateHardLinkA");
-       }
-       if (f == NULL)
-               return 0;
-       return (*f)(linkname, target, NULL);
-}
-#endif
-
 /*
  * This same file is used pretty much verbatim for all test harnesses.
  *
@@ -129,12 +89,6 @@ __FBSDID("$FreeBSD: src/lib/libarchive/test/main.c,v 1.17 2008/12/21 00:13:50 ki
 #define        DEFINE_TEST(name) void name(void);
 #include "list.h"
 
-/* Interix doesn't define these in a standard header. */
-#if __INTERIX__
-extern char *optarg;
-extern int optind;
-#endif
-
 /* Enable core dump on failure. */
 static int dump_on_failure = 0;
 /* Default is to remove temp dirs for successful tests. */
@@ -179,7 +133,8 @@ invalid_parameter_handler(const wchar_t * expression,
  *          printed if the following assertion fails, good for
  *          explaining subtle tests.
  */
-static char msg[4096];
+static char msgbuff[4096];
+static const char *msg, *nextmsg;
 
 /*
  * For each test source file, we remember how many times each
@@ -187,10 +142,9 @@ static char msg[4096];
  */
 static const char *failed_filename = NULL;
 static struct line {
-       int line;
        int count;
-       int critical;
-}  failed_lines[1000];
+       int skip;
+}  failed_lines[10000];
 
 /*
  * Called at the beginning of each assert() function.
@@ -201,40 +155,61 @@ count_assertion(const char *file, int line)
        (void)file; /* UNUSED */
        (void)line; /* UNUSED */
        ++assertions;
+       msg = nextmsg;
+       nextmsg = NULL;
        /* Uncomment to print file:line after every assertion.
         * Verbose, but occasionally useful in tracking down crashes. */
        /* printf("Checked %s:%d\n", file, line); */
 }
 
 /*
- * Count this failure; return the number of previous failures.
+ * Count this failure; return true if this failure is being reported.
  */
 static int
-previous_failures(const char *filename, int line, int critical)
+report_failure(const char *filename, int line, const char *fmt, ...)
 {
-       unsigned int i;
-       int count;
+       ++failures;
 
+       /* If this is a new file, clear the counts. */
        if (failed_filename == NULL || strcmp(failed_filename, filename) != 0)
                memset(failed_lines, 0, sizeof(failed_lines));
        failed_filename = filename;
 
-       for (i = 0; i < sizeof(failed_lines)/sizeof(failed_lines[0]); i++) {
-               if (failed_lines[i].line == line) {
-                       count = failed_lines[i].count;
-                       failed_lines[i].count++;
-                       return (count);
-               }
-               if (failed_lines[i].line == 0) {
-                       failed_lines[i].line = line;
-                       failed_lines[i].count = 1;
-                       failed_lines[i].critical = critical;
-                       return (0);
-               }
+       /* Report first hit always, every hit if verbose. */
+       if (failed_lines[line].count++ == 0 || verbose) {
+               va_list ap;
+               va_start(ap, fmt);
+               fprintf(stderr, "%s:%d: ", filename, line);
+               vfprintf(stderr, fmt, ap);
+               va_end(ap);
+               fprintf(stderr, "\n");
+               return (1);
        }
        return (0);
 }
 
+/* Complete reporting of failed tests. */
+static void
+finish_failure(void *extra)
+{
+       if (msg != NULL && msg[0] != '\0')
+               fprintf(stderr, "   Description: %s\n", msg);
+
+#ifdef EXTRA_DUMP
+       if (extra != NULL)
+               fprintf(stderr, "   detail: %s\n", EXTRA_DUMP(extra));
+#else
+       (void)extra; /* UNUSED */
+#endif
+
+       if (dump_on_failure) {
+               fprintf(stderr,
+                   " *** forcing core dump so failure can be debugged ***\n");
+               *(char *)(NULL) = 0;
+               exit(1);
+       }
+}
+
 /*
  * Copy arguments into file-local variables.
  */
@@ -255,39 +230,17 @@ test_skipping(const char *fmt, ...)
 {
        va_list ap;
 
-       if (previous_failures(test_filename, test_line, 0))
-               return;
-
-       va_start(ap, fmt);
-       fprintf(stderr, " *** SKIPPING: ");
-       vfprintf(stderr, fmt, ap);
-       fprintf(stderr, "\n");
-       va_end(ap);
-       ++skips;
-}
-
-/* Common handling of failed tests. */
-static void
-report_failure(void *extra)
-{
-       if (msg[0] != '\0') {
-               fprintf(stderr, "   Description: %s\n", msg);
-               msg[0] = '\0';
-       }
-
-#ifdef EXTRA_DUMP
-       if (extra != NULL)
-               fprintf(stderr, "   detail: %s\n", EXTRA_DUMP(extra));
-#else
-       (void)extra; /* UNUSED */
-#endif
-
-       if (dump_on_failure) {
-               fprintf(stderr,
-                   " *** forcing core dump so failure can be debugged ***\n");
-               *(char *)(NULL) = 0;
-               exit(1);
+       if (report_failure(test_filename, test_line, "SKIPPING" )) {
+               va_start(ap,fmt);
+               fprintf(stderr, "      Reason: ");
+               vfprintf(stderr, fmt, ap);
+               fprintf(stderr, "\n");
+               /* Don't finish_failure() here. */
        }
+       /* Mark as skip, so doesn't count as failed test. */
+       failed_lines[test_line].skip = 1;
+       ++skips;
+       --failures;
 }
 
 /*
@@ -295,33 +248,17 @@ report_failure(void *extra)
  * The reports above suppress multiple failures from the same source
  * line; this reports on any tests that did fail multiple times.
  */
-static int
-summarize_comparator(const void *a0, const void *b0)
-{
-       const struct line *a = a0, *b = b0;
-       if (a->line == 0 && b->line == 0)
-               return (0);
-       if (a->line == 0)
-               return (1);
-       if (b->line == 0)
-               return (-1);
-       return (a->line - b->line);
-}
-
 static void
 summarize(void)
 {
        unsigned int i;
 
-       qsort(failed_lines, sizeof(failed_lines)/sizeof(failed_lines[0]),
-           sizeof(failed_lines[0]), summarize_comparator);
        for (i = 0; i < sizeof(failed_lines)/sizeof(failed_lines[0]); i++) {
-               if (failed_lines[i].line == 0)
+               if (failed_lines[i].count == 0)
                        break;
-               if (failed_lines[i].count > 1 && failed_lines[i].critical)
+               if (failed_lines[i].count > 1 && !failed_lines[i].skip)
                        fprintf(stderr, "%s:%d: Failed %d times\n",
-                           failed_filename, failed_lines[i].line,
-                           failed_lines[i].count);
+                           failed_filename, i, failed_lines[i].count);
        }
        /* Clear the failure history for the next file. */
        memset(failed_lines, 0, sizeof(failed_lines));
@@ -333,25 +270,22 @@ failure(const char *fmt, ...)
 {
        va_list ap;
        va_start(ap, fmt);
-       vsprintf(msg, fmt, ap);
+       vsprintf(msgbuff, fmt, ap);
        va_end(ap);
+       nextmsg = msgbuff;
 }
 
 /* Generic assert() just displays the failed condition. */
 int
-test_assert(const char *file, int line, int value, const char *condition, void *extra)
+test_assert(const char *file, int line, int value,
+    const char *condition, void *extra)
 {
        count_assertion(file, line);
-       if (value) {
-               msg[0] = '\0';
+       if (value)
                return (value);
+       if (report_failure(file, line, "Assertion failed: %s", condition)) {
+               finish_failure(extra);
        }
-       ++failures;
-       if (!verbose && previous_failures(file, line, 1))
-               return (value);
-       fprintf(stderr, "%s:%d: Assertion failed\n", file, line);
-       fprintf(stderr, "   Condition: %s\n", condition);
-       report_failure(extra);
        return (value);
 }
 
@@ -361,11 +295,9 @@ test_assert_chdir(const char *file, int line, const char *pathname)
        count_assertion(file, line);
        if (chdir(pathname) == 0)
                return (1);
-       ++failures;
-       if (!verbose && previous_failures(file, line, 1))
-               return (0);
-       fprintf(stderr, "%s:%d: chdir(\"%s\") failed\n",
-               file, line, pathname);
+       if (report_failure(file, line, "chdir(\"%s\")", pathname)) {
+               finish_failure(NULL);
+       }
        return (0);
 
 }
@@ -376,23 +308,19 @@ test_assert_equal_int(const char *file, int line,
     long long v1, const char *e1, long long v2, const char *e2, void *extra)
 {
        count_assertion(file, line);
-       if (v1 == v2) {
-               msg[0] = '\0';
+       if (v1 == v2)
                return (1);
+       if (report_failure(file, line, "Ints not equal")) {
+               fprintf(stderr, "      %s=%lld\n", e1, v1);
+               fprintf(stderr, "      %s=%lld\n", e2, v2);
+               finish_failure(extra);
        }
-       ++failures;
-       if (!verbose && previous_failures(file, line, 1))
-               return (0);
-       fprintf(stderr, "%s:%d: Assertion failed: Ints not equal\n",
-           file, line);
-       fprintf(stderr, "      %s=%lld\n", e1, v1);
-       fprintf(stderr, "      %s=%lld\n", e2, v2);
-       report_failure(extra);
        return (0);
 }
 
-static void strdump(const char *p)
+static void strdump(const char *e, const char *p)
 {
+       fprintf(stderr, "      %s = ", e);
        if (p == NULL) {
                fprintf(stderr, "(null)");
                return;
@@ -413,6 +341,7 @@ static void strdump(const char *p)
                }
        }
        fprintf(stderr, "\"");
+       fprintf(stderr, " (length %d)\n", p == NULL ? 0 : (int)strlen(p));
 }
 
 /* assertEqualString() displays the values of the two strings. */
@@ -423,32 +352,21 @@ test_assert_equal_string(const char *file, int line,
     void *extra)
 {
        count_assertion(file, line);
-       if (v1 == NULL || v2 == NULL) {
-               if (v1 == v2) {
-                       msg[0] = '\0';
-                       return (1);
-               }
-       } else if (strcmp(v1, v2) == 0) {
-               msg[0] = '\0';
+       if (v1 == v2)
+               return (1);
+       else if (strcmp(v1, v2) == 0)
                return (1);
+       if (report_failure(file, line, "Strings not equal")) {
+               strdump(e1, v1);
+               strdump(e2, v2);
+               finish_failure(extra);
        }
-       ++failures;
-       if (!verbose && previous_failures(file, line, 1))
-               return (0);
-       fprintf(stderr, "%s:%d: Assertion failed: Strings not equal\n",
-           file, line);
-       fprintf(stderr, "      %s = ", e1);
-       strdump(v1);
-       fprintf(stderr, " (length %d)\n", v1 == NULL ? 0 : (int)strlen(v1));
-       fprintf(stderr, "      %s = ", e2);
-       strdump(v2);
-       fprintf(stderr, " (length %d)\n", v2 == NULL ? 0 : (int)strlen(v2));
-       report_failure(extra);
        return (0);
 }
 
-static void wcsdump(const wchar_t *w)
+static void wcsdump(const char *e, const wchar_t *w)
 {
+       fprintf(stderr, "      %s = ", e);
        if (w == NULL) {
                fprintf(stderr, "(null)");
                return;
@@ -465,7 +383,7 @@ static void wcsdump(const wchar_t *w)
                else
                        fprintf(stderr, "\\U%08X", c);
        }
-       fprintf(stderr, "\"");
+       fprintf(stderr, "\"\n");
 }
 
 /* assertEqualWString() displays the values of the two strings. */
@@ -476,32 +394,15 @@ test_assert_equal_wstring(const char *file, int line,
     void *extra)
 {
        count_assertion(file, line);
-       if (v1 == NULL) {
-               if (v2 == NULL) {
-                       msg[0] = '\0';
-                       return (1);
-               }
-       } else if (v2 == NULL) {
-               if (v1 == NULL) {
-                       msg[0] = '\0';
-                       return (1);
-               }
-       } else if (wcscmp(v1, v2) == 0) {
-               msg[0] = '\0';
+       if (v1 == v2)
                return (1);
+       else if (wcscmp(v1, v2) == 0)
+               return (1);
+       if (report_failure(file, line, "Unicode strings not equal")) {
+               wcsdump(e1, v1);
+               wcsdump(e2, v2);
+               finish_failure(extra);
        }
-       ++failures;
-       if (!verbose && previous_failures(file, line, 1))
-               return (0);
-       fprintf(stderr, "%s:%d: Assertion failed: Unicode strings not equal\n",
-           file, line);
-       fprintf(stderr, "      %s = ", e1);
-       wcsdump(v1);
-       fprintf(stderr, "\n");
-       fprintf(stderr, "      %s = ", e2);
-       wcsdump(v2);
-       fprintf(stderr, "\n");
-       report_failure(extra);
        return (0);
 }
 
@@ -554,37 +455,29 @@ test_assert_equal_mem(const char *file, int line,
        size_t offset;
 
        count_assertion(file, line);
-       if (v1 == NULL || v2 == NULL) {
-               if (v1 == v2) {
-                       msg[0] = '\0';
-                       return (1);
-               }
-       } else if (memcmp(v1, v2, l) == 0) {
-               msg[0] = '\0';
+       if (v1 == v2)
+               return (1);
+       else if (memcmp(v1, v2, l) == 0)
                return (1);
+       if (report_failure(file, line, "Memory not equal")) {
+               fprintf(stderr, "      size %s = %d\n", ld, (int)l);
+               /* Dump 48 bytes (3 lines) so that the first difference is
+                * in the second line. */
+               offset = 0;
+               while (l > 64 && memcmp(v1, v2, 32) == 0) {
+                       /* Two lines agree, so step forward one line. */
+                       v1 += 16;
+                       v2 += 16;
+                       l -= 16;
+                       offset += 16;
+               }
+               fprintf(stderr, "      Dump of %s\n", e1);
+               hexdump(v1, v2, l < 64 ? l : 64, offset);
+               fprintf(stderr, "      Dump of %s\n", e2);
+               hexdump(v2, v1, l < 64 ? l : 64, offset);
+               fprintf(stderr, "\n");
+               finish_failure(extra);
        }
-       ++failures;
-       if (!verbose && previous_failures(file, line, 1))
-               return (0);
-       fprintf(stderr, "%s:%d: Assertion failed: memory not equal\n",
-           file, line);
-       fprintf(stderr, "      size %s = %d\n", ld, (int)l);
-       /* Dump 48 bytes (3 lines) so that the first difference is
-        * in the second line. */
-       offset = 0;
-       while (l > 64 && memcmp(v1, v2, 32) == 0) {
-               /* The first two lines agree, so step forward one line. */
-               v1 += 16;
-               v2 += 16;
-               l -= 16;
-               offset += 16;
-       }
-       fprintf(stderr, "      Dump of %s\n", e1);
-       hexdump(v1, v2, l < 64 ? l : 64, offset);
-       fprintf(stderr, "      Dump of %s\n", e2);
-       hexdump(v2, v1, l < 64 ? l : 64, offset);
-       fprintf(stderr, "\n");
-       report_failure(extra);
        return (0);
 }
 
@@ -598,37 +491,35 @@ test_assert_empty_file(const char *f1fmt, ...)
        ssize_t s;
        FILE *f;
 
-
+       count_assertion(test_filename, test_line);
        va_start(ap, f1fmt);
        vsprintf(f1, f1fmt, ap);
        va_end(ap);
 
        if (stat(f1, &st) != 0) {
-               fprintf(stderr, "%s:%d: Could not stat: %s\n", test_filename, test_line, f1);
-               report_failure(NULL);
+               if (report_failure(test_filename, test_line, "Stat failed: %s", f1)) {
+                       finish_failure(NULL);
+               }
                return (0);
        }
        if (st.st_size == 0)
                return (1);
 
-       ++failures;
-       if (!verbose && previous_failures(test_filename, test_line, 1))
-               return (0);
-
-       fprintf(stderr, "%s:%d: File not empty: %s\n", test_filename, test_line, f1);
-       fprintf(stderr, "    File size: %d\n", (int)st.st_size);
-       fprintf(stderr, "    Contents:\n");
-       f = fopen(f1, "rb");
-       if (f == NULL) {
-               fprintf(stderr, "    Unable to open %s\n", f1);
-       } else {
-               s = ((off_t)sizeof(buff) < st.st_size) ?
-                   (ssize_t)sizeof(buff) : (ssize_t)st.st_size;
-               s = fread(buff, 1, s, f);
-               hexdump(buff, NULL, s, 0);
-               fclose(f);
+       if (report_failure(test_filename, test_line, "%s not empty", f1)) {
+               fprintf(stderr, "    File size: %d\n", (int)st.st_size);
+               fprintf(stderr, "    Contents:\n");
+               f = fopen(f1, "rb");
+               if (f == NULL) {
+                       fprintf(stderr, "    Unable to open %s\n", f1);
+               } else {
+                       s = ((off_t)sizeof(buff) < st.st_size) ?
+                           (ssize_t)sizeof(buff) : (ssize_t)st.st_size;
+                       s = fread(buff, 1, s, f);
+                       hexdump(buff, NULL, s, 0);
+                       fclose(f);
+               }
+               finish_failure(NULL);
        }
-       report_failure(NULL);
        return (0);
 }
 
@@ -639,28 +530,20 @@ test_assert_non_empty_file(const char *f1fmt, ...)
        struct stat st;
        va_list ap;
 
-
+       count_assertion(test_filename, test_line);
        va_start(ap, f1fmt);
        vsprintf(f1, f1fmt, ap);
        va_end(ap);
 
        if (stat(f1, &st) != 0) {
-               fprintf(stderr, "%s:%d: Could not stat: %s\n",
-                   test_filename, test_line, f1);
-               report_failure(NULL);
-               ++failures;
+               if (report_failure(test_filename, test_line, "Stat failed: %s", f1))
+                       finish_failure(NULL);
                return (0);
        }
        if (st.st_size != 0)
                return (1);
-
-       ++failures;
-       if (!verbose && previous_failures(test_filename, test_line, 1))
-               return (0);
-
-       fprintf(stderr, "%s:%d: File empty: %s\n",
-           test_filename, test_line, f1);
-       report_failure(NULL);
+       if (report_failure(test_filename, test_line, "File empty: %s", f1))
+               finish_failure(NULL);
        return (0);
 }
 
@@ -676,6 +559,7 @@ test_assert_equal_file(const char *fn1, const char *f2pattern, ...)
        FILE *f1, *f2;
        int n1, n2;
 
+       count_assertion(test_filename, test_line);
        va_start(ap, f2pattern);
        vsprintf(fn2, f2pattern, ap);
        va_end(ap);
@@ -697,14 +581,11 @@ test_assert_equal_file(const char *fn1, const char *f2pattern, ...)
        }
        fclose(f1);
        fclose(f2);
-       ++failures;
-       if (!verbose && previous_failures(test_filename, test_line, 1))
-               return (0);
-       fprintf(stderr, "%s:%d: Files are not identical\n",
-           test_filename, test_line);
-       fprintf(stderr, "  file1=\"%s\"\n", fn1);
-       fprintf(stderr, "  file2=\"%s\"\n", fn2);
-       report_failure(test_extra);
+       if (report_failure(test_filename, test_line, "Files not identical")) {
+               fprintf(stderr, "  file1=\"%s\"\n", fn1);
+               fprintf(stderr, "  file2=\"%s\"\n", fn2);
+               finish_failure(test_extra);
+       }
        return (0);
 }
 
@@ -726,12 +607,9 @@ test_assert_file_exists(const char *fpattern, ...)
        if (!access(f, F_OK))
                return (1);
 #endif
-       ++failures;
-       if (!previous_failures(test_filename, test_line, 1)) {
-               fprintf(stderr, "%s:%d: File doesn't exist\n",
-                   test_filename, test_line);
+       if (report_failure(test_filename, test_line, "File doesn't exist")) {
                fprintf(stderr, "  file=\"%s\"\n", f);
-               report_failure(test_extra);
+               finish_failure(test_extra);
        }
        return (0);
 }
@@ -754,12 +632,9 @@ test_assert_file_not_exists(const char *fpattern, ...)
        if (access(f, F_OK))
                return (1);
 #endif
-       ++failures;
-       if (!previous_failures(test_filename, test_line, 1)) {
-               fprintf(stderr, "%s:%d: File exists and shouldn't\n",
-                   test_filename, test_line);
+       if (report_failure(test_filename, test_line, "File exists")) {
                fprintf(stderr, "  file=\"%s\"\n", f);
-               report_failure(test_extra);
+               finish_failure(test_extra);
        }
        return (0);
 }
@@ -781,11 +656,8 @@ test_assert_file_contents(const void *buff, int s, const char *fpattern, ...)
 
        f = fopen(fn, "rb");
        if (f == NULL) {
-               ++failures;
-               if (!previous_failures(test_filename, test_line, 1)) {
-                       fprintf(stderr, "%s:%d: File doesn't exist: %s\n",
-                           test_filename, test_line, fn);
-                       report_failure(test_extra);
+               if (report_failure(test_filename, test_line, "File doesn't exist: %s", fn)) {
+                       finish_failure(test_extra);
                }
                return (0);
        }
@@ -796,10 +668,7 @@ test_assert_file_contents(const void *buff, int s, const char *fpattern, ...)
                free(contents);
                return (1);
        }
-       ++failures;
-       if (!previous_failures(test_filename, test_line, 1)) {
-               fprintf(stderr, "%s:%d: File contents don't match\n",
-                   test_filename, test_line);
+       if (report_failure(test_filename, test_line, "File contents don't match")) {
                fprintf(stderr, "  file=\"%s\"\n", fn);
                if (n > 0)
                        hexdump(contents, buff, n > 512 ? 512 : 0, 0);
@@ -807,7 +676,7 @@ test_assert_file_contents(const void *buff, int s, const char *fpattern, ...)
                        fprintf(stderr, "  File empty, contents should be:\n");
                        hexdump(buff, NULL, s > 512 ? 512 : 0, 0);
                }
-               report_failure(test_extra);
+               finish_failure(test_extra);
        }
        free(contents);
        return (0);
@@ -851,10 +720,7 @@ test_assert_text_file_contents(const char *buff, const char *fn)
                free(contents);
                return (1);
        }
-       ++failures;
-       if (!previous_failures(test_filename, test_line, 1)) {
-               fprintf(stderr, "%s:%d: File contents don't match\n",
-                   test_filename, test_line);
+       if (report_failure(test_filename, test_line, "Contents don't match")) {
                fprintf(stderr, "  file=\"%s\"\n", fn);
                if (n > 0)
                        hexdump(contents, buff, n, 0);
@@ -862,7 +728,7 @@ test_assert_text_file_contents(const char *buff, const char *fn)
                        fprintf(stderr, "  File empty, contents should be:\n");
                        hexdump(buff, NULL, s, 0);
                }
-               report_failure(test_extra);
+               finish_failure(test_extra);
        }
        free(contents);
        return (0);
@@ -878,28 +744,20 @@ test_assert_file_hardlinks(const char *file, int line,
        count_assertion(file, line);
        r = lstat(path1, &st1);
        if (r != 0) {
-               ++failures;
-               if (!previous_failures(file, line, 1))
-                       fprintf(stderr, "%s:%d: File ``%s'' should exist\n",
-                           file, line, path1);
+               if (report_failure(file, line, "File %s should exist", path1))
+                       finish_failure(NULL);
                return (0);
        }
        r = lstat(path2, &st2);
        if (r != 0) {
-               ++failures;
-               if (!previous_failures(file, line, 1))
-                       fprintf(stderr, "%s:%d: File ``%s'' should exist\n",
-                           file, line, path2);
+               if (report_failure(file, line, "File %s should exist", path2))
+                       finish_failure(NULL);
                return (0);
        }
        if (st1.st_ino != st2.st_ino || st1.st_dev != st2.st_dev) {
-               ++failures;
-               if (!previous_failures(file, line, 1)) {
-                       fprintf(stderr,
-                               "%s:%d: Files ``%s'' and ``%s'' are not hardlinked\n",
-                           file, line, path1, path2);
-                       report_failure(NULL);
-               }
+               if (report_failure(file, line,
+                       "Files %s and %s are not hardlinked", path1, path2))
+                       finish_failure(NULL);
                return (0);
        }
        return (1);
@@ -916,12 +774,9 @@ test_assert_file_nlinks(const char *file, int line,
        r = lstat(pathname, &st);
        if (r == 0 && st.st_nlink == nlinks)
                        return (1);
-       ++failures;
-       if (!previous_failures(file, line, 1)) {
-               fprintf(stderr, "%s:%d: File ``%s'' has %d links, expected %d\n",
-                   file, line, pathname, st.st_nlink, nlinks);
-               report_failure(NULL);
-       }
+       if (report_failure(file, line, "File %s has %d links, expected %d",
+               pathname, st.st_nlink, nlinks))
+               finish_failure(NULL);
        return (0);
 }
 
@@ -936,12 +791,9 @@ test_assert_file_size(const char *file, int line,
        r = lstat(pathname, &st);
        if (r == 0 && st.st_size == size)
                        return (1);
-       ++failures;
-       if (!previous_failures(file, line, 1)) {
-               fprintf(stderr, "%s:%d: File ``%s'' has size %ld, expected %ld\n",
-                   file, line, pathname, (long)st.st_size, (long)size);
-               report_failure(NULL);
-       }
+       if (report_failure(file, line, "File %s has size %ld, expected %ld",
+               pathname, (long)st.st_size, (long)size))
+               finish_failure(NULL);
        return (0);
 }
 
@@ -953,31 +805,26 @@ test_assert_is_dir(const char *file, int line, const char *pathname, int mode)
 
        count_assertion(file, line);
        r = lstat(pathname, &st);
-       if (r != 0 || !S_ISDIR(st.st_mode)) {
-               ++failures;
-               if (!previous_failures(file, line, 1)) {
-                       fprintf(stderr, "%s:%d: Dir ``%s'' doesn't exist\n",
-                           file, line, pathname);
-                       report_failure(NULL);
-               }
+       if (r != 0) {
+               if (report_failure(file, line, "Dir %s doesn't exist", pathname))
+                       finish_failure(NULL);
                return (0);
        }
-       if (mode < 0) {
-               msg[0] = '\0';
-               return (1);
+       if (!S_ISDIR(st.st_mode)) {
+               if (report_failure(file, line, "%s is not a dir", pathname))
+                       finish_failure(NULL);
+               return (0);
        }
+       if (mode < 0)
+               return (1);
        if (mode != (st.st_mode & 07777)) {
-               ++failures;
-               if (!previous_failures(file, line, 1)) {
-                       fprintf(stderr, "%s:%d: Dir ``%s'' has wrong mode\n",
-                           file, line, pathname);
+               if (report_failure(file, line, "Dir %s has wrong mode", pathname)) {
                        fprintf(stderr, "  Expected: 0%3o\n", mode);
                        fprintf(stderr, "  Found: 0%3o\n", st.st_mode & 07777);
-                       report_failure(NULL);
+                       finish_failure(NULL);
                }
                return (0);
        }
-       msg[0] = '\0';
        return (1);
 }
 
@@ -986,13 +833,10 @@ test_assert_is_symlink(const char *file, int line,
     const char *pathname, const char *contents)
 {
 #if defined(_WIN32) && !defined(__CYGWIN__)
+       count_assertion(file, line);
        // TODO: Vista supports symlinks
-       ++failures;
-       if (!previous_failures(file, line, 1)) {
-               fprintf(stderr, "%s:%d: Symlink ``%s'' not supported\n",
-                       file, line, pathname);
-               report_failure(NULL);
-       }
+       if (report_failure(file, line, "Symlink %s not supported", pathname))
+               finish_failure(NULL);
        return (0);
 #else
        char buff[300];
@@ -1003,44 +847,29 @@ test_assert_is_symlink(const char *file, int line,
        count_assertion(file, line);
        r = lstat(pathname, &st);
        if (r != 0) {
-               ++failures;
-               if (!previous_failures(file, line, 1)) {
-                       fprintf(stderr, "%s:%d: Symlink ``%s'' doesn't exist\n",
-                           file, line, pathname);
-                       report_failure(NULL);
-               }
+               if (report_failure(file, line, "Symlink %s doesn't exist", pathname))
+                       finish_failure(NULL);
                return (0);
        }
        if (!S_ISLNK(st.st_mode)) {
-               ++failures;
-               if (!previous_failures(file, line, 1)) {
-                       fprintf(stderr, "%s:%d:  ``%s'' should be a symlink\n",
-                           file, line, pathname);
-                       report_failure(NULL);
-               }
+               if (report_failure(file, line, "%s should be a symlink", pathname))
+                       finish_failure(NULL);
                return (0);
        }
        if (contents == NULL)
                return (1);
        linklen = readlink(pathname, buff, sizeof(buff));
        if (linklen < 0) {
-               ++failures;
-               if (!previous_failures(file, line, 1)) {
-                       fprintf(stderr, "%s:%d: symlink ``%s'' can't be read\n",
-                           file, line, pathname);
-                       report_failure(NULL);
-               }
+               if (report_failure(file, line, "Can't read symlink %s", pathname))
+                       finish_failure(NULL);
                return (0);
        }
        buff[linklen] = '\0';
        if (strcmp(buff, contents) != 0) {
-               ++failures;
-               if (!previous_failures(file, line, 1)) {
-                       fprintf(stderr, "%s:%d: Wrong symlink ``%s''\n",
-                           file, line, pathname);
+               if (report_failure(file, line, "Wrong symlink %s", pathname)) {
                        fprintf(stderr, "   Expected: %s\n", contents);
                        fprintf(stderr, "   Found: %s\n", buff);
-                       report_failure(NULL);
+                       finish_failure(NULL);
                }
                return (0);
        }
@@ -1057,24 +886,17 @@ test_assert_is_reg(const char *file, int line, const char *pathname, int mode)
        count_assertion(file, line);
        r = lstat(pathname, &st);
        if (r != 0 || !S_ISREG(st.st_mode)) {
-               ++failures;
-               if (!previous_failures(file, line, 1)) {
-                       fprintf(stderr, "%s:%d: File ``%s'' doesn't exist\n",
-                           file, line, pathname);
-                       report_failure(NULL);
-               }
+               if (report_failure(file, line, "File %s doesn't exist", pathname))
+                       finish_failure(NULL);
                return (0);
        }
        if (mode < 0)
                return (1);
        if (mode != (st.st_mode & 07777)) {
-               ++failures;
-               if (!previous_failures(file, line, 1)) {
-                       fprintf(stderr, "%s:%d: Dir ``%s'' has wrong mode\n",
-                           file, line, pathname);
+               if (report_failure(file, line, "File %s has wrong mode", pathname)) {
                        fprintf(stderr, "  Expected: 0%3o\n", mode);
                        fprintf(stderr, "  Found: 0%3o\n", st.st_mode & 07777);
-                       report_failure(NULL);
+                       finish_failure(NULL);
                }
                return (0);
        }
@@ -1084,51 +906,87 @@ test_assert_is_reg(const char *file, int line, const char *pathname, int mode)
 int
 test_assert_make_dir(const char *file, int line, const char *dirname, int mode)
 {
-       int r;
-
        count_assertion(file, line);
 #if defined(_WIN32) && !defined(__CYGWIN__)
-       r = _mkdir(dirname);
+       if (0 == _mkdir(dirname))
+               return (1);
 #else
-       r = mkdir(dirname, mode);
-#endif
-       if (r == 0) {
-               msg[0] = '\0';
+       if (0 == mkdir(dirname, mode))
                return (1);
+#endif
+       if (report_failure(file, line, "Could not create directory %s", dirname))
+               finish_failure(NULL);
+       return(0);
+}
+
+int
+test_assert_make_file(const char *file, int line,
+    const char *path, int mode, const char *contents)
+{
+#if defined(_WIN32) && !defined(__CYGWIN__)
+       /* TODO: Rework this to set file mode as well. */
+       FILE *f;
+       count_assertion(file, line);
+       f = fopen(path, "wb");
+       if (f == NULL) {
+               if (report_failure(file, line, "Could not create file %s", path))
+                       finish_failure(NULL);
+               return (0);
        }
-       ++failures;
-       if (!verbose && previous_failures(file, line, 1))
+       if (contents != NULL) {
+               if (strlen(contents)
+                   != fwrite(contents, 1, strlen(contents), f)) {
+                       fclose(f);
+                       if (report_failure(file, line, "Could not write file %s", path))
+                               finish_failure(NULL);
+                       return (0);
+               }
+       }
+       fclose(f);
+       return (1);
+#else
+       int fd;
+       count_assertion(file, line);
+       fd = open(path, O_CREAT | O_WRONLY, mode >= 0 ? mode : 0644);
+       if (fd < 0) {
+               if (report_failure(file, line, "Could not create %s", path))
+                       finish_failure(NULL);
                return (0);
-       fprintf(stderr, "%s:%d: Could not create directory\n",
-               file, line);
-       fprintf(stderr, "     Dirname: %s\n", dirname);
-       return(0);
+       }
+       if (contents != NULL) {
+               if ((ssize_t)strlen(contents)
+                   != write(fd, contents, strlen(contents))) {
+                       close(fd);
+                       if (report_failure(file, line, "Could not write to %s", path))
+                               finish_failure(NULL);
+                       return (0);
+               }
+       }
+       close(fd);
+       return (1);
+#endif
 }
 
 int
 test_assert_make_hardlink(const char *file, int line,
-                                                 const char *newpath, const char *linkto)
+    const char *newpath, const char *linkto)
 {
        int succeeded;
 
        count_assertion(file, line);
-#if defined(_WIN32) && !defined(__CYGWIN__)
-       succeeded = __CreateHardLinkA(newpath, linkto);
+#if HAVE_CREATEHARDLINK
+       succeeded = CreateHardLink(newpath, linkto, NULL);
 #elif HAVE_LINK
        succeeded = !link(linkto, newpath);
 #else
        succeeded = 0;
 #endif
-       if (succeeded) {
-               msg[0] = '\0';
+       if (succeeded)
                return (1);
-       }
-       ++failures;
-       if (verbose || !previous_failures(file, line, 1)) {
-               fprintf(stderr, "%s:%d: Could not create new hardlink\n",
-                       file, line);
+       if (report_failure(file, line, "Could not create hardlink")) {
                fprintf(stderr, "   New link: %s\n", newpath);
                fprintf(stderr, "   Old name: %s\n", linkto);
+               finish_failure(NULL);
        }
        return(0);
 }
@@ -1138,28 +996,20 @@ int
 test_assert_make_symlink(const char *file, int line,
     const char *newpath, const char *linkto)
 {
-       int succeeded;
-
-#if defined(_WIN32) && !defined(__CYGWIN__)
-       int targetIsDir = 0;
+#if HAVE_CREATESYMBOLICLINK
+       int targetIsDir = 0; /* TODO: Fix this. */
        count_assertion(file, line);
-       succeeded = __CreateSymbolicLinkA(newpath, linkto, targetIsDir);
+       if (CreateSymbolicLink(newpath, linkto, targetIsDir))
+               return (1);
 #elif HAVE_SYMLINK
        count_assertion(file, line);
-       succeeded = !symlink(linkto, newpath);
-#else
-       succeeded = 0;
-#endif
-       if (succeeded) {
-               msg[0] = '\0';
+       if (0 == symlink(linkto, newpath))
                return (1);
-       }
-       ++failures;
-       if (verbose || !previous_failures(file, line, 1)) {
-               fprintf(stderr, "%s:%d: Could not create new symlink\n",
-                       file, line);
+#endif
+       if (report_failure(file, line, "Could not create symlink")) {
                fprintf(stderr, "   New link: %s\n", newpath);
                fprintf(stderr, "   Old name: %s\n", linkto);
+               finish_failure(NULL);
        }
        return(0);
 }
@@ -1174,6 +1024,17 @@ test_assert_umask(const char *file, int line, int mask)
        return (1);
 }
 
+void
+sleepUntilAfter(time_t t)
+{
+       while (t >= time(NULL))
+#if defined(_WIN32) && !defined(__CYGWIN__)
+               Sleep(500);
+#else
+               sleep(1);
+#endif
+}
+
 /*
  * Call standard system() call, but build up the command line using
  * sprintf() conventions.
index 74104a10fa1d81306e997533ae8119f980cfa299..a633591767a97c02fba1231f042fdb9064c02f8f 100644 (file)
@@ -80,6 +80,7 @@
  * the mainline code.
  */
 
+/* Windows (including Visual Studio and MinGW but not Cygwin) */
 #if defined(_WIN32) && !defined(__CYGWIN__)
 #define strdup _strdup
 #define LOCALE_DE      "deu"
 #define LOCALE_DE      "de_DE.UTF-8"
 #endif
 
+/* Visual Studio */
 #ifdef _MSC_VER
 #define snprintf       sprintf_s
 #endif
 
+/* Cygwin */
 #if defined(__CYGWIN__)
 /* Cygwin-1.7.x is lazy about populating nlinks, so don't
  * expect it to be accurate. */
 # define NLINKS_INACCURATE_FOR_DIRS
 #endif
 
+/* FreeBSD */
 #ifdef __FreeBSD__
 #include <sys/cdefs.h>  /* For __FBSDID */
 #else
-/* Some non-FreeBSD platforms such as newlib-derived ones like
- * cygwin, have __FBSDID, so this definition must be guarded.
- */
+/* Surprisingly, some non-FreeBSD platforms define __FBSDID. */
 #ifndef __FBSDID
 #define        __FBSDID(a)     struct _undefined_hack
 #endif
 
 /* An implementation of the standard assert() macro */
 #define assert(e)   test_assert(__FILE__, __LINE__, (e), #e, NULL)
-
+/* chdir() and error if it fails */
 #define assertChdir(path)      \
        test_assert_chdir(__FILE__, __LINE__, path)
 /* Assert two integers are the same.  Reports value of each one if not. */
 #define assertEqualInt(v1,v2)   \
   test_assert_equal_int(__FILE__, __LINE__, (v1), #v1, (v2), #v2, NULL)
-
 /* Assert two strings are the same.  Reports value of each one if not. */
 #define assertEqualString(v1,v2)   \
   test_assert_equal_string(__FILE__, __LINE__, (v1), #v1, (v2), #v2, NULL)
 /* Create a directory, report error if it fails. */
 #define assertMakeDir(dirname, mode)   \
   test_assert_make_dir(__FILE__, __LINE__, dirname, mode)
+#define assertMakeFile(path, mode, contents) \
+  test_assert_make_file(__FILE__, __LINE__, path, mode, contents)
 #define assertMakeHardlink(newfile, oldfile)   \
   test_assert_make_hardlink(__FILE__, __LINE__, newfile, oldfile)
 #define assertMakeSymlink(newfile, linkto)     \
 
 /* Function declarations.  These are defined in test_utility.c. */
 void failure(const char *fmt, ...);
-void test_setup(const char *, int);
-void test_skipping(const char *fmt, ...);
 int test_assert(const char *, int, int, const char *, void *);
 int test_assert_chdir(const char *, int, const char *);
 int test_assert_empty_file(const char *, ...);
-int test_assert_non_empty_file(const char *, ...);
 int test_assert_equal_file(const char *, const char *, ...);
 int test_assert_equal_int(const char *, int, long long, const char *, long long, const char *, void *);
+int test_assert_equal_mem(const char *, int, const void *, const char *, const void *, const char *, size_t, const char *, void *);
 int test_assert_equal_string(const char *, int, const char *v1, const char *, const char *v2, const char *, void *);
 int test_assert_equal_wstring(const char *, int, const wchar_t *v1, const char *, const wchar_t *v2, const char *, void *);
-int test_assert_equal_mem(const char *, int, const void *, const char *, const void *, const char *, size_t, const char *, void *);
 int test_assert_file_contents(const void *, int, const char *, ...);
-int test_assert_text_file_contents(const char *buff, const char *f);
 int test_assert_file_exists(const char *, ...);
 int test_assert_file_hardlinks(const char *, int, const char *, const char *);
-int test_assert_file_not_exists(const char *, ...);
 int test_assert_file_nlinks(const char *, int, const char *, int);
+int test_assert_file_not_exists(const char *, ...);
 int test_assert_file_size(const char *, int, const char *, long);
 int test_assert_is_dir(const char *, int, const char *, int);
 int test_assert_is_reg(const char *, int, const char *, int);
 int test_assert_is_symlink(const char *, int, const char *, const char *);
 int test_assert_make_dir(const char *, int, const char *, int);
+int test_assert_make_file(const char *, int, const char *, int, const char *);
 int test_assert_make_hardlink(const char *, int, const char *newpath, const char *);
 int test_assert_make_symlink(const char *, int, const char *newpath, const char *);
+int test_assert_non_empty_file(const char *, ...);
+int test_assert_text_file_contents(const char *buff, const char *f);
 int test_assert_umask(const char *, int, int);
+void test_setup(const char *, int);
+void test_skipping(const char *fmt, ...);
 
 /* Like sprintf, then system() */
 int systemf(const char * fmt, ...);
 
+/* Delay until time() returns a value after this. */
+void sleepUntilAfter(time_t);
+
 /* Suck file into string allocated via malloc(). Call free() when done. */
 /* Supports printf-style args: slurpfile(NULL, "%s/myfile", refdir); */
 char *slurpfile(size_t *, const char *fmt, ...);
index ea52a336a8df0a59f946855f754dc2d8c2d07700..b48fae0c24520b5ccbdb97380ed73f3c0c4a5caa 100644 (file)
@@ -206,7 +206,7 @@ DEFINE_TEST(test_acl_freebsd)
        acl = acl_from_text("u::rwx,u:1:rw,g::rwx,g:15:rx,o::rwx,m::rwx");
        assert((void *)acl != NULL);
        /* Create a test file and try to set an ACL on it. */
-       fd = open("pretest", O_WRONLY | O_CREAT | O_EXCL | O_BINARY, 0777);
+       fd = open("pretest", O_WRONLY | O_CREAT | O_EXCL, 0777);
        failure("Could not create test file?!");
        if (!assert(fd >= 0)) {
                acl_free(acl);
index 3814230ea617ec9399a3c47e8bcb37bd56a97524..8b8cc7e6eac2c6a4637f501fa4cc2a08f79d088b 100644 (file)
@@ -56,7 +56,7 @@ DEFINE_TEST(test_extattr_freebsd)
         * doesn't, we'll simply skip the remaining tests.
         */
        /* Create a test file and try to set an ACL on it. */
-       fd = open("pretest", O_RDWR | O_CREAT | O_BINARY, 0777);
+       fd = open("pretest", O_RDWR | O_CREAT, 0777);
        failure("Could not create test file?!");
        if (!assert(fd >= 0))
                return;
@@ -78,7 +78,7 @@ DEFINE_TEST(test_extattr_freebsd)
         * permissions, not file permissions), but is known broken on
         * some versions of FreeBSD.
         */
-       fd = open("pretest2", O_RDWR | O_CREAT | O_BINARY, 00000);
+       fd = open("pretest2", O_RDWR | O_CREAT, 00000);
        failure("Could not create test file?!");
        if (!assert(fd >= 0))
                return;
index 3a1b7abd9b676de2bd9acb2a82255b2ff7346082..dfa35a8b125f081b6d637bd5718c15fdc268f5c9 100644 (file)
@@ -50,7 +50,6 @@
 #define S_ISREG(m)  ((m) & _S_IFREG)
 #endif
 #define access _access
-#undef chdir
 #define chdir _chdir
 #ifndef fileno
 #define fileno _fileno
@@ -91,12 +90,6 @@ __FBSDID("$FreeBSD: src/usr.bin/tar/test/main.c,v 1.6 2008/11/05 06:40:53 kientz
 #define        DEFINE_TEST(name) void name(void);
 #include "list.h"
 
-/* Interix doesn't define these in a standard header. */
-#if __INTERIX__
-extern char *optarg;
-extern int optind;
-#endif
-
 /* Enable core dump on failure. */
 static int dump_on_failure = 0;
 /* Default is to remove temp dirs for successful tests. */
@@ -141,7 +134,8 @@ invalid_parameter_handler(const wchar_t * expression,
  *          printed if the following assertion fails, good for
  *          explaining subtle tests.
  */
-static char msg[4096];
+static char msgbuff[4096];
+static const char *msg, *nextmsg;
 
 /*
  * For each test source file, we remember how many times each
@@ -149,10 +143,9 @@ static char msg[4096];
  */
 static const char *failed_filename = NULL;
 static struct line {
-       int line;
        int count;
-       int critical;
-}  failed_lines[1000];
+       int skip;
+}  failed_lines[10000];
 
 /*
  * Called at the beginning of each assert() function.
@@ -163,40 +156,61 @@ count_assertion(const char *file, int line)
        (void)file; /* UNUSED */
        (void)line; /* UNUSED */
        ++assertions;
+       msg = nextmsg;
+       nextmsg = NULL;
        /* Uncomment to print file:line after every assertion.
         * Verbose, but occasionally useful in tracking down crashes. */
        /* printf("Checked %s:%d\n", file, line); */
 }
 
 /*
- * Count this failure; return the number of previous failures.
+ * Count this failure; return true if this failure is being reported.
  */
 static int
-previous_failures(const char *filename, int line, int critical)
+report_failure(const char *filename, int line, const char *fmt, ...)
 {
-       unsigned int i;
-       int count;
+       ++failures;
 
+       /* If this is a new file, clear the counts. */
        if (failed_filename == NULL || strcmp(failed_filename, filename) != 0)
                memset(failed_lines, 0, sizeof(failed_lines));
        failed_filename = filename;
 
-       for (i = 0; i < sizeof(failed_lines)/sizeof(failed_lines[0]); i++) {
-               if (failed_lines[i].line == line) {
-                       count = failed_lines[i].count;
-                       failed_lines[i].count++;
-                       return (count);
-               }
-               if (failed_lines[i].line == 0) {
-                       failed_lines[i].line = line;
-                       failed_lines[i].count = 1;
-                       failed_lines[i].critical = critical;
-                       return (0);
-               }
+       /* Report first hit always, every hit if verbose. */
+       if (failed_lines[line].count++ == 0 || verbose) {
+               va_list ap;
+               va_start(ap, fmt);
+               fprintf(stderr, "%s:%d: ", filename, line);
+               vfprintf(stderr, fmt, ap);
+               va_end(ap);
+               fprintf(stderr, "\n");
+               return (1);
        }
        return (0);
 }
 
+/* Complete reporting of failed tests. */
+static void
+finish_failure(void *extra)
+{
+       if (msg != NULL && msg[0] != '\0')
+               fprintf(stderr, "   Description: %s\n", msg);
+
+#ifdef EXTRA_DUMP
+       if (extra != NULL)
+               fprintf(stderr, "   detail: %s\n", EXTRA_DUMP(extra));
+#else
+       (void)extra; /* UNUSED */
+#endif
+
+       if (dump_on_failure) {
+               fprintf(stderr,
+                   " *** forcing core dump so failure can be debugged ***\n");
+               *(char *)(NULL) = 0;
+               exit(1);
+       }
+}
+
 /*
  * Copy arguments into file-local variables.
  */
@@ -217,39 +231,17 @@ test_skipping(const char *fmt, ...)
 {
        va_list ap;
 
-       if (previous_failures(test_filename, test_line, 0))
-               return;
-
-       va_start(ap, fmt);
-       fprintf(stderr, " *** SKIPPING: ");
-       vfprintf(stderr, fmt, ap);
-       fprintf(stderr, "\n");
-       va_end(ap);
-       ++skips;
-}
-
-/* Common handling of failed tests. */
-static void
-report_failure(void *extra)
-{
-       if (msg[0] != '\0') {
-               fprintf(stderr, "   Description: %s\n", msg);
-               msg[0] = '\0';
-       }
-
-#ifdef EXTRA_DUMP
-       if (extra != NULL)
-               fprintf(stderr, "   detail: %s\n", EXTRA_DUMP(extra));
-#else
-       (void)extra; /* UNUSED */
-#endif
-
-       if (dump_on_failure) {
-               fprintf(stderr,
-                   " *** forcing core dump so failure can be debugged ***\n");
-               *(char *)(NULL) = 0;
-               exit(1);
+       if (report_failure(test_filename, test_line, "SKIPPING" )) {
+               va_start(ap,fmt);
+               fprintf(stderr, "      Reason: ");
+               vfprintf(stderr, fmt, ap);
+               fprintf(stderr, "\n");
+               /* Don't finish_failure() here. */
        }
+       /* Mark as skip, so doesn't count as failed test. */
+       failed_lines[test_line].skip = 1;
+       ++skips;
+       --failures;
 }
 
 /*
@@ -257,33 +249,17 @@ report_failure(void *extra)
  * The reports above suppress multiple failures from the same source
  * line; this reports on any tests that did fail multiple times.
  */
-static int
-summarize_comparator(const void *a0, const void *b0)
-{
-       const struct line *a = a0, *b = b0;
-       if (a->line == 0 && b->line == 0)
-               return (0);
-       if (a->line == 0)
-               return (1);
-       if (b->line == 0)
-               return (-1);
-       return (a->line - b->line);
-}
-
 static void
 summarize(void)
 {
        unsigned int i;
 
-       qsort(failed_lines, sizeof(failed_lines)/sizeof(failed_lines[0]),
-           sizeof(failed_lines[0]), summarize_comparator);
        for (i = 0; i < sizeof(failed_lines)/sizeof(failed_lines[0]); i++) {
-               if (failed_lines[i].line == 0)
+               if (failed_lines[i].count == 0)
                        break;
-               if (failed_lines[i].count > 1 && failed_lines[i].critical)
+               if (failed_lines[i].count > 1 && !failed_lines[i].skip)
                        fprintf(stderr, "%s:%d: Failed %d times\n",
-                           failed_filename, failed_lines[i].line,
-                           failed_lines[i].count);
+                           failed_filename, i, failed_lines[i].count);
        }
        /* Clear the failure history for the next file. */
        memset(failed_lines, 0, sizeof(failed_lines));
@@ -295,25 +271,22 @@ failure(const char *fmt, ...)
 {
        va_list ap;
        va_start(ap, fmt);
-       vsprintf(msg, fmt, ap);
+       vsprintf(msgbuff, fmt, ap);
        va_end(ap);
+       nextmsg = msgbuff;
 }
 
 /* Generic assert() just displays the failed condition. */
 int
-test_assert(const char *file, int line, int value, const char *condition, void *extra)
+test_assert(const char *file, int line, int value,
+    const char *condition, void *extra)
 {
        count_assertion(file, line);
-       if (value) {
-               msg[0] = '\0';
+       if (value)
                return (value);
+       if (report_failure(file, line, "Assertion failed: %s", condition)) {
+               finish_failure(extra);
        }
-       ++failures;
-       if (!verbose && previous_failures(file, line, 1))
-               return (value);
-       fprintf(stderr, "%s:%d: Assertion failed\n", file, line);
-       fprintf(stderr, "   Condition: %s\n", condition);
-       report_failure(extra);
        return (value);
 }
 
@@ -323,11 +296,9 @@ test_assert_chdir(const char *file, int line, const char *pathname)
        count_assertion(file, line);
        if (chdir(pathname) == 0)
                return (1);
-       ++failures;
-       if (!verbose && previous_failures(file, line, 1))
-               return (0);
-       fprintf(stderr, "%s:%d: chdir(\"%s\") failed\n",
-               file, line, pathname);
+       if (report_failure(file, line, "chdir(\"%s\")", pathname)) {
+               finish_failure(NULL);
+       }
        return (0);
 
 }
@@ -338,23 +309,19 @@ test_assert_equal_int(const char *file, int line,
     long long v1, const char *e1, long long v2, const char *e2, void *extra)
 {
        count_assertion(file, line);
-       if (v1 == v2) {
-               msg[0] = '\0';
+       if (v1 == v2)
                return (1);
+       if (report_failure(file, line, "Ints not equal")) {
+               fprintf(stderr, "      %s=%lld\n", e1, v1);
+               fprintf(stderr, "      %s=%lld\n", e2, v2);
+               finish_failure(extra);
        }
-       ++failures;
-       if (!verbose && previous_failures(file, line, 1))
-               return (0);
-       fprintf(stderr, "%s:%d: Assertion failed: Ints not equal\n",
-           file, line);
-       fprintf(stderr, "      %s=%lld\n", e1, v1);
-       fprintf(stderr, "      %s=%lld\n", e2, v2);
-       report_failure(extra);
        return (0);
 }
 
-static void strdump(const char *p)
+static void strdump(const char *e, const char *p)
 {
+       fprintf(stderr, "      %s = ", e);
        if (p == NULL) {
                fprintf(stderr, "(null)");
                return;
@@ -375,6 +342,7 @@ static void strdump(const char *p)
                }
        }
        fprintf(stderr, "\"");
+       fprintf(stderr, " (length %d)\n", p == NULL ? 0 : (int)strlen(p));
 }
 
 /* assertEqualString() displays the values of the two strings. */
@@ -385,32 +353,21 @@ test_assert_equal_string(const char *file, int line,
     void *extra)
 {
        count_assertion(file, line);
-       if (v1 == NULL || v2 == NULL) {
-               if (v1 == v2) {
-                       msg[0] = '\0';
-                       return (1);
-               }
-       } else if (strcmp(v1, v2) == 0) {
-               msg[0] = '\0';
+       if (v1 == v2)
                return (1);
+       else if (strcmp(v1, v2) == 0)
+               return (1);
+       if (report_failure(file, line, "Strings not equal")) {
+               strdump(e1, v1);
+               strdump(e2, v2);
+               finish_failure(extra);
        }
-       ++failures;
-       if (!verbose && previous_failures(file, line, 1))
-               return (0);
-       fprintf(stderr, "%s:%d: Assertion failed: Strings not equal\n",
-           file, line);
-       fprintf(stderr, "      %s = ", e1);
-       strdump(v1);
-       fprintf(stderr, " (length %d)\n", v1 == NULL ? 0 : (int)strlen(v1));
-       fprintf(stderr, "      %s = ", e2);
-       strdump(v2);
-       fprintf(stderr, " (length %d)\n", v2 == NULL ? 0 : (int)strlen(v2));
-       report_failure(extra);
        return (0);
 }
 
-static void wcsdump(const wchar_t *w)
+static void wcsdump(const char *e, const wchar_t *w)
 {
+       fprintf(stderr, "      %s = ", e);
        if (w == NULL) {
                fprintf(stderr, "(null)");
                return;
@@ -427,7 +384,7 @@ static void wcsdump(const wchar_t *w)
                else
                        fprintf(stderr, "\\U%08X", c);
        }
-       fprintf(stderr, "\"");
+       fprintf(stderr, "\"\n");
 }
 
 /* assertEqualWString() displays the values of the two strings. */
@@ -438,32 +395,15 @@ test_assert_equal_wstring(const char *file, int line,
     void *extra)
 {
        count_assertion(file, line);
-       if (v1 == NULL) {
-               if (v2 == NULL) {
-                       msg[0] = '\0';
-                       return (1);
-               }
-       } else if (v2 == NULL) {
-               if (v1 == NULL) {
-                       msg[0] = '\0';
-                       return (1);
-               }
-       } else if (wcscmp(v1, v2) == 0) {
-               msg[0] = '\0';
+       if (v1 == v2)
                return (1);
+       else if (wcscmp(v1, v2) == 0)
+               return (1);
+       if (report_failure(file, line, "Unicode strings not equal")) {
+               wcsdump(e1, v1);
+               wcsdump(e2, v2);
+               finish_failure(extra);
        }
-       ++failures;
-       if (!verbose && previous_failures(file, line, 1))
-               return (0);
-       fprintf(stderr, "%s:%d: Assertion failed: Unicode strings not equal\n",
-           file, line);
-       fprintf(stderr, "      %s = ", e1);
-       wcsdump(v1);
-       fprintf(stderr, "\n");
-       fprintf(stderr, "      %s = ", e2);
-       wcsdump(v2);
-       fprintf(stderr, "\n");
-       report_failure(extra);
        return (0);
 }
 
@@ -516,37 +456,29 @@ test_assert_equal_mem(const char *file, int line,
        size_t offset;
 
        count_assertion(file, line);
-       if (v1 == NULL || v2 == NULL) {
-               if (v1 == v2) {
-                       msg[0] = '\0';
-                       return (1);
-               }
-       } else if (memcmp(v1, v2, l) == 0) {
-               msg[0] = '\0';
+       if (v1 == v2)
+               return (1);
+       else if (memcmp(v1, v2, l) == 0)
                return (1);
+       if (report_failure(file, line, "Memory not equal")) {
+               fprintf(stderr, "      size %s = %d\n", ld, (int)l);
+               /* Dump 48 bytes (3 lines) so that the first difference is
+                * in the second line. */
+               offset = 0;
+               while (l > 64 && memcmp(v1, v2, 32) == 0) {
+                       /* Two lines agree, so step forward one line. */
+                       v1 += 16;
+                       v2 += 16;
+                       l -= 16;
+                       offset += 16;
+               }
+               fprintf(stderr, "      Dump of %s\n", e1);
+               hexdump(v1, v2, l < 64 ? l : 64, offset);
+               fprintf(stderr, "      Dump of %s\n", e2);
+               hexdump(v2, v1, l < 64 ? l : 64, offset);
+               fprintf(stderr, "\n");
+               finish_failure(extra);
        }
-       ++failures;
-       if (!verbose && previous_failures(file, line, 1))
-               return (0);
-       fprintf(stderr, "%s:%d: Assertion failed: memory not equal\n",
-           file, line);
-       fprintf(stderr, "      size %s = %d\n", ld, (int)l);
-       /* Dump 48 bytes (3 lines) so that the first difference is
-        * in the second line. */
-       offset = 0;
-       while (l > 64 && memcmp(v1, v2, 32) == 0) {
-               /* The first two lines agree, so step forward one line. */
-               v1 += 16;
-               v2 += 16;
-               l -= 16;
-               offset += 16;
-       }
-       fprintf(stderr, "      Dump of %s\n", e1);
-       hexdump(v1, v2, l < 64 ? l : 64, offset);
-       fprintf(stderr, "      Dump of %s\n", e2);
-       hexdump(v2, v1, l < 64 ? l : 64, offset);
-       fprintf(stderr, "\n");
-       report_failure(extra);
        return (0);
 }
 
@@ -560,37 +492,35 @@ test_assert_empty_file(const char *f1fmt, ...)
        ssize_t s;
        FILE *f;
 
-
+       count_assertion(test_filename, test_line);
        va_start(ap, f1fmt);
        vsprintf(f1, f1fmt, ap);
        va_end(ap);
 
        if (stat(f1, &st) != 0) {
-               fprintf(stderr, "%s:%d: Could not stat: %s\n", test_filename, test_line, f1);
-               report_failure(NULL);
+               if (report_failure(test_filename, test_line, "Stat failed: %s", f1)) {
+                       finish_failure(NULL);
+               }
                return (0);
        }
        if (st.st_size == 0)
                return (1);
 
-       ++failures;
-       if (!verbose && previous_failures(test_filename, test_line, 1))
-               return (0);
-
-       fprintf(stderr, "%s:%d: File not empty: %s\n", test_filename, test_line, f1);
-       fprintf(stderr, "    File size: %d\n", (int)st.st_size);
-       fprintf(stderr, "    Contents:\n");
-       f = fopen(f1, "rb");
-       if (f == NULL) {
-               fprintf(stderr, "    Unable to open %s\n", f1);
-       } else {
-               s = ((off_t)sizeof(buff) < st.st_size) ?
-                   (ssize_t)sizeof(buff) : (ssize_t)st.st_size;
-               s = fread(buff, 1, s, f);
-               hexdump(buff, NULL, s, 0);
-               fclose(f);
+       if (report_failure(test_filename, test_line, "%s not empty", f1)) {
+               fprintf(stderr, "    File size: %d\n", (int)st.st_size);
+               fprintf(stderr, "    Contents:\n");
+               f = fopen(f1, "rb");
+               if (f == NULL) {
+                       fprintf(stderr, "    Unable to open %s\n", f1);
+               } else {
+                       s = ((off_t)sizeof(buff) < st.st_size) ?
+                           (ssize_t)sizeof(buff) : (ssize_t)st.st_size;
+                       s = fread(buff, 1, s, f);
+                       hexdump(buff, NULL, s, 0);
+                       fclose(f);
+               }
+               finish_failure(NULL);
        }
-       report_failure(NULL);
        return (0);
 }
 
@@ -601,28 +531,20 @@ test_assert_non_empty_file(const char *f1fmt, ...)
        struct stat st;
        va_list ap;
 
-
+       count_assertion(test_filename, test_line);
        va_start(ap, f1fmt);
        vsprintf(f1, f1fmt, ap);
        va_end(ap);
 
        if (stat(f1, &st) != 0) {
-               fprintf(stderr, "%s:%d: Could not stat: %s\n",
-                   test_filename, test_line, f1);
-               report_failure(NULL);
-               ++failures;
+               if (report_failure(test_filename, test_line, "Stat failed: %s", f1))
+                       finish_failure(NULL);
                return (0);
        }
        if (st.st_size != 0)
                return (1);
-
-       ++failures;
-       if (!verbose && previous_failures(test_filename, test_line, 1))
-               return (0);
-
-       fprintf(stderr, "%s:%d: File empty: %s\n",
-           test_filename, test_line, f1);
-       report_failure(NULL);
+       if (report_failure(test_filename, test_line, "File empty: %s", f1))
+               finish_failure(NULL);
        return (0);
 }
 
@@ -638,6 +560,7 @@ test_assert_equal_file(const char *fn1, const char *f2pattern, ...)
        FILE *f1, *f2;
        int n1, n2;
 
+       count_assertion(test_filename, test_line);
        va_start(ap, f2pattern);
        vsprintf(fn2, f2pattern, ap);
        va_end(ap);
@@ -659,14 +582,11 @@ test_assert_equal_file(const char *fn1, const char *f2pattern, ...)
        }
        fclose(f1);
        fclose(f2);
-       ++failures;
-       if (!verbose && previous_failures(test_filename, test_line, 1))
-               return (0);
-       fprintf(stderr, "%s:%d: Files are not identical\n",
-           test_filename, test_line);
-       fprintf(stderr, "  file1=\"%s\"\n", fn1);
-       fprintf(stderr, "  file2=\"%s\"\n", fn2);
-       report_failure(test_extra);
+       if (report_failure(test_filename, test_line, "Files not identical")) {
+               fprintf(stderr, "  file1=\"%s\"\n", fn1);
+               fprintf(stderr, "  file2=\"%s\"\n", fn2);
+               finish_failure(test_extra);
+       }
        return (0);
 }
 
@@ -688,12 +608,9 @@ test_assert_file_exists(const char *fpattern, ...)
        if (!access(f, F_OK))
                return (1);
 #endif
-       ++failures;
-       if (!previous_failures(test_filename, test_line, 1)) {
-               fprintf(stderr, "%s:%d: File doesn't exist\n",
-                   test_filename, test_line);
+       if (report_failure(test_filename, test_line, "File doesn't exist")) {
                fprintf(stderr, "  file=\"%s\"\n", f);
-               report_failure(test_extra);
+               finish_failure(test_extra);
        }
        return (0);
 }
@@ -716,12 +633,9 @@ test_assert_file_not_exists(const char *fpattern, ...)
        if (access(f, F_OK))
                return (1);
 #endif
-       ++failures;
-       if (!previous_failures(test_filename, test_line, 1)) {
-               fprintf(stderr, "%s:%d: File exists and shouldn't\n",
-                   test_filename, test_line);
+       if (report_failure(test_filename, test_line, "File exists")) {
                fprintf(stderr, "  file=\"%s\"\n", f);
-               report_failure(test_extra);
+               finish_failure(test_extra);
        }
        return (0);
 }
@@ -743,11 +657,8 @@ test_assert_file_contents(const void *buff, int s, const char *fpattern, ...)
 
        f = fopen(fn, "rb");
        if (f == NULL) {
-               ++failures;
-               if (!previous_failures(test_filename, test_line, 1)) {
-                       fprintf(stderr, "%s:%d: File doesn't exist: %s\n",
-                           test_filename, test_line, fn);
-                       report_failure(test_extra);
+               if (report_failure(test_filename, test_line, "File doesn't exist: %s", fn)) {
+                       finish_failure(test_extra);
                }
                return (0);
        }
@@ -758,10 +669,7 @@ test_assert_file_contents(const void *buff, int s, const char *fpattern, ...)
                free(contents);
                return (1);
        }
-       ++failures;
-       if (!previous_failures(test_filename, test_line, 1)) {
-               fprintf(stderr, "%s:%d: File contents don't match\n",
-                   test_filename, test_line);
+       if (report_failure(test_filename, test_line, "File contents don't match")) {
                fprintf(stderr, "  file=\"%s\"\n", fn);
                if (n > 0)
                        hexdump(contents, buff, n > 512 ? 512 : 0, 0);
@@ -769,7 +677,7 @@ test_assert_file_contents(const void *buff, int s, const char *fpattern, ...)
                        fprintf(stderr, "  File empty, contents should be:\n");
                        hexdump(buff, NULL, s > 512 ? 512 : 0, 0);
                }
-               report_failure(test_extra);
+               finish_failure(test_extra);
        }
        free(contents);
        return (0);
@@ -813,10 +721,7 @@ test_assert_text_file_contents(const char *buff, const char *fn)
                free(contents);
                return (1);
        }
-       ++failures;
-       if (!previous_failures(test_filename, test_line, 1)) {
-               fprintf(stderr, "%s:%d: File contents don't match\n",
-                   test_filename, test_line);
+       if (report_failure(test_filename, test_line, "Contents don't match")) {
                fprintf(stderr, "  file=\"%s\"\n", fn);
                if (n > 0)
                        hexdump(contents, buff, n, 0);
@@ -824,7 +729,7 @@ test_assert_text_file_contents(const char *buff, const char *fn)
                        fprintf(stderr, "  File empty, contents should be:\n");
                        hexdump(buff, NULL, s, 0);
                }
-               report_failure(test_extra);
+               finish_failure(test_extra);
        }
        free(contents);
        return (0);
@@ -840,28 +745,20 @@ test_assert_file_hardlinks(const char *file, int line,
        count_assertion(file, line);
        r = lstat(path1, &st1);
        if (r != 0) {
-               ++failures;
-               if (!previous_failures(file, line, 1))
-                       fprintf(stderr, "%s:%d: File ``%s'' should exist\n",
-                           file, line, path1);
+               if (report_failure(file, line, "File %s should exist", path1))
+                       finish_failure(NULL);
                return (0);
        }
        r = lstat(path2, &st2);
        if (r != 0) {
-               ++failures;
-               if (!previous_failures(file, line, 1))
-                       fprintf(stderr, "%s:%d: File ``%s'' should exist\n",
-                           file, line, path2);
+               if (report_failure(file, line, "File %s should exist", path2))
+                       finish_failure(NULL);
                return (0);
        }
        if (st1.st_ino != st2.st_ino || st1.st_dev != st2.st_dev) {
-               ++failures;
-               if (!previous_failures(file, line, 1)) {
-                       fprintf(stderr,
-                               "%s:%d: Files ``%s'' and ``%s'' are not hardlinked\n",
-                           file, line, path1, path2);
-                       report_failure(NULL);
-               }
+               if (report_failure(file, line,
+                       "Files %s and %s are not hardlinked", path1, path2))
+                       finish_failure(NULL);
                return (0);
        }
        return (1);
@@ -878,12 +775,9 @@ test_assert_file_nlinks(const char *file, int line,
        r = lstat(pathname, &st);
        if (r == 0 && st.st_nlink == nlinks)
                        return (1);
-       ++failures;
-       if (!previous_failures(file, line, 1)) {
-               fprintf(stderr, "%s:%d: File ``%s'' has %d links, expected %d\n",
-                   file, line, pathname, st.st_nlink, nlinks);
-               report_failure(NULL);
-       }
+       if (report_failure(file, line, "File %s has %d links, expected %d",
+               pathname, st.st_nlink, nlinks))
+               finish_failure(NULL);
        return (0);
 }
 
@@ -898,12 +792,9 @@ test_assert_file_size(const char *file, int line,
        r = lstat(pathname, &st);
        if (r == 0 && st.st_size == size)
                        return (1);
-       ++failures;
-       if (!previous_failures(file, line, 1)) {
-               fprintf(stderr, "%s:%d: File ``%s'' has size %ld, expected %ld\n",
-                   file, line, pathname, (long)st.st_size, (long)size);
-               report_failure(NULL);
-       }
+       if (report_failure(file, line, "File %s has size %ld, expected %ld",
+               pathname, (long)st.st_size, (long)size))
+               finish_failure(NULL);
        return (0);
 }
 
@@ -916,39 +807,25 @@ test_assert_is_dir(const char *file, int line, const char *pathname, int mode)
        count_assertion(file, line);
        r = lstat(pathname, &st);
        if (r != 0) {
-               ++failures;
-               if (!previous_failures(file, line, 1)) {
-                       fprintf(stderr, "%s:%d: Dir ``%s'' doesn't exist\n",
-                           file, line, pathname);
-                       report_failure(NULL);
-               }
+               if (report_failure(file, line, "Dir %s doesn't exist", pathname))
+                       finish_failure(NULL);
                return (0);
        }
        if (!S_ISDIR(st.st_mode)) {
-               ++failures;
-               if (!previous_failures(file, line, 1)) {
-                       fprintf(stderr, "%s:%d: ``%s'' is not a dir\n",
-                           file, line, pathname);
-                       report_failure(NULL);
-               }
+               if (report_failure(file, line, "%s is not a dir", pathname))
+                       finish_failure(NULL);
                return (0);
        }
-       if (mode < 0) {
-               msg[0] = '\0';
+       if (mode < 0)
                return (1);
-       }
        if (mode != (st.st_mode & 07777)) {
-               ++failures;
-               if (!previous_failures(file, line, 1)) {
-                       fprintf(stderr, "%s:%d: Dir ``%s'' has wrong mode\n",
-                           file, line, pathname);
+               if (report_failure(file, line, "Dir %s has wrong mode", pathname)) {
                        fprintf(stderr, "  Expected: 0%3o\n", mode);
                        fprintf(stderr, "  Found: 0%3o\n", st.st_mode & 07777);
-                       report_failure(NULL);
+                       finish_failure(NULL);
                }
                return (0);
        }
-       msg[0] = '\0';
        return (1);
 }
 
@@ -957,13 +834,10 @@ test_assert_is_symlink(const char *file, int line,
     const char *pathname, const char *contents)
 {
 #if defined(_WIN32) && !defined(__CYGWIN__)
+       count_assertion(file, line);
        // TODO: Vista supports symlinks
-       ++failures;
-       if (!previous_failures(file, line, 1)) {
-               fprintf(stderr, "%s:%d: Symlink ``%s'' not supported\n",
-                       file, line, pathname);
-               report_failure(NULL);
-       }
+       if (report_failure(file, line, "Symlink %s not supported", pathname))
+               finish_failure(NULL);
        return (0);
 #else
        char buff[300];
@@ -974,44 +848,29 @@ test_assert_is_symlink(const char *file, int line,
        count_assertion(file, line);
        r = lstat(pathname, &st);
        if (r != 0) {
-               ++failures;
-               if (!previous_failures(file, line, 1)) {
-                       fprintf(stderr, "%s:%d: Symlink ``%s'' doesn't exist\n",
-                           file, line, pathname);
-                       report_failure(NULL);
-               }
+               if (report_failure(file, line, "Symlink %s doesn't exist", pathname))
+                       finish_failure(NULL);
                return (0);
        }
        if (!S_ISLNK(st.st_mode)) {
-               ++failures;
-               if (!previous_failures(file, line, 1)) {
-                       fprintf(stderr, "%s:%d:  ``%s'' should be a symlink\n",
-                           file, line, pathname);
-                       report_failure(NULL);
-               }
+               if (report_failure(file, line, "%s should be a symlink", pathname))
+                       finish_failure(NULL);
                return (0);
        }
        if (contents == NULL)
                return (1);
        linklen = readlink(pathname, buff, sizeof(buff));
        if (linklen < 0) {
-               ++failures;
-               if (!previous_failures(file, line, 1)) {
-                       fprintf(stderr, "%s:%d: symlink ``%s'' can't be read\n",
-                           file, line, pathname);
-                       report_failure(NULL);
-               }
+               if (report_failure(file, line, "Can't read symlink %s", pathname))
+                       finish_failure(NULL);
                return (0);
        }
        buff[linklen] = '\0';
        if (strcmp(buff, contents) != 0) {
-               ++failures;
-               if (!previous_failures(file, line, 1)) {
-                       fprintf(stderr, "%s:%d: Wrong symlink ``%s''\n",
-                           file, line, pathname);
+               if (report_failure(file, line, "Wrong symlink %s", pathname)) {
                        fprintf(stderr, "   Expected: %s\n", contents);
                        fprintf(stderr, "   Found: %s\n", buff);
-                       report_failure(NULL);
+                       finish_failure(NULL);
                }
                return (0);
        }
@@ -1028,24 +887,17 @@ test_assert_is_reg(const char *file, int line, const char *pathname, int mode)
        count_assertion(file, line);
        r = lstat(pathname, &st);
        if (r != 0 || !S_ISREG(st.st_mode)) {
-               ++failures;
-               if (!previous_failures(file, line, 1)) {
-                       fprintf(stderr, "%s:%d: File ``%s'' doesn't exist\n",
-                           file, line, pathname);
-                       report_failure(NULL);
-               }
+               if (report_failure(file, line, "File %s doesn't exist", pathname))
+                       finish_failure(NULL);
                return (0);
        }
        if (mode < 0)
                return (1);
        if (mode != (st.st_mode & 07777)) {
-               ++failures;
-               if (!previous_failures(file, line, 1)) {
-                       fprintf(stderr, "%s:%d: Dir ``%s'' has wrong mode\n",
-                           file, line, pathname);
+               if (report_failure(file, line, "File %s has wrong mode", pathname)) {
                        fprintf(stderr, "  Expected: 0%3o\n", mode);
                        fprintf(stderr, "  Found: 0%3o\n", st.st_mode & 07777);
-                       report_failure(NULL);
+                       finish_failure(NULL);
                }
                return (0);
        }
@@ -1055,30 +907,70 @@ test_assert_is_reg(const char *file, int line, const char *pathname, int mode)
 int
 test_assert_make_dir(const char *file, int line, const char *dirname, int mode)
 {
-       int r;
-
        count_assertion(file, line);
 #if defined(_WIN32) && !defined(__CYGWIN__)
-       r = _mkdir(dirname);
+       if (0 == _mkdir(dirname))
+               return (1);
 #else
-       r = mkdir(dirname, mode);
-#endif
-       if (r == 0) {
-               msg[0] = '\0';
+       if (0 == mkdir(dirname, mode))
                return (1);
+#endif
+       if (report_failure(file, line, "Could not create directory %s", dirname))
+               finish_failure(NULL);
+       return(0);
+}
+
+int
+test_assert_make_file(const char *file, int line,
+    const char *path, int mode, const char *contents)
+{
+#if defined(_WIN32) && !defined(__CYGWIN__)
+       /* TODO: Rework this to set file mode as well. */
+       FILE *f;
+       count_assertion(file, line);
+       f = fopen(path, "wb");
+       if (f == NULL) {
+               if (report_failure(file, line, "Could not create file %s", path))
+                       finish_failure(NULL);
+               return (0);
        }
-       ++failures;
-       if (!verbose && previous_failures(file, line, 1))
+       if (contents != NULL) {
+               if (strlen(contents)
+                   != fwrite(contents, 1, strlen(contents), f)) {
+                       fclose(f);
+                       if (report_failure(file, line, "Could not write file %s", path))
+                               finish_failure(NULL);
+                       return (0);
+               }
+       }
+       fclose(f);
+       return (1);
+#else
+       int fd;
+       count_assertion(file, line);
+       fd = open(path, O_CREAT | O_WRONLY, mode >= 0 ? mode : 0644);
+       if (fd < 0) {
+               if (report_failure(file, line, "Could not create %s", path))
+                       finish_failure(NULL);
                return (0);
-       fprintf(stderr, "%s:%d: Could not create directory\n",
-               file, line);
-       fprintf(stderr, "     Dirname: %s\n", dirname);
-       return(0);
+       }
+       if (contents != NULL) {
+               if ((ssize_t)strlen(contents)
+                   != write(fd, contents, strlen(contents))) {
+                       close(fd);
+                       if (report_failure(file, line, "Could not write to %s", path))
+                               finish_failure(NULL);
+                       return (0);
+               }
+       }
+       close(fd);
+       return (1);
+#endif
 }
 
 int
 test_assert_make_hardlink(const char *file, int line,
-                                                 const char *newpath, const char *linkto)
+    const char *newpath, const char *linkto)
 {
        int succeeded;
 
@@ -1090,16 +982,12 @@ test_assert_make_hardlink(const char *file, int line,
 #else
        succeeded = 0;
 #endif
-       if (succeeded) {
-               msg[0] = '\0';
+       if (succeeded)
                return (1);
-       }
-       ++failures;
-       if (verbose || !previous_failures(file, line, 1)) {
-               fprintf(stderr, "%s:%d: Could not create new hardlink\n",
-                       file, line);
+       if (report_failure(file, line, "Could not create hardlink")) {
                fprintf(stderr, "   New link: %s\n", newpath);
                fprintf(stderr, "   Old name: %s\n", linkto);
+               finish_failure(NULL);
        }
        return(0);
 }
@@ -1109,28 +997,20 @@ int
 test_assert_make_symlink(const char *file, int line,
     const char *newpath, const char *linkto)
 {
-       int succeeded;
-
 #if HAVE_CREATESYMBOLICLINK
        int targetIsDir = 0; /* TODO: Fix this. */
        count_assertion(file, line);
-       succeeded = CreateSymbolicLink(newpath, linkto, targetIsDir);
+       if (CreateSymbolicLink(newpath, linkto, targetIsDir))
+               return (1);
 #elif HAVE_SYMLINK
        count_assertion(file, line);
-       succeeded = !symlink(linkto, newpath);
-#else
-       succeeded = 0;
-#endif
-       if (succeeded) {
-               msg[0] = '\0';
+       if (0 == symlink(linkto, newpath))
                return (1);
-       }
-       ++failures;
-       if (verbose || !previous_failures(file, line, 1)) {
-               fprintf(stderr, "%s:%d: Could not create new symlink\n",
-                       file, line);
+#endif
+       if (report_failure(file, line, "Could not create symlink")) {
                fprintf(stderr, "   New link: %s\n", newpath);
                fprintf(stderr, "   Old name: %s\n", linkto);
+               finish_failure(NULL);
        }
        return(0);
 }
@@ -1145,6 +1025,17 @@ test_assert_umask(const char *file, int line, int mask)
        return (1);
 }
 
+void
+sleepUntilAfter(time_t t)
+{
+       while (t >= time(NULL))
+#if defined(_WIN32) && !defined(__CYGWIN__)
+               Sleep(500);
+#else
+               sleep(1);
+#endif
+}
+
 /*
  * Call standard system() call, but build up the command line using
  * sprintf() conventions.
index da44ec6837b709b04c80231d86cd65f78b0b95a0..5fbb621452dd40fa1588afd40800773fd7088b4d 100644 (file)
@@ -80,6 +80,7 @@
  * the mainline code.
  */
 
+/* Windows (including Visual Studio and MinGW but not Cygwin) */
 #if defined(_WIN32) && !defined(__CYGWIN__)
 #include "../bsdtar_windows.h"
 #define strdup _strdup
 #define LOCALE_DE      "de_DE.UTF-8"
 #endif
 
+/* Visual Studio */
 #ifdef _MSC_VER
 #define snprintf       sprintf_s
 #endif
 
+/* Cygwin */
 #if defined(__CYGWIN__)
 /* Cygwin-1.7.x is lazy about populating nlinks, so don't
  * expect it to be accurate. */
 # define NLINKS_INACCURATE_FOR_DIRS
 #endif
 
+/* FreeBSD */
 #ifdef __FreeBSD__
 #include <sys/cdefs.h>  /* For __FBSDID */
 #else
-/* Some non-FreeBSD platforms such as newlib-derived ones like
- * cygwin, have __FBSDID, so this definition must be guarded.
- */
+/* Surprisingly, some non-FreeBSD platforms define __FBSDID. */
 #ifndef __FBSDID
 #define        __FBSDID(a)     struct _undefined_hack
 #endif
 #endif
 
+#ifndef O_BINARY
+#define        O_BINARY 0
+#endif
+
 /*
  * Redefine DEFINE_TEST for use in defining the test functions.
  */
 
 /* An implementation of the standard assert() macro */
 #define assert(e)   test_assert(__FILE__, __LINE__, (e), #e, NULL)
-
+/* chdir() and error if it fails */
 #define assertChdir(path)      \
        test_assert_chdir(__FILE__, __LINE__, path)
 /* Assert two integers are the same.  Reports value of each one if not. */
 #define assertEqualInt(v1,v2)   \
   test_assert_equal_int(__FILE__, __LINE__, (v1), #v1, (v2), #v2, NULL)
-
 /* Assert two strings are the same.  Reports value of each one if not. */
 #define assertEqualString(v1,v2)   \
   test_assert_equal_string(__FILE__, __LINE__, (v1), #v1, (v2), #v2, NULL)
 /* Create a directory, report error if it fails. */
 #define assertMakeDir(dirname, mode)   \
   test_assert_make_dir(__FILE__, __LINE__, dirname, mode)
+#define assertMakeFile(path, mode, contents) \
+  test_assert_make_file(__FILE__, __LINE__, path, mode, contents)
 #define assertMakeHardlink(newfile, oldfile)   \
   test_assert_make_hardlink(__FILE__, __LINE__, newfile, oldfile)
 #define assertMakeSymlink(newfile, linkto)     \
 
 /* Function declarations.  These are defined in test_utility.c. */
 void failure(const char *fmt, ...);
-void test_setup(const char *, int);
-void test_skipping(const char *fmt, ...);
 int test_assert(const char *, int, int, const char *, void *);
 int test_assert_chdir(const char *, int, const char *);
 int test_assert_empty_file(const char *, ...);
-int test_assert_non_empty_file(const char *, ...);
 int test_assert_equal_file(const char *, const char *, ...);
 int test_assert_equal_int(const char *, int, long long, const char *, long long, const char *, void *);
+int test_assert_equal_mem(const char *, int, const void *, const char *, const void *, const char *, size_t, const char *, void *);
 int test_assert_equal_string(const char *, int, const char *v1, const char *, const char *v2, const char *, void *);
 int test_assert_equal_wstring(const char *, int, const wchar_t *v1, const char *, const wchar_t *v2, const char *, void *);
-int test_assert_equal_mem(const char *, int, const void *, const char *, const void *, const char *, size_t, const char *, void *);
 int test_assert_file_contents(const void *, int, const char *, ...);
-int test_assert_text_file_contents(const char *buff, const char *f);
 int test_assert_file_exists(const char *, ...);
 int test_assert_file_hardlinks(const char *, int, const char *, const char *);
-int test_assert_file_not_exists(const char *, ...);
 int test_assert_file_nlinks(const char *, int, const char *, int);
+int test_assert_file_not_exists(const char *, ...);
 int test_assert_file_size(const char *, int, const char *, long);
 int test_assert_is_dir(const char *, int, const char *, int);
 int test_assert_is_reg(const char *, int, const char *, int);
 int test_assert_is_symlink(const char *, int, const char *, const char *);
 int test_assert_make_dir(const char *, int, const char *, int);
+int test_assert_make_file(const char *, int, const char *, int, const char *);
 int test_assert_make_hardlink(const char *, int, const char *newpath, const char *);
 int test_assert_make_symlink(const char *, int, const char *newpath, const char *);
+int test_assert_non_empty_file(const char *, ...);
+int test_assert_text_file_contents(const char *buff, const char *f);
 int test_assert_umask(const char *, int, int);
+void test_setup(const char *, int);
+void test_skipping(const char *fmt, ...);
 
 /* Like sprintf, then system() */
 int systemf(const char * fmt, ...);
 
+/* Delay until time() returns a value after this. */
+void sleepUntilAfter(time_t);
+
 /* Suck file into string allocated via malloc(). Call free() when done. */
 /* Supports printf-style args: slurpfile(NULL, "%s/myfile", refdir); */
 char *slurpfile(size_t *, const char *fmt, ...);