#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;
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) {
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) {
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;
}