chiark / gitweb /
@@@ remote works?
[mLib] / test / tvec-core.c
index 92f31d38a8f8eb73c08131b108a91803b10684cf..51834f43f04bcd1bfaa45be7604693acd2a37fe6 100644 (file)
 
 /*----- 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 ---------------------------------------------------*/
 
@@ -91,8 +102,10 @@ void tvec_skipgroup(struct tvec_state *tv, const char *excuse, ...)
 }
 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)
@@ -302,7 +315,7 @@ void tvec_resetoutputs(struct tvec_state *tv)
   }
 }
 
-static void init_registers(struct tvec_state *tv)
+void tvec_initregs(struct tvec_state *tv)
 {
   const struct tvec_regdef *rd;
   struct tvec_reg *r;
@@ -315,7 +328,7 @@ static void init_registers(struct tvec_state *tv)
   }
 }
 
-static void release_registers(struct tvec_state *tv)
+void tvec_releaseregs(struct tvec_state *tv)
 {
   const struct tvec_regdef *rd;
   struct tvec_reg *r;
@@ -392,18 +405,21 @@ static void check(struct tvec_state *tv, struct groupstate *g)
   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)
@@ -414,13 +430,10 @@ 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)
@@ -448,7 +461,7 @@ static void end_test_group(struct tvec_state *tv, struct groupstate *g)
   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)
@@ -611,7 +624,7 @@ int tvec_serialize(const struct tvec_reg *rv, buf *b,
   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);
@@ -632,7 +645,7 @@ int tvec_deserialize(struct tvec_reg *rv, buf *b,
   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;
@@ -750,7 +763,7 @@ int tvec_claimeq(struct tvec_state *tv,
   adhoc_claim_setup(tv, &ck, regs, file, lno);
   ok = ty->eq(&tv->in[0].v, &tv->out[0].v, &regs[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);
 }