From owner-svn-src-all@FreeBSD.ORG Wed Dec 30 05:59:22 2009 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 0BDC51065693; Wed, 30 Dec 2009 05:59:22 +0000 (UTC) (envelope-from kientzle@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id EDD218FC1F; Wed, 30 Dec 2009 05:59:21 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id nBU5xLvZ048419; Wed, 30 Dec 2009 05:59:21 GMT (envelope-from kientzle@svn.freebsd.org) Received: (from kientzle@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id nBU5xL6a048415; Wed, 30 Dec 2009 05:59:21 GMT (envelope-from kientzle@svn.freebsd.org) Message-Id: <200912300559.nBU5xL6a048415@svn.freebsd.org> From: Tim Kientzle Date: Wed, 30 Dec 2009 05:59:21 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r201247 - head/lib/libarchive/test X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 30 Dec 2009 05:59:22 -0000 Author: kientzle Date: Wed Dec 30 05:59:21 2009 New Revision: 201247 URL: http://svn.freebsd.org/changeset/base/201247 Log: A raft of test changes and improvements from the Googlecode repository. In particular, this includes tests for the new features I've merged over the last few days. Added: head/lib/libarchive/test/test_compat_cpio.c (contents, props changed) head/lib/libarchive/test/test_compat_cpio_1.cpio.uu (contents, props changed) head/lib/libarchive/test/test_compat_lzma.c (contents, props changed) head/lib/libarchive/test/test_compat_lzma_1.tlz.uu (contents, props changed) head/lib/libarchive/test/test_compat_lzma_2.tlz.uu (contents, props changed) head/lib/libarchive/test/test_compat_lzma_3.tlz.uu (contents, props changed) head/lib/libarchive/test/test_fuzz_1.iso.Z.uu (contents, props changed) head/lib/libarchive/test/test_read_format_ar.ar.uu (contents, props changed) head/lib/libarchive/test/test_read_format_cpio_bin_lzma.c (contents, props changed) head/lib/libarchive/test/test_read_format_iso.iso.Z.uu (contents, props changed) head/lib/libarchive/test/test_read_format_iso_joliet.iso.Z.uu (contents, props changed) head/lib/libarchive/test/test_read_format_iso_joliet_long.iso.Z.uu (contents, props changed) head/lib/libarchive/test/test_read_format_iso_joliet_rockridge.iso.Z.uu (contents, props changed) head/lib/libarchive/test/test_read_format_iso_multi_extent.c (contents, props changed) head/lib/libarchive/test/test_read_format_iso_multi_extent.iso.Z.uu (contents, props changed) head/lib/libarchive/test/test_read_format_iso_rockridge.iso.Z.uu (contents, props changed) head/lib/libarchive/test/test_read_format_iso_rockridge_ce.iso.Z.uu (contents, props changed) head/lib/libarchive/test/test_read_format_iso_rockridge_new.iso.Z.uu (contents, props changed) head/lib/libarchive/test/test_read_format_iso_rockridge_rr_moved.iso.Z.uu (contents, props changed) head/lib/libarchive/test/test_read_format_iso_zisofs.iso.Z.uu (contents, props changed) head/lib/libarchive/test/test_read_format_isojoliet_long.c (contents, props changed) head/lib/libarchive/test/test_read_format_isojoliet_rr.c (contents, props changed) head/lib/libarchive/test/test_read_format_isorr_ce.c (contents, props changed) head/lib/libarchive/test/test_read_format_isorr_new_bz2.c (contents, props changed) head/lib/libarchive/test/test_read_format_isorr_rr_moved.c (contents, props changed) head/lib/libarchive/test/test_read_format_isozisofs_bz2.c (contents, props changed) head/lib/libarchive/test/test_read_format_mtree.mtree.uu (contents, props changed) head/lib/libarchive/test/test_read_format_tlz.c (contents, props changed) head/lib/libarchive/test/test_write_disk_symlink.c (contents, props changed) head/lib/libarchive/test/test_write_format_zip.c (contents, props changed) head/lib/libarchive/test/test_write_format_zip_empty.c (contents, props changed) head/lib/libarchive/test/test_write_format_zip_no_compression.c (contents, props changed) Modified: head/lib/libarchive/test/Makefile head/lib/libarchive/test/main.c head/lib/libarchive/test/test.h head/lib/libarchive/test/test_acl_pax.c head/lib/libarchive/test/test_compat_bzip2.c head/lib/libarchive/test/test_compat_solaris_tar_acl.c head/lib/libarchive/test/test_entry.c head/lib/libarchive/test/test_entry_strmode.c head/lib/libarchive/test/test_extattr_freebsd.c head/lib/libarchive/test/test_fuzz.c head/lib/libarchive/test/test_open_fd.c head/lib/libarchive/test/test_open_file.c head/lib/libarchive/test/test_pax_filename_encoding.c head/lib/libarchive/test/test_read_compress_program.c head/lib/libarchive/test/test_read_data_large.c head/lib/libarchive/test/test_read_disk.c head/lib/libarchive/test/test_read_disk_entry_from_file.c head/lib/libarchive/test/test_read_extract.c head/lib/libarchive/test/test_read_format_ar.c head/lib/libarchive/test/test_read_format_cpio_bin_bz2.c head/lib/libarchive/test/test_read_format_iso_gz.c head/lib/libarchive/test/test_read_format_isojoliet_bz2.c head/lib/libarchive/test/test_read_format_isorr_bz2.c head/lib/libarchive/test/test_read_format_mtree.c head/lib/libarchive/test/test_read_format_pax_bz2.c head/lib/libarchive/test/test_read_format_tar.c head/lib/libarchive/test/test_read_format_tbz.c head/lib/libarchive/test/test_read_large.c head/lib/libarchive/test/test_tar_large.c head/lib/libarchive/test/test_write_compress_program.c head/lib/libarchive/test/test_write_disk.c head/lib/libarchive/test/test_write_disk_failures.c head/lib/libarchive/test/test_write_disk_hardlink.c head/lib/libarchive/test/test_write_disk_perms.c head/lib/libarchive/test/test_write_disk_secure.c head/lib/libarchive/test/test_write_disk_sparse.c head/lib/libarchive/test/test_write_disk_times.c head/lib/libarchive/test/test_write_format_cpio_empty.c head/lib/libarchive/test/test_write_format_cpio_newc.c head/lib/libarchive/test/test_write_format_cpio_odc.c head/lib/libarchive/test/test_write_format_tar_ustar.c Modified: head/lib/libarchive/test/Makefile ============================================================================== --- head/lib/libarchive/test/Makefile Wed Dec 30 05:30:35 2009 (r201246) +++ head/lib/libarchive/test/Makefile Wed Dec 30 05:59:21 2009 (r201247) @@ -14,8 +14,10 @@ TESTS= \ test_archive_api_feature.c \ test_bad_fd.c \ test_compat_bzip2.c \ + test_compat_cpio.c \ test_compat_gtar.c \ test_compat_gzip.c \ + test_compat_lzma.c \ test_compat_solaris_tar_acl.c \ test_compat_tar_hardlink.c \ test_compat_xz.c \ @@ -42,6 +44,7 @@ TESTS= \ test_read_format_cpio_bin_be.c \ test_read_format_cpio_bin_bz2.c \ test_read_format_cpio_bin_gz.c \ + test_read_format_cpio_bin_lzma.c \ test_read_format_cpio_bin_xz.c \ test_read_format_cpio_odc.c \ test_read_format_cpio_svr4_gzip.c \ @@ -51,8 +54,15 @@ TESTS= \ test_read_format_gtar_lzma.c \ test_read_format_gtar_sparse.c \ test_read_format_iso_gz.c \ + test_read_format_iso_multi_extent.c \ + test_read_format_isorr_rr_moved.c \ test_read_format_isojoliet_bz2.c \ + test_read_format_isojoliet_long.c \ + test_read_format_isojoliet_rr.c \ test_read_format_isorr_bz2.c \ + test_read_format_isorr_ce.c \ + test_read_format_isorr_new_bz2.c \ + test_read_format_isozisofs_bz2.c \ test_read_format_mtree.c \ test_read_format_pax_bz2.c \ test_read_format_raw.c \ @@ -60,6 +70,7 @@ TESTS= \ test_read_format_tar_empty_filename.c \ test_read_format_tbz.c \ test_read_format_tgz.c \ + test_read_format_tlz.c \ test_read_format_txz.c \ test_read_format_tz.c \ test_read_format_zip.c \ @@ -82,6 +93,7 @@ TESTS= \ test_write_disk_perms.c \ test_write_disk_secure.c \ test_write_disk_sparse.c \ + test_write_disk_symlink.c \ test_write_disk_times.c \ test_write_format_ar.c \ test_write_format_cpio.c \ @@ -94,6 +106,9 @@ TESTS= \ test_write_format_tar.c \ test_write_format_tar_empty.c \ test_write_format_tar_ustar.c \ + test_write_format_zip.c \ + test_write_format_zip_empty.c \ + test_write_format_zip_no_compression.c \ test_write_open_memory.c @@ -108,16 +123,12 @@ NO_MAN=yes PROG=libarchive_test INTERNALPROG=yes # Don't install this; it's just for testing -DPADD=${LIBBZ2} ${LIBZ} +DPADD=${LIBBZ2} ${LIBZ} ${LIBMD} ${LIBCRYPTO} ${LIBBSDXML} CFLAGS+= -DPLATFORM_CONFIG_H=\"config_freebsd.h\" -LDADD= -lz -lbz2 -lmd -lcrypto +LDADD= -lz -lbz2 -lmd -lcrypto -lbsdxml CFLAGS+= -g CFLAGS+= -I${LA_SRCDIR} -I. -# Uncomment to build and test lzma support via liblzmadec -#CFLAGS+= -I/usr/local/include -DHAVE_LIBLZMADEC=1 -DHAVE_LZMADEC_H=1 -#LDADD+= -L/usr/local/lib -llzmadec - # Uncomment to build and test lzma and xz support via liblzma #CFLAGS+= -I/usr/local/include -DHAVE_LIBLZMA=1 -DHAVE_LZMA_H=1 #LDADD+= -L/usr/local/lib -llzma @@ -125,11 +136,11 @@ CFLAGS+= -I${LA_SRCDIR} -I. # Uncomment to link against dmalloc #LDADD+= -L/usr/local/lib -ldmalloc #CFLAGS+= -I/usr/local/include -DUSE_DMALLOC -WARNS=6 +#WARNS=6 # Build libarchive_test and run it. check test: libarchive_test - ./libarchive_test -v -r ${.CURDIR} + ./libarchive_test -r ${.CURDIR} # list.h is just a list of all tests, as indicated by DEFINE_TEST macro lines list.h: ${TESTS} Makefile Modified: head/lib/libarchive/test/main.c ============================================================================== --- head/lib/libarchive/test/main.c Wed Dec 30 05:30:35 2009 (r201246) +++ head/lib/libarchive/test/main.c Wed Dec 30 05:59:21 2009 (r201247) @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2007 Tim Kientzle + * Copyright (c) 2003-2009 Tim Kientzle * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -23,74 +23,142 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* - * Various utility routines useful for test programs. - * Each test program is linked against this file. - */ #include "test.h" - #include #include #include #include -#if defined(_WIN32) && !defined(__CYGWIN__) -#include -#include -#include -#endif /* * This same file is used pretty much verbatim for all test harnesses. * * The next few lines are the only differences. + * TODO: Move this into a separate configuration header, have all test + * suites share one copy of this file. */ +__FBSDID("$FreeBSD$"); +#define KNOWNREF "test_compat_gtar_1.tar.uu" +#define ENVBASE "LIBARCHIVE" /* Prefix for environment variables. */ #undef PROGRAM /* Testing a library, not a program. */ #define LIBRARY "libarchive" -#define ENVBASE "LIBARCHIVE" /* Prefix for environment variables. */ #define EXTRA_DUMP(x) archive_error_string((struct archive *)(x)) #define EXTRA_VERSION archive_version() -#define KNOWNREF "test_compat_gtar_1.tar.uu" -__FBSDID("$FreeBSD$"); /* - * "list.h" is simply created by "grep DEFINE_TEST"; it has - * a line like - * DEFINE_TEST(test_function) - * for each test. - * Include it here with a suitable DEFINE_TEST to declare all of the - * test functions. + * + * Windows support routines + * + * Note: Configuration is a tricky issue. Using HAVE_* feature macros + * in the test harness is dangerous because they cover up + * configuration errors. The classic example of this is omitting a + * configure check. If libarchive and libarchive_test both look for + * the same feature macro, such errors are hard to detect. Platform + * macros (e.g., _WIN32 or __GNUC__) are a little better, but can + * easily lead to very messy code. It's best to limit yourself + * to only the most generic programming techniques in the test harness + * and thus avoid conditionals altogether. Where that's not possible, + * try to minimize conditionals by grouping platform-specific tests in + * one place (e.g., test_acl_freebsd) or by adding new assert() + * functions (e.g., assertMakeHardlink()) to cover up platform + * differences. Platform-specific coding in libarchive_test is often + * a symptom that some capability is missing from libarchive itself. */ -#undef DEFINE_TEST -#define DEFINE_TEST(name) void name(void); -#include "list.h" +#if defined(_WIN32) && !defined(__CYGWIN__) +#include +#include +#ifndef F_OK +#define F_OK (0) +#endif +#ifndef S_ISDIR +#define S_ISDIR(m) ((m) & _S_IFDIR) +#endif +#ifndef S_ISREG +#define S_ISREG(m) ((m) & _S_IFREG) +#endif +#if !defined(__BORLANDC__) +#define access _access +#define chdir _chdir +#endif +#ifndef fileno +#define fileno _fileno +#endif +/*#define fstat _fstat64*/ +#if !defined(__BORLANDC__) +#define getcwd _getcwd +#endif +#define lstat stat +/*#define lstat _stat64*/ +/*#define stat _stat64*/ +#define rmdir _rmdir +#if !defined(__BORLANDC__) +#define strdup _strdup +#define umask _umask +#endif +#define int64_t __int64 +#endif -/* Interix doesn't define these in a standard header. */ -#if __INTERIX__ -extern char *optarg; -extern int optind; +#if defined(HAVE__CrtSetReportMode) +# include #endif -/* Enable core dump on failure. */ -static int dump_on_failure = 0; -/* Default is to remove temp dirs for successful tests. */ -static int keep_temp_files = 0; -/* Default is to print some basic information about each test. */ -static int quiet_flag = 0; -/* Default is to summarize repeated failures. */ -static int verbose = 0; -/* Cumulative count of component failures. */ -static int failures = 0; -/* Cumulative count of skipped component tests. */ -static int skips = 0; -/* Cumulative count of assertions. */ -static int assertions = 0; +#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"); + exit(1); + } + return (void *)GetProcAddress(lib, name); +} -/* Directory where uuencoded reference files can be found. */ -static const char *refdir; +static int +my_CreateSymbolicLinkA(const char *linkname, const char *target, int flags) +{ + static BOOLEAN (WINAPI *f)(LPCSTR, LPCSTR, DWORD); + static int set; + if (!set) { + set = 1; + f = GetFunctionKernel32("CreateSymbolicLinkA"); + } + return f == NULL ? 0 : (*f)(linkname, target, flags); +} +static int +my_CreateHardLinkA(const char *linkname, const char *target) +{ + static BOOLEAN (WINAPI *f)(LPCSTR, LPCSTR, LPSECURITY_ATTRIBUTES); + static int set; + if (!set) { + set = 1; + f = GetFunctionKernel32("CreateHardLinkA"); + } + return f == NULL ? 0 : (*f)(linkname, target, NULL); +} -#if defined(_WIN32) && !defined(__CYGWIN__) +int +my_GetFileInformationByName(const char *path, BY_HANDLE_FILE_INFORMATION *bhfi) +{ + HANDLE h; + int r; + memset(bhfi, 0, sizeof(*bhfi)); + h = CreateFile(path, FILE_READ_ATTRIBUTES, 0, NULL, + OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if (h == INVALID_HANDLE_VALUE) + return (0); + r = GetFileInformationByHandle(h, bhfi); + CloseHandle(h); + return (r); +} +#endif + +#if defined(HAVE__CrtSetReportMode) static void invalid_parameter_handler(const wchar_t * expression, const wchar_t * function, const wchar_t * file, @@ -98,123 +166,181 @@ invalid_parameter_handler(const wchar_t { /* nop */ } - #endif /* - * My own implementation of the standard assert() macro emits the - * message in the same format as GCC (file:line: message). - * It also includes some additional useful information. - * This makes it a lot easier to skim through test failures in - * Emacs. ;-) * - * It also supports a few special features specifically to simplify - * test harnesses: - * failure(fmt, args) -- Stores a text string that gets - * printed if the following assertion fails, good for - * explaining subtle tests. + * OPTIONS FLAGS + * */ -static char msg[4096]; -/* - * For each test source file, we remember how many times each - * failure was reported. - */ -static const char *failed_filename = NULL; -static struct line { - int line; - int count; - int critical; -} failed_lines[1000]; +/* Enable core dump on failure. */ +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 just report pass/fail for each test. */ +static int verbosity = 0; +#define VERBOSITY_SUMMARY_ONLY -1 /* -q */ +#define VERBOSITY_PASSFAIL 0 /* Default */ +#define VERBOSITY_LIGHT_REPORT 1 /* -v */ +#define VERBOSITY_FULL 2 /* -vv */ +/* A few places generate even more output for verbosity > VERBOSITY_FULL, + * mostly for debugging the test harness itself. */ +/* Cumulative count of assertion failures. */ +static int failures = 0; +/* Cumulative count of reported skips. */ +static int skips = 0; +/* Cumulative count of assertions checked. */ +static int assertions = 0; + +/* Directory where uuencoded reference files can be found. */ +static const char *refdir; /* - * Called at the beginning of each assert() function. + * Report log information selectively to console and/or disk log. */ +static int log_console = 0; +static FILE *logfile; static void -count_assertion(const char *file, int line) +vlogprintf(const char *fmt, va_list ap) { - (void)file; /* UNUSED */ - (void)line; /* UNUSED */ - ++assertions; - /* Uncomment to print file:line after every assertion. - * Verbose, but occasionally useful in tracking down crashes. */ - /* printf("Checked %s:%d\n", file, line); */ +#ifdef va_copy + va_list lfap; + va_copy(lfap, ap); +#endif + if (log_console) + vfprintf(stdout, fmt, ap); + if (logfile != NULL) +#ifdef va_copy + vfprintf(logfile, fmt, lfap); + va_end(lfap); +#else + vfprintf(logfile, fmt, ap); +#endif } -/* - * Count this failure; return the number of previous failures. - */ -static int -previous_failures(const char *filename, int line, int critical) +static void +logprintf(const char *fmt, ...) { - unsigned int i; - int count; - - if (failed_filename == NULL || strcmp(failed_filename, filename) != 0) - memset(failed_lines, 0, sizeof(failed_lines)); - failed_filename = filename; + va_list ap; + va_start(ap, fmt); + vlogprintf(fmt, ap); + va_end(ap); +} - 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); - } - } - return (0); +/* Set up a message to display only if next assertion fails. */ +static char msgbuff[4096]; +static const char *msg, *nextmsg; +void +failure(const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + vsprintf(msgbuff, fmt, ap); + va_end(ap); + nextmsg = msgbuff; } /* * Copy arguments into file-local variables. + * This was added to permit vararg assert() functions without needing + * variadic wrapper macros. Turns out that the vararg capability is almost + * never used, so almost all of the vararg assertions can be simplified + * by removing the vararg capability and reworking the wrapper macro to + * pass __FILE__, __LINE__ directly into the function instead of using + * this hook. I suspect this machinery is used so rarely that we + * would be better off just removing it entirely. That would simplify + * the code here noticably. */ static const char *test_filename; static int test_line; static void *test_extra; -void test_setup(const char *filename, int line) +void assertion_setup(const char *filename, int line) { test_filename = filename; test_line = line; } +/* Called at the beginning of each assert() function. */ +static void +assertion_count(const char *file, int line) +{ + (void)file; /* UNUSED */ + (void)line; /* UNUSED */ + ++assertions; + /* Proper handling of "failure()" message. */ + 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); */ +} + /* - * Inform user that we're skipping a test. + * For each test source file, we remember how many times each + * assertion was reported. Cleared before each new test, + * used by test_summarize(). */ -void -test_skipping(const char *fmt, ...) +static struct line { + int count; + int skip; +} failed_lines[10000]; + +/* Count this failure, setup up log destination and handle initial report. */ +static void +failure_start(const char *filename, int line, const char *fmt, ...) { va_list ap; - if (previous_failures(test_filename, test_line, 0)) - return; + /* Record another failure for this line. */ + ++failures; + /* test_filename = filename; */ + failed_lines[line].count++; + + /* Determine whether to log header to console. */ + switch (verbosity) { + case VERBOSITY_LIGHT_REPORT: + log_console = (failed_lines[line].count < 2); + break; + default: + log_console = (verbosity >= VERBOSITY_FULL); + } + /* Log file:line header for this failure */ va_start(ap, fmt); - fprintf(stderr, " *** SKIPPING: "); - vfprintf(stderr, fmt, ap); - fprintf(stderr, "\n"); +#if _MSC_VER + logprintf("%s(%d): ", filename, line); +#else + logprintf("%s:%d: ", filename, line); +#endif + vlogprintf(fmt, ap); va_end(ap); - ++skips; + logprintf("\n"); + + if (msg != NULL && msg[0] != '\0') { + logprintf(" Description: %s\n", msg); + msg = NULL; + } + + /* Determine whether to log details to console. */ + if (verbosity == VERBOSITY_LIGHT_REPORT) + log_console = 0; } -/* Common handling of failed tests. */ +/* Complete reporting of failed tests. */ +/* + * The 'extra' hook here is used by libarchive to include libarchive + * error messages with assertion failures. It could also be used + * to add strerror() output, for example. Just define the EXTRA_DUMP() + * macro appropriately. + */ static void -report_failure(void *extra) +failure_finish(void *extra) { - if (msg[0] != '\0') { - fprintf(stderr, " Description: %s\n", msg); - msg[0] = '\0'; - } - + (void)extra; /* UNUSED (maybe) */ #ifdef EXTRA_DUMP if (extra != NULL) - fprintf(stderr, " detail: %s\n", EXTRA_DUMP(extra)); -#else - (void)extra; /* UNUSED */ + logprintf(" detail: %s\n", EXTRA_DUMP(extra)); #endif if (dump_on_failure) { @@ -225,203 +351,154 @@ report_failure(void *extra) } } -/* - * Summarize repeated failures in the just-completed test file. - * 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) - break; - if (failed_lines[i].count > 1 && failed_lines[i].critical) - fprintf(stderr, "%s:%d: Failed %d times\n", - failed_filename, failed_lines[i].line, - failed_lines[i].count); - } - /* Clear the failure history for the next file. */ - memset(failed_lines, 0, sizeof(failed_lines)); -} - -/* Set up a message to display only after a test fails. */ +/* Inform user that we're skipping some checks. */ void -failure(const char *fmt, ...) +test_skipping(const char *fmt, ...) { + char buff[1024]; va_list ap; + va_start(ap, fmt); - vsprintf(msg, fmt, ap); + vsprintf(buff, fmt, ap); va_end(ap); + /* failure_start() isn't quite right, but is awfully convenient. */ + failure_start(test_filename, test_line, "SKIPPING: %s", buff); + --failures; /* Undo failures++ in failure_start() */ + /* Don't failure_finish() here. */ + /* Mark as skip, so doesn't count as failed test. */ + failed_lines[test_line].skip = 1; + ++skips; } +/* + * + * ASSERTIONS + * + */ + /* Generic assert() just displays the failed condition. */ int -test_assert(const char *file, int line, int value, const char *condition, void *extra) +assertion_assert(const char *file, int line, int value, + const char *condition, void *extra) { - count_assertion(file, line); - if (value) { - msg[0] = '\0'; - return (value); + assertion_count(file, line); + if (!value) { + failure_start(file, line, "Assertion failed: %s", condition); + failure_finish(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); } -/* assertEqualInt() displays the values of the two integers. */ +/* chdir() and report any errors */ int -test_assert_equal_int(const char *file, int line, - int v1, const char *e1, int v2, const char *e2, void *extra) +assertion_chdir(const char *file, int line, const char *pathname) { - count_assertion(file, line); - if (v1 == v2) { - msg[0] = '\0'; + assertion_count(file, line); + if (chdir(pathname) == 0) return (1); - } - 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=%d\n", e1, v1); - fprintf(stderr, " %s=%d\n", e2, v2); - report_failure(extra); + failure_start(file, line, "chdir(\"%s\")", pathname); + failure_finish(NULL); + return (0); + +} + +/* Verify two integers are equal. */ +int +assertion_equal_int(const char *file, int line, + long long v1, const char *e1, long long v2, const char *e2, void *extra) +{ + assertion_count(file, 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); + failure_finish(extra); return (0); } -static void strdump(const char *p) +static void strdump(const char *e, const char *p) { + const char *q = p; + + logprintf(" %s = ", e); if (p == NULL) { - fprintf(stderr, "(null)"); + logprintf("NULL"); return; } - fprintf(stderr, "\""); + logprintf("\""); while (*p != '\0') { unsigned int c = 0xff & *p++; switch (c) { - case '\a': fprintf(stderr, "\a"); break; - case '\b': fprintf(stderr, "\b"); break; - case '\n': fprintf(stderr, "\n"); break; - case '\r': fprintf(stderr, "\r"); break; + case '\a': printf("\a"); break; + case '\b': printf("\b"); break; + case '\n': printf("\n"); break; + case '\r': printf("\r"); break; default: if (c >= 32 && c < 127) - fprintf(stderr, "%c", c); + logprintf("%c", c); else - fprintf(stderr, "\\x%02X", c); + logprintf("\\x%02X", c); } } - fprintf(stderr, "\""); + logprintf("\""); + logprintf(" (length %d)\n", q == NULL ? -1 : (int)strlen(q)); } -/* assertEqualString() displays the values of the two strings. */ +/* Verify two strings are equal, dump them if not. */ int -test_assert_equal_string(const char *file, int line, +assertion_equal_string(const char *file, int line, const char *v1, const char *e1, const char *v2, const char *e2, 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'; + assertion_count(file, line); + if (v1 == v2 || (v1 != NULL && v2 != NULL && strcmp(v1, v2) == 0)) return (1); - } - 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); + failure_start(file, line, "%s != %s", e1, e2); + strdump(e1, v1); + strdump(e2, v2); + failure_finish(extra); return (0); } -static void wcsdump(const wchar_t *w) +static void +wcsdump(const char *e, const wchar_t *w) { + logprintf(" %s = ", e); if (w == NULL) { - fprintf(stderr, "(null)"); + logprintf("(null)"); return; } - fprintf(stderr, "\""); + logprintf("\""); while (*w != L'\0') { unsigned int c = *w++; if (c >= 32 && c < 127) - fprintf(stderr, "%c", c); + logprintf("%c", c); else if (c < 256) - fprintf(stderr, "\\x%02X", c); + logprintf("\\x%02X", c); else if (c < 0x10000) - fprintf(stderr, "\\u%04X", c); + logprintf("\\u%04X", c); else - fprintf(stderr, "\\U%08X", c); + logprintf("\\U%08X", c); } - fprintf(stderr, "\""); + logprintf("\"\n"); } -/* assertEqualWString() displays the values of the two strings. */ +/* Verify that two wide strings are equal, dump them if not. */ int -test_assert_equal_wstring(const char *file, int line, +assertion_equal_wstring(const char *file, int line, const wchar_t *v1, const char *e1, const wchar_t *v2, const char *e2, 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'; + assertion_count(file, line); + if (v1 == v2 || wcscmp(v1, v2) == 0) return (1); - } - 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); + failure_start(file, line, "%s != %s", e1, e2); + wcsdump(e1, v1); + wcsdump(e2, v2); + failure_finish(extra); return (0); } @@ -436,35 +513,40 @@ hexdump(const char *p, const char *ref, size_t i, j; char sep; + if (p == NULL) { + logprintf("(null)\n"); + return; + } for(i=0; i < l; i+=16) { - fprintf(stderr, "%04x", (unsigned)(i + offset)); + logprintf("%04x", (unsigned)(i + offset)); sep = ' '; for (j = 0; j < 16 && i + j < l; j++) { if (ref != NULL && p[i + j] != ref[i + j]) sep = '_'; - fprintf(stderr, "%c%02x", sep, 0xff & (int)p[i+j]); + logprintf("%c%02x", sep, 0xff & (int)p[i+j]); if (ref != NULL && p[i + j] == ref[i + j]) sep = ' '; } for (; j < 16; j++) { - fprintf(stderr, "%c ", sep); + logprintf("%c ", sep); sep = ' '; } - fprintf(stderr, "%c", sep); + logprintf("%c", sep); for (j=0; j < 16 && i + j < l; j++) { int c = p[i + j]; if (c >= ' ' && c <= 126) - fprintf(stderr, "%c", c); + logprintf("%c", c); else - fprintf(stderr, "."); + logprintf("."); } - fprintf(stderr, "\n"); + logprintf("\n"); } } -/* assertEqualMem() displays the values of the two memory blocks. */ +/* Verify that two blocks of memory are the same, display the first + * block of differences if they're not. */ int -test_assert_equal_mem(const char *file, int line, +assertion_equal_mem(const char *file, int line, const void *_v1, const char *e1, const void *_v2, const char *e2, size_t l, const char *ld, void *extra) @@ -473,200 +555,906 @@ test_assert_equal_mem(const char *file, const char *v2 = (const char *)_v2; 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'; + assertion_count(file, line); + if (v1 == v2 || (v1 != NULL && v2 != NULL && memcmp(v1, v2, l) == 0)) return (1); - } - 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); + + failure_start(file, line, "%s != %s", e1, e2); + logprintf(" 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. */ + /* Two lines agree, so step forward one line. */ v1 += 16; v2 += 16; l -= 16; offset += 16; } - fprintf(stderr, " Dump of %s\n", e1); + logprintf(" Dump of %s\n", e1); hexdump(v1, v2, l < 64 ? l : 64, offset); - fprintf(stderr, " Dump of %s\n", e2); + logprintf(" Dump of %s\n", e2); hexdump(v2, v1, l < 64 ? l : 64, offset); - fprintf(stderr, "\n"); - report_failure(extra); + logprintf("\n"); + failure_finish(extra); return (0); } +/* Verify that the named file exists and is empty. */ int -test_assert_empty_file(const char *f1fmt, ...) +assertion_empty_file(const char *f1fmt, ...) { char buff[1024]; char f1[1024]; struct stat st; va_list ap; ssize_t s; - int fd; - + FILE *f; + assertion_count(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); + failure_start(test_filename, test_line, "Stat failed: %s", f1); + failure_finish(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"); - fd = open(f1, O_RDONLY); - if (fd < 0) { - fprintf(stderr, " Unable to open %s\n", f1); + failure_start(test_filename, test_line, "File should be empty: %s", f1); + logprintf(" File size: %d\n", (int)st.st_size); + logprintf(" Contents:\n"); + f = fopen(f1, "rb"); + if (f == NULL) { + logprintf(" Unable to open %s\n", f1); } else { - s = sizeof(buff) < st.st_size ? sizeof(buff) : st.st_size; - s = read(fd, buff, s); + 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); } - report_failure(NULL); + failure_finish(NULL); return (0); } -/* assertEqualFile() asserts that two files have the same contents. */ +/* Verify that the named file exists and is not empty. */ +int +assertion_non_empty_file(const char *f1fmt, ...) *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***