Fix: syscall event rule: emission sites not compared in is_equal
[lttng-tools.git] / tests / utils / tap / tap.c
CommitLineData
9f4a25d3 1/*
9d16b343
MJ
2 * SPDX-License-Identifier: BSD-2-Clause
3 *
9f4a25d3
SM
4 * Copyright (C) 2004 Nik Clayton
5 * Copyright (C) 2017 Jérémie Galarneau
86a96e6c
CB
6 */
7
2a69bf14
KS
8#include "../utils.h"
9#include "common/compat/time.hpp"
28f23191
JG
10#include "tap.h"
11
12#include <assert.h>
86a96e6c 13#include <ctype.h>
01076722 14#include <errno.h>
28f23191 15#include <limits.h>
86a96e6c
CB
16#include <stdarg.h>
17#include <stdio.h>
18#include <stdlib.h>
9f4a25d3 19#include <string.h>
2a69bf14 20#include <time.h>
86a96e6c
CB
21
22static int no_plan = 0;
23static int skip_all = 0;
24static int have_plan = 0;
25static unsigned int test_count = 0; /* Number of tests that have been run */
26static unsigned int e_tests = 0; /* Expected number of tests to run */
27static unsigned int failures = 0; /* Number of tests that failed */
28static char *todo_msg = NULL;
b53d4e59 29static const char *todo_msg_fixed = "libtap malloc issue";
86a96e6c
CB
30static int todo = 0;
31static int test_died = 0;
2a69bf14
KS
32static int time_tests = 1;
33struct timespec last_time;
86a96e6c
CB
34
35/* Encapsulate the pthread code in a conditional. In the absence of
36 libpthread the code does nothing */
37#ifdef HAVE_LIBPTHREAD
38#include <pthread.h>
39static pthread_mutex_t M = PTHREAD_MUTEX_INITIALIZER;
28f23191
JG
40#define LOCK pthread_mutex_lock(&M);
41#define UNLOCK pthread_mutex_unlock(&M);
86a96e6c 42#else
28f23191
JG
43#define LOCK
44#define UNLOCK
86a96e6c
CB
45#endif
46
47static void _expected_tests(unsigned int);
48static void _tap_init(void);
49static void _cleanup(void);
50
9f4a25d3 51#ifdef __MINGW32__
28f23191
JG
52static inline void flockfile(FILE *filehandle)
53{
54 return;
9f4a25d3
SM
55}
56
28f23191
JG
57static inline void funlockfile(FILE *filehandle)
58{
59 return;
9f4a25d3
SM
60}
61#endif
62
86a96e6c
CB
63/*
64 * Generate a test result.
65 *
66 * ok -- boolean, indicates whether or not the test passed.
67 * test_name -- the name of the test, may be NULL
68 * test_comment -- a comment to print afterwards, may be NULL
69 */
28f23191
JG
70unsigned int _gen_result(
71 int ok, const char *func, const char *file, unsigned int line, const char *test_name, ...)
86a96e6c
CB
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 */
28f23191 84 if (test_name != NULL) {
86a96e6c 85 va_start(ap, test_name);
f2068bce
JG
86 if (vasprintf(&local_test_name, test_name, ap) == -1) {
87 local_test_name = NULL;
88 }
86a96e6c
CB
89 va_end(ap);
90
91 /* Make sure the test name contains more than digits
92 and spaces. Emit an error message and exit if it
93 does */
28f23191 94 if (local_test_name) {
86a96e6c 95 name_is_digits = 1;
28f23191
JG
96 for (c = local_test_name; *c != '\0'; c++) {
97 if (!isdigit((unsigned char) *c) && !isspace((unsigned char) *c)) {
86a96e6c
CB
98 name_is_digits = 0;
99 break;
100 }
101 }
102
28f23191
JG
103 if (name_is_digits) {
104 diag(" You named your test '%s'. You shouldn't use numbers for your test names.",
105 local_test_name);
86a96e6c
CB
106 diag(" Very confusing.");
107 }
108 }
109 }
110
28f23191 111 if (!ok) {
86a96e6c
CB
112 printf("not ");
113 failures++;
114 }
115
116 printf("ok %d", test_count);
117
28f23191 118 if (test_name != NULL) {
86a96e6c
CB
119 printf(" - ");
120
121 /* Print the test name, escaping any '#' characters it
122 might contain */
28f23191 123 if (local_test_name != NULL) {
86a96e6c 124 flockfile(stdout);
28f23191
JG
125 for (c = local_test_name; *c != '\0'; c++) {
126 if (*c == '#')
86a96e6c 127 fputc('\\', stdout);
28f23191 128 fputc((int) *c, stdout);
86a96e6c
CB
129 }
130 funlockfile(stdout);
28f23191 131 } else { /* vasprintf() failed, use a fixed message */
86a96e6c
CB
132 printf("%s", todo_msg_fixed);
133 }
134 }
135
136 /* If we're in a todo_start() block then flag the test as being
137 TODO. todo_msg should contain the message to print at this
138 point. If it's NULL then asprintf() failed, and we should
139 use the fixed message.
140
141 This is not counted as a failure, so decrement the counter if
142 the test failed. */
28f23191 143 if (todo) {
86a96e6c 144 printf(" # TODO %s", todo_msg ? todo_msg : todo_msg_fixed);
28f23191 145 if (!ok)
86a96e6c
CB
146 failures--;
147 }
148
149 printf("\n");
2a69bf14 150 _output_test_time();
86a96e6c 151
28f23191
JG
152 if (!ok) {
153 if (getenv("HARNESS_ACTIVE") != NULL)
86a96e6c
CB
154 fputs("\n", stderr);
155
156 diag(" Failed %stest (%s:%s() at line %d)",
28f23191
JG
157 todo ? "(TODO) " : "",
158 file,
159 func,
160 line);
86a96e6c
CB
161 }
162 free(local_test_name);
163
164 UNLOCK;
165
166 /* We only care (when testing) that ok is positive, but here we
167 specifically only want to return 1 or 0 */
168 return ok ? 1 : 0;
169}
170
171/*
172 * Initialise the TAP library. Will only do so once, however many times it's
173 * called.
174 */
28f23191 175void _tap_init(void)
86a96e6c
CB
176{
177 static int run_once = 0;
178
28f23191 179 if (!run_once) {
86a96e6c
CB
180 atexit(_cleanup);
181
182 /* stdout needs to be unbuffered so that the output appears
183 in the same place relative to stderr output as it does
184 with Test::Harness */
185 setbuf(stdout, 0);
2a69bf14 186
01076722 187 /*
83dc3923
MJ
188 * Check if the LTTNG_TESTS_TAP_AUTOTIME environment variable
189 * is set and contains at least one byte.
01076722 190 */
83dc3923 191 const char *autotime_env = getenv("LTTNG_TESTS_TAP_AUTOTIME");
01076722
MJ
192 if (autotime_env != NULL && strnlen(autotime_env, 1)) {
193 int tap_autotime;
194
195 /*
83dc3923
MJ
196 * Check if LTTNG_TESTS_TAP_AUTOTIME is '0', also check
197 * errno because strtol() can return '0' on error.
01076722
MJ
198 */
199 errno = 0;
200 tap_autotime = strtol(autotime_env, NULL, 10);
201 if (tap_autotime == 0 && errno == 0) {
202 time_tests = 0;
2a69bf14
KS
203 }
204 }
205
86a96e6c
CB
206 run_once = 1;
207 }
2a69bf14 208 lttng_clock_gettime(CLOCK_MONOTONIC, &last_time);
86a96e6c
CB
209}
210
211/*
212 * Note that there's no plan.
213 */
28f23191 214int plan_no_plan(void)
86a96e6c 215{
86a96e6c
CB
216 LOCK;
217
218 _tap_init();
219
28f23191 220 if (have_plan != 0) {
86a96e6c
CB
221 fprintf(stderr, "You tried to plan twice!\n");
222 test_died = 1;
223 UNLOCK;
224 exit(255);
225 }
226
227 have_plan = 1;
228 no_plan = 1;
229
230 UNLOCK;
231
232 return 1;
233}
234
235/*
236 * Note that the plan is to skip all tests
237 */
28f23191 238int plan_skip_all(const char *reason)
86a96e6c 239{
86a96e6c
CB
240 LOCK;
241
242 _tap_init();
243
244 skip_all = 1;
245
246 printf("1..0");
247
28f23191 248 if (reason != NULL)
86a96e6c
CB
249 printf(" # Skip %s", reason);
250
251 printf("\n");
252
253 UNLOCK;
254
255 exit(0);
256}
257
258/*
259 * Note the number of tests that will be run.
260 */
28f23191 261int plan_tests(unsigned int tests)
86a96e6c 262{
86a96e6c
CB
263 LOCK;
264
265 _tap_init();
266
28f23191 267 if (have_plan != 0) {
86a96e6c
CB
268 fprintf(stderr, "You tried to plan twice!\n");
269 test_died = 1;
270 UNLOCK;
271 exit(255);
272 }
273
28f23191 274 if (tests == 0) {
86a96e6c
CB
275 fprintf(stderr, "You said to run 0 tests! You've got to run something.\n");
276 test_died = 1;
277 UNLOCK;
278 exit(255);
279 }
280
281 have_plan = 1;
282
283 _expected_tests(tests);
284
285 UNLOCK;
286
287 return e_tests;
288}
289
28f23191 290unsigned int diag(const char *fmt, ...)
86a96e6c
CB
291{
292 va_list ap;
293
294 fputs("# ", stderr);
295
296 va_start(ap, fmt);
297 vfprintf(stderr, fmt, ap);
298 va_end(ap);
299
300 fputs("\n", stderr);
301
302 return 0;
303}
304
28f23191 305void diag_multiline(const char *val)
9f4a25d3
SM
306{
307 size_t len, i, line_start_idx = 0;
308
309 assert(val);
310 len = strlen(val);
311
312 for (i = 0; i < len; i++) {
313 int line_length;
314
315 if (val[i] != '\n') {
316 continue;
317 }
318
319 assert((i - line_start_idx + 1) <= INT_MAX);
320 line_length = i - line_start_idx + 1;
321 fprintf(stderr, "# %.*s", line_length, &val[line_start_idx]);
322 line_start_idx = i + 1;
323 }
324}
325
28f23191 326void _expected_tests(unsigned int tests)
86a96e6c 327{
86a96e6c
CB
328 printf("1..%d\n", tests);
329 e_tests = tests;
330}
331
28f23191 332int skip(unsigned int n, const char *fmt, ...)
86a96e6c
CB
333{
334 va_list ap;
c2788d69 335 char *skip_msg = NULL;
86a96e6c
CB
336
337 LOCK;
338
339 va_start(ap, fmt);
9f4a25d3 340 if (vasprintf(&skip_msg, fmt, ap) == -1) {
f2068bce
JG
341 skip_msg = NULL;
342 }
86a96e6c
CB
343 va_end(ap);
344
28f23191 345 while (n-- > 0) {
86a96e6c 346 test_count++;
28f23191
JG
347 printf("ok %d # skip %s\n",
348 test_count,
349 skip_msg != NULL ? skip_msg : "libtap():malloc() failed");
2a69bf14 350 _output_test_time();
86a96e6c
CB
351 }
352
353 free(skip_msg);
354
355 UNLOCK;
356
357 return 1;
358}
359
2a69bf14
KS
360void _output_test_time(void)
361{
362 struct timespec new_time;
363 int64_t time_ns;
364 if (time_tests) {
365 lttng_clock_gettime(CLOCK_MONOTONIC, &new_time);
366 time_ns = elapsed_time_ns(&last_time, &new_time);
367 printf(" ---\n duration_ms: %ld.%ld\n ...\n",
368 time_ns / 1000000,
369 time_ns % 1000000);
370 }
371 lttng_clock_gettime(CLOCK_MONOTONIC, &last_time);
372}
373
28f23191 374void todo_start(const char *fmt, ...)
86a96e6c
CB
375{
376 va_list ap;
377
378 LOCK;
379
380 va_start(ap, fmt);
f2068bce
JG
381 if (vasprintf(&todo_msg, fmt, ap) == -1) {
382 todo_msg = NULL;
383 }
86a96e6c
CB
384 va_end(ap);
385
386 todo = 1;
387
388 UNLOCK;
389}
390
28f23191 391void todo_end(void)
86a96e6c 392{
86a96e6c
CB
393 LOCK;
394
395 todo = 0;
396 free(todo_msg);
397
398 UNLOCK;
399}
400
28f23191 401int exit_status(void)
86a96e6c
CB
402{
403 int r;
404
405 LOCK;
406
407 /* If there's no plan, just return the number of failures */
28f23191 408 if (no_plan || !have_plan) {
86a96e6c
CB
409 UNLOCK;
410 return failures;
411 }
412
413 /* Ran too many tests? Return the number of tests that were run
414 that shouldn't have been */
28f23191 415 if (e_tests < test_count) {
86a96e6c
CB
416 r = test_count - e_tests;
417 UNLOCK;
418 return r;
419 }
420
421 /* Return the number of tests that failed + the number of tests
422 that weren't run */
423 r = failures + e_tests - test_count;
424 UNLOCK;
425
426 return r;
427}
428
429/*
430 * Cleanup at the end of the run, produce any final output that might be
431 * required.
432 */
28f23191 433void _cleanup(void)
86a96e6c 434{
86a96e6c
CB
435 LOCK;
436
437 /* If plan_no_plan() wasn't called, and we don't have a plan,
438 and we're not skipping everything, then something happened
439 before we could produce any output */
28f23191 440 if (!no_plan && !have_plan && !skip_all) {
86a96e6c
CB
441 diag("Looks like your test died before it could output anything.");
442 UNLOCK;
443 return;
444 }
445
28f23191 446 if (test_died) {
86a96e6c
CB
447 diag("Looks like your test died just after %d.", test_count);
448 UNLOCK;
449 return;
450 }
451
86a96e6c
CB
452 /* No plan provided, but now we know how many tests were run, and can
453 print the header at the end */
28f23191 454 if (!skip_all && (no_plan || !have_plan)) {
86a96e6c
CB
455 printf("1..%d\n", test_count);
456 }
457
28f23191 458 if ((have_plan && !no_plan) && e_tests < test_count) {
86a96e6c 459 diag("Looks like you planned %d %s but ran %d extra.",
28f23191
JG
460 e_tests,
461 e_tests == 1 ? "test" : "tests",
462 test_count - e_tests);
86a96e6c
CB
463 UNLOCK;
464 return;
465 }
466
28f23191 467 if ((have_plan || !no_plan) && e_tests > test_count) {
86a96e6c 468 diag("Looks like you planned %d %s but only ran %d.",
28f23191
JG
469 e_tests,
470 e_tests == 1 ? "test" : "tests",
471 test_count);
86a96e6c
CB
472 UNLOCK;
473 return;
474 }
475
28f23191 476 if (failures)
86a96e6c 477 diag("Looks like you failed %d %s of %d.",
28f23191
JG
478 failures,
479 failures == 1 ? "test" : "tests",
480 test_count);
86a96e6c
CB
481
482 UNLOCK;
483}
This page took 0.078556 seconds and 5 git commands to generate.