]> git.mdlowis.com Git - projs/tide.git/commitdiff
expanded quickcheck-like functionality
authorMichael D. Lowis <mike.lowis@gentex.com>
Wed, 27 Feb 2019 17:20:22 +0000 (12:20 -0500)
committerMichael D. Lowis <mike.lowis@gentex.com>
Wed, 27 Feb 2019 17:20:22 +0000 (12:20 -0500)
config.mk
src/lib/buf.c
tests/test_tide.c

index 6eadce4027492c51696b63f2d2048dc40f537c85..f8b9eb2789deaa90673eedb0922b855892314b77 100644 (file)
--- 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
index 32ffcede17a4c0d8c616803c89e0f9db03b40014..51c7307442932f92b9cf6ca8792f9e872889a453 100644 (file)
@@ -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);
 }
index fd04b6909990b6e3ab1f24265553662f8b1dc044..33d3df152f2652beaeb4e54913d0cd5fca591927 100644 (file)
@@ -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;
 }