diff options
Diffstat (limited to 'contrib/libarchive/test_utils/test_main.c')
| -rw-r--r-- | contrib/libarchive/test_utils/test_main.c | 192 |
1 files changed, 153 insertions, 39 deletions
diff --git a/contrib/libarchive/test_utils/test_main.c b/contrib/libarchive/test_utils/test_main.c index 76fcd79406ff..fe330e5a052e 100644 --- a/contrib/libarchive/test_utils/test_main.c +++ b/contrib/libarchive/test_utils/test_main.c @@ -370,6 +370,8 @@ invalid_parameter_handler(const wchar_t * expression, static int dump_on_failure = 0; /* Default is to remove temp dirs and log data for successful tests. */ static int keep_temp_files = 0; +/* Default is to only return a failure code (1) if there were test failures. If enabled, exit with code 2 if there were no failures, but some tests were skipped. */ +static int fail_if_tests_skipped = 0; /* Default is to run the specified tests once and report errors. */ static int until_failure = 0; /* Default is to just report pass/fail for each test. */ @@ -609,9 +611,10 @@ int assertion_chmod(const char *file, int line, const char *pathname, int mode) { assertion_count(file, line); - if (chmod(pathname, mode) == 0) + if (chmod(pathname, (mode_t)mode) == 0) return (1); - failure_start(file, line, "chmod(\"%s\", %4.o)", pathname, mode); + failure_start(file, line, "chmod(\"%s\", %4.o)", pathname, + (unsigned int)mode); failure_finish(NULL); return (0); @@ -626,8 +629,10 @@ assertion_equal_int(const char *file, int line, if (v1 == v2) return (1); failure_start(file, line, "%s != %s", e1, e2); - logprintf(" %s=%lld (0x%llx, 0%llo)\n", e1, v1, v1, v1); - logprintf(" %s=%lld (0x%llx, 0%llo)\n", e2, v2, v2, v2); + logprintf(" %s=%lld (0x%llx, 0%llo)\n", e1, v1, + (unsigned long long)v1, (unsigned long long)v1); + logprintf(" %s=%lld (0x%llx, 0%llo)\n", e2, v2, + (unsigned long long)v2, (unsigned long long)v2); failure_finish(extra); return (0); } @@ -755,7 +760,7 @@ static void strdump(const char *e, const char *p, int ewidth, int utf8) case '\r': logprintf("\\r"); break; default: if (c >= 32 && c < 127) - logprintf("%c", c); + logprintf("%c", (int)c); else logprintf("\\x%02X", c); } @@ -829,7 +834,7 @@ wcsdump(const char *e, const wchar_t *w) while (*w != L'\0') { unsigned int c = *w++; if (c >= 32 && c < 127) - logprintf("%c", c); + logprintf("%c", (int)c); else if (c < 256) logprintf("\\x%02X", c); else if (c < 0x10000) @@ -896,7 +901,7 @@ hexdump(const char *p, const char *ref, size_t l, size_t offset) for (j = 0; j < 16 && i + j < l; j++) { if (ref != NULL && p[i + j] != ref[i + j]) sep = '_'; - logprintf("%c%02x", sep, 0xff & (int)p[i+j]); + logprintf("%c%02x", sep, 0xff & (unsigned int)p[i+j]); if (ref != NULL && p[i + j] == ref[i + j]) sep = ' '; } @@ -1600,7 +1605,7 @@ assertion_file_mode(const char *file, int line, const char *pathname, int expect if (r == 0 && mode == expected_mode) return (1); failure_start(file, line, "File %s has mode %o, expected %o", - pathname, mode, expected_mode); + pathname, (unsigned int)mode, (unsigned int)expected_mode); #endif failure_finish(NULL); return (0); @@ -1710,8 +1715,8 @@ assertion_is_dir(const char *file, int line, const char *pathname, int mode) /* TODO: Can we do better here? */ if (mode >= 0 && (mode_t)mode != (st.st_mode & 07777)) { failure_start(file, line, "Dir %s has wrong mode", pathname); - logprintf(" Expected: 0%3o\n", mode); - logprintf(" Found: 0%3o\n", st.st_mode & 07777); + logprintf(" Expected: 0%3o\n", (unsigned int)mode); + logprintf(" Found: 0%3o\n", (unsigned int)st.st_mode & 07777); failure_finish(NULL); return (0); } @@ -1743,8 +1748,8 @@ assertion_is_reg(const char *file, int line, const char *pathname, int mode) /* TODO: Can we do better here? */ if (mode >= 0 && (mode_t)mode != (st.st_mode & 07777)) { failure_start(file, line, "File %s has wrong mode", pathname); - logprintf(" Expected: 0%3o\n", mode); - logprintf(" Found: 0%3o\n", st.st_mode & 07777); + logprintf(" Expected: 0%3o\n", (unsigned int)mode); + logprintf(" Found: 0%3o\n", (unsigned int)st.st_mode & 07777); failure_finish(NULL); return (0); } @@ -1945,8 +1950,8 @@ assertion_make_dir(const char *file, int line, const char *dirname, int mode) if (0 == _mkdir(dirname)) return (1); #else - if (0 == mkdir(dirname, mode)) { - if (0 == chmod(dirname, mode)) { + if (0 == mkdir(dirname, (mode_t)mode)) { + if (0 == chmod(dirname, (mode_t)mode)) { assertion_file_mode(file, line, dirname, mode); return (1); } @@ -2000,9 +2005,9 @@ assertion_make_file(const char *file, int line, return (0); } #ifdef HAVE_FCHMOD - if (0 != fchmod(fd, mode)) + if (0 != fchmod(fd, (mode_t)mode)) #else - if (0 != chmod(path, mode)) + if (0 != chmod(path, (mode_t)mode)) #endif { failure_start(file, line, "Could not chmod %s", path); @@ -2091,7 +2096,7 @@ assertion_umask(const char *file, int line, int mask) assertion_count(file, line); (void)file; /* UNUSED */ (void)line; /* UNUSED */ - umask(mask); + umask((mode_t)mask); return (1); } @@ -2103,7 +2108,7 @@ assertion_utimes(const char *file, int line, const char *pathname, int r; #if defined(_WIN32) && !defined(__CYGWIN__) -#define WINTIME(sec, nsec) ((Int32x32To64(sec, 10000000) + EPOC_TIME)\ +#define WINTIME(sec, nsec) (((sec * 10000000LL) + EPOC_TIME)\ + (((nsec)/1000)*10)) HANDLE h; ULARGE_INTEGER wintm; @@ -2451,7 +2456,7 @@ void assertVersion(const char *prog, const char *base) /* Skip arbitrary third-party version numbers. */ while (s > 0 && (*q == ' ' || *q == '-' || *q == '/' || *q == '.' || - isalnum((unsigned char)*q))) { + *q == '_' || isalnum((unsigned char)*q))) { ++q; --s; } @@ -3317,7 +3322,8 @@ assertion_entry_set_acls(const char *file, int line, struct archive_entry *ae, ret = 1; failure_start(file, line, "type=%#010x, " "permset=%#010x, tag=%d, qual=%d name=%s", - acls[i].type, acls[i].permset, acls[i].tag, + (unsigned int)acls[i].type, + (unsigned int)acls[i].permset, acls[i].tag, acls[i].qual, acls[i].name); failure_finish(NULL); } @@ -3411,8 +3417,9 @@ assertion_entry_compare_acls(const char *file, int line, } if ((permset << 6) != (mode & 0700)) { failure_start(file, line, "USER_OBJ permset " - "(%02o) != user mode (%02o)", permset, - 07 & (mode >> 6)); + "(%02o) != user mode (%02o)", + (unsigned int)permset, + (unsigned int)(07 & (mode >> 6))); failure_finish(NULL); ret = 1; } @@ -3426,8 +3433,9 @@ assertion_entry_compare_acls(const char *file, int line, } if ((permset << 3) != (mode & 0070)) { failure_start(file, line, "GROUP_OBJ permset " - "(%02o) != group mode (%02o)", permset, - 07 & (mode >> 3)); + "(%02o) != group mode (%02o)", + (unsigned int)permset, + (unsigned int)(07 & (mode >> 3))); failure_finish(NULL); ret = 1; } @@ -3441,15 +3449,17 @@ assertion_entry_compare_acls(const char *file, int line, } if ((permset << 0) != (mode & 0007)) { failure_start(file, line, "OTHER permset " - "(%02o) != other mode (%02o)", permset, - mode & 07); + "(%02o) != other mode (%02o)", + (unsigned int)permset, + (unsigned int)mode & 07); failure_finish(NULL); ret = 1; } } else if (matched != 1) { failure_start(file, line, "Could not find match for " "ACL (type=%#010x,permset=%#010x,tag=%d,qual=%d," - "name=``%s'')", type, permset, tag, qual, name); + "name=``%s'')", (unsigned int)type, + (unsigned int)permset, tag, qual, name); failure_finish(NULL); ret = 1; } @@ -3462,14 +3472,16 @@ assertion_entry_compare_acls(const char *file, int line, if ((want_type & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0 && (mode_t)(mode & 0777) != (archive_entry_mode(ae) & 0777)) { failure_start(file, line, "Mode (%02o) and entry mode (%02o) " - "mismatch", mode, archive_entry_mode(ae)); + "mismatch", (unsigned int)mode, + (unsigned int)archive_entry_mode(ae)); failure_finish(NULL); ret = 1; } if (n != 0) { failure_start(file, line, "Could not find match for ACL " "(type=%#010x,permset=%#010x,tag=%d,qual=%d,name=``%s'')", - acls[marker[0]].type, acls[marker[0]].permset, + (unsigned int)acls[marker[0]].type, + (unsigned int)acls[marker[0]].permset, acls[marker[0]].tag, acls[marker[0]].qual, acls[marker[0]].name); failure_finish(NULL); @@ -3526,7 +3538,7 @@ test_summarize(int failed, int skips_num) fflush(stdout); break; case VERBOSITY_PASSFAIL: - printf(failed ? "FAIL\n" : skips_num ? "ok (S)\n" : "ok\n"); + printf(failed ? "FAIL\n" : skips_num ? "skipped\n" : "ok\n"); break; } @@ -3534,7 +3546,7 @@ test_summarize(int failed, int skips_num) for (i = 0; i < sizeof(failed_lines)/sizeof(failed_lines[0]); i++) { if (failed_lines[i].count > 1 && !failed_lines[i].skip) - logprintf("%s:%d: Summary: Failed %d times\n", + logprintf("%s:%u: Summary: Failed %d times\n", failed_filename, i, failed_lines[i].count); } /* Clear the failure history for the next file. */ @@ -3543,6 +3555,59 @@ test_summarize(int failed, int skips_num) } /* + * Set or unset environment variable. + */ +static void +set_environment(const char *key, const char *value) +{ + +#if defined(_WIN32) && !defined(__CYGWIN__) + if (!SetEnvironmentVariable(key, value)) { + fprintf(stderr, "SetEnvironmentVariable failed with %d\n", + (int)GetLastError()); + } +#else + if (value == NULL) { + if (unsetenv(key) == -1) + fprintf(stderr, "unsetenv: %s\n", strerror(errno)); + } else { + if (setenv(key, value, 1) == -1) + fprintf(stderr, "setenv: %s\n", strerror(errno)); + } +#endif +} + +/* + * Enforce C locale for (sub)processes. + */ +static void +set_c_locale(void) +{ + static const char *lcs[] = { + "LC_ADDRESS", + "LC_ALL", + "LC_COLLATE", + "LC_CTYPE", + "LC_IDENTIFICATION", + "LC_MEASUREMENT", + "LC_MESSAGES", + "LC_MONETARY", + "LC_NAME", + "LC_NUMERIC", + "LC_PAPER", + "LC_TELEPHONE", + "LC_TIME", + NULL + }; + size_t i; + + setlocale(LC_ALL, "C"); + set_environment("LANG", "C"); + for (i = 0; lcs[i] != NULL; i++) + set_environment(lcs[i], NULL); +} + +/* * Actually run a single test, with appropriate setup and cleanup. */ static int @@ -3553,10 +3618,11 @@ test_run(int i, const char *tmpdir) #else char workdir[1024 * 2]; #endif - char logfilename[64]; + char logfilename[256]; int failures_before = failures; int skips_before = skips; - int oldumask; + int tmp; + mode_t oldumask; switch (verbosity) { case VERBOSITY_SUMMARY_ONLY: /* No per-test reports at all */ @@ -3576,11 +3642,38 @@ test_run(int i, const char *tmpdir) exit(1); } /* Create a log file for this test. */ - snprintf(logfilename, sizeof(logfilename), "%s.log", tests[i].name); + tmp = snprintf(logfilename, sizeof(logfilename), "%s.log", tests[i].name); + if (tmp < 0) { + fprintf(stderr, + "ERROR can't create %s.log: %s\n", + tests[i].name, strerror(errno)); + exit(1); + } + if ((size_t)tmp >= sizeof(logfilename)) { + fprintf(stderr, + "ERROR can't create %s.log: Name too long. " + "Length %d; Max allowed length %zu\n", + tests[i].name, tmp, sizeof(logfilename) - 1); + exit(1); + } logfile = fopen(logfilename, "w"); fprintf(logfile, "%s\n\n", tests[i].name); /* Chdir() to a work dir for this specific test. */ - snprintf(workdir, sizeof(workdir), "%s/%s", tmpdir, tests[i].name); + tmp = snprintf(workdir, + sizeof(workdir), "%s/%s", tmpdir, tests[i].name); + if (tmp < 0) { + fprintf(stderr, + "ERROR can't create %s/%s: %s\n", + tmpdir, tests[i].name, strerror(errno)); + exit(1); + } + if ((size_t)tmp >= sizeof(workdir)) { + fprintf(stderr, + "ERROR can't create %s/%s: Path too long. " + "Length %d; Max allowed length %zu\n", + tmpdir, tests[i].name, tmp, sizeof(workdir) - 1); + exit(1); + } testworkdir = workdir; if (!assertMakeDir(testworkdir, 0755) || !assertChdir(testworkdir)) { @@ -3589,7 +3682,7 @@ test_run(int i, const char *tmpdir) exit(1); } /* Explicitly reset the locale before each test. */ - setlocale(LC_ALL, "C"); + set_c_locale(); /* Record the umask before we run the test. */ umask(oldumask = umask(0)); /* @@ -3603,7 +3696,7 @@ test_run(int i, const char *tmpdir) /* Restore umask */ umask(oldumask); /* Reset locale. */ - setlocale(LC_ALL, "C"); + set_c_locale(); /* Reset directory. */ if (!assertChdir(tmpdir)) { fprintf(stderr, "ERROR: Couldn't chdir to temp dir %s\n", @@ -3672,7 +3765,8 @@ usage(const char *program) printf(" -q Quiet.\n"); printf(" -r <dir> Path to dir containing reference files.\n"); printf(" Default: Current directory.\n"); - printf(" -u Keep running specifies tests until one fails.\n"); + printf(" -s Exit with code 2 if any tests were skipped.\n"); + printf(" -u Keep running specified tests until one fails.\n"); printf(" -v Verbose.\n"); printf("Available tests:\n"); for (i = 0; i < limit; i++) @@ -4065,6 +4159,9 @@ main(int argc, char **argv) case 'r': refdir = option_arg; break; + case 's': + fail_if_tests_skipped = 1; + break; case 'u': until_failure++; break; @@ -4118,6 +4215,19 @@ main(int argc, char **argv) strncat(testprg, "\"", testprg_len); testprog = testprg; } + + /* Sanity check: reject a relative path for refdir. */ + if (refdir != NULL) { +#if defined(_WIN32) && !defined(__CYGWIN__) + /* TODO: probably use PathIsRelative() from <shlwapi.h>. */ +#else + if (refdir[0] != '/') { + fprintf(stderr, + "ERROR: Cannot use relative path for refdir\n"); + exit(1); + } +#endif + } #endif #if !defined(_WIN32) && defined(SIGPIPE) @@ -4263,5 +4373,9 @@ finish: assertChdir(".."); rmdir(tmpdir); - return (tests_failed ? 1 : 0); + if (tests_failed) return 1; + + if (fail_if_tests_skipped == 1 && skips > 0) return 2; + + return 0; } |
