From: Tim Kientzle Date: Sun, 23 Aug 2009 03:18:13 +0000 (-0400) Subject: Rewrite a lot of the test assertion framework. X-Git-Tag: v2.8.0~418 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=42dff835d25e6fe925ee016a46e9bb93eb8d3bca;p=thirdparty%2Flibarchive.git Rewrite a lot of the test assertion framework. 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 --- diff --git a/cpio/test/main.c b/cpio/test/main.c index 7c480f1ac..3d9992854 100644 --- a/cpio/test/main.c +++ b/cpio/test/main.c @@ -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 -} diff --git a/cpio/test/test.h b/cpio/test/test.h index ad504770c..a3dddc89d 100644 --- a/cpio/test/test.h +++ b/cpio/test/test.h @@ -111,6 +111,10 @@ #endif #endif +#ifndef O_BINARY +#define O_BINARY 0 +#endif + /* * Redefine DEFINE_TEST for use in defining the test functions. */ diff --git a/libarchive/config_freebsd.h b/libarchive/config_freebsd.h index 37c806605..2ebfe2091 100644 --- a/libarchive/config_freebsd.h +++ b/libarchive/config_freebsd.h @@ -25,10 +25,6 @@ * $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 diff --git a/libarchive/test/main.c b/libarchive/test/main.c index 3357b565d..c3b48af4e 100644 --- a/libarchive/test/main.c +++ b/libarchive/test/main.c @@ -39,6 +39,7 @@ #endif #include #include +#include #ifndef F_OK #define F_OK (0) #endif @@ -63,47 +64,6 @@ #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. diff --git a/libarchive/test/test.h b/libarchive/test/test.h index 74104a10f..a63359176 100644 --- a/libarchive/test/test.h +++ b/libarchive/test/test.h @@ -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" @@ -87,22 +88,23 @@ #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 /* 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 @@ -120,13 +122,12 @@ /* 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) @@ -173,6 +174,8 @@ /* 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) \ @@ -191,35 +194,39 @@ /* 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, ...); diff --git a/libarchive/test/test_acl_freebsd.c b/libarchive/test/test_acl_freebsd.c index ea52a336a..b48fae0c2 100644 --- a/libarchive/test/test_acl_freebsd.c +++ b/libarchive/test/test_acl_freebsd.c @@ -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); diff --git a/libarchive/test/test_extattr_freebsd.c b/libarchive/test/test_extattr_freebsd.c index 3814230ea..8b8cc7e6e 100644 --- a/libarchive/test/test_extattr_freebsd.c +++ b/libarchive/test/test_extattr_freebsd.c @@ -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; diff --git a/tar/test/main.c b/tar/test/main.c index 3a1b7abd9..dfa35a8b1 100644 --- a/tar/test/main.c +++ b/tar/test/main.c @@ -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. diff --git a/tar/test/test.h b/tar/test/test.h index da44ec683..5fbb62145 100644 --- a/tar/test/test.h +++ b/tar/test/test.h @@ -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 @@ -88,27 +89,32 @@ #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 /* 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. */ @@ -117,13 +123,12 @@ /* 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) @@ -170,6 +175,8 @@ /* 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) \ @@ -188,35 +195,39 @@ /* 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, ...);