From: Michael D. Lowis Date: Wed, 27 Feb 2019 17:20:22 +0000 (-0500) Subject: expanded quickcheck-like functionality X-Git-Url: https://git.mdlowis.com/?a=commitdiff_plain;h=6afc0c4837f77bdfac4c8e4ac315c4df3a9dbd4c;p=projs%2Ftide.git expanded quickcheck-like functionality --- diff --git a/config.mk b/config.mk index 6eadce4..f8b9eb2 100644 --- a/config.mk +++ b/config.mk @@ -33,8 +33,8 @@ ARFLAGS = rcs #LDFLAGS += -g -fsanitize=address,undefined # GCC - Enable Sanitizers -#CFLAGS += -g -fsanitize=address,leak,undefined -#LDFLAGS += -g -fsanitize=address,leak,undefined -lasan +CFLAGS += -g -fsanitize=address,undefined +LDFLAGS += -g -fsanitize=address,undefined -lasan # GCC/Clang Profiling #CFLAGS += -pg diff --git a/src/lib/buf.c b/src/lib/buf.c index 32ffced..51c7307 100644 --- a/src/lib/buf.c +++ b/src/lib/buf.c @@ -83,6 +83,7 @@ void buf_init(Buf* buf) { buf->bufstart = NULL; buf_logclear(buf); } + /* reset the state to defaults */ buf->status = NORMAL; buf->bufsize = 8192; @@ -139,6 +140,7 @@ void buf_load(Buf* buf, char* path) { void buf_reload(Buf* buf) { char* path = buf->path; + buf->path = NULL; buf_init(buf); buf_load(buf, path); } diff --git a/tests/test_tide.c b/tests/test_tide.c index fd04b69..33d3df1 100644 --- a/tests/test_tide.c +++ b/tests/test_tide.c @@ -3,15 +3,16 @@ #define TEST #include "src/tide.c" -typedef struct { - void *value; - int nelem; -// QCC_showValue show; -// QCC_freeValue free; -} QCValue; +typedef struct QCValue QCValue; +struct QCValue { + void (*showfn)(QCValue* val); + void (*freefn)(QCValue* val); + int data[]; +}; typedef struct { - int status, nvals; + int status; + int nvals; QCValue** vals; } QCResult; @@ -19,14 +20,18 @@ typedef int (*QCProp)(QCValue** vals, int nvals); typedef QCValue* (*QCGenFn)(void); +int Seed = 0, NTrials = 10000; +void qcinit(int seed) { + Seed = (seed ? seed : time(NULL)); + srand(Seed); +} - -void qc_init(int seed) { - srand(seed ? seed : time(NULL)); +void qcntrials(int ntrials) { + NTrials = ntrials; } -QCResult vforAll(QCProp prop, int nvals, va_list vals) { +QCResult vqcheck(QCProp prop, int nvals, va_list vals) { /* generate the input values */ QCValue** values = NULL; if (nvals) { @@ -42,28 +47,68 @@ QCResult vforAll(QCProp prop, int nvals, va_list vals) { return result; } -int forAll(int num, QCProp prop, int nvals, ...) { - (void)num, (void)prop, (void)nvals; +void qcfree(QCValue** vals, int nvals) { + for (int i = 0; i < nvals; i++) { + if (vals[i]->freefn) vals[i]->freefn(vals[i]); + free(vals[i]); + } + free(vals); +} + +void qcshow(QCValue** vals, int nvals) { + for (int i = 0; i < nvals; i++) { + printf("Argument %d: ", i); + vals[i]->showfn(vals[i]); + } +} + +int qcheck(char* desc, QCProp prop, int nvals, ...) { int passed = 0; QCResult result; va_list vals; - for (int i = 0; i < num; i++) { + for (int i = 0; i < NTrials; i++) { va_start(vals, nvals); - result = vforAll(prop, nvals, vals); + result = vqcheck(prop, nvals, vals); va_end(vals); if (!result.status) break; + qcfree(result.vals, result.nvals); passed++; } /* show 'em the results */ - if (passed == num) { - printf("%d tests passed\n", passed); - } else if (result.status == 0) { - printf("Falsifiable after %d tests\n", passed+1); + if (passed == NTrials) { + printf("%d tests passed for property: %s\n", passed, desc); + } else if (!result.status) { + printf("Property: %s\nFalsifiable after %d tests (seed: %d)\n", desc, passed+1, Seed); + qcshow(result.vals, result.nvals); + /* should investigate shrinking input here as well */ + qcfree(result.vals, result.nvals); return 0; } return 1; } +QCValue* qcalloc(size_t sz, void* data) { + QCValue* value = calloc(1, sizeof(QCValue) + sz); + memcpy(value->data, data, sz); + return value; +} + +/************************************************/ +void ShowInt(QCValue* val) { + printf("%d\n", (val->data[0])); +} + +int randint(int from, int to) { + return ((rand() % (to - from)) + from); +} + +QCValue* GenInt(void) { + int ival = rand(); + QCValue* value = qcalloc(sizeof(int), &ival); + value->showfn = ShowInt; + return value; +} + /************************************************/ void tide_init(void) { @@ -79,9 +124,18 @@ void tide_init(void) { xupdate(NULL); } +/************************************************/ + +int divisible_by_two(QCValue** vals, int nvals) { + (void)nvals; + return ((vals[0]->data[0] % 2) == 0); +} int main(int argc, char** argv) { (void)argc, (void)argv, (void)usage; - puts("running prop tests"); + + qcinit(0); + qcheck("all numbers are divisible by 2", divisible_by_two, 1, GenInt); + return 0; }