@@@ all the mess ever
[mLib] / utils / t / control-test.c
index 51a9adf..772ddd2 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);
+  }
+
+  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);
+  }
+
+  TESTGROUP("loop") {
+    for (;;) {
+      MC_AFTER(after1, STEP(1); break) STEP(0);
+      MISSTEP; break;
+    }
+    STEP(2);
   }
-  step++;
-}
 
-#define LASTSTEP(s) laststep(s, __FILE__ ": " STR(__LINE__))
-static void laststep(int s, const char *where)
-  { check_step(s, where); step = 0; }
+#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);
+  }
+
+#undef FORELSE
+
+  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);
+  }
+
+#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);
+  }
+
+#undef WRAPELSE_TEST
+
+  TESTGROUP("decl") {
+#if __STDC_VERSION__ >= 199901 || defined(__cplusplus)
+    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)                                 \
-       FIRSTBRANCH(fizzbuzz0) GOBRANCH(fizzbuzz2);                     \
-       MIDBRANCH(fizzbuzz1) ;                                          \
-       LASTBRANCH(fizzbuzz2)                                           \
-       DECL(fizzbuzz3, int _i = base COMMA _limit = limit)             \
-         for (; _i < _limit; _i++)                                     \
-           DECL(fizzbuzz4, char _buf[24])                              \
-           DECL(fizzbuzz5, const char *var)                            \
-           WRAP(fizzbuzz6, {                                           \
-             switch (_i%15) {                                          \
+       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;    \
-             }                                                         \
-           },                                                          \
+             } },                                                      \
            { ; },                                                      \
-           { GOBRANCH(fizzbuzz1); })
-
-int main(void)
-{
-  BEFORE(before0, { STEP(0); }) STEP(1);
-  AFTER(after0, { STEP(3); }) STEP(2);
-  LASTSTEP(4);
-
-  WRAP(wrap0, { STEP(0); }, { STEP(2); }, { MISSTEP; }) STEP(1);
-  WRAP(wrap1, { STEP(3); }, { MISSTEP; }, { STEP(5); }) { STEP(4); break; }
-  LASTSTEP(6);
-
-  STEP(0);
-  for (;;) {
-    AFTER(after1, { STEP(2); break; }) STEP(1);
-    MISSTEP; 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]);
   }
-  LASTSTEP(3);
-
-  STEP(0);
-  DECL(decl0, int i = 1) STEP(i);
-  LASTSTEP(2);
 
-  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 -------------------------------------------------*/