aboutsummaryrefslogtreecommitdiff
path: root/contrib/libarchive/test_utils/test_main.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/libarchive/test_utils/test_main.c')
-rw-r--r--contrib/libarchive/test_utils/test_main.c192
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;
}