Revert "Device/Driver/LX: Add small delay after baud rate change"
[xcsoar.git] / test / src / tap.c
blob91eba3ed3a48fad82c15f0b5377a727b942397d6
1 /*-
2 * Copyright (c) 2004 Nik Clayton
3 * All rights reserved.
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.
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.
27 #ifndef _GNU_SOURCE
28 #define _GNU_SOURCE
29 #endif
31 #include <ctype.h>
32 #include <stdarg.h>
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
37 #include "tap.h"
39 int verbose;
41 static int no_plan = 0;
42 static int skip_all = 0;
43 static int have_plan = 0;
44 static unsigned int test_count = 0; /* Number of tests that have been run */
45 static unsigned int e_tests = 0; /* Expected number of tests to run */
46 static unsigned int failures = 0; /* Number of tests that failed */
47 static char *todo_msg = NULL;
48 static const char *todo_msg_fixed = "libtap malloc issue";
49 static int todo = 0;
50 static int test_died = 0;
52 /* Encapsulate the pthread code in a conditional. In the absence of
53 libpthread the code does nothing */
55 //#ifdef HAVE_LIBPTHREAD
56 //#include <pthread.h>
57 //static pthread_mutex_t M = PTHREAD_MUTEX_INITIALIZER;
58 //# define LOCK pthread_mutex_lock(&M);
59 //# define UNLOCK pthread_mutex_unlock(&M);
60 //#else
61 # define LOCK
62 # define UNLOCK
63 //#endif
65 static void _expected_tests(unsigned int);
66 static void _tap_init(void);
67 static void _cleanup(void);
70 * Generate a test result.
72 * ok -- boolean, indicates whether or not the test passed.
73 * test_name -- the name of the test, may be NULL
74 * test_comment -- a comment to print afterwards, may be NULL
76 unsigned int
77 _gen_result(int ok, const char *func, const char *file, unsigned int line,
78 const char *test_name, ...)
80 va_list ap;
81 char *local_test_name = NULL;
82 char *c;
83 int name_is_digits;
85 LOCK;
87 test_count++;
89 /* Start by taking the test name and performing any printf()
90 expansions on it */
91 if(test_name != NULL) {
92 #ifdef HAVE_VASPRINTF
93 va_start(ap, test_name);
94 vasprintf(&local_test_name, test_name, ap);
95 va_end(ap);
96 #else
97 (void)ap;
98 local_test_name = strdup(test_name);
99 #endif
101 /* Make sure the test name contains more than digits
102 and spaces. Emit an error message and exit if it
103 does */
104 if(local_test_name) {
105 name_is_digits = 1;
106 for(c = local_test_name; *c != '\0'; c++) {
107 if(!isdigit(*c) && !isspace(*c)) {
108 name_is_digits = 0;
109 break;
113 if(name_is_digits) {
114 diag(" You named your test '%s'. You shouldn't use numbers for your test names.", local_test_name);
115 diag(" Very confusing.");
120 if(!ok) {
121 printf("not ");
122 failures++;
125 printf("ok %d", test_count);
127 if(test_name != NULL) {
128 printf(" - ");
130 /* Print the test name, escaping any '#' characters it
131 might contain */
132 if(local_test_name != NULL) {
133 #ifdef HAVE_VASPRINTF
134 flockfile(stdout);
135 #endif
136 for(c = local_test_name; *c != '\0'; c++) {
137 if(*c == '#')
138 fputc('\\', stdout);
139 fputc((int)*c, stdout);
141 #ifdef HAVE_VASPRINTF
142 funlockfile(stdout);
143 #endif
144 } else { /* vasprintf() failed, use a fixed message */
145 printf("%s", todo_msg_fixed);
149 /* If we're in a todo_start() block then flag the test as being
150 TODO. todo_msg should contain the message to print at this
151 point. If it's NULL then asprintf() failed, and we should
152 use the fixed message.
154 This is not counted as a failure, so decrement the counter if
155 the test failed. */
156 if(todo) {
157 printf(" # TODO %s", todo_msg ? todo_msg : todo_msg_fixed);
158 if(!ok)
159 failures--;
162 printf("\n");
164 if(!ok) {
165 #ifndef WIN32
166 if(getenv("HARNESS_ACTIVE") != NULL)
167 fputs("\n", stderr);
168 #endif
170 diag(" Failed %stest (%s:%s() at line %d)",
171 todo ? "(TODO) " : "", file, func, line);
173 if (verbose>1) {
174 exit(1);
177 free(local_test_name);
179 #ifdef WIN32
180 // Flush the pipe content after each test
181 // to prevent a flooded pipe that freezes the application
182 fflush(stdout);
183 #endif
185 UNLOCK;
187 /* We only care (when testing) that ok is positive, but here we
188 specifically only want to return 1 or 0 */
189 return ok ? 1 : 0;
193 * Initialise the TAP library. Will only do so once, however many times it's
194 * called.
196 void
197 _tap_init(void)
199 static int run_once = 0;
201 if(!run_once) {
202 atexit(_cleanup);
204 #ifndef WIN32
205 /* stdout needs to be unbuffered so that the output appears
206 in the same place relative to stderr output as it does
207 with Test::Harness */
208 setbuf(stdout, 0);
209 #endif
210 run_once = 1;
215 * Note that there's no plan.
218 plan_no_plan(void)
221 LOCK;
223 _tap_init();
225 if(have_plan != 0) {
226 fprintf(stderr, "You tried to plan twice!\n");
227 test_died = 1;
228 UNLOCK;
229 exit(255);
232 have_plan = 1;
233 no_plan = 1;
235 UNLOCK;
237 return 1;
241 * Note that the plan is to skip all tests
244 plan_skip_all(char *reason)
247 LOCK;
249 _tap_init();
251 skip_all = 1;
253 printf("1..0");
255 if(reason != NULL)
256 printf(" # Skip %s", reason);
258 printf("\n");
260 UNLOCK;
262 exit(0);
266 * Note the number of tests that will be run.
269 plan_tests(unsigned int tests)
272 LOCK;
274 _tap_init();
276 if(have_plan != 0) {
277 fprintf(stderr, "You tried to plan twice!\n");
278 test_died = 1;
279 UNLOCK;
280 exit(255);
283 if(tests == 0) {
284 fprintf(stderr, "You said to run 0 tests! You've got to run something.\n");
285 test_died = 1;
286 UNLOCK;
287 exit(255);
290 have_plan = 1;
292 _expected_tests(tests);
294 UNLOCK;
296 return e_tests;
299 unsigned int
300 diag(const char *fmt, ...)
302 va_list ap;
304 fputs("# ", stderr);
306 va_start(ap, fmt);
307 vfprintf(stderr, fmt, ap);
308 va_end(ap);
310 fputs("\n", stderr);
312 return 0;
315 void
316 _expected_tests(unsigned int tests)
319 printf("1..%d\n", tests);
320 e_tests = tests;
324 skip(unsigned int n, unsigned int ok, const char *fmt, ...)
326 #ifdef HAVE_VASPRINTF
327 va_list ap;
328 char *skip_msg;
329 #endif
331 LOCK;
333 #ifdef HAVE_VASPRINTF
334 va_start(ap, fmt);
335 asprintf(&skip_msg, fmt, ap);
336 va_end(ap);
337 #else
338 #define skip_msg fmt
339 #endif
341 while(n-- > 0) {
342 test_count++;
344 if (!ok) {
345 failures++;
346 printf("not ok %d # skip: %s\n", test_count,
347 skip_msg != NULL ?
348 skip_msg : "libtap():malloc() failed");
349 } else {
350 printf("ok %d # skip: %s\n", test_count,
351 skip_msg != NULL ?
352 skip_msg : "libtap():malloc() failed");
356 #ifdef HAVE_VASPRINTF
357 free(skip_msg);
358 #endif
360 UNLOCK;
362 return 1;
365 void
366 todo_start(char *fmt, ...)
368 va_list ap;
370 LOCK;
372 #ifdef HAVE_VASPRINTF
373 va_start(ap, fmt);
374 vasprintf(&todo_msg, fmt, ap);
375 va_end(ap);
376 #else
377 (void)ap;
378 todo_msg = fmt;
379 #endif
380 todo = 1;
382 UNLOCK;
385 void
386 todo_end(void)
389 LOCK;
391 todo = 0;
392 free(todo_msg);
394 UNLOCK;
398 exit_status(void)
400 int r;
402 LOCK;
404 /* If there's no plan, just return the number of failures */
405 if(no_plan || !have_plan) {
406 UNLOCK;
407 return failures;
410 /* Ran too many tests? Return the number of tests that were run
411 that shouldn't have been */
412 if(e_tests < test_count) {
413 r = test_count - e_tests;
414 UNLOCK;
415 return r;
418 /* Return the number of tests that failed + the number of tests
419 that weren't run */
420 r = failures + e_tests - test_count;
421 UNLOCK;
423 return r;
427 * Cleanup at the end of the run, produce any final output that might be
428 * required.
430 void
431 _cleanup(void)
434 LOCK;
436 /* If plan_no_plan() wasn't called, and we don't have a plan,
437 and we're not skipping everything, then something happened
438 before we could produce any output */
439 if(!no_plan && !have_plan && !skip_all) {
440 diag("Looks like your test died before it could output anything.");
441 UNLOCK;
442 return;
445 if(test_died) {
446 diag("Looks like your test died just after %d.", test_count);
447 UNLOCK;
448 return;
452 /* No plan provided, but now we know how many tests were run, and can
453 print the header at the end */
454 if(!skip_all && (no_plan || !have_plan)) {
455 printf("1..%d\n", test_count);
458 if((have_plan && !no_plan) && e_tests < test_count) {
459 diag("Looks like you planned %d %s but ran %d extra.",
460 e_tests, e_tests == 1 ? "test" : "tests", test_count - e_tests);
461 UNLOCK;
462 return;
465 if((have_plan || !no_plan) && e_tests > test_count) {
466 diag("Looks like you planned %d %s but only ran %d.",
467 e_tests, e_tests == 1 ? "test" : "tests", test_count);
468 UNLOCK;
469 return;
472 if(failures)
473 diag("Looks like you failed %d %s of %d.",
474 failures, failures == 1 ? "test" : "tests", test_count);
476 UNLOCK;