#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;
+static struct tvec_state tvstate;
+static int step;
-#define STEP(s) check_step(s, __FILE__ ": " STR(__LINE__))
-#define MISSTEP STEP(-1)
-static void check_step(int s, const char *where)
+#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);
+ }
+
+ 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);
+ }
+
+#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);
}
- step++;
-}
-#define LASTSTEP(s) laststep(s, __FILE__ ": " STR(__LINE__))
-static void laststep(int s, const char *where)
- { check_step(s, where); step = 0; }
+#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); })
+ { MC_GOTARGET(out); })
-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);
+ 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
+ };
- STEP(0);
- DECL(decl0, int i = 1) STEP(i);
- LASTSTEP(2);
+ 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, 27) printf("%s\n", fb);
+#undef FIZZBUZZ_DECLS
+#undef FOR_FIZZBUZZ
- return (rc);
+ return (tvec_end(&tvstate));
}
/*----- That's all, folks -------------------------------------------------*/