typedef QCValue* (*QCGenFn)(void);
-#define VAL(v, type) ((type)((v)->data[0]))
+#define PROPERTY(name) \
+ int name (int nvals, QCValue** vals)
+
+#define VAL(i, type) \
+ (type)&(qcgetval(nvals, vals, i)->data[0])
+
+#define IVAL(i) \
+ (qcgetval(nvals, vals, i)->data[0])
+
+#define QASSERT(cond) \
+ if (!(cond)) return 0
+
+static inline QCValue* qcgetval(int nvals, QCValue** vals, int i) {
+ return vals[i < nvals ? i : nvals-1];
+}
void qcinit(int seed);
void qcntrials(int ntrials);
QCResult vqcheck(QCProp prop, int nvals, va_list vals);
int qcheck(char* desc, QCProp prop, int nvals, ...);
-void ShowLong(QCValue* val);
-void ShowBool(QCValue* val);
-void ShowChar(QCValue* val);
+void show_long(QCValue* val);
+void show_bool(QCValue* val);
+void show_char(QCValue* val);
+void show_byte(QCValue* val);
+void show_string(QCValue* val);
QCValue* MkLong(long val, void (*showfn)(QCValue* val));
+QCValue* MkArray(size_t nelems, size_t elemsz, void (*showfn)(QCValue* val));
QCValue* GenLongR(long from, long to);
QCValue* GenLong(void);
QCValue* GenU8(void);
QCValue* GenBool(void);
QCValue* GenByte(void);
QCValue* GenAsciiChar(void);
+QCValue* GenAsciiStringL(size_t len);
QCValue* GenAsciiString(void);
/* Function Definitions
#include <stdlib.h>
#include <stdio.h>
-static int Seed = 0, NTrials = 1000;
+static int Seed = 0, NTrials = 5000;
void qcinit(int seed) {
Seed = (seed ? seed : time(NULL));
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);
+ printf("\nProperty: %s\nFalsifiable after %d tests (seed: %d)\n", desc, passed+1, Seed);
qcshow(result.nvals, result.vals);
qcfree(result.nvals, result.vals);
+ puts("");
return 0;
}
return 1;
}
-void ShowLong(QCValue* val) {
+void show_long(QCValue* val) {
printf("%ld\n", (val->data[0]));
}
-void ShowBool(QCValue* val) {
+void show_bool(QCValue* val) {
printf("%s\n", (val->data[0] ? "true" : "false"));
}
-void ShowChar(QCValue* val) {
+void show_char(QCValue* val) {
printf("'%c'\n", (char)(val->data[0]));
}
-void ShowByte(QCValue* val) {
+void show_byte(QCValue* val) {
printf("0x%02x\n", (char)(val->data[0]));
}
-void ShowString(QCValue* val) {
+void show_string(QCValue* val) {
printf("'%s'\n", (char*)(val->data));
}
}
QCValue* GenLongR(long from, long to) {
- return MkLong(qcrandr(from, to), ShowLong);
+ return MkLong(qcrandr(from, to), show_long);
}
QCValue* GenLong(void) {
- return MkLong(qcrand(), ShowLong);
+ return MkLong(qcrand(), show_long);
}
QCValue* GenU8(void) {
}
QCValue* GenBool(void) {
- return MkLong(qcrandr(0, 1), ShowBool);
+ return MkLong(qcrandr(0, 1), show_bool);
}
QCValue* GenByte(void) {
- return MkLong(qcrandr(0, 255), ShowByte);
+ return MkLong(qcrandr(0, 255), show_byte);
}
QCValue* GenAsciiChar(void) {
- return MkLong(qcrandr(32, 127), ShowChar);
+ return MkLong(qcrandr(32, 127), show_char);
}
-QCValue* GenAsciiString(void) {
- size_t nelem = qcrandr(1, 1024);
- QCValue* value = MkArray(nelem+1, 1, ShowString);
+QCValue* GenAsciiStringL(size_t len) {
+ QCValue* value = MkArray(len+1, 1, show_string);
+ value->ndata = len+1;
char* string = (char*)value->data;
- for (size_t i = 0; i < nelem; i++)
+ for (size_t i = 0; i < len; i++)
*(string++) = qcrandr(32,127);
return value;
}
+QCValue* GenAsciiString(void) {
+ return GenAsciiStringL(qcrandr(1, 1024));
+}
#endif
#endif /* QCHECK_H */
return (!strcmp(str, Output));
}
-
-#define QCHECK(desc, prop, ...) \
- CHECK(qcheck(desc, prop, __VA_ARGS__))
-
-#define QASSERT(cond) \
- if (!(cond)) return 0
+static int selection_equals(char* str) {
+ free(Output), Output = NULL;
+ Output = buf_gets(&TestBuf);
+ return (!strcmp(str, Output));
+}
void setup_buffer(void) {
free(Output), Output = NULL;
buf_init(&TestBuf);
}
-int getc_returns_putc(int nvals, QCValue** vals) {
+PROPERTY(getc_returns_putc) {
setup_buffer();
- buf_putc(&TestBuf, vals[0]->data[0]);
+ buf_putc(&TestBuf, IVAL(0));
TestBuf.selection.end = TestBuf.selection.beg = 0;
- return (vals[0]->data[0] == buf_getc(&TestBuf));
+ return (IVAL(0) == buf_getc(&TestBuf));
}
-int gets_returns_puts(int nvals, QCValue** vals) {
+PROPERTY(gets_returns_puts) {
setup_buffer();
- char* input = (char*)(vals[0]->data);
+ char* input = VAL(0,char*);
buf_puts(&TestBuf, input);
QASSERT(buffer_equals(input));
return 1;
}
-int edit_operations_are_reversible(int nvals, QCValue** vals) {
+PROPERTY(edit_operations_are_reversible) {
setup_buffer();
- char* input = (char*)(vals[0]->data);
+ char* input = VAL(0,char*);
buf_logstart(&TestBuf);
buf_puts(&TestBuf, input);
buf_logstop(&TestBuf);
QASSERT(buffer_equals(input));
-// buf_putc(&TestBuf, 'A');
-// TestBuf.selection.end = buf_byrune(&TestBuf, TestBuf.selection.end, LEFT);
-// /* selection equals 'A' */
-// buf_del(&TestBuf); // delete 'A'
-// buf_undo(&TestBuf);
-// QASSERT(buffer_equals(input));
+ buf_logstart(&TestBuf);
+ buf_putc(&TestBuf, 'A');
+ buf_logstop(&TestBuf);
+ buf_lastins(&TestBuf);
+ QASSERT(selection_equals("A"));
+ buf_del(&TestBuf); // delete 'A'
+ buf_undo(&TestBuf);
+ QASSERT(selection_equals("A"));
+ buf_undo(&TestBuf);
+ QASSERT(buffer_equals(input));
buf_undo(&TestBuf);
QASSERT(buffer_equals(""));
buf_redo(&TestBuf);
return 1;
}
+QCValue* GenCodepoint(void) {
+ return GenLongR(0, 0x10FFFF);
+}
+
TEST_SUITE(BufferTests) {
TEST(buf should adhere to specific properties) {
QCHECK("getc should return the same printable ascii value inserted with putc",
getc_returns_putc, 1, GenAsciiChar);
+// QCHECK("getc should return the same printable unicode value inserted with putc",
+// getc_returns_putc, 1, GenCodepoint);
QCHECK("gets should return the same printable ascii string inserted with puts",
gets_returns_puts, 1, GenAsciiString);
QCHECK("edit operations should be reversible",