dbmalloc.c (6499B)
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* This Source Code Form is subject to the terms of the Mozilla Public 3 * License, v. 2.0. If a copy of the MPL was not distributed with this 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 5 6 /*********************************************************************** 7 ** 8 ** Name: dbmalloc.c 9 ** 10 ** Description: Testing malloc (OBSOLETE) 11 ** 12 ** Modification History: 13 ** 14-May-97 AGarcia- Converted the test to accomodate the debug_mode flag. 14 ** The debug mode will print all of the printfs associated with this 15 *test. 16 ** The regress mode will be the default mode. Since the regress tool 17 *limits 18 ** the output to a one line status:PASS or FAIL,all of the printf 19 *statements 20 ** have been handled with an if (debug_mode) statement. 21 ***********************************************************************/ 22 #include <stdio.h> 23 #include <stdlib.h> 24 #include <time.h> 25 #include <string.h> 26 #include "nspr.h" 27 28 void usage(void) { 29 fprintf(stderr, 30 "Usage: dbmalloc ('-m'|'-s') '-f' num_fails ('-d'|'-n') filename " 31 "[...]\n"); 32 exit(0); 33 } 34 35 typedef struct node_struct { 36 struct node_struct *next, *prev; 37 int line; 38 char value[4]; 39 } node_t, *node_pt; 40 41 node_pt get_node(const char* line) { 42 node_pt rv; 43 int l = strlen(line); 44 rv = (node_pt)PR_MALLOC(sizeof(node_t) + l + 1 - 4); 45 if ((node_pt)0 == rv) { 46 return (node_pt)0; 47 } 48 memcpy(&rv->value[0], line, l + 1); 49 rv->next = rv->prev = (node_pt)0; 50 return rv; 51 } 52 53 void dump(const char* name, node_pt node, int mf, int debug) { 54 if ((node_pt)0 != node->prev) { 55 dump(name, node->prev, mf, debug); 56 } 57 if (0 != debug) { 58 printf("[%s]: %6d: %s", name, node->line, node->value); 59 } 60 if (node->line == mf) { 61 fprintf(stderr, "[%s]: Line %d was allocated!\n", name, node->line); 62 } 63 if ((node_pt)0 != node->next) { 64 dump(name, node->next, mf, debug); 65 } 66 return; 67 } 68 69 void release(node_pt node) { 70 if ((node_pt)0 != node->prev) { 71 release(node->prev); 72 } 73 if ((node_pt)0 != node->next) { 74 release(node->next); 75 } 76 PR_DELETE(node); 77 } 78 79 int t2(const char* name, int mf, int debug) { 80 int rv; 81 FILE* fp; 82 int l = 0; 83 node_pt head = (node_pt)0; 84 char buffer[BUFSIZ]; 85 86 fp = fopen(name, "r"); 87 if ((FILE*)0 == fp) { 88 fprintf(stderr, "[%s]: Cannot open \"%s.\"\n", name, name); 89 return -1; 90 } 91 92 /* fgets mallocs a buffer, first time through. */ 93 if ((char*)0 == fgets(buffer, BUFSIZ, fp)) { 94 fprintf(stderr, "[%s]: \"%s\" is empty.\n", name, name); 95 (void)fclose(fp); 96 return -1; 97 } 98 99 rewind(fp); 100 101 if (PR_SUCCESS != PR_ClearMallocCount()) { 102 fprintf(stderr, "[%s]: Cannot clear malloc count.\n", name); 103 (void)fclose(fp); 104 return -1; 105 } 106 107 if (PR_SUCCESS != PR_SetMallocCountdown(mf)) { 108 fprintf(stderr, "[%s]: Cannot set malloc countdown to %d\n", name, mf); 109 (void)fclose(fp); 110 return -1; 111 } 112 113 while (fgets(buffer, BUFSIZ, fp)) { 114 node_pt n; 115 node_pt* w = &head; 116 117 if ((strlen(buffer) == (BUFSIZ - 1)) && (buffer[BUFSIZ - 2] != '\n')) { 118 buffer[BUFSIZ - 2] == '\n'; 119 } 120 121 l++; 122 123 n = get_node(buffer); 124 if ((node_pt)0 == n) { 125 printf("[%s]: Line %d: malloc failure!\n", name, l); 126 continue; 127 } 128 129 n->line = l; 130 131 while (1) { 132 int comp; 133 134 if ((node_pt)0 == *w) { 135 *w = n; 136 break; 137 } 138 139 comp = strcmp((*w)->value, n->value); 140 if (comp < 0) { 141 w = &(*w)->next; 142 } else { 143 w = &(*w)->prev; 144 } 145 } 146 } 147 148 (void)fclose(fp); 149 150 dump(name, head, mf, debug); 151 152 rv = PR_GetMallocCount(); 153 PR_ClearMallocCountdown(); 154 155 release(head); 156 157 return rv; 158 } 159 160 int nf = 0; 161 int debug = 0; 162 163 void test(const char* name) { 164 int n, i; 165 166 extern int nf, debug; 167 168 printf("[%s]: starting test 0\n", name); 169 n = t2(name, 0, debug); 170 if (-1 == n) { 171 return; 172 } 173 printf("[%s]: test 0 had %ld allocations.\n", name, n); 174 175 if (0 >= n) { 176 return; 177 } 178 179 for (i = 0; i < nf; i++) { 180 int which = rand() % n; 181 if (0 == which) { 182 printf("[%s]: starting test %d -- no allocation should fail\n", name, 183 i + 1); 184 } else { 185 printf("[%s]: starting test %d -- allocation %d should fail\n", name, 186 i + 1, which); 187 } 188 (void)t2(name, which, debug); 189 printf("[%s]: test %d done.\n", name, i + 1); 190 } 191 192 return; 193 } 194 195 int main(int argc, char** argv) { 196 int okay = 0; 197 int multithread = 0; 198 199 struct threadlist { 200 struct threadlist* next; 201 PRThread* thread; 202 }* threadhead = (struct threadlist*)0; 203 204 extern int nf, debug; 205 206 srand(time(0)); 207 208 PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0); 209 210 printf("[main]: We %s using the debugging malloc.\n", 211 PR_IsDebuggingMalloc() ? "ARE" : "ARE NOT"); 212 213 while (argv++, --argc) { 214 if ('-' == argv[0][0]) { 215 switch (argv[0][1]) { 216 case 'f': 217 nf = atoi(argv[0][2] ? &argv[0][2] : --argc ? *++argv : "0"); 218 break; 219 case 'd': 220 debug = 1; 221 break; 222 case 'n': 223 debug = 0; 224 break; 225 case 'm': 226 multithread = 1; 227 break; 228 case 's': 229 multithread = 0; 230 break; 231 default: 232 usage(); 233 break; 234 } 235 } else { 236 FILE* fp = fopen(*argv, "r"); 237 if ((FILE*)0 == fp) { 238 fprintf(stderr, "Cannot open \"%s.\"\n", *argv); 239 continue; 240 } 241 242 okay++; 243 (void)fclose(fp); 244 if (multithread) { 245 struct threadlist* n; 246 247 n = (struct threadlist*)malloc(sizeof(struct threadlist)); 248 if ((struct threadlist*)0 == n) { 249 fprintf(stderr, "This is getting tedious. \"%s\"\n", *argv); 250 continue; 251 } 252 253 n->next = threadhead; 254 n->thread = PR_CreateThread(PR_USER_THREAD, (void (*)(void*))test, 255 *argv, PR_PRIORITY_NORMAL, PR_LOCAL_THREAD, 256 PR_JOINABLE_THREAD, 0); 257 if ((PRThread*)0 == n->thread) { 258 fprintf(stderr, "Can't create thread for \"%s.\"\n", *argv); 259 continue; 260 } else { 261 threadhead = n; 262 } 263 } else { 264 test(*argv); 265 } 266 } 267 } 268 269 if (okay == 0) { 270 usage(); 271 } else 272 while ((struct threadlist*)0 != threadhead) { 273 struct threadlist* x = threadhead->next; 274 (void)PR_JoinThread(threadhead->thread); 275 PR_DELETE(threadhead); 276 threadhead = x; 277 } 278 279 return 0; 280 }