X-Git-Url: https://git.distorted.org.uk/~mdw/mLib/blobdiff_plain/2edecb46edfcdc4b25c9d12bcfe23a5d66ec3f33..b64eb60f6c1fdb12f3922e04913e137199838807:/utils/t/control-test.c diff --git a/utils/t/control-test.c b/utils/t/control-test.c index d69572b..772ddd2 100644 --- a/utils/t/control-test.c +++ b/utils/t/control-test.c @@ -29,127 +29,168 @@ #include #include +#include #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 -------------------------------------------------*/