/*----- Output ------------------------------------------------------------*/
-/* --- @tvec_error@, @tvec_error_v@ --- *
+/* --- @tvec_report@, @tvec_report_v@ --- *
*
* Arguments: @struct tvec_state *tv@ = test-vector state
* @const char *msg@, @va_list ap@ = error message
*
- * Returns: @-1@.
+ * Returns: ---
*
- * Use: Report an error. Errors are distinct from test failures,
- * and indicate that a problem was encountered which compromised
- * the activity of testing.
+ * Use: Report an message with a given severity. Messages with level
+ * @TVLEV_ERR@ or higher force a nonzero exit code.
*/
-int tvec_error(struct tvec_state *tv, const char *msg, ...)
+void tvec_report(struct tvec_state *tv, unsigned level, const char *msg, ...)
{
va_list ap;
- va_start(ap, msg); tvec_error_v(tv, msg, &ap); va_end(ap);
- return (-1);
+ va_start(ap, msg); tvec_report_v(tv, level, msg, &ap); va_end(ap);
}
-int tvec_error_v(struct tvec_state *tv, const char *msg, va_list *ap)
+
+void tvec_report_v(struct tvec_state *tv, unsigned level,
+ const char *msg, va_list *ap)
{
- tv->output->ops->error(tv->output, msg, ap);
- tv->f |= TVSF_ERROR; return (-1);
+ tv->output->ops->report(tv->output, level, msg, ap);
+ if (level >= TVLEV_ERR) tv->f |= TVSF_ERROR;
}
-/* --- @tvec_notice@, @tvec_notice_v@ --- *
+/* --- @tvec_error@, @tvec_notice@ --- *
*
* Arguments: @struct tvec_state *tv@ = test-vector state
- * @const char *msg@, @va_list ap@ = message
+ * @const char *msg@, @va_list ap@ = error message
*
- * Returns: ---
+ * Returns: The @tvec_error@ function returns @-1@ as a trivial
+ * convenience; @tvec_notice@ does not return a value.
*
- * Use: Output a notice: essentially, some important information
- * which doesn't fit into any of the existing categories.
+ * Use: Report an error or a notice. Errors are distinct from test
+ * failures, and indicate that a problem was encountered which
+ * compromised the activity of testing. Notices are important
+ * information which doesn't fit into any other obvious
+ * category.
*/
+int tvec_error(struct tvec_state *tv, const char *msg, ...)
+{
+ va_list ap;
+
+ va_start(ap, msg); tvec_report_v(tv, TVLEV_ERR, msg, &ap); va_end(ap);
+ return (-1);
+}
+
void tvec_notice(struct tvec_state *tv, const char *msg, ...)
{
va_list ap;
- va_start(ap, msg); tvec_notice_v(tv, msg, &ap); va_end(ap);
+
+ va_start(ap, msg); tvec_report_v(tv, TVLEV_NOTE, msg, &ap); va_end(ap);
}
-void tvec_notice_v(struct tvec_state *tv, const char *msg, va_list *ap)
- { tv->output->ops->notice(tv->output, msg, ap); }
/*----- Test processing ---------------------------------------------------*/
}
void tvec_skipgroup_v(struct tvec_state *tv, const char *excuse, va_list *ap)
{
- tv->f |= TVSF_SKIP; tv->grps[TVOUT_SKIP]++;
- tv->output->ops->skipgroup(tv->output, excuse, ap);
+ if (!(tv->f&TVSF_SKIP)) {
+ tv->f |= TVSF_SKIP; tv->grps[TVOUT_SKIP]++;
+ tv->output->ops->skipgroup(tv->output, excuse, ap);
+ }
}
static void set_outcome(struct tvec_state *tv, unsigned out)
}
}
-static void init_registers(struct tvec_state *tv)
+void tvec_initregs(struct tvec_state *tv)
{
const struct tvec_regdef *rd;
struct tvec_reg *r;
}
}
-static void release_registers(struct tvec_state *tv)
+void tvec_releaseregs(struct tvec_state *tv)
{
const struct tvec_regdef *rd;
struct tvec_reg *r;
if (!(tv->f&TVSF_SKIP)) {
begin_test(tv);
env = t->env;
- if (env && env->before && env->before(tv, g->ctx))
- tvec_skip(tv, "test setup failed");
+ if (env && env->before) env->before(tv, g->ctx);
+ if (!(tv->f&TVSF_ACTIVE))
+ /* setup forced a skip */;
+ else if (env && env->run)
+ env->run(tv, t->fn, g->ctx);
else {
- if (env && env->run) env->run(tv, t->fn, g->ctx);
- else { t->fn(tv->in, tv->out, g->ctx); tvec_check(tv, 0); }
+ t->fn(tv->in, tv->out, g->ctx);
+ tvec_check(tv, 0);
}
if (env && env->after) env->after(tv, g->ctx);
tvec_endtest(tv);
}
end:
- tv->f &= ~TVSF_OPEN; release_registers(tv); init_registers(tv);
+ tv->f &= ~TVSF_OPEN; tvec_releaseregs(tv); tvec_initregs(tv);
}
static void begin_test_group(struct tvec_state *tv, struct groupstate *g)
tv->output->ops->bgroup(tv->output);
tv->f &= ~TVSF_SKIP;
- init_registers(tv);
+ tvec_initregs(tv);
for (i = 0; i < TVOUT_LIMIT; i++) tv->curr[i] = 0;
if (env && env->ctxsz) g->ctx = xmalloc(env->ctxsz);
- if (env && env->setup && env->setup(tv, env, 0, g->ctx)) {
- tvec_skipgroup(tv, "setup failed");
- xfree(g->ctx); g->ctx = 0;
- }
+ if (env && env->setup) env->setup(tv, env, 0, g->ctx);
}
static void report_group(struct tvec_state *tv)
if (tv->f&TVSF_OPEN) check(tv, g);
if (!(tv->f&TVSF_SKIP)) report_group(tv);
env = t->env; if (env && env->teardown) env->teardown(tv, g->ctx);
- release_registers(tv); tv->test = 0; xfree(g->ctx); g->ctx = 0;
+ tvec_releaseregs(tv); tv->test = 0; xfree(g->ctx); g->ctx = 0;
}
int tvec_read(struct tvec_state *tv, const char *infile, FILE *fp)
for (rd = regs, i = 0; rd->name; rd++, i++) {
if (rd->i >= nr) continue;
r = TVEC_GREG(rv, rd->i, regsz); if (!(r->f&TVRF_LIVE)) continue;
- bitmap = BBASE(b) + bitoff; bitmap[rd->i/8] |= 1 << rd->i%8;
+ bitmap = BBASE(b) + bitoff; bitmap[i/8] |= 1 << i%8;
if (rd->ty->tobuf(b, &r->v, rd)) return (-1);
}
return (0);
bitmap = buf_get(b, bitsz); if (!bitmap) return (-1);
for (rd = regs, i = 0; rd->name; rd++, i++) {
if (rd->i >= nr) continue;
- if (!(bitmap[rd->i/8]&(1 << rd->i%8))) continue;
+ if (!(bitmap[i/8]&(1 << i%8))) continue;
r = TVEC_GREG(rv, rd->i, regsz);
if (rd->ty->frombuf(b, &r->v, rd)) return (-1);
r->f |= TVRF_LIVE;
adhoc_claim_setup(tv, &ck, regs, file, lno);
ok = ty->eq(&tv->in[0].v, &tv->out[0].v, ®s[0]);
if (!ok)
- { tvec_fail(tv, "%s", expr ); tvec_mismatch(tv, TVMF_IN | TVMF_OUT); }
+ { tvec_fail(tv, "%s", expr); tvec_mismatch(tv, TVMF_IN | TVMF_OUT); }
adhoc_claim_teardown(tv, &ck);
return (ok);
}