Missing NULL pointer init in tap.c
[lttng-ust.git] / tests / tap.c
CommitLineData
d23b20e9
JG
1/*-
2 * Copyright (c) 2004 Nik Clayton
3 * All rights reserved.
48beefc9 4 *
d23b20e9
JG
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
48beefc9 13 *
d23b20e9
JG
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
48beefc9 25 */
d23b20e9
JG
26
27#define _GNU_SOURCE
28#include <ctype.h>
48beefc9
NC
29#include <stdarg.h>
30#include <stdio.h>
d23b20e9
JG
31#include <stdlib.h>
32
33#include "tap.h"
34
35static int no_plan = 0;
36static int skip_all = 0;
37static int have_plan = 0;
38static unsigned int test_count = 0; /* Number of tests that have been run */
39static unsigned int e_tests = 0; /* Expected number of tests to run */
40static unsigned int failures = 0; /* Number of tests that failed */
41static char *todo_msg = NULL;
42static char *todo_msg_fixed = "libtap malloc issue";
43static int todo = 0;
44static int test_died = 0;
45
46/* Encapsulate the pthread code in a conditional. In the absence of
47 libpthread the code does nothing */
48#ifdef HAVE_LIBPTHREAD
49#include <pthread.h>
50static pthread_mutex_t M = PTHREAD_MUTEX_INITIALIZER;
51# define LOCK pthread_mutex_lock(&M);
52# define UNLOCK pthread_mutex_unlock(&M);
53#else
54# define LOCK
55# define UNLOCK
56#endif
57
58static void _expected_tests(unsigned int);
59static void _tap_init(void);
60static void _cleanup(void);
61
62/*
63 * Generate a test result.
64 *
65 * ok -- boolean, indicates whether or not the test passed.
66 * test_name -- the name of the test, may be NULL
67 * test_comment -- a comment to print afterwards, may be NULL
68 */
69unsigned int
70_gen_result(int ok, const char *func, char *file, unsigned int line,
71 char *test_name, ...)
72{
73 va_list ap;
74 char *local_test_name = NULL;
75 char *c;
76 int name_is_digits;
77
78 LOCK;
79
80 test_count++;
81
82 /* Start by taking the test name and performing any printf()
83 expansions on it */
84 if(test_name != NULL) {
85 va_start(ap, test_name);
86 vasprintf(&local_test_name, test_name, ap);
87 va_end(ap);
88
89 /* Make sure the test name contains more than digits
90 and spaces. Emit an error message and exit if it
91 does */
92 if(local_test_name) {
93 name_is_digits = 1;
94 for(c = local_test_name; *c != '\0'; c++) {
95 if(!isdigit(*c) && !isspace(*c)) {
96 name_is_digits = 0;
97 break;
98 }
99 }
100
101 if(name_is_digits) {
102 diag(" You named your test '%s'. You shouldn't use numbers for your test names.", local_test_name);
103 diag(" Very confusing.");
104 }
105 }
106 }
48beefc9 107
d23b20e9
JG
108 if(!ok) {
109 printf("not ");
110 failures++;
111 }
48beefc9 112
d23b20e9
JG
113 printf("ok %d", test_count);
114
115 if(test_name != NULL) {
116 printf(" - ");
117
118 /* Print the test name, escaping any '#' characters it
119 might contain */
120 if(local_test_name != NULL) {
121 flockfile(stdout);
122 for(c = local_test_name; *c != '\0'; c++) {
123 if(*c == '#')
124 fputc('\\', stdout);
125 fputc((int)*c, stdout);
126 }
127 funlockfile(stdout);
128 } else { /* vasprintf() failed, use a fixed message */
129 printf("%s", todo_msg_fixed);
130 }
131 }
48beefc9 132
d23b20e9
JG
133 /* If we're in a todo_start() block then flag the test as being
134 TODO. todo_msg should contain the message to print at this
135 point. If it's NULL then asprintf() failed, and we should
136 use the fixed message.
137
138 This is not counted as a failure, so decrement the counter if
139 the test failed. */
140 if(todo) {
141 printf(" # TODO %s", todo_msg ? todo_msg : todo_msg_fixed);
142 if(!ok)
143 failures--;
144 }
48beefc9 145
d23b20e9
JG
146 printf("\n");
147
148 if(!ok) {
149 if(getenv("HARNESS_ACTIVE") != NULL)
150 fputs("\n", stderr);
151
152 diag(" Failed %stest (%s:%s() at line %d)",
153 todo ? "(TODO) " : "", file, func, line);
48beefc9 154 }
d23b20e9
JG
155 free(local_test_name);
156
157 UNLOCK;
158
159 /* We only care (when testing) that ok is positive, but here we
160 specifically only want to return 1 or 0 */
161 return ok ? 1 : 0;
48beefc9
NC
162}
163
d23b20e9
JG
164/*
165 * Initialise the TAP library. Will only do so once, however many times it's
166 * called.
167 */
168void
169_tap_init(void)
48beefc9 170{
d23b20e9 171 static int run_once = 0;
48beefc9 172
d23b20e9
JG
173 if(!run_once) {
174 atexit(_cleanup);
48beefc9 175
d23b20e9
JG
176 /* stdout needs to be unbuffered so that the output appears
177 in the same place relative to stderr output as it does
178 with Test::Harness */
179 setbuf(stdout, 0);
180 run_once = 1;
48beefc9 181 }
d23b20e9 182}
48beefc9 183
d23b20e9
JG
184/*
185 * Note that there's no plan.
186 */
187int
188plan_no_plan(void)
189{
ee103ff3 190
d23b20e9 191 LOCK;
48beefc9 192
d23b20e9 193 _tap_init();
48beefc9 194
d23b20e9
JG
195 if(have_plan != 0) {
196 fprintf(stderr, "You tried to plan twice!\n");
197 test_died = 1;
198 UNLOCK;
199 exit(255);
48beefc9
NC
200 }
201
d23b20e9
JG
202 have_plan = 1;
203 no_plan = 1;
48beefc9 204
d23b20e9 205 UNLOCK;
48beefc9 206
d23b20e9
JG
207 return 1;
208}
48beefc9 209
d23b20e9
JG
210/*
211 * Note that the plan is to skip all tests
212 */
213int
214plan_skip_all(char *reason)
215{
216
217 LOCK;
218
219 _tap_init();
220
221 skip_all = 1;
222
223 printf("1..0");
224
225 if(reason != NULL)
226 printf(" # Skip %s", reason);
227
228 printf("\n");
229
230 UNLOCK;
231
232 exit(0);
233}
234
235/*
236 * Note the number of tests that will be run.
237 */
238int
239plan_tests(unsigned int tests)
240{
241
242 LOCK;
48beefc9 243
d23b20e9
JG
244 _tap_init();
245
246 if(have_plan != 0) {
247 fprintf(stderr, "You tried to plan twice!\n");
248 test_died = 1;
249 UNLOCK;
250 exit(255);
48beefc9
NC
251 }
252
d23b20e9
JG
253 if(tests == 0) {
254 fprintf(stderr, "You said to run 0 tests! You've got to run something.\n");
255 test_died = 1;
256 UNLOCK;
257 exit(255);
48beefc9
NC
258 }
259
d23b20e9
JG
260 have_plan = 1;
261
262 _expected_tests(tests);
263
264 UNLOCK;
265
266 return e_tests;
267}
268
269unsigned int
270diag(char *fmt, ...)
271{
272 va_list ap;
273
274 fputs("# ", stderr);
275
276 va_start(ap, fmt);
277 vfprintf(stderr, fmt, ap);
278 va_end(ap);
ee103ff3 279
d23b20e9 280 fputs("\n", stderr);
48beefc9 281
d23b20e9
JG
282 return 0;
283}
284
285void
286_expected_tests(unsigned int tests)
287{
48beefc9 288
d23b20e9
JG
289 printf("1..%d\n", tests);
290 e_tests = tests;
291}
292
293int
294skip(unsigned int n, char *fmt, ...)
295{
296 va_list ap;
bbd25c0d 297 char *skip_msg = NULL;
d23b20e9
JG
298
299 LOCK;
300
301 va_start(ap, fmt);
302 asprintf(&skip_msg, fmt, ap);
303 va_end(ap);
304
305 while(n-- > 0) {
306 test_count++;
307 printf("ok %d # skip %s\n", test_count,
308 skip_msg != NULL ?
309 skip_msg : "libtap():malloc() failed");
310 }
311
312 free(skip_msg);
313
314 UNLOCK;
315
316 return 1;
317}
48beefc9 318
d23b20e9
JG
319void
320todo_start(char *fmt, ...)
321{
322 va_list ap;
48beefc9 323
d23b20e9 324 LOCK;
48beefc9 325
d23b20e9
JG
326 va_start(ap, fmt);
327 vasprintf(&todo_msg, fmt, ap);
328 va_end(ap);
48beefc9 329
d23b20e9 330 todo = 1;
48beefc9 331
d23b20e9 332 UNLOCK;
48beefc9
NC
333}
334
d23b20e9
JG
335void
336todo_end(void)
48beefc9 337{
48beefc9 338
d23b20e9 339 LOCK;
48beefc9 340
d23b20e9
JG
341 todo = 0;
342 free(todo_msg);
48beefc9 343
d23b20e9 344 UNLOCK;
48beefc9
NC
345}
346
d23b20e9
JG
347int
348exit_status(void)
48beefc9 349{
d23b20e9
JG
350 int r;
351
352 LOCK;
353
354 /* If there's no plan, just return the number of failures */
355 if(no_plan || !have_plan) {
356 UNLOCK;
357 return failures;
48beefc9 358 }
d23b20e9
JG
359
360 /* Ran too many tests? Return the number of tests that were run
361 that shouldn't have been */
362 if(e_tests < test_count) {
363 r = test_count - e_tests;
364 UNLOCK;
365 return r;
366 }
367
368 /* Return the number of tests that failed + the number of tests
369 that weren't run */
370 r = failures + e_tests - test_count;
371 UNLOCK;
372
373 return r;
48beefc9
NC
374}
375
d23b20e9
JG
376/*
377 * Cleanup at the end of the run, produce any final output that might be
378 * required.
379 */
380void
381_cleanup(void)
48beefc9 382{
48beefc9 383
d23b20e9
JG
384 LOCK;
385
386 /* If plan_no_plan() wasn't called, and we don't have a plan,
387 and we're not skipping everything, then something happened
388 before we could produce any output */
389 if(!no_plan && !have_plan && !skip_all) {
390 diag("Looks like your test died before it could output anything.");
391 UNLOCK;
392 return;
393 }
394
395 if(test_died) {
396 diag("Looks like your test died just after %d.", test_count);
397 UNLOCK;
398 return;
399 }
400
401
402 /* No plan provided, but now we know how many tests were run, and can
403 print the header at the end */
404 if(!skip_all && (no_plan || !have_plan)) {
405 printf("1..%d\n", test_count);
406 }
407
408 if((have_plan && !no_plan) && e_tests < test_count) {
409 diag("Looks like you planned %d %s but ran %d extra.",
410 e_tests, e_tests == 1 ? "test" : "tests", test_count - e_tests);
411 UNLOCK;
412 return;
413 }
414
415 if((have_plan || !no_plan) && e_tests > test_count) {
416 diag("Looks like you planned %d %s but only ran %d.",
417 e_tests, e_tests == 1 ? "test" : "tests", test_count);
418 UNLOCK;
419 return;
420 }
48beefc9 421
d23b20e9
JG
422 if(failures)
423 diag("Looks like you failed %d %s of %d.",
424 failures, failures == 1 ? "test" : "tests", test_count);
48beefc9 425
d23b20e9 426 UNLOCK;
48beefc9 427}
This page took 0.043464 seconds and 4 git commands to generate.