/*----- Header files ------------------------------------------------------*/
+#include "config.h"
+
#include <assert.h>
#include <stdarg.h>
#include <stdio.h>
/*----- Common machinery --------------------------------------------------*/
-enum { INPUT, OUTPUT, MATCH, EXPECT, FOUND };
-struct mismatchfns {
- void (*report_status)(unsigned /*disp*/, int /*st*/,
- struct tvec_state */*tv*/);
- void (*report_register)(unsigned /*disp*/,
- const struct tvec_reg */*r*/,
- const struct tvec_regdef */*rd*/,
- struct tvec_state */*tv*/);
-};
-
-static const char *stdisp(unsigned disp)
-{
- switch (disp) {
- case MATCH: return "final";
- case EXPECT: return "expected";
- case FOUND: return "actual";
- default: abort();
- }
-}
-
static const char *regdisp(unsigned disp)
{
switch (disp) {
- case INPUT: return "input";
- case OUTPUT: return "output";
- case MATCH: return "matched";
- case EXPECT: return "expected";
- case FOUND: return "computed";
+ case TVRD_INPUT: return "input";
+ case TVRD_OUTPUT: return "output";
+ case TVRD_MATCH: return "matched";
+ case TVRD_EXPECT: return "expected";
+ case TVRD_FOUND: return "found";
default: abort();
}
}
STRCMP(p, ==, "1"))
return (1);
else if (STRCMP(p, ==, "n") || STRCMP(p, ==, "no") ||
+ STRCMP(p, ==, "f") || STRCMP(p, ==, "false") ||
STRCMP(p, ==, "nil") || STRCMP(p, ==, "off") ||
STRCMP(p, ==, "0"))
return (0);
}
}
-static void basic_report_status(unsigned disp, int st, struct tvec_state *tv)
- { tvec_write(tv, " %8s status = `%c'\n", stdisp(disp), st); }
-
-static void basic_report_register(unsigned disp,
- const struct tvec_reg *r,
- const struct tvec_regdef *rd,
- struct tvec_state *tv)
-{
- tvec_write(tv, " %8s %s = ", regdisp(disp), rd->name);
- if (r->f&TVRF_LIVE) rd->ty->dump(&r->v, rd, tv, 0);
- else tvec_write(tv, "#<unset>");
- tvec_write(tv, "\n");
-}
-
-static const struct mismatchfns basic_mismatchfns =
- { basic_report_status, basic_report_register };
-
-static void dump_inreg(const struct tvec_regdef *rd,
- const struct mismatchfns *fns, struct tvec_state *tv)
- { fns->report_register(INPUT, TVEC_REG(tv, in, rd->i), rd, tv); }
-
-static void dump_outreg(const struct tvec_regdef *rd,
- const struct mismatchfns *fns, struct tvec_state *tv)
-{
- const struct tvec_reg
- *rin = TVEC_REG(tv, in, rd->i), *rout = TVEC_REG(tv, out, rd->i);
-
- if (tv->st == '.') {
- if (!(rout->f&TVRF_LIVE)) {
- if (!(rin->f&TVRF_LIVE))
- fns->report_register(INPUT, rin, rd, tv);
- else {
- fns->report_register(FOUND, rout, rd, tv);
- fns->report_register(EXPECT, rin, rd, tv);
- }
- } else {
- if (!(rin->f&TVRF_LIVE)) fns->report_register(OUTPUT, rout, rd, tv);
- else if (rd->ty->eq(&rin->v, &rout->v, rd))
- fns->report_register(MATCH, rin, rd, tv);
- else {
- fns->report_register(FOUND, rout, rd, tv);
- fns->report_register(EXPECT, rin, rd, tv);
- }
- }
- }
-}
-
-static void mismatch(const struct mismatchfns *fns, struct tvec_state *tv)
-{
- const struct tvec_regdef *rd;
-
- if (tv->st != tv->expst) {
- fns->report_status(FOUND, tv->st, tv);
- fns->report_status(EXPECT, tv->expst, tv);
- } else if (tv->st != '.')
- fns->report_status(MATCH, tv->st, tv);
-
- for (rd = tv->test->regs; rd->name; rd++) {
- if (rd->i < tv->nrout) dump_outreg(rd, fns, tv);
- else dump_inreg(rd, fns, tv);
- }
-}
-
-static void bench_summary(struct tvec_state *tv)
+static int register_maxnamelen(const struct tvec_state *tv)
{
const struct tvec_regdef *rd;
- unsigned f = 0;
-#define f_any 1u
+ int maxlen = 6, n;
for (rd = tv->test->regs; rd->name; rd++)
- if (rd->f&TVRF_ID) {
- if (f&f_any) tvec_write(tv, ", ");
- else f |= f_any;
- tvec_write(tv, "%s = ", rd->name);
- rd->ty->dump(&TVEC_REG(tv, in, rd->i)->v, rd, tv, TVSF_COMPACT);
- }
-
-#undef f_any
-}
-
-static void normalize(double *x_inout, const char **unit_out, double scale)
-{
- static const char
- *const nothing = "",
- *const big[] = { "k", "M", "G", "T", "P", "E", 0 },
- *const little[] = { "m", "ยต", "n", "p", "f", "a", 0 };
- const char *const *u;
- double x = *x_inout;
-
- if (x < 1)
- for (u = little, x *= scale; x < 1 && u[1]; u++, x *= scale);
- else if (x >= scale)
- for (u = big, x /= scale; x >= scale && u[1]; u++, x /= scale);
- else
- u = ¬hing;
-
- *x_inout = x; *unit_out = *u;
-}
-
-static void bench_report(struct tvec_state *tv,
- const struct bench_timing *tm)
-{
- const struct tvec_bench *b = tv->test->arg.p;
- double n = (double)tm->n*b->niter;
- double x, scale;
- const char *u, *what, *whats;
-
- assert(tm->f&BTF_TIMEOK);
-
- if (b->rbuf == -1) {
- tvec_write(tv, " -- %.0f iterations ", n);
- what = "op"; whats = "ops"; scale = 1000;
- } else {
- n *= TVEC_REG(tv, in, b->rbuf)->v.bytes.sz;
- x = n; normalize(&x, &u, 1024); tvec_write(tv, " -- %.3f %sB ", x, u);
- what = whats = "B"; scale = 1024;
- }
- x = tm->t; normalize(&x, &u, 1000);
- tvec_write(tv, "in %.3f %ss", x, u);
- if (tm->f&BTF_CYOK) {
- x = tm->cy; normalize(&x, &u, 1000);
- tvec_write(tv, " (%.3f %scy)", x, u);
- }
- tvec_write(tv, ": ");
-
- x = n/tm->t; normalize(&x, &u, scale);
- tvec_write(tv, "%.3f %s%s/s", x, u, whats);
- x = tm->t/n; normalize(&x, &u, 1000);
- tvec_write(tv, ", %.3f %ss/%s", x, u, what);
- if (tm->f&BTF_CYOK) {
- x = tm->cy/n; normalize(&x, &u, 1000);
- tvec_write(tv, " (%.3f %scy/%s)", x, u, what);
- }
- tvec_write(tv, "\n");
+ { n = strlen(rd->name); if (n > maxlen) maxlen = n; }
+ return (maxlen);
}
/*----- Skeleton ----------------------------------------------------------*/
/*
-static void ..._error(struct tvec_output *o, const char *msg, va_list *ap)
-static void ..._notice(struct tvec_output *o, const char *msg, va_list *ap)
-static void ..._write(struct tvec_output *o, const char *p, size_t sz)
-static void ..._bsession(struct tvec_output *o)
+static void ..._bsession(struct tvec_output *o, struct tvec_state *tv)
static int ..._esession(struct tvec_output *o)
static void ..._bgroup(struct tvec_output *o)
-static void ..._egroup(struct tvec_output *o, unsigned outcome)
static void ..._skipgroup(struct tvec_output *o,
const char *excuse, va_list *ap)
+static void ..._egroup(struct tvec_output *o)
static void ..._btest(struct tvec_output *o)
-static void ..._skip(struct tvec_output *o, const char *detail, va_list *ap)
+static void ..._skip(struct tvec_output *o, const char *excuse, va_list *ap)
static void ..._fail(struct tvec_output *o, const char *detail, va_list *ap)
-static void ..._mismatch(struct tvec_output *o)
+static void ..._dumpreg(struct tvec_output *o, unsigned disp,
+ union tvec_regval *rv, const struct tvec_regdef *rd)
static void ..._etest(struct tvec_output *o, unsigned outcome)
-static void ..._bbench(struct tvec_output *o)
-static void ..._ebench(struct tvec_output *o, const struct tvec_timing *t)
+static void ..._bbench(struct tvec_output *o,
+ const char *ident, unsigned unit)
+static void ..._ebench(struct tvec_output *o,
+ const char *ident, unsigned unit,
+ const struct tvec_timing *t)
+static void ..._error(struct tvec_output *o, const char *msg, va_list *ap)
+static void ..._notice(struct tvec_output *o, const char *msg, va_list *ap)
static void ..._destroy(struct tvec_output *o)
static const struct tvec_outops ..._ops = {
- ..._error, ..._notice, ..._write,
..._bsession, ..._esession,
..._bgroup, ..._egroup, ..._skip,
- ..._btest, ..._skip, ..._fail, ..._mismatch, ..._etest,
+ ..._btest, ..._skip, ..._fail, ..._dumpreg, ..._etest,
..._bbench, ..._ebench,
+ ..._error, ..._notice,
..._destroy
};
*/
struct human_output {
struct tvec_output _o;
+ struct tvec_state *tv;
FILE *fp;
dstr scoreboard;
unsigned attr;
+ int maxlen;
unsigned f;
#define HOF_TTY 1u
#define HOF_DUPERR 2u
size_t i, n;
if (h->f&HOF_PROGRESS) {
- n = strlen(h->_o.tv->test->name) + 2 + h->scoreboard.len;
+ n = strlen(h->tv->test->name) + 2 + h->scoreboard.len;
for (i = 0; i < n; i++) fputs("\b \b", h->fp);
h->f &= ~HOF_PROGRESS;
}
static void show_progress(struct human_output *h)
{
- struct tvec_state *tv = h->_o.tv;
+ struct tvec_state *tv = h->tv;
const char *p, *l;
if (tv->test && (h->f&HOF_TTY) && !(h->f&HOF_PROGRESS)) {
- fprintf(h->fp, "%s: ", h->_o.tv->test->name);
+ fprintf(h->fp, "%s: ", tv->test->name);
if (!(h->f&HOF_COLOUR))
dstr_write(&h->scoreboard, h->fp);
else for (p = h->scoreboard.buf, l = p + h->scoreboard.len; p < l; p++)
#undef FLUSH
}
-static void human_report(struct tvec_output *o, const char *msg, va_list *ap)
-{
- struct human_output *h = (struct human_output *)o;
- struct tvec_state *tv = h->_o.tv;
-
- clear_progress(h); fflush(h->fp);
- fprintf(stderr, "%s: ", QUIS);
- report_location(h, stderr, tv->infile, tv->lno);
- vfprintf(stderr, msg, *ap);
- fputc('\n', stderr);
-
- if (h->f&HOF_DUPERR) {
- report_location(h, stderr, tv->infile, tv->lno);
- vfprintf(h->fp, msg, *ap);
- fputc('\n', h->fp);
- }
- show_progress(h);
-}
-
-static void human_write(struct tvec_output *o, const char *p, size_t sz)
-{
- struct human_output *h = (struct human_output *)o;
- fwrite(p, 1, sz, h->fp);
-}
-
-static void human_bsession(struct tvec_output *o) { ; }
+static void human_bsession(struct tvec_output *o, struct tvec_state *tv)
+ { struct human_output *h = (struct human_output *)o; h->tv = tv; }
static void report_skipped(struct human_output *h, unsigned n)
{
static int human_esession(struct tvec_output *o)
{
struct human_output *h = (struct human_output *)o;
- struct tvec_state *tv = h->_o.tv;
+ struct tvec_state *tv = h->tv;
unsigned
all_win = tv->all[TVOUT_WIN], grps_win = tv->grps[TVOUT_WIN],
all_lose = tv->all[TVOUT_LOSE], grps_lose = tv->grps[TVOUT_LOSE],
fputs(" found in input; tests may not have run correctly\n", h->fp);
}
- return (tv->f&TVSF_ERROR ? 2 : tv->all[TVOUT_LOSE] ? 1 : 0);
+ h->tv = 0; return (tv->f&TVSF_ERROR ? 2 : tv->all[TVOUT_LOSE] ? 1 : 0);
}
static void human_bgroup(struct tvec_output *o)
{
struct human_output *h = (struct human_output *)o;
+
+ h->maxlen = register_maxnamelen(h->tv);
dstr_reset(&h->scoreboard); show_progress(h);
}
-static void human_grpsumm(struct human_output *h, unsigned outcome)
+static void human_skipgroup(struct tvec_output *o,
+ const char *excuse, va_list *ap)
{
- struct tvec_state *tv = h->_o.tv;
- unsigned win = tv->curr[TVOUT_WIN], lose = tv->curr[TVOUT_LOSE],
- skip = tv->curr[TVOUT_SKIP], run = win + lose;
+ struct human_output *h = (struct human_output *)o;
- if (lose) {
- assert(outcome == TVOUT_LOSE);
- fprintf(h->fp, " %u/%u ", lose, run);
- setattr(h, HA_LOSE); fputs("FAILED", h->fp); setattr(h, 0);
- report_skipped(h, skip);
+ if (!(~h->f&(HOF_TTY | HOF_PROGRESS))) {
+ h->f &= ~HOF_PROGRESS;
+ setattr(h, HA_SKIP); fputs("skipped", h->fp); setattr(h, 0);
} else {
- assert(outcome == TVOUT_WIN);
- fputc(' ', h->fp); setattr(h, HA_WIN); fputs("ok", h->fp); setattr(h, 0);
- report_skipped(h, skip);
+ fprintf(h->fp, "%s: ", h->tv->test->name);
+ setattr(h, HA_SKIP); fputs("skipped", h->fp); setattr(h, 0);
}
+ if (excuse) { fputs(": ", h->fp); vfprintf(h->fp, excuse, *ap); }
fputc('\n', h->fp);
}
-static void human_egroup(struct tvec_output *o, unsigned outcome)
+static void human_egroup(struct tvec_output *o)
{
struct human_output *h = (struct human_output *)o;
+ struct tvec_state *tv = h->tv;
+ unsigned win = tv->curr[TVOUT_WIN], lose = tv->curr[TVOUT_LOSE],
+ skip = tv->curr[TVOUT_SKIP], run = win + lose;
if (h->f&HOF_TTY) h->f &= ~HOF_PROGRESS;
- else fprintf(h->fp, "%s:", h->_o.tv->test->name);
- human_grpsumm(h, outcome);
-}
+ else fprintf(h->fp, "%s:", h->tv->test->name);
-static void human_skipgroup(struct tvec_output *o,
- const char *excuse, va_list *ap)
-{
- struct human_output *h = (struct human_output *)o;
-
- if (!(~h->f&(HOF_TTY | HOF_PROGRESS))) {
- h->f &= ~HOF_PROGRESS;
- setattr(h, HA_SKIP); fputs("skipped", h->fp); setattr(h, 0);
+ if (lose) {
+ fprintf(h->fp, " %u/%u ", lose, run);
+ setattr(h, HA_LOSE); fputs("FAILED", h->fp); setattr(h, 0);
+ report_skipped(h, skip);
} else {
- fprintf(h->fp, "%s: ", h->_o.tv->test->name);
- setattr(h, HA_SKIP); fputs("skipped", h->fp); setattr(h, 0);
+ fputc(' ', h->fp); setattr(h, HA_WIN); fputs("ok", h->fp); setattr(h, 0);
+ report_skipped(h, skip);
}
- if (excuse) { fputs(": ", h->fp); vfprintf(h->fp, excuse, *ap); }
fputc('\n', h->fp);
}
const char *excuse, va_list *ap)
{
struct human_output *h = (struct human_output *)o;
- struct tvec_state *tv = h->_o.tv;
+ struct tvec_state *tv = h->tv;
clear_progress(h);
report_location(h, h->fp, tv->infile, tv->test_lno);
const char *detail, va_list *ap)
{
struct human_output *h = (struct human_output *)o;
- struct tvec_state *tv = h->_o.tv;
+ struct tvec_state *tv = h->tv;
clear_progress(h);
report_location(h, h->fp, tv->infile, tv->test_lno);
fputc('\n', h->fp);
}
-static void set_dispattr(struct human_output *h, unsigned disp)
-{
- switch (disp) {
- case EXPECT: setattr(h, HFG(GREEN)); break;
- case FOUND: setattr(h, HFG(RED)); break;
- default: setattr(h, 0); break;
- }
-}
-
-static void human_report_status(unsigned disp, int st, struct tvec_state *tv)
-{
- struct human_output *h = (struct human_output *)tv->output;
-
- fprintf(h->fp, " %8s status = ", stdisp(disp));
- set_dispattr(h, disp); fprintf(h->fp, "`%c'", st); setattr(h, 0);
- fputc('\n', h->fp);
-}
-
-static void human_report_register(unsigned disp,
- const struct tvec_reg *r,
- const struct tvec_regdef *rd,
- struct tvec_state *tv)
-{
- struct human_output *h = (struct human_output *)tv->output;
-
- fprintf(h->fp, " %8s %s = ", regdisp(disp), rd->name);
- if (!(r->f&TVRF_LIVE))
- tvec_write(tv, "#<unset>");
- else {
- set_dispattr(h, disp);
- rd->ty->dump(&r->v, rd, tv, 0);
- setattr(h, 0);
- }
- tvec_write(tv, "\n");
-}
-
-static const struct mismatchfns human_mismatchfns =
- { human_report_status, human_report_register };
-
-static void human_mismatch(struct tvec_output *o)
+static void human_dumpreg(struct tvec_output *o,
+ unsigned disp, const union tvec_regval *rv,
+ const struct tvec_regdef *rd)
{
struct human_output *h = (struct human_output *)o;
+ const char *ds = regdisp(disp); int n = strlen(ds) + strlen(rd->name);
- if (h->f&HOF_COLOUR) mismatch(&human_mismatchfns, h->_o.tv);
- else mismatch(&basic_mismatchfns, h->_o.tv);
+ fprintf(h->fp, "%*s%s %s = ", 10 + h->maxlen - n, "", ds, rd->name);
+ if (h->f&HOF_COLOUR) {
+ if (!rv) setattr(h, HFG(YELLOW));
+ else if (disp == TVRD_FOUND) setattr(h, HFG(RED));
+ else if (disp == TVRD_EXPECT) setattr(h, HFG(GREEN));
+ }
+ if (!rv) fprintf(h->fp, "#<unset>");
+ else rd->ty->dump(rv, rd, 0, &file_printops, h->fp);
+ setattr(h, 0); fputc('\n', h->fp);
}
static void human_etest(struct tvec_output *o, unsigned outcome)
}
}
-static void human_bbench(struct tvec_output *o)
+static void human_bbench(struct tvec_output *o,
+ const char *ident, unsigned unit)
{
struct human_output *h = (struct human_output *)o;
- struct tvec_state *tv = h->_o.tv;
+ struct tvec_state *tv = h->tv;
clear_progress(h);
- fprintf(h->fp, "%s: ", tv->test->name);
- bench_summary(tv); fflush(h->fp);
+ fprintf(h->fp, "%s: %s: ", tv->test->name, ident); fflush(h->fp);
}
static void human_ebench(struct tvec_output *o,
+ const char *ident, unsigned unit,
const struct bench_timing *tm)
{
struct human_output *h = (struct human_output *)o;
- bench_report(h->_o.tv, tm);
+ tvec_benchreport(&file_printops, h->fp, unit, tm); fputc('\n', h->fp);
+}
+
+static void human_report(struct tvec_output *o, const char *msg, va_list *ap)
+{
+ struct human_output *h = (struct human_output *)o;
+ struct tvec_state *tv = h->tv;
+ dstr d = DSTR_INIT;
+
+ dstr_vputf(&d, msg, ap); dstr_putc(&d, '\n');
+
+ clear_progress(h); fflush(h->fp);
+ fprintf(stderr, "%s: ", QUIS);
+ report_location(h, stderr, tv->infile, tv->lno);
+ fwrite(d.buf, 1, d.len, stderr);
+
+ if (h->f&HOF_DUPERR) {
+ report_location(h, h->fp, tv->infile, tv->lno);
+ fwrite(d.buf, 1, d.len, h->fp);
+ }
+ show_progress(h);
}
static void human_destroy(struct tvec_output *o)
}
static const struct tvec_outops human_ops = {
- human_report, human_report, human_write,
human_bsession, human_esession,
- human_bgroup, human_egroup, human_skipgroup,
- human_btest, human_skip, human_fail, human_mismatch, human_etest,
+ human_bgroup, human_skipgroup, human_egroup,
+ human_btest, human_skip, human_fail, human_dumpreg, human_etest,
human_bbench, human_ebench,
+ human_report, human_report,
human_destroy
};
h->f = 0; h->attr = 0;
h->fp = fp;
- if (fp != stdout && fp != stderr) h->f |= HOF_DUPERR;
switch (getenv_boolean("TVEC_TTY", -1)) {
case 1: h->f |= HOF_TTY; break;
break;
}
+ if (fp != stderr && (fp != stdout || !(h->f&HOF_TTY))) h->f |= HOF_DUPERR;
dstr_create(&h->scoreboard);
return (&h->_o);
}
struct tap_output {
struct tvec_output _o;
+ struct tvec_state *tv;
FILE *fp;
+ dstr d;
+ int maxlen;
unsigned f;
#define TOF_FRESHLINE 1u
};
-static void tap_report(struct tap_output *t, const char *msg, va_list *ap)
+static int tap_writech(void *go, int ch)
{
- struct tvec_state *tv = t->_o.tv;
+ struct tap_output *t = go;
- if (tv->infile) fprintf(t->fp, "%s:%u: ", tv->infile, tv->lno);
- vfprintf(t->fp, msg, *ap); fputc('\n', t->fp);
+ if (t->f&TOF_FRESHLINE) {
+ if (fputs("## ", t->fp) < 0) return (-1);
+ t->f &= ~TOF_FRESHLINE;
+ }
+ if (putc(ch, t->fp) < 0) return (-1);
+ if (ch == '\n') t->f |= TOF_FRESHLINE;
+ return (1);
}
-static void tap_error(struct tvec_output *o, const char *msg, va_list *ap)
+static int tap_writem(void *go, const char *p, size_t sz)
{
- struct tap_output *t = (struct tap_output *)o;
- fputs("Bail out! ", t->fp); tap_report(t, msg, ap);
+ struct tap_output *t = go;
+ const char *q, *l = p + sz;
+ size_t n;
+
+ if (p == l) return (0);
+ if (t->f&TOF_FRESHLINE)
+ if (fputs("## ", t->fp) < 0) return (-1);
+ for (;;) {
+ q = memchr(p, '\n', l - p); if (!q) break;
+ n = q + 1 - p; if (fwrite(p, 1, n, t->fp) < n) return (-1);
+ p = q + 1;
+ if (p == l) { t->f |= TOF_FRESHLINE; return (sz); }
+ if (fputs("## ", t->fp) < 0) return (-1);
+ }
+ n = l - p; if (fwrite(p, 1, n, t->fp) < n) return (-1);
+ t->f &= ~TOF_FRESHLINE; return (0);
}
-static void tap_notice(struct tvec_output *o, const char *msg, va_list *ap)
+static int tap_nwritef(void *go, size_t maxsz, const char *p, ...)
{
- struct tap_output *t = (struct tap_output *)o;
- fputs("## ", t->fp); tap_report(t, msg, ap);
+ struct tap_output *t = go;
+ va_list ap;
+ int n;
+
+ va_start(ap, p); DRESET(&t->d); DENSURE(&t->d, maxsz + 1);
+#ifdef HAVE_SNPRINTF
+ n = vsnprintf(t->d.buf, maxsz + 1, p, ap);
+#else
+ n = vsprintf(t->d.buf, p, ap);
+#endif
+ assert(0 <= n && n <= maxsz);
+ va_end(ap);
+ return (tap_writem(t, t->d.buf, n));
}
-static void tap_write(struct tvec_output *o, const char *p, size_t sz)
+static const struct gprintf_ops tap_printops =
+ { tap_writech, tap_writem, tap_nwritef };
+
+static void tap_bsession(struct tvec_output *o, struct tvec_state *tv)
{
struct tap_output *t = (struct tap_output *)o;
- const char *q, *l = p + sz;
- if (p == l) return;
- if (t->f&TOF_FRESHLINE) fputs("## ", t->fp);
- for (;;) {
- q = memchr(p, '\n', l - p); if (!q) break;
- fwrite(p, 1, q + 1 - p, t->fp); p = q + 1;
- if (p == l) { t->f |= TOF_FRESHLINE; return; }
- fputs("## ", t->fp);
- }
- fwrite(p, 1, l - p, t->fp); t->f &= ~TOF_FRESHLINE;
+ t->tv = tv;
+ fputs("TAP version 13\n", t->fp);
}
-static void tap_bsession(struct tvec_output *o) { ; }
-
static unsigned tap_grpix(struct tap_output *t)
{
- struct tvec_state *tv = t->_o.tv;
+ struct tvec_state *tv = t->tv;
return (tv->grps[TVOUT_WIN] +
tv->grps[TVOUT_LOSE] +
static int tap_esession(struct tvec_output *o)
{
struct tap_output *t = (struct tap_output *)o;
- struct tvec_state *tv = t->_o.tv;
+ struct tvec_state *tv = t->tv;
if (tv->f&TVSF_ERROR) {
fputs("Bail out! "
}
fprintf(t->fp, "1..%u\n", tap_grpix(t));
- return (tv->all[TVOUT_LOSE] ? 1 : 0);
+ t->tv = 0; return (tv->all[TVOUT_LOSE] ? 1 : 0);
}
-static void tap_bgroup(struct tvec_output *o) { ; }
+static void tap_bgroup(struct tvec_output *o)
+{
+ struct tap_output *t = (struct tap_output *)o;
+ t->maxlen = register_maxnamelen(t->tv);
+}
+
+static void tap_skipgroup(struct tvec_output *o,
+ const char *excuse, va_list *ap)
+{
+ struct tap_output *t = (struct tap_output *)o;
+
+ fprintf(t->fp, "ok %u %s # SKIP", tap_grpix(t), t->tv->test->name);
+ if (excuse) { fputc(' ', t->fp); vfprintf(t->fp, excuse, *ap); }
+ fputc('\n', t->fp);
+}
-static void tap_egroup(struct tvec_output *o, unsigned outcome)
+static void tap_egroup(struct tvec_output *o)
{
struct tap_output *t = (struct tap_output *)o;
- struct tvec_state *tv = t->_o.tv;
+ struct tvec_state *tv = t->tv;
unsigned
grpix = tap_grpix(t),
win = tv->curr[TVOUT_WIN],
skip = tv->curr[TVOUT_SKIP];
if (lose) {
- assert(outcome == TVOUT_LOSE);
- fprintf(t->fp, "not ok %u %s: FAILED %u/%u",
+ fprintf(t->fp, "not ok %u - %s: FAILED %u/%u",
grpix, tv->test->name, lose, win + lose);
if (skip) fprintf(t->fp, " (skipped %u)", skip);
} else {
- assert(outcome == TVOUT_WIN);
- fprintf(t->fp, "ok %u %s: passed %u", grpix, tv->test->name, win);
+ fprintf(t->fp, "ok %u - %s: passed %u", grpix, tv->test->name, win);
if (skip) fprintf(t->fp, " (skipped %u)", skip);
}
fputc('\n', t->fp);
}
-static void tap_skipgroup(struct tvec_output *o,
- const char *excuse, va_list *ap)
-{
- struct tap_output *t = (struct tap_output *)o;
-
- fprintf(t->fp, "ok %u %s # SKIP", tap_grpix(t), t->_o.tv->test->name);
- if (excuse)
- { fputc(' ', t->fp); vfprintf(t->fp, excuse, *ap); }
- fputc('\n', t->fp);
-}
-
static void tap_btest(struct tvec_output *o) { ; }
static void tap_skip(struct tvec_output *o, const char *excuse, va_list *ap)
{
struct tap_output *t = (struct tap_output *)o;
- struct tvec_state *tv = t->_o.tv;
+ struct tvec_state *tv = t->tv;
fprintf(t->fp, "## %s:%u: `%s' skipped",
tv->infile, tv->test_lno, tv->test->name);
static void tap_fail(struct tvec_output *o, const char *detail, va_list *ap)
{
struct tap_output *t = (struct tap_output *)o;
- struct tvec_state *tv = t->_o.tv;
+ struct tvec_state *tv = t->tv;
fprintf(t->fp, "## %s:%u: `%s' FAILED",
tv->infile, tv->test_lno, tv->test->name);
fputc('\n', t->fp);
}
-static void tap_mismatch(struct tvec_output *o)
- { mismatch(&basic_mismatchfns, o->tv); }
+static void tap_dumpreg(struct tvec_output *o,
+ unsigned disp, const union tvec_regval *rv,
+ const struct tvec_regdef *rd)
+{
+ struct tap_output *t = (struct tap_output *)o;
+ const char *ds = regdisp(disp); int n = strlen(ds) + strlen(rd->name);
+
+ fprintf(t->fp, "## %*s%s %s = ", 10 + t->maxlen - n, "", ds, rd->name);
+ if (!rv)
+ fprintf(t->fp, "#<unset>\n");
+ else {
+ t->f &= ~TOF_FRESHLINE;
+ rd->ty->dump(rv, rd, 0, &tap_printops, t);
+ fputc('\n', t->fp);
+ }
+}
static void tap_etest(struct tvec_output *o, unsigned outcome) { ; }
-static void tap_bbench(struct tvec_output *o) { ; }
+static void tap_bbench(struct tvec_output *o,
+ const char *ident, unsigned unit)
+ { ; }
static void tap_ebench(struct tvec_output *o,
+ const char *ident, unsigned unit,
const struct bench_timing *tm)
{
struct tap_output *t = (struct tap_output *)o;
- struct tvec_state *tv = t->_o.tv;
+ struct tvec_state *tv = t->tv;
- tvec_write(tv, "%s: ", tv->test->name); bench_summary(tv);
- bench_report(tv, tm);
+ fprintf(t->fp, "## %s: %s: ", tv->test->name, ident);
+ t->f &= ~TOF_FRESHLINE; tvec_benchreport(&tap_printops, t, unit, tm);
+ fputc('\n', t->fp);
+}
+
+static void tap_report(struct tap_output *t, const char *msg, va_list *ap)
+{
+ struct tvec_state *tv = t->tv;
+
+ if (tv->infile) fprintf(t->fp, "%s:%u: ", tv->infile, tv->lno);
+ vfprintf(t->fp, msg, *ap); fputc('\n', t->fp);
+}
+
+static void tap_error(struct tvec_output *o, const char *msg, va_list *ap)
+{
+ struct tap_output *t = (struct tap_output *)o;
+ fputs("Bail out! ", t->fp); tap_report(t, msg, ap);
+}
+
+static void tap_notice(struct tvec_output *o, const char *msg, va_list *ap)
+{
+ struct tap_output *t = (struct tap_output *)o;
+ fputs("## ", t->fp); tap_report(t, msg, ap);
}
static void tap_destroy(struct tvec_output *o)
struct tap_output *t = (struct tap_output *)o;
if (t->fp != stdout && t->fp != stderr) fclose(t->fp);
+ dstr_destroy(&t->d);
xfree(t);
}
static const struct tvec_outops tap_ops = {
- tap_error, tap_notice, tap_write,
tap_bsession, tap_esession,
- tap_bgroup, tap_egroup, tap_skipgroup,
- tap_btest, tap_skip, tap_fail, tap_mismatch, tap_etest,
+ tap_bgroup, tap_skipgroup, tap_egroup,
+ tap_btest, tap_skip, tap_fail, tap_dumpreg, tap_etest,
tap_bbench, tap_ebench,
+ tap_error, tap_notice,
tap_destroy
};
struct tap_output *t;
t = xmalloc(sizeof(*t)); t->_o.ops = &tap_ops;
- t->f = TOF_FRESHLINE;
- t->fp = fp;
+ dstr_create(&t->d);
+ t->f = 0; t->fp = fp;
return (&t->_o);
}