1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/nsprpub/pr/tests/dbmalloc.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,310 @@ 1.4 +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +/*********************************************************************** 1.10 +** 1.11 +** Name: dbmalloc.c 1.12 +** 1.13 +** Description: Testing malloc (OBSOLETE) 1.14 +** 1.15 +** Modification History: 1.16 +** 14-May-97 AGarcia- Converted the test to accomodate the debug_mode flag. 1.17 +** The debug mode will print all of the printfs associated with this test. 1.18 +** The regress mode will be the default mode. Since the regress tool limits 1.19 +** the output to a one line status:PASS or FAIL,all of the printf statements 1.20 +** have been handled with an if (debug_mode) statement. 1.21 +***********************************************************************/ 1.22 +#include <stdio.h> 1.23 +#include <stdlib.h> 1.24 +#include <time.h> 1.25 +#include <string.h> 1.26 +#include "nspr.h" 1.27 + 1.28 +void 1.29 +usage 1.30 +( 1.31 + void 1.32 +) 1.33 +{ 1.34 + fprintf(stderr, "Usage: dbmalloc ('-m'|'-s') '-f' num_fails ('-d'|'-n') filename [...]\n"); 1.35 + exit(0); 1.36 +} 1.37 + 1.38 +typedef struct node_struct 1.39 +{ 1.40 + struct node_struct *next, *prev; 1.41 + int line; 1.42 + char value[4]; 1.43 +} 1.44 + node_t, 1.45 + *node_pt; 1.46 + 1.47 +node_pt get_node(const char *line) 1.48 +{ 1.49 + node_pt rv; 1.50 + int l = strlen(line); 1.51 + rv = (node_pt)PR_MALLOC(sizeof(node_t) + l + 1 - 4); 1.52 + if( (node_pt)0 == rv ) return (node_pt)0; 1.53 + memcpy(&rv->value[0], line, l+1); 1.54 + rv->next = rv->prev = (node_pt)0; 1.55 + return rv; 1.56 +} 1.57 + 1.58 +void 1.59 +dump 1.60 +( 1.61 + const char *name, 1.62 + node_pt node, 1.63 + int mf, 1.64 + int debug 1.65 +) 1.66 +{ 1.67 + if( (node_pt)0 != node->prev ) dump(name, node->prev, mf, debug); 1.68 + if( 0 != debug ) printf("[%s]: %6d: %s", name, node->line, node->value); 1.69 + if( node->line == mf ) fprintf(stderr, "[%s]: Line %d was allocated!\n", name, node->line); 1.70 + if( (node_pt)0 != node->next ) dump(name, node->next, mf, debug); 1.71 + return; 1.72 +} 1.73 + 1.74 +void 1.75 +release 1.76 +( 1.77 + node_pt node 1.78 +) 1.79 +{ 1.80 + if( (node_pt)0 != node->prev ) release(node->prev); 1.81 + if( (node_pt)0 != node->next ) release(node->next); 1.82 + PR_DELETE(node); 1.83 +} 1.84 + 1.85 +int 1.86 +t2 1.87 +( 1.88 + const char *name, 1.89 + int mf, 1.90 + int debug 1.91 +) 1.92 +{ 1.93 + int rv; 1.94 + FILE *fp; 1.95 + int l = 0; 1.96 + node_pt head = (node_pt)0; 1.97 + char buffer[ BUFSIZ ]; 1.98 + 1.99 + fp = fopen(name, "r"); 1.100 + if( (FILE *)0 == fp ) 1.101 + { 1.102 + fprintf(stderr, "[%s]: Cannot open \"%s.\"\n", name, name); 1.103 + return -1; 1.104 + } 1.105 + 1.106 + /* fgets mallocs a buffer, first time through. */ 1.107 + if( (char *)0 == fgets(buffer, BUFSIZ, fp) ) 1.108 + { 1.109 + fprintf(stderr, "[%s]: \"%s\" is empty.\n", name, name); 1.110 + (void)fclose(fp); 1.111 + return -1; 1.112 + } 1.113 + 1.114 + rewind(fp); 1.115 + 1.116 + if( PR_SUCCESS != PR_ClearMallocCount() ) 1.117 + { 1.118 + fprintf(stderr, "[%s]: Cannot clear malloc count.\n", name); 1.119 + (void)fclose(fp); 1.120 + return -1; 1.121 + } 1.122 + 1.123 + if( PR_SUCCESS != PR_SetMallocCountdown(mf) ) 1.124 + { 1.125 + fprintf(stderr, "[%s]: Cannot set malloc countdown to %d\n", name, mf); 1.126 + (void)fclose(fp); 1.127 + return -1; 1.128 + } 1.129 + 1.130 + while( fgets(buffer, BUFSIZ, fp) ) 1.131 + { 1.132 + node_pt n; 1.133 + node_pt *w = &head; 1.134 + 1.135 + if( (strlen(buffer) == (BUFSIZ-1)) && (buffer[BUFSIZ-2] != '\n') ) 1.136 + buffer[BUFSIZ-2] == '\n'; 1.137 + 1.138 + l++; 1.139 + 1.140 + n = get_node(buffer); 1.141 + if( (node_pt)0 == n ) 1.142 + { 1.143 + printf("[%s]: Line %d: malloc failure!\n", name, l); 1.144 + continue; 1.145 + } 1.146 + 1.147 + n->line = l; 1.148 + 1.149 + while( 1 ) 1.150 + { 1.151 + int comp; 1.152 + 1.153 + if( (node_pt)0 == *w ) 1.154 + { 1.155 + *w = n; 1.156 + break; 1.157 + } 1.158 + 1.159 + comp = strcmp((*w)->value, n->value); 1.160 + if( comp < 0 ) w = &(*w)->next; 1.161 + else w = &(*w)->prev; 1.162 + } 1.163 + } 1.164 + 1.165 + (void)fclose(fp); 1.166 + 1.167 + dump(name, head, mf, debug); 1.168 + 1.169 + rv = PR_GetMallocCount(); 1.170 + PR_ClearMallocCountdown(); 1.171 + 1.172 + release(head); 1.173 + 1.174 + return rv; 1.175 +} 1.176 + 1.177 +int nf = 0; 1.178 +int debug = 0; 1.179 + 1.180 +void 1.181 +test 1.182 +( 1.183 + const char *name 1.184 +) 1.185 +{ 1.186 + int n, i; 1.187 + 1.188 + extern int nf, debug; 1.189 + 1.190 + printf("[%s]: starting test 0\n", name); 1.191 + n = t2(name, 0, debug); 1.192 + if( -1 == n ) return; 1.193 + printf("[%s]: test 0 had %ld allocations.\n", name, n); 1.194 + 1.195 + if( 0 >= n ) return; 1.196 + 1.197 + for( i = 0; i < nf; i++ ) 1.198 + { 1.199 + int which = rand() % n; 1.200 + if( 0 == which ) printf("[%s]: starting test %d -- no allocation should fail\n", name, i+1); 1.201 + else printf("[%s]: starting test %d -- allocation %d should fail\n", name, i+1, which); 1.202 + (void)t2(name, which, debug); 1.203 + printf("[%s]: test %d done.\n", name, i+1); 1.204 + } 1.205 + 1.206 + return; 1.207 +} 1.208 + 1.209 +int main(int argc, char **argv) 1.210 +{ 1.211 + int okay = 0; 1.212 + int multithread = 0; 1.213 + 1.214 + struct threadlist 1.215 + { 1.216 + struct threadlist *next; 1.217 + PRThread *thread; 1.218 + } 1.219 + *threadhead = (struct threadlist *)0; 1.220 + 1.221 + extern int nf, debug; 1.222 + 1.223 + srand(time(0)); 1.224 + 1.225 + PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0); 1.226 + PR_STDIO_INIT(); 1.227 + 1.228 + printf("[main]: We %s using the debugging malloc.\n", 1.229 + PR_IsDebuggingMalloc() ? "ARE" : "ARE NOT"); 1.230 + 1.231 + while( argv++, --argc ) 1.232 + { 1.233 + if( '-' == argv[0][0] ) 1.234 + { 1.235 + switch( argv[0][1] ) 1.236 + { 1.237 + case 'f': 1.238 + nf = atoi(argv[0][2] ? &argv[0][2] : 1.239 + --argc ? *++argv : "0"); 1.240 + break; 1.241 + case 'd': 1.242 + debug = 1; 1.243 + break; 1.244 + case 'n': 1.245 + debug = 0; 1.246 + break; 1.247 + case 'm': 1.248 + multithread = 1; 1.249 + break; 1.250 + case 's': 1.251 + multithread = 0; 1.252 + break; 1.253 + default: 1.254 + usage(); 1.255 + break; 1.256 + } 1.257 + } 1.258 + else 1.259 + { 1.260 + FILE *fp = fopen(*argv, "r"); 1.261 + if( (FILE *)0 == fp ) 1.262 + { 1.263 + fprintf(stderr, "Cannot open \"%s.\"\n", *argv); 1.264 + continue; 1.265 + } 1.266 + 1.267 + okay++; 1.268 + (void)fclose(fp); 1.269 + if( multithread ) 1.270 + { 1.271 + struct threadlist *n; 1.272 + 1.273 + n = (struct threadlist *)malloc(sizeof(struct threadlist)); 1.274 + if( (struct threadlist *)0 == n ) 1.275 + { 1.276 + fprintf(stderr, "This is getting tedious. \"%s\"\n", *argv); 1.277 + continue; 1.278 + } 1.279 + 1.280 + n->next = threadhead; 1.281 + n->thread = PR_CreateThread(PR_USER_THREAD, (void (*)(void *))test, 1.282 + *argv, PR_PRIORITY_NORMAL, 1.283 + PR_LOCAL_THREAD, PR_JOINABLE_THREAD, 1.284 + 0); 1.285 + if( (PRThread *)0 == n->thread ) 1.286 + { 1.287 + fprintf(stderr, "Can't create thread for \"%s.\"\n", *argv); 1.288 + continue; 1.289 + } 1.290 + else 1.291 + { 1.292 + threadhead = n; 1.293 + } 1.294 + } 1.295 + else 1.296 + { 1.297 + test(*argv); 1.298 + } 1.299 + } 1.300 + } 1.301 + 1.302 + if( okay == 0 ) usage(); 1.303 + else while( (struct threadlist *)0 != threadhead ) 1.304 + { 1.305 + struct threadlist *x = threadhead->next; 1.306 + (void)PR_JoinThread(threadhead->thread); 1.307 + PR_DELETE(threadhead); 1.308 + threadhead = x; 1.309 + } 1.310 + 1.311 + return 0; 1.312 +} 1.313 +