summaryrefslogtreecommitdiff
path: root/tests/convey.c
diff options
context:
space:
mode:
authorGarrett D'Amore <garrett@damore.org>2017-01-16 12:21:16 -0800
committerGarrett D'Amore <garrett@damore.org>2017-01-16 12:21:16 -0800
commitfd4e5b0d49ee84b14753109de8a8df9b694f3dca (patch)
treecf3906b75e332490b6eeb123a3ee62b367596941 /tests/convey.c
parent656f091858b26e6fb61e5a9dd8395268dbee2447 (diff)
downloadnng-fd4e5b0d49ee84b14753109de8a8df9b694f3dca.tar.gz
nng-fd4e5b0d49ee84b14753109de8a8df9b694f3dca.tar.bz2
nng-fd4e5b0d49ee84b14753109de8a8df9b694f3dca.zip
Import updated C-Convey (for color on Windows).
Diffstat (limited to 'tests/convey.c')
-rw-r--r--tests/convey.c253
1 files changed, 185 insertions, 68 deletions
diff --git a/tests/convey.c b/tests/convey.c
index 9a56cf82..62471a2c 100644
--- a/tests/convey.c
+++ b/tests/convey.c
@@ -91,42 +91,42 @@ static int convey_nassert = 0;
static int convey_nskip = 0;
static const char *convey_assert_color = "";
-#define CONVEY_EXIT_OK 0
-#define CONVEY_EXIT_USAGE 1
-#define CONVEY_EXIT_FAIL 2
-#define CONVEY_EXIT_FATAL 3
-#define CONVEY_EXIT_NOMEM 4
+#define CONVEY_EXIT_OK 0
+#define CONVEY_EXIT_USAGE 1
+#define CONVEY_EXIT_FAIL 2
+#define CONVEY_EXIT_FATAL 3
+#define CONVEY_EXIT_NOMEM 4
struct convey_timer {
- uint64_t timer_base;
- uint64_t timer_count;
- uint64_t timer_rate;
- int timer_running;
+ uint64_t timer_base;
+ uint64_t timer_count;
+ uint64_t timer_rate;
+ int timer_running;
};
struct convey_log {
- char *log_buf;
- size_t log_size;
- size_t log_length;
+ char * log_buf;
+ size_t log_size;
+ size_t log_length;
};
struct convey_ctx {
char ctx_name[256];
- struct convey_ctx *ctx_parent;
- struct convey_ctx *ctx_root; /* the root node on the list */
- struct convey_ctx *ctx_next; /* root list only, cleanup */
+ struct convey_ctx * ctx_parent;
+ struct convey_ctx * ctx_root; /* the root node on the list */
+ struct convey_ctx * ctx_next; /* root list only, cleanup */
int ctx_level;
int ctx_done;
int ctx_started;
- jmp_buf *ctx_jmp;
+ jmp_buf * ctx_jmp;
int ctx_fatal;
int ctx_fail;
int ctx_skip;
int ctx_printed;
struct convey_timer ctx_timer;
- struct convey_log *ctx_errlog;
- struct convey_log *ctx_faillog;
- struct convey_log *ctx_dbglog;
+ struct convey_log * ctx_errlog;
+ struct convey_log * ctx_faillog;
+ struct convey_log * ctx_dbglog;
};
static void convey_print_result(struct convey_ctx *);
@@ -145,6 +145,55 @@ static void convey_log_emit(struct convey_log *, const char *, const char *);
static void convey_log_free(struct convey_log *);
static struct convey_log *convey_log_alloc(void);
static char *convey_nextline(char **);
+static void convey_emit_color(const char *);
+
+/*
+ * convey_emit_color just changes the output text to the color
+ * requested. It is Windows console aware.
+ */
+static void
+convey_emit_color(const char *color)
+{
+#if defined(_WIN32)
+ static WORD baseattr;
+ static HANDLE hStdout;
+ WORD attr;
+
+ // This covers the case of mingw style terminals.
+ (void) fputs(color, stdout);
+
+ if (baseattr == 0) {
+ CONSOLE_SCREEN_BUFFER_INFO info;
+
+ hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
+ if (!GetConsoleScreenBufferInfo(hStdout, &info)) {
+ return;
+ }
+ baseattr = info.wAttributes;
+ }
+ attr = baseattr &
+ ~(FOREGROUND_BLUE|FOREGROUND_GREEN|FOREGROUND_RED|
+ FOREGROUND_INTENSITY);
+
+ if (color == convey_nocolor) {
+ attr = baseattr;
+ } else if (color == convey_yellow) {
+ attr |= FOREGROUND_GREEN | FOREGROUND_RED |
+ FOREGROUND_INTENSITY;
+ } else if (color == convey_green) {
+ attr |= FOREGROUND_GREEN | FOREGROUND_INTENSITY;
+ } else if (color == convey_red) {
+ attr |= FOREGROUND_RED | FOREGROUND_INTENSITY;
+ } else {
+ return;
+ }
+ SetConsoleTextAttribute(hStdout, attr);
+
+#else
+ (void) fputs(color, stdout);
+#endif
+}
+
/*
* convey_print_result prints the test results. It prints more information
@@ -162,7 +211,7 @@ convey_print_result(struct convey_ctx *t)
int secs, usecs;
if (t->ctx_root == t) {
- convey_stop_timer(&t->ctx_timer); /* This is idempotent */
+ convey_stop_timer(&t->ctx_timer); /* This is idempotent */
convey_read_timer(&t->ctx_timer, &secs, &usecs);
@@ -173,7 +222,7 @@ convey_print_result(struct convey_ctx *t)
"PASS", t->ctx_name, secs, usecs / 10000);
if (convey_verbose) {
- (void) printf("\n");
+ (void) puts("");
}
convey_log_emit(t->ctx_errlog, "Errors:", convey_red);
convey_log_emit(t->ctx_faillog, "Failures:", convey_yellow);
@@ -181,15 +230,18 @@ convey_print_result(struct convey_ctx *t)
convey_log_emit(t->ctx_dbglog, "Log:", convey_nocolor);
}
if (convey_verbose) {
- (void) printf("\n\n%s%d assertions thus far%s",
- convey_assert_color,
- convey_nassert,
- convey_nocolor);
+ (void) puts("");
+ (void) puts("");
+ convey_emit_color(convey_assert_color);
+ (void) printf("%d assertions thus far", convey_nassert);
+ convey_emit_color(convey_nocolor);
+
if (convey_nskip) {
- (void) printf(" %s%s%s",
- convey_yellow,
- "(one or more sections skipped)",
- convey_nocolor);
+ (void) fputs(" ", stdout);
+ convey_emit_color(convey_yellow);
+ (void) fputs("(one or more sections skipped)",
+ stdout);
+ convey_emit_color(convey_nocolor);
}
(void) printf("\n\n--- %s: %s (%d.%02ds)\n",
t->ctx_fatal ? "FATAL" :
@@ -214,6 +266,7 @@ convey_print_result(struct convey_ctx *t)
}
}
+
/*
* conveyStart is called when the context starts, before any call to
* setjmp is made. If the context isn't initialized already, that is
@@ -233,9 +286,9 @@ conveyStart(conveyScope *scope, const char *name)
if ((t = scope->cs_data) != NULL) {
if (t->ctx_done) {
convey_print_result(t);
- return (1); /* all done, skip */
+ return (1); /* all done, skip */
}
- return (0); /* continue onward */
+ return (0); /* continue onward */
}
scope->cs_data = (t = calloc(1, sizeof (struct convey_ctx)));
if (t == NULL) {
@@ -266,6 +319,7 @@ conveyStart(conveyScope *scope, const char *name)
"Test Started: %s\n", t->ctx_name);
}
return (0);
+
allocfail:
if (t != NULL) {
convey_log_free(t->ctx_errlog);
@@ -280,9 +334,10 @@ allocfail:
return (1);
}
+
/*
- * conveyLoop is called right after setjmp. The jumped being true indicates
- * that setjmp returned true, and we are popping the stack. In that case
+ * conveyLoop is called right after setjmp. If unwind is true it indicates
+ * that setjmp returned true, and we are unwinding the stack. In that case
* we perform a local cleanup and keep popping back up the stack. We
* always come through this, even if the test finishes successfully, so
* that we can do this stack unwind. If we are unwinding, and we are
@@ -294,6 +349,7 @@ conveyLoop(conveyScope *scope, int unwind)
{
struct convey_ctx *t;
int i;
+
if ((t = scope->cs_data) == NULL) {
return (1);
}
@@ -313,9 +369,9 @@ conveyLoop(conveyScope *scope, int unwind)
if (t->ctx_root == t) {
(void) printf("=== RUN: %s\n", t->ctx_name);
} else {
- (void) printf("\n");
+ (void) puts("");
for (i = 0; i < t->ctx_level; i++) {
- (void) printf(" ");
+ (void) fputs(" ", stdout);
}
(void) printf("%s ", t->ctx_name);
(void) fflush(stdout);
@@ -330,10 +386,12 @@ conveyLoop(conveyScope *scope, int unwind)
return (0);
}
+
void
conveyFinish(conveyScope *scope, int *rvp)
{
struct convey_ctx *t;
+
if ((t = scope->cs_data) == NULL) {
/* allocation failure */
*rvp = CONVEY_EXIT_NOMEM;
@@ -353,41 +411,47 @@ conveyFinish(conveyScope *scope, int *rvp)
longjmp(*t->ctx_jmp, 1);
}
+
void
conveySkip(const char *file, int line, const char *fmt, ...)
{
va_list ap;
struct convey_ctx *t = convey_get_ctx();
struct convey_log *dlog = t->ctx_dbglog;
+
if (convey_verbose) {
- (void) printf("%s%s%s",
- convey_yellow, convey_sym_skip, convey_nocolor);
+ convey_emit_color(convey_yellow);
+ (void) fputs(convey_sym_skip, stdout);
+ convey_emit_color(convey_nocolor);
}
convey_logf(dlog, "* %s (%s:%d) (Skip): ",
t->ctx_name, file, line);
va_start(ap, fmt);
convey_vlogf(dlog, fmt, ap, 1);
va_end(ap);
- t->ctx_done = 1; /* This forces an end */
+ t->ctx_done = 1; /* This forces an end */
convey_nskip++;
longjmp(*t->ctx_jmp, 1);
}
+
void
conveyAssertFail(const char *cond, const char *file, int line)
{
struct convey_ctx *t = convey_get_ctx();
+
convey_nassert++;
if (convey_verbose) {
- (void) printf("%s%s%s",
- convey_yellow, convey_sym_fail, convey_nocolor);
+ convey_emit_color(convey_yellow);
+ (void) fputs(convey_sym_fail, stdout);
+ convey_emit_color(convey_nocolor);
}
if (t->ctx_root != t) {
t->ctx_root->ctx_fail++;
}
convey_assert_color = convey_yellow;
t->ctx_fail++;
- t->ctx_done = 1; /* This forces an end */
+ t->ctx_done = 1; /* This forces an end */
convey_logf(t->ctx_faillog, "* %s (Assertion Failed)\n",
t->ctx_name);
convey_logf(t->ctx_faillog, "File: %s\n", file);
@@ -398,43 +462,50 @@ conveyAssertFail(const char *cond, const char *file, int line)
longjmp(*t->ctx_jmp, 1);
}
+
void
conveyAssertPass(const char *cond, const char *file, int line)
{
struct convey_ctx *t = convey_get_ctx();
+
convey_nassert++;
if (convey_verbose) {
- (void) printf("%s%s%s",
- convey_green, convey_sym_pass, convey_nocolor);
+ convey_emit_color(convey_green);
+ (void) fputs(convey_sym_pass, stdout);
+ convey_emit_color(convey_nocolor);
}
convey_logf(t->ctx_dbglog, "* %s (%s:%d) (Passed): %s\n",
t->ctx_name, file, line, cond);
}
+
void
conveyAssertSkip(const char *cond, const char *file, int line)
{
struct convey_ctx *t = convey_get_ctx();
+
convey_nskip++;
if (convey_verbose) {
- (void) printf("%s%s%s",
- convey_yellow, convey_sym_pass, convey_nocolor);
+ convey_emit_color(convey_yellow);
+ (void) fputs(convey_sym_pass, stdout);
+ convey_emit_color(convey_nocolor);
}
convey_logf(t->ctx_dbglog, "* %s (%s:%d) (Skip): %s\n",
t->ctx_name, file, line, cond);
}
+
/*
* Performance counters. Really we just want to start and stop timers, to
* measure elapsed time in usec.
*/
-
static void
convey_init_timer(struct convey_timer *pc)
{
memset(pc, 0, sizeof (*pc));
}
+
static void
convey_start_timer(struct convey_timer *pc)
{
@@ -466,6 +537,7 @@ convey_start_timer(struct convey_timer *pc)
pc->timer_running = 1;
}
+
static void
convey_stop_timer(struct convey_timer *pc)
{
@@ -497,6 +569,7 @@ convey_stop_timer(struct convey_timer *pc)
} while (0);
}
+
static void
convey_read_timer(struct convey_timer *pc, int *secp, int *usecp)
{
@@ -515,13 +588,14 @@ convey_read_timer(struct convey_timer *pc, int *secp, int *usecp)
usec = (delta * 1000000) / rate;
if (secp) {
- *secp = (int)sec;
+ *secp = (int) sec;
}
if (usecp) {
- *usecp = (int)usec;
+ *usecp = (int) usec;
}
}
+
/*
* Thread-specific data. Pthreads uses one way, Win32 another. If you
* lack threads, just #define CONVEY_NO_THREADS. C11 thread support is pending.
@@ -536,6 +610,7 @@ convey_tls_init(void)
return (0);
}
+
static int
convey_tls_set(void *v)
{
@@ -543,11 +618,14 @@ convey_tls_set(void *v)
return (0);
}
+
static void *
convey_tls_get(void)
{
return (convey_tls_key);
}
+
+
#elif defined(_WIN32)
static DWORD convey_tls_key;
@@ -561,6 +639,7 @@ convey_tls_init(void)
return (0);
}
+
static int
convey_tls_set(void *v)
{
@@ -570,12 +649,14 @@ convey_tls_set(void *v)
return (0);
}
+
static void *
convey_tls_get(void)
{
- return ((void *)TlsGetValue(convey_tls_key));
+ return ((void *) TlsGetValue(convey_tls_key));
}
+
#else
pthread_key_t convey_tls_key;
@@ -589,6 +670,7 @@ convey_tls_init(void)
return (0);
}
+
static int
convey_tls_set(void *v)
{
@@ -598,11 +680,14 @@ convey_tls_set(void *v)
return (0);
}
+
static void *
convey_tls_get(void)
{
return (pthread_getspecific(convey_tls_key));
}
+
+
#endif
static struct convey_ctx *
@@ -611,6 +696,7 @@ convey_get_ctx(void)
return (convey_tls_get());
}
+
/*
* Log stuff.
*/
@@ -619,7 +705,7 @@ convey_vlogf(struct convey_log *log, const char *fmt, va_list va, int addnl)
{
/* Grow the log buffer if we need to */
while ((log->log_size - log->log_length) < 256) {
- size_t newsz = log->log_size + 2000;
+ int newsz = log->log_size + 2000;
char *ptr = malloc(newsz);
if (ptr == NULL) {
return;
@@ -635,35 +721,48 @@ convey_vlogf(struct convey_log *log, const char *fmt, va_list va, int addnl)
(void) vsnprintf(log->log_buf + log->log_length,
log->log_size - (log->log_length + 2), fmt, va);
log->log_length += strlen(log->log_buf + log->log_length);
- if (addnl && log->log_buf[log->log_length-1] != '\n') {
+ if (addnl && (log->log_buf[log->log_length-1] != '\n')) {
log->log_buf[log->log_length++] = '\n';
}
}
+
static void
convey_logf(struct convey_log *log, const char *fmt, ...)
{
va_list va;
+
va_start(va, fmt);
convey_vlogf(log, fmt, va, 0);
va_end(va);
}
+
static void
convey_log_emit(struct convey_log *log, const char *header, const char *color)
{
char *s;
char *last = log->log_buf;
+
if (log->log_length == 0) {
return;
}
- (void) printf("\n\n%s%s%s\n\n", color, header, convey_nocolor);
+ (void) fputs("\n\n", stdout);
+ convey_emit_color(color);
+ (void) fputs(header, stdout);
+ convey_emit_color(convey_nocolor);
+ (void) fputs("\n\n", stdout);
while ((s = convey_nextline(&last)) != NULL) {
- (void) printf(" %s%s%s\n", color, s, convey_nocolor);
+ (void) fputs(" ", stdout);
+ convey_emit_color(color);
+ (void) fputs(s, stdout);
+ convey_emit_color(convey_nocolor);
+ (void) fputs("\n", stdout);
}
}
+
static void
convey_log_free(struct convey_log *log)
{
@@ -675,12 +774,14 @@ convey_log_free(struct convey_log *log)
}
}
+
static struct convey_log *
convey_log_alloc(void)
{
return (calloc(1, sizeof (struct convey_log)));
}
+
/*
* ConveyInit initializes some common global stuff. Call it from main(),
* if you don't use the framework provided main.
@@ -700,12 +801,14 @@ ConveyInit(void)
return (0);
}
+
void
ConveySetVerbose(void)
{
convey_verbose = 1;
}
+
void
conveyFail(const char *file, int line, const char *fmt, ...)
{
@@ -732,10 +835,11 @@ conveyFail(const char *file, int line, const char *fmt, ...)
}
convey_assert_color = convey_yellow;
t->ctx_fail++;
- t->ctx_done = 1; /* This forces an end */
+ t->ctx_done = 1; /* This forces an end */
longjmp(*t->ctx_jmp, 1);
}
+
void
conveyError(const char *file, int line, const char *fmt, ...)
{
@@ -762,10 +866,11 @@ conveyError(const char *file, int line, const char *fmt, ...)
}
convey_assert_color = convey_red;
t->ctx_fail++;
- t->ctx_done = 1; /* This forces an end */
+ t->ctx_done = 1; /* This forces an end */
longjmp(*t->ctx_jmp, 1);
}
+
void
conveyPrintf(const char *file, int line, const char *fmt, ...)
{
@@ -779,15 +884,17 @@ conveyPrintf(const char *file, int line, const char *fmt, ...)
va_end(ap);
}
+
extern int conveyMainImpl(void);
static void
convey_init_term(void)
{
+ const char *term;
+
#ifndef _WIN32
/* Windows console doesn't do Unicode (consistently). */
const char *codeset;
- const char *term;
(void) setlocale(LC_ALL, "");
codeset = nl_langinfo(CODESET);
@@ -797,22 +904,30 @@ convey_init_term(void)
convey_sym_fatal = "🔥";
convey_sym_skip = "âš ";
}
+#endif
term = getenv("TERM");
- if (isatty(1) && (term != NULL)) {
+
+#ifndef _WIN32
+ if (!isatty(1)) {
+ term = NULL;
+ }
+#endif
+
+ if (term != NULL) {
if ((strstr(term, "xterm") != NULL) ||
(strstr(term, "ansi") != NULL) ||
(strstr(term, "color") != NULL)) {
- convey_nocolor = "\e[0m";
- convey_green = "\e[32m";
- convey_yellow = "\e[33m";
- convey_red = "\e[31m";
- convey_assert_color = convey_green;
+ convey_nocolor = "\033[0m";
+ convey_green = "\033[32m";
+ convey_yellow = "\033[33m";
+ convey_red = "\033[31m";
}
}
-#endif
+ convey_assert_color = convey_green;
}
+
/*
* This function exists because strtok isn't safe, and strtok_r and
* strsep are not universally available. Its like strsep, but only does
@@ -836,6 +951,7 @@ convey_nextline(char **next)
return (line);
}
}
+
/*
* If the last character in the file is a newline, treat it as
* the end. (This will appear as a blank last line.)
@@ -847,6 +963,7 @@ convey_nextline(char **next)
return (line);
}
+
int
conveyMain(int argc, char **argv)
{
@@ -878,7 +995,7 @@ conveyMain(int argc, char **argv)
}
}
if (ConveyInit() != 0) {
- (void) fprintf(stderr, "Cannot initialize test framework\n");
+ (void) fputs("Cannot initialize test framework\n", stderr);
exit(CONVEY_EXIT_NOMEM);
}
@@ -889,24 +1006,24 @@ conveyMain(int argc, char **argv)
switch (i) {
case CONVEY_EXIT_NOMEM:
- (void) fprintf(stderr, "Cannot initialize root test context\n");
+ (void) fputs("Cannot initialize root test context\n", stderr);
exit(CONVEY_EXIT_NOMEM);
case CONVEY_EXIT_OK:
if (convey_verbose) {
- (void) printf("PASS\n");
+ (void) puts("PASS");
}
status = "ok";
break;
case CONVEY_EXIT_FAIL:
status = "FAIL";
if (convey_verbose) {
- (void) printf("FAIL\n");
+ (void) puts("FAIL");
}
break;
default:
status = "FATAL";
if (convey_verbose) {
- (void) printf("FATAL\n");
+ (void) puts("FATAL");
}
break;
}