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