@@@ so much mess
[mLib] / test / t / tvec-test.c
index 8b27f7f..f2ed3da 100644 (file)
 
 /*----- Register definitions ----------------------------------------------*/
 
-enum {
-  /* Standard outputs. */
-  RRC,                                 /* return code from deserialize */
-
-  /* Output registers, one for each register type. */
-  RI, RU, RIE, RUE, RPE, RF, RSTR, RBY, RBUF,
-
-  /* Additional diagnostic outputs. */
-  RSER,                                        /* serialized data */
-
-  NROUT,
-
-  /* Some additional inputs. */
-  RSAB = NROUT,                                /* which register to sabotage */
-
-  NREG,
-
-  /* Single register for copy tests. */
-  RV = 0
-};
-
 static const struct tvec_iassoc ienum_assocs[] = {
   { "less",           -1 },
   { "equal",           0 },
@@ -66,6 +45,13 @@ static const struct tvec_uassoc uenum_assocs[] = {
   { 0 }
 };
 
+static const struct tvec_fassoc fenum_assocs[] = {
+  { "e",               2.718281828459045 },
+  { "pi",              3.141592653589793 },
+  { "tau",             6.283185307179586 },
+  { 0 }
+};
+
 static const struct tvec_passoc penum_assocs[] = {
   { "alice",           &uenum_assocs[0] },
   { "bob",             &uenum_assocs[1] },
@@ -73,19 +59,28 @@ static const struct tvec_passoc penum_assocs[] = {
   { 0 }
 };
 
-#if __STDC_VERSION__ >= 199901
+#if __STDC_VERSION__x >= 199901
 #  define DSGINIT(x) x
 #else
 #  define DSGINIT(x)
 #endif
 
-static DSGINIT(const) struct tvec_enuminfo
-  ienum_info = { "order", TVMISC_INT,
-                DSGINIT({ .i = { ienum_assocs COMMA &tvrange_i16 } }) },
-  uenum_info = { "fruit", TVMISC_UINT,
-                DSGINIT({ .u = { uenum_assocs COMMA &tvrange_u16 } }) },
-  penum_info = { "player", TVMISC_PTR,
-                DSGINIT({ .p = { penum_assocs } }) };
+static const struct tvec_floatinfo fenum_fltinfo =
+  { TVFF_ABSDELTA, -10, +10, 1e-3 };
+
+#define DEFENUM(tag, ty, slot)                                         \
+  static const struct tvec_##slot##enuminfo slot##enum_info =          \
+    { { slot##enum_NAME, TVMISC_##tag }, slot##enum_assocs slot##enum_ARGS };
+#define ienum_NAME "order"
+#define ienum_ARGS , &tvrange_i16
+#define uenum_NAME "fruit"
+#define uenum_ARGS , &tvrange_u16
+#define fenum_NAME "const"
+#define fenum_ARGS , &fenum_fltinfo
+#define penum_NAME "actor"
+#define penum_ARGS
+TVEC_MISCSLOTS(DEFENUM)
+#undef DEFENUM
 
 static const struct tvec_flag attr_flags[] = {
   { "black-fg",                0x07, 0x00 },
@@ -116,37 +111,70 @@ static const struct tvec_flag attr_flags[] = {
 static const struct tvec_flaginfo attr_info =
   { "attr", attr_flags, &tvrange_u16 };
 
+static const struct tvec_floatinfo fltish_info =
+  { TVFF_RELDELTA, -1.0, +1.0, 1e-6 };
+
 static const struct tvec_urange range_32 = { 0, 31 };
 
 #define TYPEREGS(_)                                                    \
   _(int,       RI,     int,                    p, &tvrange_i16)        \
   _(uint,      RU,     uint,                   p, &tvrange_u16)        \
+  _(float,     RFP,    float,                  p, 0)                   \
+  _(fltish,    RFISH,  float,                  p, &fltish_info)        \
+  _(char,      RCH,    char,                   p, 0)                   \
   _(ienum,     RIE,    enum,                   p, &ienum_info)         \
   _(uenum,     RUE,    enum,                   p, &uenum_info)         \
+  _(fenum,     RFE,    enum,                   p, &fenum_info)         \
   _(penum,     RPE,    enum,                   p, &penum_info)         \
   _(flags,     RF,     flags,                  p, &attr_info)          \
   _(string,    RSTR,   string,                 p, &range_32)           \
   _(bytes,     RBY,    bytes,                  p, &tvrange_byte)       \
   _(buffer,    RBUF,   buffer,                 p, &tvrange_u16)
 
+enum {
+  /* Output registers, one for each register type. */
+#define DEFREG(name, i, ty, argslot, argval) i,
+  TYPEREGS(DEFREG)
+#undef DEFREG
+  NSER,
+
+  /* Standard outputs. */
+  RRC = NSER,                          /* return code from deserialize */
+
+  /* Additional diagnostic outputs. */
+  RSER,                                        /* serialized data */
+
+  NROUT,
+
+  /* Some additional inputs. */
+  RSAB = NROUT,                                /* which register to sabotage */
+
+  NREG,
+
+  /* Single register for copy tests. */
+  RV = 0
+};
+
 /*----- Serialization test ------------------------------------------------*/
 
 struct test_context {
   struct tvec_state *tv;
 };
 
-static int capture_state_and_run(struct tvec_state *tv)
-{
-  struct test_context tctx;
+static int capture_setup(struct tvec_state *tv,
+                        const struct tvec_env *env, void *pctx, void *ctx)
+  { struct test_context *tctx = ctx; tctx->tv = tv; return (0); }
 
-  tctx.tv = tv; tv->test->fn(tv->in, tv->out, &tctx);
+static void capture_run(struct tvec_state *tv, tvec_testfn *fn, void *ctx)
+{
   if (!(tv->in[RRC].f&TVRF_LIVE)) {
-    tv->in[RRC].v.i = 0;
-    tv->in[RRC].f |= TVRF_LIVE; tv->out[RRC].f |= TVRF_LIVE;
+    tv->in[RRC].f |= TVRF_LIVE; tv->in[RRC].v.i = 0;
+    tv->out[RRC].f |= TVRF_LIVE;
   }
-  tvec_check(tv, 0);
-  return (0);
+  fn(tv->in, tv->out, ctx); tvec_check(tv, 0);
 }
+static const struct tvec_env capture_testenv =
+  { sizeof(struct test_context), capture_setup, 0, 0, capture_run, 0, 0 };
 
 static void test_serialization
   (const struct tvec_reg *in, struct tvec_reg *out, void *ctx)
@@ -155,17 +183,21 @@ static void test_serialization
   struct tvec_state *tv = tctx->tv;
   const struct tvec_regdef *rd;
   union tvec_regval *rv;
-  void *p; size_t sz;
+  dbuf b = DBUF_INIT;
 
-  if (tvec_serialize(tv->in, tv->test->regs,
-                    NROUT, sizeof(struct tvec_reg), &p, &sz))
-    { out[RRC].v.i = -1; return; }
+  if (tvec_serialize(tv->in, DBUF_BUF(&b), tv->test->regs,
+                    NSER, sizeof(struct tvec_reg)))
+    { out[NSER].v.i = -1; goto end; }
+  tvec_allocbytes(&out[RSER].v, DBLEN(&b));
+  memcpy(out[RSER].v.bytes.p, DBBASE(&b), DBLEN(&b));
   out[RSER].f |= TVRF_LIVE;
-  out[RSER].v.bytes.p = p; out[RSER].v.bytes.sz = sz;
+  buf_flip(DBUF_BUF(&b));
 
-  if (tvec_deserialize(tv->out, tv->test->regs,
-                       NROUT, sizeof(struct tvec_reg), p, sz))
-    { out[RRC].v.i = -1; return; }
+  if (tvec_deserialize(tv->out, DBUF_BUF(&b), tv->test->regs,
+                      NSER, sizeof(struct tvec_reg)))
+    { out[RRC].v.i = -2; goto end; }
+  if (BLEFT(&b._b))
+    { out[RRC].v.i = -3; goto end; }
 
   if (in[RSAB].f&TVRF_LIVE) {
     for (rd = tv->test->regs; rd->name; rd++)
@@ -173,12 +205,19 @@ static void test_serialization
        rv = &out[rd->i].v;
        if (rd->ty == &tvty_int ||
            (rd->ty == &tvty_enum &&
-            ((struct tvec_enuminfo *)rd->arg.p)->mv == TVMISC_INT))
+            ((const struct tvec_enuminfo *)rd->arg.p)->mv == TVMISC_INT))
          rv->i ^= 1;
        else if (rd->ty == &tvty_uint || rd->ty == &tvty_flags ||
                 (rd->ty == &tvty_enum &&
-                 ((struct tvec_enuminfo *)rd->arg.p)->mv == TVMISC_INT))
+                 ((const struct tvec_enuminfo *)rd->arg.p)->mv ==
+                   TVMISC_INT))
          rv->u ^= 1;
+       else if (rd->ty == &tvty_enum &&
+                ((const struct tvec_enuminfo *)rd->arg.p)->mv == TVMISC_PTR)
+         rv->p = rv->p
+           ? 0
+           : (/*unconst*/ void *)
+               ((const struct tvec_penuminfo *)rd->arg.p)->av[0].p;
        else if (rd->ty == &tvty_string)
          { if (rv->str.sz) rv->str.p[0] ^= 1; }
        else if (rd->ty == &tvty_bytes)
@@ -187,9 +226,11 @@ static void test_serialization
   }
 
   out[RRC].v.i = 0;
+end:
+  dbuf_destroy(&b);
 }
 
-DSGINIT(static) const struct tvec_regdef test_regs[] = {
+static DSGINIT(const) struct tvec_regdef test_regs[] = {
 #define DEFREG(name, i, ty, argslot, argval)                           \
   { #name,     i,      &tvty_##ty,     TVRF_OPT,                       \
                                            DSGINIT({ .argslot = argval }) },
@@ -226,8 +267,12 @@ static void test_copy_bytes
 #define test_copy_uint test_copy_simple
 #define test_copy_ienum test_copy_simple
 #define test_copy_uenum test_copy_simple
+#define test_copy_fenum test_copy_simple
 #define test_copy_penum test_copy_simple
+#define test_copy_char test_copy_simple
 #define test_copy_flags test_copy_simple
+#define test_copy_float test_copy_simple
+#define test_copy_fltish test_copy_simple
 #define test_copy_buffer test_copy_bytes
 
 #define SINGLEREG(name, i, ty, argslot, argval)                                \
@@ -238,14 +283,63 @@ static void test_copy_bytes
 TYPEREGS(SINGLEREG)
 #undef SINGLEREG
 
+struct singlectx {
+  unsigned f;
+#define SF_SHOW 1u
+};
+
+static int single_setup(struct tvec_state *tv, const struct tvec_env *env,
+                       void *pctx, void *ctx)
+  { struct singlectx *s = ctx; s->f = 0; return (0); }
+
+static int single_set(struct tvec_state *tv, const char *name,
+                     const struct tvec_env *env, void *ctx)
+{
+  struct singlectx *s = ctx;
+  union tvec_regval rv;
+  static const struct tvec_regdef rd =
+    { "@show", -1, &tvty_enum, 0, { &tvenum_bool } };
+
+  if (STRCMP(name, ==, "@show")) {
+    if (tvty_enum.parse(&rv, &rd, tv)) return (-1);
+    if (s) {
+      if (rv.i) s->f |= SF_SHOW;
+      else s->f &= ~SF_SHOW;
+    }
+    return (1);
+  } else
+    return (0);
+}
+
+static void single_run(struct tvec_state *tv, tvec_testfn *fn, void *ctx)
+{
+  struct singlectx *s = ctx;
+  unsigned f = s->f;
+
+  fn(tv->in, tv->out, 0);
+  if (tvec_checkregs(tv)) { tvec_fail(tv, 0); f |= SF_SHOW; }
+  if (f&SF_SHOW) tvec_mismatch(tv, TVMF_IN | TVMF_OUT);
+}
+
+static void single_after(struct tvec_state *tv, void *ctx)
+  { struct singlectx *s = ctx; s->f = 0; }
+
+static const struct tvec_env single_testenv =
+  { sizeof(struct singlectx),
+    single_setup,
+    single_set,
+    0,
+    single_run,
+    single_after,
+    0 };
+
 /*----- Front end ---------------------------------------------------------*/
 
 static const struct tvec_test tests[] = {
-  { "types",   test_regs,      0,      capture_state_and_run,
-                                                       test_serialization },
+  { "types",   test_regs,      &capture_testenv,       test_serialization },
 
 #define DEFCOPY(name, i, ty, argslot, argval)                          \
-  { #name,     name##_regs,    0,      tvec_runtest,   test_copy_##name },
+  { #name,     name##_regs,    &single_testenv,        test_copy_##name },
   TYPEREGS(DEFCOPY)
 #undef DEFCOPY
 
@@ -259,12 +353,9 @@ static const struct tvec_info testinfo = {
 
 int main(int argc, char *argv[])
 {
-#if __STDC_VERSION__ < 199901
-#  define POKE(tag, ty, slot)                                          \
-       slot##enum_info.u.slot.av = slot##enum_assocs;                  \
-  TVEC_MISCSLOTS(POKE)
-#  undef POKE
+#if __STDC_VERSION__x < 199901
 #  define POKE(name, i, ty, argslot, argval)                           \
+       test_regs[i].arg.argslot = argval;                              \
        name##_regs->arg.argslot = argval;
   TYPEREGS(POKE)
 #  undef POKE