source: web/old/remctl-2.14/tests/util/xmalloc.c @ f6f3e91

web
Last change on this file since f6f3e91 was f6f3e91, checked in by Jessica B. Hamrick <jhamrick@…>, 15 years ago

Preserve directory hierarchy (not sure what happened to it)

  • Property mode set to 100644
File size: 7.7 KB
Line 
1/*
2 * Test suite for xmalloc and family.
3 *
4 * Copyright 2008 Board of Trustees, Leland Stanford Jr. University
5 * Copyright 2004, 2005, 2006
6 *     by Internet Systems Consortium, Inc. ("ISC")
7 * Copyright 1991, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
8 *     2003 by The Internet Software Consortium and Rich Salz
9 *
10 * See LICENSE for licensing terms.
11 */
12
13#line 1 "xmalloc.c"
14
15#include <config.h>
16#include <portable/system.h>
17
18#include <ctype.h>
19#include <errno.h>
20#include <sys/time.h>
21
22/* Linux requires sys/time.h be included before sys/resource.h. */
23#include <sys/resource.h>
24
25#include <util/util.h>
26
27
28/*
29 * A customized error handler for checking xmalloc's support of them.  Prints
30 * out the error message and exits with status 1.
31 */
32static void
33test_handler(const char *function, size_t size, const char *file, int line)
34{
35    die("%s %lu %s %d", function, (unsigned long) size, file, line);
36}
37
38
39/*
40 * Allocate the amount of memory given and write to all of it to make sure we
41 * can, returning true if that succeeded and false on any sort of detectable
42 * error.
43 */
44static int
45test_malloc(size_t size)
46{
47    char *buffer;
48    size_t i;
49
50    buffer = xmalloc(size);
51    if (buffer == NULL)
52        return 0;
53    if (size > 0)
54        memset(buffer, 1, size);
55    for (i = 0; i < size; i++)
56        if (buffer[i] != 1)
57            return 0;
58    free(buffer);
59    return 1;
60}
61
62
63/*
64 * Allocate half the memory given, write to it, then reallocate to the desired
65 * size, writing to the rest and then checking it all.  Returns true on
66 * success, false on any failure.
67 */
68static int
69test_realloc(size_t size)
70{
71    char *buffer;
72    size_t i;
73
74    buffer = xmalloc(10);
75    if (buffer == NULL)
76        return 0;
77    memset(buffer, 1, 10);
78    buffer = xrealloc(buffer, size);
79    if (buffer == NULL)
80        return 0;
81    if (size > 0)
82        memset(buffer + 10, 2, size - 10);
83    for (i = 0; i < 10; i++)
84        if (buffer[i] != 1)
85            return 0;
86    for (i = 10; i < size; i++)
87        if (buffer[i] != 2)
88            return 0;
89    free(buffer);
90    return 1;
91}
92
93
94/*
95 * Generate a string of the size indicated, call xstrdup on it, and then
96 * ensure the result matches.  Returns true on success, false on any failure.
97 */
98static int
99test_strdup(size_t size)
100{
101    char *string, *copy;
102    int match;
103
104    string = xmalloc(size);
105    if (string == NULL)
106        return 0;
107    memset(string, 1, size - 1);
108    string[size - 1] = '\0';
109    copy = xstrdup(string);
110    if (copy == NULL)
111        return 0;
112    match = strcmp(string, copy);
113    free(string);
114    free(copy);
115    return (match == 0);
116}
117
118
119/*
120 * Generate a string of the size indicated plus some, call xstrndup on it, and
121 * then ensure the result matches.  Returns true on success, false on any
122 * failure.
123 */
124static int
125test_strndup(size_t size)
126{
127    char *string, *copy;
128    int match, toomuch;
129
130    string = xmalloc(size + 1);
131    if (string == NULL)
132        return 0;
133    memset(string, 1, size - 1);
134    string[size - 1] = 2;
135    string[size] = '\0';
136    copy = xstrndup(string, size - 1);
137    if (copy == NULL)
138        return 0;
139    match = strncmp(string, copy, size - 1);
140    toomuch = strcmp(string, copy);
141    free(string);
142    free(copy);
143    return (match == 0 && toomuch != 0);
144}
145
146
147/*
148 * Allocate the amount of memory given and check that it's all zeroed,
149 * returning true if that succeeded and false on any sort of detectable error.
150 */
151static int
152test_calloc(size_t size)
153{
154    char *buffer;
155    size_t i, nelems;
156
157    nelems = size / 4;
158    if (nelems * 4 != size)
159        return 0;
160    buffer = xcalloc(nelems, 4);
161    if (buffer == NULL)
162        return 0;
163    for (i = 0; i < size; i++)
164        if (buffer[i] != 0)
165            return 0;
166    free(buffer);
167    return 1;
168}
169
170
171/*
172 * Test asprintf with a large string (essentially using it as strdup).
173 * Returns true if successful, false otherwise.
174 */
175static int
176test_asprintf(size_t size)
177{
178    char *copy, *string;
179    int status;
180    size_t i;
181
182    string = xmalloc(size);
183    memset(string, 42, size - 1);
184    string[size - 1] = '\0';
185    status = xasprintf(&copy, "%s", string);
186    free(string);
187    for (i = 0; i < size - 1; i++)
188        if (copy[i] != 42)
189            return 0;
190    if (copy[size - 1] != '\0')
191        return 0;
192    free(copy);
193    return 1;
194}
195
196
197/* Wrapper around vasprintf to do the va_list stuff. */
198static int
199xvasprintf_wrapper(char **strp, const char *format, ...)
200{
201    va_list args;
202    int status;
203
204    va_start(args, format);
205    status = xvasprintf(strp, format, args);
206    va_end(args);
207    return status;
208}
209
210
211/*
212 * Test vasprintf with a large string (essentially using it as strdup).
213 * Returns true if successful, false otherwise.
214 */
215static int
216test_vasprintf(size_t size)
217{
218    char *copy, *string;
219    int status;
220    size_t i;
221
222    string = xmalloc(size);
223    memset(string, 42, size - 1);
224    string[size - 1] = '\0';
225    status = xvasprintf_wrapper(&copy, "%s", string);
226    free(string);
227    for (i = 0; i < size - 1; i++)
228        if (copy[i] != 42)
229            return 0;
230    if (copy[size - 1] != '\0')
231        return 0;
232    free(copy);
233    return 1;
234}
235
236
237/*
238 * Take the amount of memory to allocate in bytes as a command-line argument
239 * and call test_malloc with that amount of memory.
240 */
241int
242main(int argc, char *argv[])
243{
244    size_t size, max;
245    size_t limit = 0;
246    int willfail = 0;
247    unsigned char code;
248    struct rlimit rl;
249    void *tmp;
250
251    if (argc < 3)
252        die("Usage error.  Type, size, and limit must be given.");
253    errno = 0;
254    size = strtol(argv[2], 0, 10);
255    if (size == 0 && errno != 0)
256        sysdie("Invalid size");
257    errno = 0;
258    limit = strtol(argv[3], 0, 10);
259    if (limit == 0 && errno != 0)
260        sysdie("Invalid limit");
261
262    /* If the code is capitalized, install our customized error handler. */
263    code = argv[1][0];
264    if (isupper(code)) {
265        xmalloc_error_handler = test_handler;
266        code = tolower(code);
267    }
268
269    /*
270     * Decide if the allocation should fail.  If it should, set willfail to 2,
271     * so that if it unexpectedly succeeds, we exit with a status indicating
272     * that the test should be skipped.
273     */
274    max = size;
275    if (code == 's' || code == 'n' || code == 'a' || code == 'v') {
276        max += size;
277        if (limit > 0)
278            limit += size;
279    }
280    if (limit > 0 && max > limit)
281        willfail = 2;
282
283    /*
284     * If a memory limit was given and we can set memory limits, set it.
285     * Otherwise, exit 2, signalling to the driver that the test should be
286     * skipped.  We do this here rather than in the driver due to some
287     * pathological problems with Linux (setting ulimit in the shell caused
288     * the shell to die).
289     */
290    if (limit > 0) {
291#if HAVE_SETRLIMIT && defined(RLIMIT_AS)
292        rl.rlim_cur = limit;
293        rl.rlim_max = limit;
294        if (setrlimit(RLIMIT_AS, &rl) < 0) {
295            syswarn("Can't set data limit to %lu", (unsigned long) limit);
296            exit(2);
297        }
298        if (size < limit || code == 'r') {
299            tmp = malloc(code == 'r' ? 10 : size);
300            if (tmp == NULL) {
301                syswarn("Can't allocate initial memory of %lu",
302                        (unsigned long) size);
303                exit(2);
304            }
305            free(tmp);
306        }
307#else
308        warn("Data limits aren't supported.");
309        exit(2);
310#endif
311    }
312
313    switch (code) {
314    case 'c': exit(test_calloc(size) ? willfail : 1);
315    case 'm': exit(test_malloc(size) ? willfail : 1);
316    case 'r': exit(test_realloc(size) ? willfail : 1);
317    case 's': exit(test_strdup(size) ? willfail : 1);
318    case 'n': exit(test_strndup(size) ? willfail : 1);
319    case 'a': exit(test_asprintf(size) ? willfail : 1);
320    case 'v': exit(test_vasprintf(size) ? willfail : 1);
321    default:
322        die("Unknown mode %c", argv[1][0]);
323        break;
324    }
325    exit(1);
326}
Note: See TracBrowser for help on using the repository browser.