Print this page
5293 desire symbol visibility test
Reviewed by: Robert Mustacchi <rm@joyent.com>
Approved by: TBD
   1 /*
   2  * This file and its contents are supplied under the terms of the
   3  * Common Development and Distribution License ("CDDL"), version 1.0.
   4  * You may only use this file in accordance with the terms of version
   5  * 1.0 of the CDDL.
   6  *
   7  * A full copy of the text of the CDDL should have accompanied this
   8  * source.  A copy of the CDDL is also available via the Internet at
   9  * http://www.illumos.org/license/CDDL.
  10  */
  11 
  12 /*
  13  * Copyright 2014 Garrett D'Amore <garrett@damore.org>
  14  */
  15 
  16 /*
  17  * Common handling for test programs.
  18  */
  19 
  20 #include <stdio.h>
  21 #include <stdlib.h>
  22 #include <stdarg.h>


  23 #include <pthread.h>



  24 #include "test_common.h"
  25 
  26 static int debug = 0;
  27 static int force = 0;
  28 static pthread_mutex_t lk;
  29 



  30 struct test {
  31         char            *name;
  32         int             ntids;
  33         pthread_t       *tids;
  34         int             fails;
  35         void            *arg;
  36         void            (*func)(test_t t, void *);
  37 };
  38 
  39 void
  40 test_set_debug(void)
  41 {
  42         debug++;
  43 }
  44 
  45 void
  46 test_set_force(void)
  47 {
  48         force++;
  49 }


  59         va_start(args, format);
  60         (void) vasprintf(&s, format, args);
  61         va_end(args);
  62 
  63         (void) asprintf(&t->name, "%s (%s)", s, ARCH);
  64         free(s);
  65 
  66         (void) pthread_mutex_lock(&lk);
  67         (void) printf("TEST STARTING %s:\n", t->name);
  68         (void) fflush(stdout);
  69         (void) pthread_mutex_unlock(&lk);
  70 
  71 #ifdef  LINT
  72         /* We inject references to make avoid name unused warnings */
  73         test_run(0, NULL, NULL, NULL);
  74         test_debugf(t, NULL);
  75         test_failed(t, NULL);
  76         test_passed(t);
  77         test_set_debug();
  78         test_set_force();


  79 #endif
  80 

  81         return (t);
  82 
  83 }
  84 
  85 void
  86 test_failed(test_t t, const char *format, ...)
  87 {
  88         va_list args;
  89 
  90         (void) pthread_mutex_lock(&lk);










  91         if (force || (t->ntids > 0)) {
  92                 (void) printf("TEST FAILING %s: ", t->name);
  93         } else {
  94                 (void) printf("TEST FAILED %s: ", t->name);
  95         }
  96 
  97         va_start(args, format);
  98         (void) vprintf(format, args);
  99         va_end(args);
 100         (void) printf("\n");
 101         (void) fflush(stdout);
 102         (void) pthread_mutex_unlock(&lk);
 103 
 104         t->fails++;
 105         if (!force) {
 106                 if (t->ntids > 0) {
 107                         pthread_exit(NULL);
 108                 } else {
 109                         (void) exit(EXIT_FAILURE);
 110                 }
 111         }
 112 }
 113 
 114 void
 115 test_passed(test_t t)
 116 {



 117         if (t->ntids > 0) {
 118                 if (debug) {
 119                         (void) pthread_mutex_lock(&lk);
 120                         (void) printf("TEST PASSING: %s\n", t->name);
 121                         (void) pthread_mutex_unlock(&lk);
 122                 }
 123                 return;
 124         }
 125         (void) pthread_mutex_lock(&lk);
 126         if (t->fails == 0) {

 127                 (void) printf("TEST PASS: %s\n", t->name);
 128         } else {
 129                 (void) printf("TEST FAILED: %d failures\n", t->fails);
 130         }
 131         (void) fflush(stdout);
 132         (void) pthread_mutex_unlock(&lk);
 133         free(t->name);
 134         if (t->tids) {
 135                 free(t->tids);
 136         }
 137         free(t);
 138 }
 139 
 140 void











 141 test_debugf(test_t t, const char *format, ...)
 142 {
 143         va_list args;
 144 
 145         if (!debug)
 146                 return;
 147 
 148         (void) pthread_mutex_lock(&lk);

 149         (void) printf("TEST DEBUG %s: ", t->name);
 150 


 151         va_start(args, format);
 152         (void) vprintf(format, args);
 153         va_end(args);
 154         (void) printf("\n");
 155         (void) fflush(stdout);
 156         (void) pthread_mutex_unlock(&lk);
 157 }
 158 
 159 static void *
 160 test_thr_one(void *arg)
 161 {
 162         test_t t = arg;
 163         t->func(t, t->arg);
 164         return (NULL);
 165 }
 166 
 167 void
 168 test_run(int nthr, void (*func)(test_t, void *), void *arg,
 169     const char *tname, ...)
 170 {


 186         free(s);
 187 
 188         (void) pthread_mutex_lock(&lk);
 189         (void) printf("TEST STARTING %s:\n", t->name);
 190         (void) fflush(stdout);
 191         (void) pthread_mutex_unlock(&lk);
 192 
 193         test_debugf(t, "running %d threads", nthr);
 194 
 195         for (int i = 0; i < nthr; i++) {
 196                 test_debugf(t, "started thread %d", i);
 197                 (void) pthread_create(&t->tids[i], NULL, test_thr_one, t);
 198         }
 199 
 200         for (int i = 0; i < nthr; i++) {
 201                 (void) pthread_join(t->tids[i], NULL);
 202                 test_debugf(t, "thread %d joined", i);
 203                 t->ntids--;
 204         }
 205         test_passed(t);


































































































































































 206 }
   1 /*
   2  * This file and its contents are supplied under the terms of the
   3  * Common Development and Distribution License ("CDDL"), version 1.0.
   4  * You may only use this file in accordance with the terms of version
   5  * 1.0 of the CDDL.
   6  *
   7  * A full copy of the text of the CDDL should have accompanied this
   8  * source.  A copy of the CDDL is also available via the Internet at
   9  * http://www.illumos.org/license/CDDL.
  10  */
  11 
  12 /*
  13  * Copyright 2015 Garrett D'Amore <garrett@damore.org>
  14  */
  15 
  16 /*
  17  * Common handling for test programs.
  18  */
  19 
  20 #include <stdio.h>
  21 #include <stdlib.h>
  22 #include <stdarg.h>
  23 #include <string.h>
  24 #include <errno.h>
  25 #include <pthread.h>
  26 #include <ctype.h>
  27 #include <unistd.h>
  28 #include <sys/param.h>
  29 #include "test_common.h"
  30 
  31 static int debug = 0;
  32 static int force = 0;
  33 static pthread_mutex_t lk;
  34 
  35 static int passes;
  36 static int tests;
  37 
  38 struct test {
  39         char            *name;
  40         int             ntids;
  41         pthread_t       *tids;
  42         int             fails;
  43         void            *arg;
  44         void            (*func)(test_t t, void *);
  45 };
  46 
  47 void
  48 test_set_debug(void)
  49 {
  50         debug++;
  51 }
  52 
  53 void
  54 test_set_force(void)
  55 {
  56         force++;
  57 }


  67         va_start(args, format);
  68         (void) vasprintf(&s, format, args);
  69         va_end(args);
  70 
  71         (void) asprintf(&t->name, "%s (%s)", s, ARCH);
  72         free(s);
  73 
  74         (void) pthread_mutex_lock(&lk);
  75         (void) printf("TEST STARTING %s:\n", t->name);
  76         (void) fflush(stdout);
  77         (void) pthread_mutex_unlock(&lk);
  78 
  79 #ifdef  LINT
  80         /* We inject references to make avoid name unused warnings */
  81         test_run(0, NULL, NULL, NULL);
  82         test_debugf(t, NULL);
  83         test_failed(t, NULL);
  84         test_passed(t);
  85         test_set_debug();
  86         test_set_force();
  87         test_summary();
  88         (void) test_load_config(t, NULL, NULL);
  89 #endif
  90 
  91         tests++;
  92         return (t);

  93 }
  94 
  95 void
  96 test_failed(test_t t, const char *format, ...)
  97 {
  98         va_list args;
  99 
 100         (void) pthread_mutex_lock(&lk);
 101         if (t == NULL) {
 102                 (void) printf("FAILURE: ");
 103                 va_start(args, format);
 104                 (void) vprintf(format, args);
 105                 va_end(args);
 106                 (void) printf("\n");
 107                 (void) fflush(stdout);
 108                 (void) pthread_mutex_unlock(&lk);
 109                 return;
 110         }
 111         if (force || (t->ntids > 0)) {
 112                 (void) printf("TEST FAILING %s: ", t->name);
 113         } else {
 114                 (void) printf("TEST FAILED %s: ", t->name);
 115         }
 116 
 117         va_start(args, format);
 118         (void) vprintf(format, args);
 119         va_end(args);
 120         (void) printf("\n");
 121         (void) fflush(stdout);
 122         (void) pthread_mutex_unlock(&lk);
 123 
 124         t->fails++;
 125         if (!force) {
 126                 if (t->ntids > 0) {
 127                         pthread_exit(NULL);
 128                 } else {
 129                         (void) exit(EXIT_FAILURE);
 130                 }
 131         }
 132 }
 133 
 134 void
 135 test_passed(test_t t)
 136 {
 137         if (t == NULL) {
 138                 return;
 139         }
 140         if (t->ntids > 0) {
 141                 if (debug) {
 142                         (void) pthread_mutex_lock(&lk);
 143                         (void) printf("TEST PASSING: %s\n", t->name);
 144                         (void) pthread_mutex_unlock(&lk);
 145                 }
 146                 return;
 147         }
 148         (void) pthread_mutex_lock(&lk);
 149         if (t->fails == 0) {
 150                 passes++;
 151                 (void) printf("TEST PASS: %s\n", t->name);
 152         } else {
 153                 (void) printf("TEST FAILED: %d failures\n", t->fails);
 154         }
 155         (void) fflush(stdout);
 156         (void) pthread_mutex_unlock(&lk);
 157         free(t->name);
 158         if (t->tids) {
 159                 free(t->tids);
 160         }
 161         free(t);
 162 }
 163 
 164 void
 165 test_summary(void)
 166 {
 167         if (passes == tests) {
 168                 (void) printf("TEST SUMMARY: %d / %d (ok)\n", passes, tests);
 169         } else {
 170                 (void) printf("TEST SUMMARY: %d / %d (%d failing)\n",
 171                     passes, tests, tests - passes);
 172         }
 173 }
 174 
 175 void
 176 test_debugf(test_t t, const char *format, ...)
 177 {
 178         va_list args;
 179 
 180         if (!debug)
 181                 return;
 182 
 183         (void) pthread_mutex_lock(&lk);
 184         if (t) {
 185                 (void) printf("TEST DEBUG %s: ", t->name);
 186         } else {
 187                 (void) printf("TEST DEBUG: ");
 188         }
 189         va_start(args, format);
 190         (void) vprintf(format, args);
 191         va_end(args);
 192         (void) printf("\n");
 193         (void) fflush(stdout);
 194         (void) pthread_mutex_unlock(&lk);
 195 }
 196 
 197 static void *
 198 test_thr_one(void *arg)
 199 {
 200         test_t t = arg;
 201         t->func(t, t->arg);
 202         return (NULL);
 203 }
 204 
 205 void
 206 test_run(int nthr, void (*func)(test_t, void *), void *arg,
 207     const char *tname, ...)
 208 {


 224         free(s);
 225 
 226         (void) pthread_mutex_lock(&lk);
 227         (void) printf("TEST STARTING %s:\n", t->name);
 228         (void) fflush(stdout);
 229         (void) pthread_mutex_unlock(&lk);
 230 
 231         test_debugf(t, "running %d threads", nthr);
 232 
 233         for (int i = 0; i < nthr; i++) {
 234                 test_debugf(t, "started thread %d", i);
 235                 (void) pthread_create(&t->tids[i], NULL, test_thr_one, t);
 236         }
 237 
 238         for (int i = 0; i < nthr; i++) {
 239                 (void) pthread_join(t->tids[i], NULL);
 240                 test_debugf(t, "thread %d joined", i);
 241                 t->ntids--;
 242         }
 243         test_passed(t);
 244 }
 245 
 246 void
 247 test_trim(char **ptr)
 248 {
 249         char *p = *ptr;
 250         while (isspace(*p)) {
 251                 p++;
 252         }
 253         *ptr = p;
 254         p += strlen(p);
 255         while ((--p >= *ptr) && (isspace(*p))) {
 256                 *p = 0;
 257         }
 258 }
 259 
 260 #define MAXCB           20
 261 #define MAXFIELD        20
 262 
 263 int
 264 test_load_config(test_t t, const char *fname, ...)
 265 {
 266         va_list         va;
 267         const char      *keyws[MAXCB];
 268         test_cfg_func_t callbs[MAXCB];
 269         char            *fields[MAXFIELD];
 270         int             nfields;
 271 
 272         FILE            *cfg;
 273         char            line[1024];
 274         char            buf[1024];
 275         int             done;
 276         char            *ptr;
 277         char            *tok;
 278         char            *err;
 279         int             lineno;
 280         int             rv;
 281         int             found;
 282         char            path[MAXPATHLEN];
 283         int             i;
 284 
 285         va_start(va, fname);
 286         for (i = 0; i < MAXCB; i++) {
 287                 keyws[i] = (const char *)va_arg(va, const char *);
 288                 if (keyws[i] == NULL)
 289                         break;
 290                 callbs[i] = (test_cfg_func_t)va_arg(va, test_cfg_func_t);
 291         }
 292         va_end(va);
 293         if (i == MAXCB) {
 294                 test_debugf(t, "too many arguments to function >= %d", MAXCB);
 295         }
 296 
 297         found = 0;
 298 
 299         if (access(fname, F_OK) == 0) {
 300                 found++;
 301         }
 302         if (!found && fname[0] != '/') {
 303                 char *stf = getenv("STF_SUITE");
 304                 if (stf == NULL) {
 305                         stf = "../..";
 306                 }
 307                 (void) snprintf(path, sizeof (path), "%s/cfg/%s", stf, fname);
 308                 if (access(path, F_OK) == 0) {
 309                         fname = path;
 310                         found++;
 311                 } else {
 312                         (void) snprintf(path, sizeof (path), "cfg/%s", fname);
 313                         if (access(path, F_OK) == 0) {
 314                                 fname = path;
 315                                 found++;
 316                         }
 317                 }
 318         }
 319 
 320         if ((cfg = fopen(fname, "r")) ==  NULL) {
 321                 test_failed(t, "open(%s): %s", fname, strerror(errno));
 322                 return (-1);
 323         }
 324 
 325         line[0] = 0;
 326         done = 0;
 327         lineno = 0;
 328 
 329         while (!done) {
 330 
 331                 lineno++;
 332 
 333                 if (fgets(buf, sizeof (buf), cfg) == NULL) {
 334                         done++;
 335                 } else {
 336                         (void) strtok(buf, "\n");
 337                         if ((*buf != 0) && (buf[strlen(buf)-1] == '\\')) {
 338                                 /*
 339                                  * Continuation.  This isn't quite right,
 340                                  * as it doesn't allow for a "\" at the
 341                                  * end of line (no escaping).
 342                                  */
 343                                 buf[strlen(buf)-1] = 0;
 344                                 (void) strlcat(line, buf, sizeof (line));
 345                                 continue;
 346                         }
 347                         (void) strlcat(line, buf, sizeof (line));
 348                 }
 349 
 350                 /* got a line */
 351                 ptr = line;
 352                 test_trim(&ptr);
 353 
 354                 /* skip comments and empty lines */
 355                 if (ptr[0] == 0 || ptr[0] == '#') {
 356                         line[0] = 0;
 357                         continue;
 358                 }
 359 
 360                 tok = strsep(&ptr, "|");
 361                 if (tok == NULL) {
 362                         break;
 363                 }
 364                 test_trim(&tok);
 365 
 366                 for (nfields = 0; nfields < MAXFIELD; nfields++) {
 367                         fields[nfields] = strsep(&ptr, "|");
 368                         if (fields[nfields] == NULL) {
 369                                 break;
 370                         }
 371                         test_trim(&fields[nfields]);
 372                 }
 373 
 374                 found = 0;
 375                 rv = 0;
 376 
 377                 for (int i = 0; keyws[i] != NULL; i++) {
 378                         if (strcmp(tok, keyws[i]) == 0) {
 379                                 found++;
 380                                 err = NULL;
 381                                 rv = callbs[i](fields, nfields, &err);
 382                         }
 383                 }
 384                 if (!found) {
 385                         rv = -1;
 386                         err = NULL;
 387                         (void) asprintf(&err, "unknown keyword %s", tok);
 388                 }
 389                 if (rv != 0) {
 390                         if (err) {
 391                                 test_failed(t, "%s:%d: %s", fname,
 392                                     lineno, err);
 393                                 free(err);
 394                         } else {
 395                                 test_failed(t, "%s:%d: unknown error",
 396                                     fname, lineno);
 397                         }
 398                         (void) fclose(cfg);
 399                         return (rv);
 400                 }
 401 
 402                 line[0] = 0;
 403         }
 404         (void) fclose(cfg);
 405         return (0);
 406 }