56#if defined(_WIN32) || defined(__CYGWIN__)
58#elif defined(__unix__) || defined(__APPLE__)
64#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L && !defined(__STDC_NO_ATOMICS__)
66#define TAP_ATOMIC_SIZE_T _Atomic size_t
67#define TAP_ATOMIC_FETCH_ADD(ptr, val) atomic_fetch_add(ptr, val)
68#elif defined(__GNUC__) || defined(__clang__)
69#define TAP_ATOMIC_SIZE_T size_t
70#define TAP_ATOMIC_FETCH_ADD(ptr, val) __sync_fetch_and_add(ptr, val)
73#define TAP_ATOMIC_SIZE_T size_t
74#define TAP_ATOMIC_FETCH_ADD(ptr, val) ((*ptr) += (val))
75#warning "Compiler does not support C11 atomics or GCC builtins; global counters will not be thread-safe."
78#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L && !defined(__STDC_NO_THREADS__)
79#define TAP_THREAD_LOCAL _Thread_local
80#elif defined(__GNUC__) || defined(__clang__)
81#define TAP_THREAD_LOCAL __thread
82#elif defined(_MSC_VER)
83#define TAP_THREAD_LOCAL __declspec(thread)
85#define TAP_THREAD_LOCAL
86#warning "Compiler does not support thread-local storage; tests will not be thread-safe."
90#if defined(__GNUC__) || defined(__clang__)
91#define DBLTAP_PRINTF_FORMAT(fmt_index, arg_index) __attribute__((format(printf, fmt_index, arg_index)))
93#define DBLTAP_PRINTF_FORMAT(fmt_index, arg_index)
99void tap_plan(
size_t count);
101void tap_bail_out(
const char * reason, ...) DBLTAP_PRINTF_FORMAT(1, 2);
102bool tap_ok(
bool condition, const
char * file,
int line, const
char * func, const
char * expr, const
char * name, ...)
103 DBLTAP_PRINTF_FORMAT(6, 7);
104bool tap_subtest_start(const
char * name);
105bool tap_subtest_end(
void);
106void tap_todo_start(const
char * reason, ...) DBLTAP_PRINTF_FORMAT(1, 2);
107void tap_todo_end(
void);
108void tap_skip(
size_t count, const
char * reason, ...) DBLTAP_PRINTF_FORMAT(2, 3);
109void tap_skip_all(const
char * reason, ...) DBLTAP_PRINTF_FORMAT(1, 2);
110void diag(const
char * fmt, ...) DBLTAP_PRINTF_FORMAT(1, 2);
111void tap_note(const
char * fmt, ...) DBLTAP_PRINTF_FORMAT(1, 2);
116#define plan(count) tap_plan(count)
119#define done() tap_done()
122#define bail_out(...) tap_bail_out(__VA_ARGS__)
126#define ok(cond, ...) tap_ok(!!(cond), __FILE__, __LINE__, __func__, #cond, __VA_ARGS__)
129#define pass(...) ok(true, __VA_ARGS__)
132#define fail(...) ok(false, __VA_ARGS__)
135#define subtest(name) \
136 for (bool _tap_subtest_once = tap_subtest_start(name); _tap_subtest_once; _tap_subtest_once = tap_subtest_end())
139#define skip(count, ...) tap_skip(count, __VA_ARGS__)
142#define skip_all(...) tap_skip_all(__VA_ARGS__)
146#define TODO(reason) \
147 for (int _tap_todo_once = (tap_todo_start(reason), 1); _tap_todo_once; _tap_todo_once = (tap_todo_end(), 0))
150#define diag(...) diag(__VA_ARGS__)
154#define note(...) tap_note(__VA_ARGS__)
158#define TEST void test_body(void)
163#define plan(count) ((void)0)
165#define bail_out(...) \
167 fprintf(stderr, "Bail out! "); \
168 fprintf(stderr, __VA_ARGS__); \
169 fprintf(stderr, "\n"); \
172#define ok(cond, ...) (true)
173#define pass(...) ((void)0)
174#define fail(...) ((void)0)
175#define subtest(name) if (0)
176#define skip(count, ...) ((void)0)
177#define skip_all(...) ((void)0)
178#define TODO(reason, ...) if (0)
179#define diag(...) ((void)0)
181#define note(...) ((void)0)
184 int main(void) { return 0; }
188#if defined(DBLTAP_ENABLE) && defined(DBLTAP_IMPLEMENTATION)
208 char subtest_name[256];
209 char todo_reason[256];
210 char skip_reason[256];
214#define NO_PLAN ((size_t)-1)
217static TAP_THREAD_LOCAL tap_state_t state_stack[MAX_DEPTH];
219static TAP_THREAD_LOCAL tap_state_t * current_state = NULL;
222static TAP_ATOMIC_SIZE_T g_total_failed = 0;
226#if defined(_WIN32) || defined(__CYGWIN__)
227static INIT_ONCE g_tap_init_once = INIT_ONCE_STATIC_INIT;
228static BOOL CALLBACK _tap_init_routine(PINIT_ONCE initOnce, PVOID param, PVOID * context) {
232 printf(
"TAP version %d\n", TAP_VERSION);
236#elif defined(__unix__) || defined(__APPLE__)
237static pthread_once_t g_tap_init_once = PTHREAD_ONCE_INIT;
238static void _tap_init_routine(
void) {
239 printf(
"TAP version %d\n", TAP_VERSION);
251static void _tap_ensure_initialized(
void) {
252#if defined(_WIN32) || defined(__CYGWIN__)
253 InitOnceExecuteOnce(&g_tap_init_once, _tap_init_routine, NULL, NULL);
254#elif defined(__unix__) || defined(__APPLE__)
255 pthread_once(&g_tap_init_once, _tap_init_routine);
257 if (!current_state) {
258 current_state = &state_stack[0];
259 memset(current_state, 0,
sizeof(tap_state_t));
260 current_state->plan = NO_PLAN;
267static void print_indent(FILE * stream) {
268 _tap_ensure_initialized();
269 for (
int i = 0; i < current_state->indent_level; ++i)
270 fprintf(stream,
" ");
274static void push_state(
void) {
275 if (current_state >= &state_stack[MAX_DEPTH - 1])
276 tap_bail_out(
"Exceeded maximum subtest depth of %d", MAX_DEPTH);
277 tap_state_t * parent = current_state;
279 memset(current_state, 0,
sizeof(tap_state_t));
280 current_state->plan = NO_PLAN;
281 current_state->indent_level = parent->indent_level + 1;
285 current_state->todo =
true;
286 snprintf(current_state->todo_reason,
sizeof(current_state->todo_reason),
"%s", parent->todo_reason);
291static void pop_state(
void) {
292 if (current_state <= &state_stack[0])
293 tap_bail_out(
"Internal error: Attempted to pop base test state");
299void tap_init(
void) { _tap_ensure_initialized(); }
301void tap_plan(
size_t count) {
302 _tap_ensure_initialized();
303 if (current_state->has_plan || current_state->count > 0)
304 tap_bail_out(
"Plan declared after tests have run or a plan was already set");
305 current_state->plan = count;
306 current_state->has_plan =
true;
307 print_indent(stdout);
308 printf(
"1..%llu\n", (
unsigned long long)count);
312bool tap_ok(
bool condition,
const char * file,
int line,
const char * func,
const char * expr,
const char * name, ...) {
313 _tap_ensure_initialized();
314 if (current_state->skipping) {
315 current_state->count++;
319 char name_buffer[256] = {0};
320 if (name && name[0] !=
'\0') {
322 va_start(
args, name);
323 vsnprintf(name_buffer,
sizeof(name_buffer), name,
args);
327 current_state->count++;
330 if (current_state->todo)
331 current_state->failed_todo++;
333 current_state->failed++;
334 if (current_state == &state_stack[0])
335 TAP_ATOMIC_FETCH_ADD(&g_total_failed, 1);
339 print_indent(stdout);
340 printf(
"%s %llu", condition ?
"ok" :
"not ok", (unsigned long long)current_state->count);
341 if (name_buffer[0] !=
'\0')
342 printf(
" - %s", name_buffer);
344 if (current_state->todo)
345 printf(
" # TODO %s", current_state->todo_reason);
349 if (!condition && !current_state->todo) {
351 print_indent(stdout);
352 fprintf(stdout,
"#\n");
353 print_indent(stdout);
354 fprintf(stdout,
"# message: 'Test failed'\n");
355 print_indent(stdout);
356 fprintf(stdout,
"# severity: fail\n");
357 print_indent(stdout);
358 fprintf(stdout,
"# data:\n");
359 print_indent(stdout);
360 fprintf(stdout,
"# file: %s\n", file);
361 print_indent(stdout);
362 fprintf(stdout,
"# line: %d\n", line);
363 print_indent(stdout);
364 fprintf(stdout,
"# function: %s\n", func);
365 print_indent(stdout);
366 fprintf(stdout,
"# expression: '%s'\n", expr);
367 print_indent(stdout);
368 fprintf(stdout,
"# ...\n");
374void tap_skip(
size_t count,
const char * reason, ...) {
375 _tap_ensure_initialized();
378 va_start(
args, reason);
379 vsnprintf(buffer,
sizeof(buffer), reason,
args);
381 for (
size_t i = 0; i < count; ++i) {
382 current_state->count++;
383 print_indent(stdout);
384 printf(
"ok %llu # SKIP %s\n", (
unsigned long long)current_state->count, buffer);
389void tap_skip_all(
const char * reason, ...) {
390 _tap_ensure_initialized();
391 current_state->skipping =
true;
393 va_start(
args, reason);
394 vsnprintf(current_state->skip_reason,
sizeof(current_state->skip_reason), reason,
args);
398void tap_todo_start(
const char * reason, ...) {
399 _tap_ensure_initialized();
400 current_state->todo =
true;
402 va_start(
args, reason);
403 vsnprintf(current_state->todo_reason,
sizeof(current_state->todo_reason), reason,
args);
407void tap_todo_end(
void) {
408 _tap_ensure_initialized();
409 current_state->todo =
false;
410 current_state->todo_reason[0] =
'\0';
413void diag(
const char * fmt, ...) {
414 _tap_ensure_initialized();
418 vsnprintf(buffer,
sizeof(buffer), fmt,
args);
421 print_indent(stderr);
422 fprintf(stderr,
"# %s\n", buffer);
426void tap_note(
const char * fmt, ...) {
427 _tap_ensure_initialized();
431 vsnprintf(buffer,
sizeof(buffer), fmt,
args);
434 print_indent(stdout);
435 fprintf(stdout,
"# %s\n", buffer);
439void tap_bail_out(
const char * reason, ...) {
440 fprintf(stderr,
"Bail out! ");
442 va_start(
args, reason);
443 vfprintf(stderr, reason,
args);
445 fprintf(stderr,
"\n");
450bool tap_subtest_start(
const char * name) {
451 _tap_ensure_initialized();
452 print_indent(stdout);
453 fprintf(stdout,
"# Subtest: %s\n", name);
456 snprintf(current_state->subtest_name,
sizeof(current_state->subtest_name),
"%s", name);
460bool tap_subtest_end(
void) {
461 _tap_ensure_initialized();
463 if (!current_state->has_plan) {
465 current_state->plan = current_state->count;
466 print_indent(stdout);
467 printf(
"1..%llu\n", (
unsigned long long)current_state->plan);
469 bool plan_ok = (current_state->plan == current_state->count);
470 bool subtest_ok = (current_state->failed == 0) && plan_ok;
472 char name_buffer[256];
473 snprintf(name_buffer,
sizeof(name_buffer),
"%s", current_state->subtest_name);
478 ok(subtest_ok,
"%s", name_buffer);
484 _tap_ensure_initialized();
486 if (current_state != &state_stack[0])
487 tap_bail_out(
"tap_done() called inside a subtest");
489 if (!current_state->has_plan) {
490 current_state->plan = current_state->count;
491 print_indent(stdout);
492 printf(
"1..%llu\n", (
unsigned long long)current_state->plan);
496 if (current_state->skipping) {
497 print_indent(stdout);
498 printf(
"1..%llu # SKIP %s\n", (
unsigned long long)current_state->plan, current_state->skip_reason);
503 if (current_state->plan != current_state->count)
504 fail(
"Test plan adherence (planned %llu, but ran %llu)",
505 (
unsigned long long)current_state->plan,
506 (
unsigned long long)current_state->count);
508 size_t final_failed_count = (size_t)TAP_ATOMIC_FETCH_ADD(&g_total_failed, 0);
509 if (final_failed_count > 0)
510 diag(
"Looks like you failed %llu out of %llu tests.",
511 (
unsigned long long)final_failed_count,
512 (
unsigned long long)current_state->plan);
514 return (
int)final_failed_count;
521 return (
int)tap_done();
void * args[]
Definition 202_in_structs.c:64
int main(void)
Definition 821_threading_bare.c:81
#define plan(count)
Definition double_tap.h:163
#define diag(...)
Definition double_tap.h:179
#define ok(cond,...)
Definition double_tap.h:172
#define fail(...)
Definition double_tap.h:174