chiark / gitweb /
@@@ all the mess ever
[mLib] / utils / t / control-test.c
index 0f47e26662e8ccb012ae37dcaef7623716291e75..772ddd29a03fdcf6361e931d39ca22e96e11dcc9 100644 (file)
 
 #include <stdio.h>
 #include <stdlib.h>
+#include <string.h>
 
 #include "control.h"
+#include "report.h"
+#include "tvec.h"
 
 /*----- Main code ---------------------------------------------------------*/
 
-static int step = 0;
-static int rc = 0;
-
-#define STEP(s) check_step(s, __FILE__ ": " STR(__LINE__))
-#define MISSTEP STEP(-1)
-static void check_step(int s, const char *where)
+static struct tvec_state tvstate;
+static int step;
+
+#define TESTGROUP(name)                                                        \
+       TVEC_TESTGROUP(tg, &tvstate, name)                              \
+       MC_BEFORE(init, { step = 0; })
+#define TEST TVEC_TEST(test, &tvstate)
+#define STEP(s) do {                                                   \
+         tvec_claim(&tvstate, s == step, __FILE__, __LINE__,           \
+                    "found %d /= expected %d", s, step);               \
+         step++;                                                       \
+       } while (0)
+#define MISSTEP do {                                                   \
+         tvec_claim(&tvstate, 0, __FILE__, __LINE__,                   \
+                    "shouldn't have reached here");                    \
+         step++;                                                       \
+       } while (0)
+
+int main(int argc, char *argv[])
 {
-  if (step != s) {
-    fprintf(stderr, "misstep at %s: expected %d but found %d\n",
-           where, step, s);
-    rc = 2;
+  struct tvec_test test;
+  int argpos;
+  int i;
+
+  tvec_parseargs(argc, argv, &tvstate, &argpos, &tvec_adhocinfo);
+  if (argpos < argc) die(2, "no input files expected");
+  tvec_adhoc(&tvstate, &test);
+
+  TESTGROUP("before-after") {
+    MC_BEFORE(before0, STEP(0)) STEP(1);
+    MC_AFTER(after0, STEP(3)) STEP(2);
+    STEP(4);
   }
-  step++;
-}
 
-#define LASTSTEP(s) laststep(s, __FILE__ ": " STR(__LINE__))
-static void laststep(int s, const char *where)
-  { check_step(s, where); step = 0; }
+  TESTGROUP("wrap") {
+    MC_WRAP(wrap0, STEP(0), STEP(2), MISSTEP)
+      STEP(1);
+    MC_WRAP(wrap1, STEP(3), MISSTEP, STEP(5))
+      { STEP(4); break; }
+    STEP(6);
+  }
 
-#define FORELSE(head)                                                  \
-                       MC_GOTO(top)                                    \
-  MC_LABEL(out)                MC_ACT(;)                                       \
-  MC_LABEL(top)                ALLOWELSE(els)                                  \
-                       AFTER(outer, GOELSE(els))                       \
-                       for (head)                                      \
-                         WRAP(inner, { ; },                            \
-                                     { ; },                            \
-                                     { MC_GOTO(out); })
+  TESTGROUP("loop") {
+    for (;;) {
+      MC_AFTER(after1, STEP(1); break) STEP(0);
+      MISSTEP; break;
+    }
+    STEP(2);
+  }
 
-#define FOR_FIZZBUZZ(var, base, limit)                                 \
-                       MC_GOTO(top)                                    \
-  MC_LABEL(out)                MC_ACT({ ; })                                   \
-  MC_LABEL(top)                DECL(bounds,                                    \
-                            int _i = base COMMA _limit = limit)        \
-                       for (; _i < _limit; _i++)                       \
-                         DECL(buf, char _buf[24])                      \
-                         DECL(var, const char *var)                    \
-                         WRAP(wrap, {                                  \
-                           switch (_i%15) {                            \
-                             case 0:                                   \
-                               var = "fizzbuzz";                       \
-                               break;                                  \
-                             case 3: case 6: case 9: case 12:          \
-                               var = "fizz";                           \
-                               break;                                  \
-                             case 5: case 10:                          \
-                               var = "buzz";                           \
-                               break;                                  \
-                             default:                                  \
-                               sprintf(_buf, "%d", _i); var = _buf;    \
-                               break;                                  \
-                           }                                           \
-                         },                                            \
-                         { ; },                                        \
-                         { MC_GOTO(out); })
-
-int main(void)
-{
-  int i;
+#define FORELSE(head) MC_LOOPELSE(forelse, for (head))
+
+  TESTGROUP("for-else") {
+    FORELSE (i = 0; i < 10; i++) {
+      STEP(i);
+      if (i == 7) break;
+    } else
+      MISSTEP;
+    STEP(8);
+  }
+
+  TESTGROUP("for-else-break") {
+    FORELSE (i = 0; i < 10; i++) {
+      STEP(i);
+      if (i == 12) break;
+    } else
+      STEP(10);
+    STEP(11);
+  }
 
-  BEFORE(before0, STEP(0)) STEP(1);
-  AFTER(after0, STEP(3)) STEP(2);
-  LASTSTEP(4);
+#undef FORELSE
 
-  WRAP(wrap0, STEP(0), STEP(2), MISSTEP) STEP(1);
-  WRAP(wrap1, STEP(3), MISSTEP, STEP(5)) { STEP(4); break; }
-  LASTSTEP(6);
+  TESTGROUP("loop-between") {
+    MC_LOOPBETWEEN(x, i = 0, i < 5, i++) STEP(2*i);
+    else STEP(2*i - 1);
+    STEP(9);
+  }
+
+  TESTGROUP("loop-between-continue-break") {
+    MC_LOOPBETWEEN(x, i = 0, i < 5, i++) {
+      if (i == 1) { STEP(2); continue; }
+      STEP(2*i);
+      if (i == 3) break;
+    } else
+      STEP(2*i - 1);
+    STEP(7);
+  }
 
-  STEP(0);
-  for (;;) {
-    AFTER(after1, STEP(2); break) STEP(1);
-    MISSTEP; break;
+#define WRAPELSE_TEST                                                  \
+       MC_TARGET(done_plain, { STEP(4); MC_GOELSE(elsie); })           \
+       MC_WRAP(outer_wrap, { STEP(0); },                               \
+                           { STEP(6); },                               \
+                           { MISSTEP; })                               \
+       MC_ALLOWELSE(elsie)                                             \
+       MC_WRAP(inner_wrap, { STEP(1); },                               \
+                           { STEP(3); MC_GOTARGET(done_plain); },      \
+                           { MISSTEP; })
+
+  TESTGROUP("wrap-else") {
+    WRAPELSE_TEST STEP(2);
+    else STEP(5);
+    STEP(7);
   }
-  LASTSTEP(3);
-
-  FORELSE (i = 0; i < 10; i++) {
-    STEP(i);
-    if (i == 7) break;
-  } else
-    MISSTEP;
-  LASTSTEP(8);
-
-  FORELSE (i = 0; i < 10; i++) {
-    STEP(i);
-    if (i == 12) break;
-  } else
-    STEP(10);
-  LASTSTEP(11);
-
-#define TEST                                                           \
-                       MC_ACT(STEP(0); MC_GOTO(in_plain))              \
-  MC_LABEL(done_plain) MC_ACT(STEP(5); GOELSE(elsie))                  \
-  MC_LABEL(in_plain)   WRAP(outer_wrap, { STEP(1); },                  \
-                                        { STEP(7); },                  \
-                                        { MISSTEP; })                  \
-                       ALLOWELSE(elsie)                                \
-                         WRAP(inner_wrap, { STEP(2); },                \
-                                          { STEP(4);                   \
-                                            MC_GOTO(done_plain); },    \
-                                          { MISSTEP; })                \
-                         STEP(3);                                      \
-                       else                                            \
-                         STEP(6);                                      \
-                       LASTSTEP(8);
-  TEST
-#undef TEST
 
+#undef WRAPELSE_TEST
+
+  TESTGROUP("decl") {
 #if __STDC_VERSION__ >= 199901 || defined(__cplusplus)
-  STEP(0);
-  DECL(decl0, int j = 1) STEP(j);
-  LASTSTEP(2);
+    STEP(0);
+    MC_DECL(decl0, int j = 1) STEP(j);
+    STEP(2);
+#else
+    tvec_skipgroup(&tvstate, "`MC_DECL' not supported on C89");
 #endif
+  }
+
+#define FIZZBUZZ_DECLS(var)                                            \
+       int _i, _limit;                                                 \
+       char _buf[24];                                                  \
+       const char *var
+#define FOR_FIZZBUZZ(var, base, limit)                                 \
+       MC_TARGET(out, { ; })                                           \
+       MC_BEFORE(bounds, { _i = base; _limit = limit; })               \
+       for (; _i < _limit; _i++)                                       \
+         MC_WRAP(wrap,                                                 \
+           { switch (_i%15) {                                          \
+               case 0: var = "fizzbuzz"; break;                        \
+               case 3: case 6: case 9: case 12: var = "fizz"; break;   \
+               case 5: case 10: var = "buzz"; break;                   \
+               default: sprintf(_buf, "%d", _i); var = _buf; break;    \
+             } },                                                      \
+           { ; },                                                      \
+           { MC_GOTARGET(out); })
+
+  TESTGROUP("fizzbuzz") {
+    FIZZBUZZ_DECLS(fb);
+    unsigned i;
+    static const char *const ref[] = {
+      "19", "buzz", "fizz", "22", "23", "fizz", "buzz",
+      "26", "fizz", "28", "29", "fizzbuzz", "31", 0
+    };
+
+    i = 0;
+    FOR_FIZZBUZZ(fb, 19, 32)
+      TEST
+       if (TVEC_CLAIM(&tvstate, ref[i]))
+         { TVEC_CLAIMEQ_STRZ(&tvstate, fb, ref[i]); i++; }
+    TVEC_CLAIM(&tvstate, !ref[i]);
+  }
 
-  FOR_FIZZBUZZ(fb, 19, 32) printf("%s\n", fb);
+#undef FIZZBUZZ_DECLS
+#undef FOR_FIZZBUZZ
 
-  return (rc);
+  return (tvec_end(&tvstate));
 }
 
 /*----- That's all, folks -------------------------------------------------*/