chiark / gitweb /
@@@ wip mostly xfail
[mLib] / test / tvec-core.c
index 51834f43f04bcd1bfaa45be7604693acd2a37fe6..36a54edd7c7ce6167aeabdf8dedc1daec390668e 100644 (file)
@@ -367,6 +367,14 @@ void tvec_check_v(struct tvec_state *tv, const char *detail, va_list *ap)
     { 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;
@@ -377,8 +385,10 @@ void tvec_endtest(struct tvec_state *tv)
 {
   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;
@@ -464,6 +474,20 @@ static void end_test_group(struct tvec_state *tv, struct groupstate *g)
   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;
@@ -472,6 +496,7 @@ int tvec_read(struct tvec_state *tv, const char *infile, FILE *fp)
   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;
@@ -523,15 +548,21 @@ int tvec_read(struct tvec_state *tv, const char *infile, FILE *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;
@@ -539,8 +570,7 @@ int tvec_read(struct tvec_state *tv, const char *infile, FILE *fp)
                       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) {