{ tvec_fail_v(tv, detail, ap); tvec_mismatch(tv, TVMF_IN | TVMF_OUT); }
}
+static void open_test(struct tvec_state *tv)
+{
+ if (!(tv->f&TVSF_OPEN)) {
+ tv->test_lno = tv->lno;
+ tv->f |= TVSF_OPEN; tv->f &= ~TVSF_XFAIL;
+ }
+}
+
static void begin_test(struct tvec_state *tv)
{
tv->f |= TVSF_ACTIVE; tv->f &= ~TVSF_OUTMASK;
{
unsigned out;
- if (tv->f&TVSF_ACTIVE) out = TVOUT_WIN;
- else out = (tv->f&TVSF_OUTMASK) >> TVSF_OUTSHIFT;
+ if (!(tv->f&TVSF_ACTIVE)) /* nothing to do */;
+ else if (tv->f&TVSF_XFAIL) set_outcome(tv, TVOUT_XFAIL);
+ else set_outcome(tv, TVOUT_WIN);
+ out = (tv->f&TVSF_OUTMASK) >> TVSF_OUTSHIFT;
assert(out < TVOUT_LIMIT); tv->curr[out]++;
tv->output->ops->etest(tv->output, out);
tv->f &= ~TVSF_OPEN;
tvec_releaseregs(tv); tv->test = 0; xfree(g->ctx); g->ctx = 0;
}
+enum { WIN, XFAIL, NOUT };
+static const struct tvec_uassoc outcome_assoc[] = {
+ { "success", WIN },
+ { "win", WIN },
+ { "expected-failure", XFAIL },
+ { "xfail", XFAIL },
+ TVEC_ENDENUM
+};
+static const struct tvec_urange outcome_range = { 0, NOUT - 1 };
+static const struct tvec_uenuminfo outcome_enum =
+ { "test-outcome", outcome_assoc, &outcome_range };
+static const struct tvec_regdef outcome_regdef =
+ { "outcome", 0, &tvty_uenum, 0, { &outcome_enum } };
+
int tvec_read(struct tvec_state *tv, const char *infile, FILE *fp)
{
dstr d = DSTR_INIT;
const struct tvec_regdef *rd;
struct tvec_reg *r;
struct groupstate g = GROUPSTATE_INIT;
+ union tvec_regval rv;
int ch, ret, rc = 0;
tv->infile = infile; tv->lno = 1; tv->fp = fp;
{ tvec_error(tv, "no current test"); goto flush_line; }
if (d.buf[0] == '@') {
env = tv->test->env;
- if (!env || !env->set) ret = 0;
+ if (STRCMP(d.buf, ==, "@outcome")) {
+ if (tvty_uenum.parse(&rv, &outcome_regdef, tv))
+ ret = -1;
+ else {
+ if (rv.u == XFAIL) tv->f |= TVSF_XFAIL;
+ ret = 1;
+ }
+ } else if (!env || !env->set) ret = 0;
else ret = env->set(tv, d.buf, env, g.ctx);
if (ret <= 0) {
if (!ret)
tvec_error(tv, "unknown special register `%s'", d.buf);
goto flush_line;
}
- if (!(tv->f&TVSF_OPEN))
- { tv->test_lno = tv->lno; tv->f |= TVSF_OPEN; }
+ open_test(tv);
} else {
for (rd = tv->test->regs; rd->name; rd++)
if (STRCMP(rd->name, ==, d.buf)) goto found_reg;
d.buf, tv->test->name);
goto flush_line;
found_reg:
- if (!(tv->f&TVSF_OPEN))
- { tv->test_lno = tv->lno; tv->f |= TVSF_OPEN; }
+ open_test(tv);
tvec_skipspc(tv);
r = TVEC_REG(tv, in, rd->i);
if (r->f&TVRF_LIVE) {