1*538aa54dSGarrett D'Amore /* 2*538aa54dSGarrett D'Amore * This file and its contents are supplied under the terms of the 3*538aa54dSGarrett D'Amore * Common Development and Distribution License ("CDDL"), version 1.0. 4*538aa54dSGarrett D'Amore * You may only use this file in accordance with the terms of version 5*538aa54dSGarrett D'Amore * 1.0 of the CDDL. 6*538aa54dSGarrett D'Amore * 7*538aa54dSGarrett D'Amore * A full copy of the text of the CDDL should have accompanied this 8*538aa54dSGarrett D'Amore * source. A copy of the CDDL is also available via the Internet at 9*538aa54dSGarrett D'Amore * http://www.illumos.org/license/CDDL. 10*538aa54dSGarrett D'Amore */ 11*538aa54dSGarrett D'Amore 12*538aa54dSGarrett D'Amore /* 13*538aa54dSGarrett D'Amore * Copyright 2014 Garrett D'Amore <garrett@damore.org> 14*538aa54dSGarrett D'Amore */ 15*538aa54dSGarrett D'Amore 16*538aa54dSGarrett D'Amore /* 17*538aa54dSGarrett D'Amore * Common handling for test programs. 18*538aa54dSGarrett D'Amore */ 19*538aa54dSGarrett D'Amore 20*538aa54dSGarrett D'Amore #include <stdio.h> 21*538aa54dSGarrett D'Amore #include <stdlib.h> 22*538aa54dSGarrett D'Amore #include <stdarg.h> 23*538aa54dSGarrett D'Amore #include <pthread.h> 24*538aa54dSGarrett D'Amore #include "test_common.h" 25*538aa54dSGarrett D'Amore 26*538aa54dSGarrett D'Amore static int debug = 0; 27*538aa54dSGarrett D'Amore static int force = 0; 28*538aa54dSGarrett D'Amore static pthread_mutex_t lk; 29*538aa54dSGarrett D'Amore 30*538aa54dSGarrett D'Amore struct test { 31*538aa54dSGarrett D'Amore char *name; 32*538aa54dSGarrett D'Amore int ntids; 33*538aa54dSGarrett D'Amore pthread_t *tids; 34*538aa54dSGarrett D'Amore int fails; 35*538aa54dSGarrett D'Amore void *arg; 36*538aa54dSGarrett D'Amore void (*func)(test_t t, void *); 37*538aa54dSGarrett D'Amore }; 38*538aa54dSGarrett D'Amore 39*538aa54dSGarrett D'Amore void 40*538aa54dSGarrett D'Amore test_set_debug(void) 41*538aa54dSGarrett D'Amore { 42*538aa54dSGarrett D'Amore debug++; 43*538aa54dSGarrett D'Amore } 44*538aa54dSGarrett D'Amore 45*538aa54dSGarrett D'Amore void 46*538aa54dSGarrett D'Amore test_set_force(void) 47*538aa54dSGarrett D'Amore { 48*538aa54dSGarrett D'Amore force++; 49*538aa54dSGarrett D'Amore } 50*538aa54dSGarrett D'Amore 51*538aa54dSGarrett D'Amore test_t 52*538aa54dSGarrett D'Amore test_start(const char *format, ...) 53*538aa54dSGarrett D'Amore { 54*538aa54dSGarrett D'Amore va_list args; 55*538aa54dSGarrett D'Amore test_t t; 56*538aa54dSGarrett D'Amore char *s; 57*538aa54dSGarrett D'Amore 58*538aa54dSGarrett D'Amore t = calloc(1, sizeof (*t)); 59*538aa54dSGarrett D'Amore va_start(args, format); 60*538aa54dSGarrett D'Amore (void) vasprintf(&s, format, args); 61*538aa54dSGarrett D'Amore va_end(args); 62*538aa54dSGarrett D'Amore 63*538aa54dSGarrett D'Amore (void) asprintf(&t->name, "%s (%s)", s, ARCH); 64*538aa54dSGarrett D'Amore free(s); 65*538aa54dSGarrett D'Amore 66*538aa54dSGarrett D'Amore (void) pthread_mutex_lock(&lk); 67*538aa54dSGarrett D'Amore (void) printf("TEST STARTING %s:\n", t->name); 68*538aa54dSGarrett D'Amore (void) fflush(stdout); 69*538aa54dSGarrett D'Amore (void) pthread_mutex_unlock(&lk); 70*538aa54dSGarrett D'Amore 71*538aa54dSGarrett D'Amore #ifdef LINT 72*538aa54dSGarrett D'Amore /* We inject references to make avoid name unused warnings */ 73*538aa54dSGarrett D'Amore test_run(0, NULL, NULL, NULL); 74*538aa54dSGarrett D'Amore test_debugf(t, NULL); 75*538aa54dSGarrett D'Amore test_failed(t, NULL); 76*538aa54dSGarrett D'Amore test_passed(t); 77*538aa54dSGarrett D'Amore test_set_debug(); 78*538aa54dSGarrett D'Amore test_set_force(); 79*538aa54dSGarrett D'Amore #endif 80*538aa54dSGarrett D'Amore 81*538aa54dSGarrett D'Amore return (t); 82*538aa54dSGarrett D'Amore 83*538aa54dSGarrett D'Amore } 84*538aa54dSGarrett D'Amore 85*538aa54dSGarrett D'Amore void 86*538aa54dSGarrett D'Amore test_failed(test_t t, const char *format, ...) 87*538aa54dSGarrett D'Amore { 88*538aa54dSGarrett D'Amore va_list args; 89*538aa54dSGarrett D'Amore 90*538aa54dSGarrett D'Amore (void) pthread_mutex_lock(&lk); 91*538aa54dSGarrett D'Amore if (force || (t->ntids > 0)) { 92*538aa54dSGarrett D'Amore (void) printf("TEST FAILING %s: ", t->name); 93*538aa54dSGarrett D'Amore } else { 94*538aa54dSGarrett D'Amore (void) printf("TEST FAILED %s: ", t->name); 95*538aa54dSGarrett D'Amore } 96*538aa54dSGarrett D'Amore 97*538aa54dSGarrett D'Amore va_start(args, format); 98*538aa54dSGarrett D'Amore (void) vprintf(format, args); 99*538aa54dSGarrett D'Amore va_end(args); 100*538aa54dSGarrett D'Amore (void) printf("\n"); 101*538aa54dSGarrett D'Amore (void) fflush(stdout); 102*538aa54dSGarrett D'Amore (void) pthread_mutex_unlock(&lk); 103*538aa54dSGarrett D'Amore 104*538aa54dSGarrett D'Amore t->fails++; 105*538aa54dSGarrett D'Amore if (!force) { 106*538aa54dSGarrett D'Amore if (t->ntids > 0) { 107*538aa54dSGarrett D'Amore pthread_exit(NULL); 108*538aa54dSGarrett D'Amore } else { 109*538aa54dSGarrett D'Amore (void) exit(EXIT_FAILURE); 110*538aa54dSGarrett D'Amore } 111*538aa54dSGarrett D'Amore } 112*538aa54dSGarrett D'Amore } 113*538aa54dSGarrett D'Amore 114*538aa54dSGarrett D'Amore void 115*538aa54dSGarrett D'Amore test_passed(test_t t) 116*538aa54dSGarrett D'Amore { 117*538aa54dSGarrett D'Amore if (t->ntids > 0) { 118*538aa54dSGarrett D'Amore if (debug) { 119*538aa54dSGarrett D'Amore (void) pthread_mutex_lock(&lk); 120*538aa54dSGarrett D'Amore (void) printf("TEST PASSING: %s\n", t->name); 121*538aa54dSGarrett D'Amore (void) pthread_mutex_unlock(&lk); 122*538aa54dSGarrett D'Amore } 123*538aa54dSGarrett D'Amore return; 124*538aa54dSGarrett D'Amore } 125*538aa54dSGarrett D'Amore (void) pthread_mutex_lock(&lk); 126*538aa54dSGarrett D'Amore if (t->fails == 0) { 127*538aa54dSGarrett D'Amore (void) printf("TEST PASS: %s\n", t->name); 128*538aa54dSGarrett D'Amore } else { 129*538aa54dSGarrett D'Amore (void) printf("TEST FAILED: %d failures\n", t->fails); 130*538aa54dSGarrett D'Amore } 131*538aa54dSGarrett D'Amore (void) fflush(stdout); 132*538aa54dSGarrett D'Amore (void) pthread_mutex_unlock(&lk); 133*538aa54dSGarrett D'Amore free(t->name); 134*538aa54dSGarrett D'Amore if (t->tids) { 135*538aa54dSGarrett D'Amore free(t->tids); 136*538aa54dSGarrett D'Amore } 137*538aa54dSGarrett D'Amore free(t); 138*538aa54dSGarrett D'Amore } 139*538aa54dSGarrett D'Amore 140*538aa54dSGarrett D'Amore void 141*538aa54dSGarrett D'Amore test_debugf(test_t t, const char *format, ...) 142*538aa54dSGarrett D'Amore { 143*538aa54dSGarrett D'Amore va_list args; 144*538aa54dSGarrett D'Amore 145*538aa54dSGarrett D'Amore if (!debug) 146*538aa54dSGarrett D'Amore return; 147*538aa54dSGarrett D'Amore 148*538aa54dSGarrett D'Amore (void) pthread_mutex_lock(&lk); 149*538aa54dSGarrett D'Amore (void) printf("TEST DEBUG %s: ", t->name); 150*538aa54dSGarrett D'Amore 151*538aa54dSGarrett D'Amore va_start(args, format); 152*538aa54dSGarrett D'Amore (void) vprintf(format, args); 153*538aa54dSGarrett D'Amore va_end(args); 154*538aa54dSGarrett D'Amore (void) printf("\n"); 155*538aa54dSGarrett D'Amore (void) fflush(stdout); 156*538aa54dSGarrett D'Amore (void) pthread_mutex_unlock(&lk); 157*538aa54dSGarrett D'Amore } 158*538aa54dSGarrett D'Amore 159*538aa54dSGarrett D'Amore static void * 160*538aa54dSGarrett D'Amore test_thr_one(void *arg) 161*538aa54dSGarrett D'Amore { 162*538aa54dSGarrett D'Amore test_t t = arg; 163*538aa54dSGarrett D'Amore t->func(t, t->arg); 164*538aa54dSGarrett D'Amore return (NULL); 165*538aa54dSGarrett D'Amore } 166*538aa54dSGarrett D'Amore 167*538aa54dSGarrett D'Amore void 168*538aa54dSGarrett D'Amore test_run(int nthr, void (*func)(test_t, void *), void *arg, 169*538aa54dSGarrett D'Amore const char *tname, ...) 170*538aa54dSGarrett D'Amore { 171*538aa54dSGarrett D'Amore test_t t; 172*538aa54dSGarrett D'Amore char *s; 173*538aa54dSGarrett D'Amore va_list args; 174*538aa54dSGarrett D'Amore 175*538aa54dSGarrett D'Amore t = calloc(1, sizeof (*t)); 176*538aa54dSGarrett D'Amore t->ntids = nthr; 177*538aa54dSGarrett D'Amore t->tids = calloc(nthr, sizeof (pthread_t)); 178*538aa54dSGarrett D'Amore t->func = func; 179*538aa54dSGarrett D'Amore t->arg = arg; 180*538aa54dSGarrett D'Amore 181*538aa54dSGarrett D'Amore va_start(args, tname); 182*538aa54dSGarrett D'Amore (void) vasprintf(&s, tname, args); 183*538aa54dSGarrett D'Amore va_end(args); 184*538aa54dSGarrett D'Amore 185*538aa54dSGarrett D'Amore (void) asprintf(&t->name, "%s (%s)", s, ARCH); 186*538aa54dSGarrett D'Amore free(s); 187*538aa54dSGarrett D'Amore 188*538aa54dSGarrett D'Amore (void) pthread_mutex_lock(&lk); 189*538aa54dSGarrett D'Amore (void) printf("TEST STARTING %s:\n", t->name); 190*538aa54dSGarrett D'Amore (void) fflush(stdout); 191*538aa54dSGarrett D'Amore (void) pthread_mutex_unlock(&lk); 192*538aa54dSGarrett D'Amore 193*538aa54dSGarrett D'Amore test_debugf(t, "running %d threads", nthr); 194*538aa54dSGarrett D'Amore 195*538aa54dSGarrett D'Amore for (int i = 0; i < nthr; i++) { 196*538aa54dSGarrett D'Amore test_debugf(t, "started thread %d", i); 197*538aa54dSGarrett D'Amore (void) pthread_create(&t->tids[i], NULL, test_thr_one, t); 198*538aa54dSGarrett D'Amore } 199*538aa54dSGarrett D'Amore 200*538aa54dSGarrett D'Amore for (int i = 0; i < nthr; i++) { 201*538aa54dSGarrett D'Amore (void) pthread_join(t->tids[i], NULL); 202*538aa54dSGarrett D'Amore test_debugf(t, "thread %d joined", i); 203*538aa54dSGarrett D'Amore t->ntids--; 204*538aa54dSGarrett D'Amore } 205*538aa54dSGarrett D'Amore test_passed(t); 206*538aa54dSGarrett D'Amore } 207