#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_TAG(grp, &tvstate, name) \
+ MC_BEFORE(init, { step = 0; })
+#define TEST TVEC_TEST_TAG(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_adhocconfig);
+ 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_TEXTZ(&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 -------------------------------------------------*/