diff options
| author | Russ Allbery <rra@stanford.edu> | 2007-10-04 22:21:19 +0000 | 
|---|---|---|
| committer | Russ Allbery <rra@stanford.edu> | 2007-10-04 22:21:19 +0000 | 
| commit | 9ff667addf39128f43d08d4ec56a6a94ec3bb062 (patch) | |
| tree | 41cd39045fb2d37d343608af57aebf844ecd5690 /tests/util | |
| parent | 2f9387bdf0e047bbd193532c4fed209acabd0e7a (diff) | |
Initial import of a C portability framework and utility functions from
remctl so that the wallet client error handling can rest on a firmer
foundation.
Diffstat (limited to 'tests/util')
| -rw-r--r-- | tests/util/concat-t.c | 54 | ||||
| -rw-r--r-- | tests/util/messages-t.c | 278 | ||||
| -rw-r--r-- | tests/util/xmalloc-t.in | 107 | ||||
| -rw-r--r-- | tests/util/xmalloc.c | 294 | 
4 files changed, 733 insertions, 0 deletions
diff --git a/tests/util/concat-t.c b/tests/util/concat-t.c new file mode 100644 index 0000000..c18cd19 --- /dev/null +++ b/tests/util/concat-t.c @@ -0,0 +1,54 @@ +/* $Id$ */ +/* concat test suite. */ + +/* Copyright (c) 2004, 2005, 2006 +       by Internet Systems Consortium, Inc. ("ISC") +   Copyright (c) 1991, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, +       2002, 2003 by The Internet Software Consortium and Rich Salz + +   This code is derived from software contributed to the Internet Software +   Consortium by Rich Salz. + +   Permission to use, copy, modify, and distribute this software for any +   purpose with or without fee is hereby granted, provided that the above +   copyright notice and this permission notice appear in all copies. + +   THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH +   REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +   MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY +   SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +   WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +   ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +   OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include <config.h> +#include <system.h> + +#include <tests/libtest.h> +#include <util/util.h> + +#define END     (char *) 0 + +/* Memory leaks everywhere!  Whoo-hoo! */ +int +main(void) +{ +    test_init(13); + +    ok_string( 1, "a",     concat("a",                   END)); +    ok_string( 2, "ab",    concat("a", "b",              END)); +    ok_string( 3, "ab",    concat("ab", "",              END)); +    ok_string( 4, "ab",    concat("", "ab",              END)); +    ok_string( 5, "",      concat("",                    END)); +    ok_string( 6, "abcde", concat("ab", "c", "", "de",   END)); +    ok_string( 7, "abcde", concat("abc", "de", END, "f", END)); + +    ok_string( 8, "/foo",             concatpath("/bar", "/foo")); +    ok_string( 9, "/foo/bar",         concatpath("/foo", "bar")); +    ok_string(10, "./bar",            concatpath("/foo", "./bar")); +    ok_string(11, "/bar/baz/foo/bar", concatpath("/bar/baz", "foo/bar")); +    ok_string(12, "./foo",            concatpath(NULL, "foo")); +    ok_string(13, "/foo/bar",         concatpath(NULL, "/foo/bar")); + +    return 0; +} diff --git a/tests/util/messages-t.c b/tests/util/messages-t.c new file mode 100644 index 0000000..ef58737 --- /dev/null +++ b/tests/util/messages-t.c @@ -0,0 +1,278 @@ +/* $Id$ */ +/* Test suite for error handling routines. */ + +/* Copyright (c) 2004, 2005, 2006 +       by Internet Systems Consortium, Inc. ("ISC") +   Copyright (c) 1991, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, +       2002, 2003 by The Internet Software Consortium and Rich Salz + +   This code is derived from software contributed to the Internet Software +   Consortium by Rich Salz. + +   Permission to use, copy, modify, and distribute this software for any +   purpose with or without fee is hereby granted, provided that the above +   copyright notice and this permission notice appear in all copies. + +   THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH +   REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +   MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY +   SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +   WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +   ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +   OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include <config.h> +#include <system.h> + +#include <errno.h> +#include <fcntl.h> +#include <sys/stat.h> +#include <sys/wait.h> + +#include <tests/libtest.h> +#include <util/util.h> + +#define END     (char *) 0 + +/* Test function type. */ +typedef void (*test_function_t)(void); + +/* Fork and execute the provided function, connecting stdout and stderr to a +   pipe.  Captures the output into the provided buffer and returns the exit +   status as a waitpid status value. */ +static int +run_test(test_function_t function, char *buf, size_t buflen) +{ +    int fds[2]; +    pid_t child; +    ssize_t count, status; +    int rval; + +    /* Flush stdout before we start to avoid odd forking issues. */ +    fflush(stdout); + +    /* Set up the pipe and call the function, collecting its output. */ +    if (pipe(fds) == -1) +        sysdie("can't create pipe"); +    child = fork(); +    if (child == (pid_t) -1) { +        sysdie("can't fork"); +    } else if (child == 0) { +        /* In child.  Set up our stdout and stderr. */ +        close(fds[0]); +        if (dup2(fds[1], 1) == -1) +            _exit(255); +        if (dup2(fds[1], 2) == -1) +            _exit(255); + +        /* Now, run the function and exit successfully if it returns. */ +        (*function)(); +        fflush(stdout); +        _exit(0); +    } else { +        /* In the parent; close the extra file descriptor, read the output +           if any, and then collect the exit status. */ +        close(fds[1]); +        count = 0; +        do { +            status = read(fds[0], buf + count, buflen - count - 1); +            if (status > 0) +                count += status; +        } while (status > 0); +        buf[count < 0 ? 0 : count] = '\0'; +        if (waitpid(child, &rval, 0) == (pid_t) -1) +            sysdie("waitpid failed"); +    } +    return rval; +} + +/* Test functions. */ +static void test1(void) { warn("warning"); } +static void test2(void) { die("fatal"); } +static void test3(void) { errno = EPERM; syswarn("permissions"); } +static void test4(void) { errno = EACCES; sysdie("fatal access"); } +static void test5(void) { +    message_program_name = "test5"; +    warn("warning"); +} +static void test6(void) { +    message_program_name = "test6"; +    die("fatal"); +} +static void test7(void) { +    message_program_name = "test7"; +    errno = EPERM; +    syswarn("perms %d", 7); +} +static void test8(void) { +    message_program_name = "test8"; +    errno = EACCES; +    sysdie("%st%s", "fa", "al"); +} + +static int return10(void) { return 10; } + +static void test9(void) { +    message_fatal_cleanup = return10; +    die("fatal"); +} +static void test10(void) { +    message_program_name = 0; +    message_fatal_cleanup = return10; +    errno = EPERM; +    sysdie("fatal perm"); +} +static void test11(void) { +    message_program_name = "test11"; +    message_fatal_cleanup = return10; +    errno = EPERM; +    fputs("1st ", stdout); +    sysdie("fatal"); +} + +static void log_msg(int len, const char *format, va_list args, int error) { +    fprintf(stderr, "%d %d ", len, error); +    vfprintf(stderr, format, args); +    fprintf(stderr, "\n"); +} + +static void test12(void) { +    message_handlers_warn(1, log_msg); +    warn("warning"); +} +static void test13(void) { +    message_handlers_die(1, log_msg); +    die("fatal"); +} +static void test14(void) { +    message_handlers_warn(2, log_msg, log_msg); +    errno = EPERM; +    syswarn("warning"); +} +static void test15(void) { +    message_handlers_die(2, log_msg, log_msg); +    message_fatal_cleanup = return10; +    errno = EPERM; +    sysdie("fatal"); +} +static void test16(void) { +    message_handlers_warn(2, message_log_stderr, log_msg); +    message_program_name = "test16"; +    errno = EPERM; +    syswarn("warning"); +} +static void test17(void) { notice("notice"); } +static void test18(void) { +    message_program_name = "test18"; +    notice("notice"); +} +static void test19(void) { debug("debug"); } +static void test20(void) { +    message_handlers_notice(1, log_msg); +    notice("foo"); +} +static void test21(void) { +    message_handlers_debug(1, message_log_stdout); +    message_program_name = "test23"; +    debug("baz"); +} +static void test22(void) { +    message_handlers_die(0); +    die("hi mom!"); +} +static void test23(void) { +    message_handlers_warn(0); +    warn("this is a test"); +} +static void test24(void) { +    notice("first"); +    message_handlers_notice(0); +    notice("second"); +    message_handlers_notice(1, message_log_stdout); +    notice("third"); +} + +/* Given the test number, intended exit status and message, and the function +   to run, print ok or not ok. */ +static void +test_error(int n, int status, const char *output, test_function_t function) +{ +    int real_status; +    char buf[256]; +    int succeeded = 1; + +    real_status = run_test(function, buf, sizeof(buf)); +    if (!WIFEXITED(real_status) || status != WEXITSTATUS(real_status)) { +        printf("  unexpected exit status %d\n", real_status); +        succeeded = 0; +    } +    if (strcmp(output, buf)) { +        printf("  unexpected output: %s", buf); +        printf("    expected output: %s", output); +        succeeded = 0; +    } +    printf("%sok %d\n", succeeded ? "" : "not ", n); +} + +/* Given the test number, intended status, intended message sans the +   appended strerror output, errno, and the function to run, print ok or not +   ok. */ +static void +test_strerror(int n, int status, const char *output, int error, +              test_function_t function) +{ +    char *full_output; + +    full_output = concat(output, ": ", strerror(error), "\n", END); +    test_error(n, status, full_output, function); +    free(full_output); +} + +/* Run the tests. */ +int +main(void) +{ +    char buff[32]; + +    test_init(24); + +    test_error(1, 0, "warning\n", test1); +    test_error(2, 1, "fatal\n", test2); +    test_strerror(3, 0, "permissions", EPERM, test3); +    test_strerror(4, 1, "fatal access", EACCES, test4); +    test_error(5, 0, "test5: warning\n", test5); +    test_error(6, 1, "test6: fatal\n", test6); +    test_strerror(7, 0, "test7: perms 7", EPERM, test7); +    test_strerror(8, 1, "test8: fatal", EACCES, test8); +    test_error(9, 10, "fatal\n", test9); +    test_strerror(10, 10, "fatal perm", EPERM, test10); +    test_strerror(11, 10, "1st test11: fatal", EPERM, test11); +    test_error(12, 0, "7 0 warning\n", test12); +    test_error(13, 1, "5 0 fatal\n", test13); + +    sprintf(buff, "%d", EPERM); + +    test_error(14, 0, +               concat("7 ", buff, " warning\n7 ", buff, " warning\n", END), +               test14); +    test_error(15, 10, +               concat("5 ", buff, " fatal\n5 ", buff, " fatal\n", END), +               test15); +    test_error(16, 0, +               concat("test16: warning: ", strerror(EPERM), "\n7 ", buff, +                      " warning\n", END), +               test16); + +    test_error(17, 0, "notice\n", test17); +    test_error(18, 0, "test18: notice\n", test18); +    test_error(19, 0, "", test19); +    test_error(20, 0, "3 0 foo\n", test20); +    test_error(21, 0, "test23: baz\n", test21); + +    /* Make sure that it's possible to turn off a message type entirely. */  +    test_error(22, 1, "", test22); +    test_error(23, 0, "", test23); +    test_error(24, 0, "first\nthird\n", test24); + +    return 0; +} diff --git a/tests/util/xmalloc-t.in b/tests/util/xmalloc-t.in new file mode 100644 index 0000000..e4e971d --- /dev/null +++ b/tests/util/xmalloc-t.in @@ -0,0 +1,107 @@ +#! /bin/sh +# $Id$ +# +# Test suite for xmalloc and friends. + +# The count starts at 1 and is updated each time ok is printed.  printcount +# takes "ok" or "not ok". +count=1 +printcount () { +    echo "$1 $count $2" +    count=`expr $count + 1` +} + +# Run a program expected to succeed, and print ok if it does. +runsuccess () { +    output=`$xmalloc "$1" "$2" "$3" 2>&1 >/dev/null` +    status=$? +    if test $status = 0 && test -z "$output" ; then +        printcount "ok" +    else +        if test $status = 2 ; then +            printcount "ok" "# skip no data limit support" +        else +            printcount "not ok" +            echo "  $output" +        fi +    fi +} + +# Run a program expected to fail and make sure it fails with an exit status +# of 2 and the right failure message.  Strip the colon and everything after +# it off the error message since it's system-specific. +runfailure () { +    output=`$xmalloc "$1" "$2" "$3" 2>&1 >/dev/null` +    status=$? +    output=`echo "$output" | sed 's/:.*//' \ +                | sed 's% [^ ]*/xmalloc.c% xmalloc.c%'` +    if test $status = 1 && test x"$output" = x"$4" ; then +        printcount "ok" +    else +        if test $status = 2 ; then +            printcount "ok" "# skip no data limit support" +        else +            printcount "not ok" +            echo "  saw: $output" +            echo "  not: $4" +        fi +    fi +} + +# Find where the helper program is. +xmalloc="@abs_top_builddir@/tests/util/xmalloc" + +# Total tests. +echo 36 + +# First run the tests expected to succeed. +runsuccess "m" "21"     "0" +runsuccess "m" "128000" "0" +runsuccess "m" "0"      "0" +runsuccess "r" "21"     "0" +runsuccess "r" "128000" "0" +runsuccess "s" "21"     "0" +runsuccess "s" "128000" "0" +runsuccess "n" "21"     "0" +runsuccess "n" "128000" "0" +runsuccess "c" "24"     "0" +runsuccess "c" "128000" "0" +runsuccess "a" "24"     "0" +runsuccess "a" "128000" "0" +runsuccess "v" "24"     "0" +runsuccess "v" "128000" "0" + +# Now limit our memory to 120KB and then try the large ones again, all of +# which should fail. +runfailure "m" "128000" "120000" \ +    "failed to malloc 128000 bytes at xmalloc.c line 54" +runfailure "r" "128000" "120000" \ +    "failed to realloc 128000 bytes at xmalloc.c line 80" +runfailure "s" "64000"  "120000" \ +    "failed to strdup 64000 bytes at xmalloc.c line 109" +runfailure "n" "64000"  "120000" \ +    "failed to strndup 64000 bytes at xmalloc.c line 133" +runfailure "c" "128000" "120000" \ +    "failed to calloc 128000 bytes at xmalloc.c line 155" +runfailure "a" "64000" "120000" \ +    "failed to asprintf 64000 bytes at xmalloc.c line 177" +runfailure "v" "64000" "120000" \ +    "failed to vasprintf 64000 bytes at xmalloc.c line 196" + +# Check our custom error handler. +runfailure "M" "128000" "120000" "malloc 128000 xmalloc.c 54" +runfailure "R" "128000" "120000" "realloc 128000 xmalloc.c 80" +runfailure "S" "64000"  "120000" "strdup 64000 xmalloc.c 109" +runfailure "N" "64000"  "120000" "strndup 64000 xmalloc.c 133" +runfailure "C" "128000" "120000" "calloc 128000 xmalloc.c 155" +runfailure "A" "64000"  "120000" "asprintf 64000 xmalloc.c 177" +runfailure "V" "64000"  "120000" "vasprintf 64000 xmalloc.c 196" + +# Check the smaller ones again just for grins. +runsuccess "m" "21" "96000" +runsuccess "r" "32" "96000" +runsuccess "s" "64" "96000" +runsuccess "n" "20" "96000" +runsuccess "c" "24" "96000" +runsuccess "a" "30" "96000" +runsuccess "v" "35" "96000" diff --git a/tests/util/xmalloc.c b/tests/util/xmalloc.c new file mode 100644 index 0000000..4327681 --- /dev/null +++ b/tests/util/xmalloc.c @@ -0,0 +1,294 @@ +/* $Id$ */ +/* Test suite for xmalloc and family. */ + +/* Copyright (c) 2004, 2005, 2006 +       by Internet Systems Consortium, Inc. ("ISC") +   Copyright (c) 1991, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, +       2002, 2003 by The Internet Software Consortium and Rich Salz + +   This code is derived from software contributed to the Internet Software +   Consortium by Rich Salz. + +   Permission to use, copy, modify, and distribute this software for any +   purpose with or without fee is hereby granted, provided that the above +   copyright notice and this permission notice appear in all copies. + +   THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH +   REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +   MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY +   SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +   WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +   ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +   OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include <config.h> +#include <system.h> + +#include <ctype.h> +#include <errno.h> +#include <sys/time.h> +#include <unistd.h> + +/* Linux requires sys/time.h be included before sys/resource.h. */ +#include <sys/resource.h> + +#include <util/util.h> + +/* A customized error handler for checking xmalloc's support of them. +   Prints out the error message and exits with status 1. */ +static void +test_handler(const char *function, size_t size, const char *file, int line) +{ +    die("%s %lu %s %d", function, (unsigned long) size, file, line); +} + +/* Allocate the amount of memory given and write to all of it to make sure +   we can, returning true if that succeeded and false on any sort of +   detectable error. */ +static int +test_malloc(size_t size) +{ +    char *buffer; +    size_t i; + +    buffer = xmalloc(size); +    if (buffer == NULL) +        return 0; +    if (size > 0) +        memset(buffer, 1, size); +    for (i = 0; i < size; i++) +        if (buffer[i] != 1) +            return 0; +    free(buffer); +    return 1; +} + +/* Allocate half the memory given, write to it, then reallocate to the +   desired size, writing to the rest and then checking it all.  Returns true +   on success, false on any failure. */ +static int +test_realloc(size_t size) +{ +    char *buffer; +    size_t i; + +    buffer = xmalloc(size / 2); +    if (buffer == NULL) +        return 0; +    if (size / 2 > 0) +        memset(buffer, 1, size / 2); +    buffer = xrealloc(buffer, size); +    if (buffer == NULL) +        return 0; +    if (size > 0) +        memset(buffer + size / 2, 2, size - size / 2); +    for (i = 0; i < size / 2; i++) +        if (buffer[i] != 1) +            return 0; +    for (i = size / 2; i < size; i++) +        if (buffer[i] != 2) +            return 0; +    free(buffer); +    return 1; +} + +/* Generate a string of the size indicated, call xstrdup on it, and then +   ensure the result matches.  Returns true on success, false on any +   failure. */ +static int +test_strdup(size_t size) +{ +    char *string, *copy; +    int match; + +    string = xmalloc(size); +    if (string == NULL) +        return 0; +    memset(string, 1, size - 1); +    string[size - 1] = '\0'; +    copy = xstrdup(string); +    if (copy == NULL) +        return 0; +    match = strcmp(string, copy); +    free(string); +    free(copy); +    return (match == 0); +} + +/* Generate a string of the size indicated plus some, call xstrndup on it, and +   then ensure the result matches.  Returns true on success, false on any +   failure. */ +static int +test_strndup(size_t size) +{ +    char *string, *copy; +    int match, toomuch; + +    string = xmalloc(size + 1); +    if (string == NULL) +        return 0; +    memset(string, 1, size - 1); +    string[size - 1] = 2; +    string[size] = '\0'; +    copy = xstrndup(string, size - 1); +    if (copy == NULL) +        return 0; +    match = strncmp(string, copy, size - 1); +    toomuch = strcmp(string, copy); +    free(string); +    free(copy); +    return (match == 0 && toomuch != 0); +} + +/* Allocate the amount of memory given and check that it's all zeroed, +   returning true if that succeeded and false on any sort of detectable +   error. */ +static int +test_calloc(size_t size) +{ +    char *buffer; +    size_t i, nelems; + +    nelems = size / 4; +    if (nelems * 4 != size) +        return 0; +    buffer = xcalloc(nelems, 4); +    if (buffer == NULL) +        return 0; +    for (i = 0; i < size; i++) +        if (buffer[i] != 0) +            return 0; +    free(buffer); +    return 1; +} + +/* Test asprintf with a large string (essentially using it as strdup). +   Returns true if successful, false otherwise. */ +static int +test_asprintf(size_t size) +{ +    char *copy, *string; +    int status; +    size_t i; + +    string = xmalloc(size); +    memset(string, 42, size - 1); +    string[size - 1] = '\0'; +    status = xasprintf(©, "%s", string); +    free(string); +    for (i = 0; i < size - 1; i++) +        if (copy[i] != 42) +            return 0; +    if (copy[size - 1] != '\0') +        return 0; +    free(copy); +    return 1; +} + +/* Wrapper around vasprintf to do the va_list stuff. */ +static int +xvasprintf_wrapper(char **strp, const char *format, ...) +{ +    va_list args; +    int status; + +    va_start(args, format); +    status = xvasprintf(strp, format, args); +    va_end(args); +    return status; +} + +/* Test vasprintf with a large string (essentially using it as strdup). +   Returns true if successful, false otherwise. */ +static int +test_vasprintf(size_t size) +{ +    char *copy, *string; +    int status; +    size_t i; + +    string = xmalloc(size); +    memset(string, 42, size - 1); +    string[size - 1] = '\0'; +    status = xvasprintf_wrapper(©, "%s", string); +    free(string); +    for (i = 0; i < size - 1; i++) +        if (copy[i] != 42) +            return 0; +    if (copy[size - 1] != '\0') +        return 0; +    free(copy); +    return 1; +} + +/* Take the amount of memory to allocate in bytes as a command-line argument +   and call test_malloc with that amount of memory. */ +int +main(int argc, char *argv[]) +{ +    size_t size, max; +    size_t limit = 0; +    int willfail = 0; +    unsigned char code; +    struct rlimit rl; + +    if (argc < 3) +        die("Usage error.  Type, size, and limit must be given."); +    errno = 0; +    size = strtol(argv[2], 0, 10); +    if (size == 0 && errno != 0) +        sysdie("Invalid size"); +    errno = 0; +    limit = strtol(argv[3], 0, 10); +    if (limit == 0 && errno != 0) +        sysdie("Invalid limit"); + +    /* If a memory limit was given and we can set memory limits, set it. +       Otherwise, exit 2, signalling to the driver that the test should be +       skipped.  We do this here rather than in the driver due to some +       pathological problems with Linux (setting ulimit in the shell caused +       the shell to die). */ +    if (limit > 0) { +#if HAVE_SETRLIMIT && defined(RLIMIT_DATA) +        rl.rlim_cur = limit; +        rl.rlim_max = limit; +        if (setrlimit(RLIMIT_DATA, &rl) < 0) { +            syswarn("Can't set data limit to %lu", (unsigned long) limit); +            exit(2); +        } +#else +        warn("Data limits aren't supported."); +        exit(2); +#endif +    } + +    /* If the code is capitalized, install our customized error handler. */ +    code = argv[1][0]; +    if (isupper(code)) { +        xmalloc_error_handler = test_handler; +        code = tolower(code); +    } + +    /* Decide if the allocation should fail.  If it should, set willfail to +       2, so that if it unexpectedly succeeds, we exit with a status +       indicating that the test should be skipped. */ +    max = size; +    if (code == 's' || code == 'n' || code == 'a' || code == 'v') +        max *= 2; +    if (limit > 0 && max > limit) +        willfail = 2; + +    switch (code) { +    case 'c': exit(test_calloc(size) ? willfail : 1); +    case 'm': exit(test_malloc(size) ? willfail : 1); +    case 'r': exit(test_realloc(size) ? willfail : 1); +    case 's': exit(test_strdup(size) ? willfail : 1); +    case 'n': exit(test_strndup(size) ? willfail : 1); +    case 'a': exit(test_asprintf(size) ? willfail : 1); +    case 'v': exit(test_vasprintf(size) ? willfail : 1); +    default: +        die("Unknown mode %c", argv[1][0]); +        break; +    } +    exit(1); +}  | 
