/*----- 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 },
{ 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] },
{ 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 },
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)
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++)
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)
}
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 }) },
#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) \
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
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