]> git.sur5r.net Git - openldap/blob - tests/progs/slapd-tester.c
fix testers (tnx to Luca)
[openldap] / tests / progs / slapd-tester.c
1 /* $OpenLDAP$ */
2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
3  *
4  * Copyright 1999-2005 The OpenLDAP Foundation.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted only as authorized by the OpenLDAP
9  * Public License.
10  *
11  * A copy of this license is available in file LICENSE in the
12  * top-level directory of the distribution or, alternatively, at
13  * <http://www.OpenLDAP.org/license.html>.
14  */
15 /* ACKNOWLEDGEMENTS:
16  * This work was initially developed by Kurt Spanier for inclusion
17  * in OpenLDAP Software.
18  */
19
20 #include "portable.h"
21
22 #include <stdio.h>
23
24 #include <ac/stdlib.h>
25
26 #include <ac/ctype.h>
27 #include <ac/dirent.h>
28 #include <ac/param.h>
29 #include <ac/socket.h>
30 #include <ac/string.h>
31 #include <ac/unistd.h>
32 #include <ac/wait.h>
33
34
35 #include "ldap_defaults.h"
36
37
38 #define SEARCHCMD               "slapd-search"
39 #define READCMD                 "slapd-read"
40 #define ADDCMD                  "slapd-addel"
41 #define MODRDNCMD               "slapd-modrdn"
42 #define MODIFYCMD               "slapd-modify"
43 #define MAXARGS                 100
44 #define MAXREQS                 5000
45 #define LOOPS                   "100"
46 #define RETRIES                 "0"
47
48 #define TSEARCHFILE             "do_search.0"
49 #define TREADFILE               "do_read.0"
50 #define TADDFILE                "do_add."
51 #define TMODRDNFILE             "do_modrdn.0"
52 #define TMODIFYFILE             "do_modify.0"
53
54 static char *get_file_name( char *dirname, char *filename );
55 static int  get_search_filters( char *filename, char *filters[], char *bases[] );
56 static int  get_read_entries( char *filename, char *entries[] );
57 static void fork_child( char *prog, char **args );
58 static void     wait4kids( int nkidval );
59
60 static int      maxkids = 20;
61 static int      nkids;
62
63 #ifdef HAVE_WINSOCK
64 static HANDLE   *children;
65 static char argbuf[BUFSIZ];
66 #define ArgDup(x) strdup(strcat(strcat(strcpy(argbuf,"\""),x),"\""))
67 #else
68 #define ArgDup(x) strdup(x)
69 #endif
70
71 static void
72 usage( char *name )
73 {
74         fprintf( stderr,
75                 "usage: %s "
76                 "-H <uri> | ([-h <host>] -p <port>) "
77                 "-D <manager> "
78                 "-w <passwd> "
79                 "-d <datadir> "
80                 "[-j <maxchild>] "
81                 "[-l <loops>] "
82                 "-P <progdir> "
83                 "[-r <maxretries>]\n",
84                 name );
85         exit( EXIT_FAILURE );
86 }
87
88 int
89 main( int argc, char **argv )
90 {
91         int             i, j;
92         char            *uri = NULL;
93         char            *host = "localhost";
94         char            *port = NULL;
95         char            *manager = NULL;
96         char            *passwd = NULL;
97         char            *dirname = NULL;
98         char            *progdir = NULL;
99         char            *loops = LOOPS;
100         char            *retries = RETRIES;
101         DIR                     *datadir;
102         struct dirent   *file;
103         char            *sfile = NULL;
104         char            *sreqs[MAXREQS];
105         char            *sbase[MAXREQS];
106         int         snum = 0;
107         char            *rfile = NULL;
108         char            *rreqs[MAXREQS];
109         int         rnum = 0;
110         char            *afiles[MAXREQS];
111         int         anum = 0;
112         char            *mfile = NULL;
113         char            *mreqs[MAXREQS];
114         int             mnum = 0;
115         char            *sargs[MAXARGS];
116         int                     sanum;
117         char            scmd[MAXPATHLEN];
118         char            *rargs[MAXARGS];
119         int                     ranum;
120         char            rcmd[MAXPATHLEN];
121         char            *aargs[MAXARGS];
122         int                     aanum;
123         char            acmd[MAXPATHLEN];
124         char            *margs[MAXARGS];
125         int             manum;
126         char            mcmd[MAXPATHLEN];
127         char            *modargs[MAXARGS];
128         int             modanum;
129         char            modcmd[MAXPATHLEN];
130         char            *modfile = NULL;
131         char            *modreqs[MAXREQS];
132         char            *moddn[MAXREQS];
133         int             modnum = 0;
134
135         while ( (i = getopt( argc, argv, "D:d:H:h:j:l:P:p:r:w:" )) != EOF ) {
136                 switch( i ) {
137                 case 'D':               /* slapd manager */
138                         manager = ArgDup( optarg );
139                         break;
140
141                 case 'd':               /* data directory */
142                         dirname = strdup( optarg );
143                         break;
144
145                 case 'H':               /* slapd uri */
146                         uri = strdup( optarg );
147                         break;
148
149                 case 'h':               /* slapd host */
150                         host = strdup( optarg );
151                         break;
152
153                 case 'j':               /* the number of parallel clients */
154                         maxkids = atoi( optarg );
155                         break;
156
157                 case 'l':               /* the number of loops per client */
158                         loops = strdup( optarg );
159                         break;
160
161                 case 'P':               /* prog directory */
162                         progdir = strdup( optarg );
163                         break;
164
165                 case 'p':               /* the servers port number */
166                         port = strdup( optarg );
167                         break;
168
169                 case 'r':
170                         retries = strdup( optarg );
171                         break;
172
173                 case 'w':               /* the managers passwd */
174                         passwd = ArgDup( optarg );
175                         break;
176
177                 default:
178                         usage( argv[0] );
179                         break;
180                 }
181         }
182
183         if (( dirname == NULL ) || ( port == NULL && uri == NULL ) ||
184                         ( manager == NULL ) || ( passwd == NULL ) || ( progdir == NULL ))
185                 usage( argv[0] );
186
187 #ifdef HAVE_WINSOCK
188         children = malloc( maxkids * sizeof(HANDLE) );
189 #endif
190         /* get the file list */
191         if ( ( datadir = opendir( dirname )) == NULL ) {
192
193                 fprintf( stderr, "%s: couldn't open data directory \"%s\".\n",
194                                         argv[0], dirname );
195                 exit( EXIT_FAILURE );
196
197         }
198
199         /*  look for search, read, modrdn, and add/delete files */
200         for ( file = readdir( datadir ); file; file = readdir( datadir )) {
201
202                 if ( !strcasecmp( file->d_name, TSEARCHFILE )) {
203                         sfile = get_file_name( dirname, file->d_name );
204                         continue;
205                 } else if ( !strcasecmp( file->d_name, TREADFILE )) {
206                         rfile = get_file_name( dirname, file->d_name );
207                         continue;
208                 } else if ( !strcasecmp( file->d_name, TMODRDNFILE )) {
209                         mfile = get_file_name( dirname, file->d_name );
210                         continue;
211                 } else if ( !strcasecmp( file->d_name, TMODIFYFILE )) {
212                         modfile = get_file_name( dirname, file->d_name );
213                         continue;
214                 } else if ( !strncasecmp( file->d_name, TADDFILE, strlen( TADDFILE ))
215                         && ( anum < MAXREQS )) {
216                         afiles[anum++] = get_file_name( dirname, file->d_name );
217                         continue;
218                 }
219         }
220
221         closedir( datadir );
222
223         /* look for search requests */
224         if ( sfile ) {
225                 snum = get_search_filters( sfile, sreqs, sbase );
226         }
227
228         /* look for read requests */
229         if ( rfile ) {
230                 rnum = get_read_entries( rfile, rreqs );
231         }
232
233         /* look for modrdn requests */
234         if ( mfile ) {
235                 mnum = get_read_entries( mfile, mreqs );
236         }
237         /* look for modify requests */
238         if ( modfile ) {
239                 modnum = get_search_filters( modfile, modreqs, moddn );
240         }
241
242         /*
243          * generate the search clients
244          */
245
246         sanum = 0;
247         snprintf( scmd, sizeof scmd, "%s" LDAP_DIRSEP SEARCHCMD,
248                 progdir );
249         sargs[sanum++] = scmd;
250         if ( uri ) {
251                 sargs[sanum++] = "-H";
252                 sargs[sanum++] = uri;
253         } else {
254                 sargs[sanum++] = "-h";
255                 sargs[sanum++] = host;
256                 sargs[sanum++] = "-p";
257                 sargs[sanum++] = port;
258         }
259         sargs[sanum++] = "-D";
260         sargs[sanum++] = manager;
261         sargs[sanum++] = "-w";
262         sargs[sanum++] = passwd;
263         sargs[sanum++] = "-l";
264         sargs[sanum++] = loops;
265         sargs[sanum++] = "-r";
266         sargs[sanum++] = retries;
267         sargs[sanum++] = "-b";
268         sargs[sanum++] = NULL;          /* will hold the search base */
269         sargs[sanum++] = "-f";
270         sargs[sanum++] = NULL;          /* will hold the search request */
271         sargs[sanum++] = NULL;
272
273         /*
274          * generate the read clients
275          */
276
277         ranum = 0;
278         snprintf( rcmd, sizeof rcmd, "%s" LDAP_DIRSEP READCMD,
279                 progdir );
280         rargs[ranum++] = rcmd;
281         if ( uri ) {
282                 rargs[ranum++] = "-H";
283                 rargs[ranum++] = uri;
284         } else {
285                 rargs[ranum++] = "-h";
286                 rargs[ranum++] = host;
287                 rargs[ranum++] = "-p";
288                 rargs[ranum++] = port;
289         }
290         rargs[ranum++] = "-l";
291         rargs[ranum++] = loops;
292         rargs[ranum++] = "-r";
293         rargs[ranum++] = retries;
294         rargs[ranum++] = "-e";
295         rargs[ranum++] = NULL;          /* will hold the read entry */
296         rargs[ranum++] = NULL;
297
298         /*
299          * generate the modrdn clients
300          */
301
302         manum = 0;
303         snprintf( mcmd, sizeof mcmd, "%s" LDAP_DIRSEP MODRDNCMD,
304                 progdir );
305         margs[manum++] = mcmd;
306         if ( uri ) {
307                 margs[manum++] = "-H";
308                 margs[manum++] = uri;
309         } else {
310                 margs[manum++] = "-h";
311                 margs[manum++] = host;
312                 margs[manum++] = "-p";
313                 margs[manum++] = port;
314         }
315         margs[manum++] = "-D";
316         margs[manum++] = manager;
317         margs[manum++] = "-w";
318         margs[manum++] = passwd;
319         margs[manum++] = "-l";
320         margs[manum++] = loops;
321         margs[manum++] = "-r";
322         margs[manum++] = retries;
323         margs[manum++] = "-e";
324         margs[manum++] = NULL;          /* will hold the modrdn entry */
325         margs[manum++] = NULL;
326         
327         /*
328          * generate the modify clients
329          */
330
331         modanum = 0;
332         snprintf( modcmd, sizeof modcmd, "%s" LDAP_DIRSEP MODIFYCMD,
333                 progdir );
334         modargs[modanum++] = modcmd;
335         if ( uri ) {
336                 modargs[modanum++] = "-H";
337                 modargs[modanum++] = uri;
338         } else {
339                 modargs[modanum++] = "-h";
340                 modargs[modanum++] = host;
341                 modargs[modanum++] = "-p";
342                 modargs[modanum++] = port;
343         }
344         modargs[modanum++] = "-D";
345         modargs[modanum++] = manager;
346         modargs[modanum++] = "-w";
347         modargs[modanum++] = passwd;
348         modargs[modanum++] = "-l";
349         modargs[modanum++] = loops;
350         modargs[modanum++] = "-r";
351         modargs[modanum++] = retries;
352         modargs[modanum++] = "-e";
353         modargs[modanum++] = NULL;              /* will hold the modify entry */
354         modargs[modanum++] = "-a";;
355         modargs[modanum++] = NULL;              /* will hold the ava */
356         modargs[modanum++] = NULL;
357
358         /*
359          * generate the add/delete clients
360          */
361
362         aanum = 0;
363         snprintf( acmd, sizeof acmd, "%s" LDAP_DIRSEP ADDCMD,
364                 progdir );
365         aargs[aanum++] = acmd;
366         if ( uri ) {
367                 aargs[aanum++] = "-H";
368                 aargs[aanum++] = uri;
369         } else {
370                 aargs[aanum++] = "-h";
371                 aargs[aanum++] = host;
372                 aargs[aanum++] = "-p";
373                 aargs[aanum++] = port;
374         }
375         aargs[aanum++] = "-D";
376         aargs[aanum++] = manager;
377         aargs[aanum++] = "-w";
378         aargs[aanum++] = passwd;
379         aargs[aanum++] = "-l";
380         aargs[aanum++] = loops;
381         aargs[aanum++] = "-r";
382         aargs[aanum++] = retries;
383         aargs[aanum++] = "-f";
384         aargs[aanum++] = NULL;          /* will hold the add data file */
385         aargs[aanum++] = NULL;
386
387         for ( j = 0; j < MAXREQS; j++ ) {
388
389                 if ( j < snum ) {
390
391                         sargs[sanum - 2] = sreqs[j];
392                         sargs[sanum - 4] = sbase[j];
393                         fork_child( scmd, sargs );
394
395                 }
396
397                 if ( j < rnum ) {
398
399                         rargs[ranum - 2] = rreqs[j];
400                         fork_child( rcmd, rargs );
401
402                 }
403
404                 if ( j < mnum ) {
405
406                         margs[manum - 2] = mreqs[j];
407                         fork_child( mcmd, margs );
408
409                 }
410                 if ( j < modnum ) {
411
412                         modargs[modanum - 4] = moddn[j];
413                         modargs[modanum - 2] = modreqs[j];
414                         fork_child( modcmd, modargs );
415
416                 }
417
418                 if ( j < anum ) {
419
420                         aargs[aanum - 2] = afiles[j];
421                         fork_child( acmd, aargs );
422
423                 }
424
425         }
426
427         wait4kids( -1 );
428
429         exit( EXIT_SUCCESS );
430 }
431
432 static char *
433 get_file_name( char *dirname, char *filename )
434 {
435         char buf[MAXPATHLEN];
436
437         snprintf( buf, sizeof buf, "%s" LDAP_DIRSEP "%s",
438                 dirname, filename );
439         return( strdup( buf ));
440 }
441
442
443 static int
444 get_search_filters( char *filename, char *filters[], char *bases[] )
445 {
446         FILE    *fp;
447         int     filter = 0;
448
449         if ( (fp = fopen( filename, "r" )) != NULL ) {
450                 char  line[BUFSIZ];
451
452                 while (( filter < MAXREQS ) && ( fgets( line, BUFSIZ, fp ))) {
453                         char *nl;
454
455                         if (( nl = strchr( line, '\r' )) || ( nl = strchr( line, '\n' )))
456                                 *nl = '\0';
457                         bases[filter] = ArgDup( line );
458                         fgets( line, BUFSIZ, fp );
459                         if (( nl = strchr( line, '\r' )) || ( nl = strchr( line, '\n' )))
460                                 *nl = '\0';
461
462                         filters[filter++] = ArgDup( line );
463
464                 }
465                 fclose( fp );
466         }
467
468         return( filter );
469 }
470
471
472 static int
473 get_read_entries( char *filename, char *entries[] )
474 {
475         FILE    *fp;
476         int     entry = 0;
477
478         if ( (fp = fopen( filename, "r" )) != NULL ) {
479                 char  line[BUFSIZ];
480
481                 while (( entry < MAXREQS ) && ( fgets( line, BUFSIZ, fp ))) {
482                         char *nl;
483
484                         if (( nl = strchr( line, '\r' )) || ( nl = strchr( line, '\n' )))
485                                 *nl = '\0';
486                         entries[entry++] = ArgDup( line );
487
488                 }
489                 fclose( fp );
490         }
491
492         return( entry );
493 }
494
495 #ifndef HAVE_WINSOCK
496 static void
497 fork_child( char *prog, char **args )
498 {
499         pid_t   pid;
500
501         wait4kids( maxkids );
502
503         switch ( pid = fork() ) {
504         case 0:         /* child */
505 #ifdef HAVE_EBCDIC
506                 /* The __LIBASCII execvp only handles ASCII "prog",
507                  * we still need to translate the arg vec ourselves.
508                  */
509                 { char *arg2[MAXREQS];
510                 int i;
511
512                 for (i=0; args[i]; i++) {
513                         arg2[i] = ArgDup(args[i]);
514                         __atoe(arg2[i]);
515                 }
516                 arg2[i] = NULL;
517                 args = arg2; }
518 #endif
519                 execvp( prog, args );
520                 fprintf( stderr, "%s: ", prog );
521                 perror( "execv" );
522                 exit( EXIT_FAILURE );
523                 break;
524
525         case -1:        /* trouble */
526                 fprintf( stderr, "Could not fork to run %s\n", prog );
527                 perror( "fork" );
528                 break;
529
530         default:        /* parent */
531                 nkids++;
532                 break;
533         }
534 }
535
536 static void
537 wait4kids( int nkidval )
538 {
539         int             status;
540
541         while ( nkids >= nkidval ) {
542                 wait( &status );
543
544                 if ( WIFSTOPPED(status) ) {
545                         fprintf( stderr,
546                             "stopping: child stopped with signal %d\n",
547                             (int) WSTOPSIG(status) );
548
549                 } else if ( WIFSIGNALED(status) ) {
550                         fprintf( stderr, 
551                             "stopping: child terminated with signal %d%s\n",
552                             (int) WTERMSIG(status),
553 #ifdef WCOREDUMP
554                                 WCOREDUMP(status) ? ", core dumped" : ""
555 #else
556                                 ""
557 #endif
558                                 );
559                         exit( WEXITSTATUS(status)  );
560
561                 } else if ( WEXITSTATUS(status) != 0 ) {
562                         fprintf( stderr, 
563                             "stopping: child exited with status %d\n",
564                             (int) WEXITSTATUS(status) );
565                         exit( WEXITSTATUS(status) );
566
567                 } else {
568                         nkids--;
569                 }
570         }
571 }
572 #else
573
574 static void
575 wait4kids( int nkidval )
576 {
577         int rc, i;
578
579         while ( nkids >= nkidval ) {
580                 rc = WaitForMultipleObjects( nkids, children, FALSE, INFINITE );
581                 for ( i=rc - WAIT_OBJECT_0; i<nkids-1; i++)
582                         children[i] = children[i+1];
583                 nkids--;
584         }
585 }
586
587 static void
588 fork_child( char *prog, char **args )
589 {
590         int rc;
591
592         wait4kids( maxkids );
593
594         rc = _spawnvp( _P_NOWAIT, prog, args );
595
596         if ( rc == -1 ) {
597                 fprintf( stderr, "%s: ", prog );
598                 perror("spawnvp");
599         } else {
600                 children[nkids++] = (HANDLE)rc;
601         }
602 }
603 #endif