Refactor testing system, and add more tests

Couple macros to make printing nicer, use assertions instead to fail
if a test doesn't work.
This commit is contained in:
2025-08-21 23:19:18 +01:00
parent 49a3302fd6
commit bbb405fca9

144
test.c
View File

@@ -18,7 +18,33 @@
#include "./alisp.h" #include "./alisp.h"
#define TEST_PASSED() printf("[%s]: Pass\n", __func__)
#define TEST(NAME, COND) \
do \
{ \
if (!(COND)) \
{ \
printf("[%s]: `%s` failed!\n", __func__, (NAME)); \
assert(0); \
} \
} while (0)
// Sample data // Sample data
const char *unique_words[] = {
"bibendum", "etiam", "gravida", "dui", "cursus",
"purus", "diam", "phasellus", "nam", "fermentum",
"leo", "enim", "ac", "semper", "non",
"mauris", "proin", "tellus", "vivamus", "lobortis",
"lacus", "neque", "in", "nullam", "felis",
"orci", "pede", "tempus", "nec", "at",
"tortor", "massa", "sed", "magna", "eget",
"tempor", "velit", "imperdiet", "praesent", "volutpat",
"tristique", "id", "commodo", "aliquet", "quis",
"pellentesque", "eleifend", "porta", "nunc", "euismod",
"aliquam", "a", "erat", "dignissim", "ut",
"vitae", "vel", "donec",
};
char *words[] = { char *words[] = {
"aliquam", "erat", "volutpat", "nunc", "eleifend", "aliquam", "erat", "volutpat", "nunc", "eleifend",
"leo", "vitae", "magna", "in", "id", "leo", "vitae", "magna", "in", "id",
@@ -37,6 +63,15 @@ char *words[] = {
"euismod", "tellus", "id", "erat", "euismod", "tellus", "id", "erat",
}; };
char words_text[] =
"aliquam erat volutpat nunc eleifend leo vitae magna in id erat non orci "
"commodo lobortis proin neque massa cursus ut gravida ut lobortis eget "
"lacus sed diam praesent fermentum tempor tellus nullam tempus mauris ac "
"felis vel velit tristique imperdiet donec at pede etiam vel neque nec dui "
"dignissim bibendum vivamus id enim phasellus neque orci porta a aliquet "
"quis semper a massa phasellus purus pellentesque tristique imperdiet "
"tortor nam euismod tellus id erat";
char text[] = char text[] =
"Pellentesque dapibus suscipit ligula. Donec posuere augue in quam. " "Pellentesque dapibus suscipit ligula. Donec posuere augue in quam. "
"Etiam vel tortor sodales tellus ultricies commodo. Suspendisse potenti. " "Etiam vel tortor sodales tellus ultricies commodo. Suspendisse potenti. "
@@ -55,23 +90,20 @@ void symtable_test(void)
sym_table_t table = {0}; sym_table_t table = {0};
sym_table_init(&table); sym_table_init(&table);
for (u64 i = 0; i < ARRSIZE(words); ++i) for (u64 i = 0; i < ARRSIZE(words); ++i)
{ sym_table_find(&table, SV(words[i], strlen(words[i])));
char *ptr = sym_table_find(&table, SV(words[i], strlen(words[i])));
printf("[symtable_test]: %s => %p\n", words[i], ptr);
}
printf( TEST("|table|=|set(words)|", table.count == ARRSIZE(unique_words));
"[symtable_test]: |words|=%lu, |table|= %lu => Unique word ratio: %lf\n", TEST("|table| < |words|", table.count < ARRSIZE(words));
ARRSIZE(words), table.count, table.count / (double)ARRSIZE(words));
TEST_PASSED();
sym_table_cleanup(&table); sym_table_cleanup(&table);
} }
void make_int_test(void) void int_test(void)
{ {
i64 ints[] = { i64 ints[] = {
1, -1, (1 << 10) - 1, (-1) * ((1 << 10) - 1), 1, -1, (1 << 10) - 1, (-1) * ((1 << 10) - 1), INT_MIN, INT_MAX,
INT_MIN, INT_MAX, INT64_MAX, INT64_MIN,
}; };
for (u64 i = 0; i < ARRSIZE(ints); ++i) for (u64 i = 0; i < ARRSIZE(ints); ++i)
@@ -80,11 +112,13 @@ void make_int_test(void)
lisp_t *lisp = make_int(in); lisp_t *lisp = make_int(in);
i64 out = as_int(lisp); i64 out = as_int(lisp);
printf("[make_int_test]: %#16lx => %#16lx => %#16lx\n", in, (u64)lisp, out); TEST("in == out", in == out);
} }
TEST_PASSED();
} }
void intern_test(void) void sym_test(void)
{ {
sys_t system = {0}; sys_t system = {0};
sys_init(&system); sys_init(&system);
@@ -93,29 +127,44 @@ void intern_test(void)
char *in = words[i]; char *in = words[i];
lisp_t *lisp = intern(&system, SV(in, strlen(in))); lisp_t *lisp = intern(&system, SV(in, strlen(in)));
char *out = as_sym(lisp); char *out = as_sym(lisp);
printf("[intern test]: `%s` -> %p -> `%s`\n", in, lisp, out); TEST("unique pointers when interning a symbol", in != out);
TEST("same size", strlen(in) == strlen(out));
TEST("same string", strncmp(in, out, strlen(in)) == 0);
} }
TEST_PASSED();
sys_cleanup(&system); sys_cleanup(&system);
} }
void make_vec_test(void) void vec_test1(void)
{ {
sys_t system = {0}; sys_t system = {0};
sys_init(&system); sys_init(&system);
// Generating a vector word by word // Generating a vector word by word
lisp_t *vec = make_vec(&system, 0); lisp_t *lvec = make_vec(&system, 0);
for (u64 i = 0; i < ARRSIZE(words); ++i) for (u64 i = 0; i < ARRSIZE(words); ++i)
{ {
char *word = words[i]; char *word = words[i];
vec_append(as_vec(vec), word, strlen(word)); vec_append(as_vec(lvec), word, strlen(word));
vec_append(as_vec(vec), " ", 1); if (i != ARRSIZE(words) - 1)
vec_append(as_vec(lvec), " ", 1);
} }
printf("[make_vec_test]: %lu/%lu, inlined?: %s, text=%.*s\n", vec_append(as_vec(lvec), "\0", 1);
as_vec(vec)->size, as_vec(vec)->capacity,
as_vec(vec)->is_inlined ? "yes" : "no", (int)as_vec(vec)->size,
(char *)vec_data(as_vec(vec)));
vec_t *vec = as_vec(lvec);
TEST("same size vector", vec->size == ARRSIZE(words_text));
TEST("same as actually concatenated string",
strncmp(vec_data(vec), words_text, vec->size) == 0);
TEST_PASSED();
sys_cleanup(&system);
}
void vec_test2(void)
{
sys_t system = {0};
sys_init(&system);
// Generating substrings // Generating substrings
struct Test struct Test
{ {
@@ -126,19 +175,21 @@ void make_vec_test(void)
{32, 64}, {32, 64},
{0, ARRSIZE(text)}, {0, ARRSIZE(text)},
}; };
for (u64 i = 0; i < ARRSIZE(tests); ++i) for (u64 i = 0; i < ARRSIZE(tests); ++i)
{ {
struct Test test = tests[i]; struct Test test = tests[i];
// Always initialise below what we expect const sv_t substr = SV(text + test.start, test.size);
lisp_t *lvec = make_vec(&system, test.size / 2); const u64 size = test.size / 2;
vec_t *vec = as_vec(lvec);
printf("[make_vec_test]: %p -> %p[%lu/%lu] -> ", lvec, vec, vec->size, lisp_t *lvec = make_vec(&system, size);
vec->capacity); vec_append(as_vec(lvec), text + test.start, test.size);
vec_append(vec, text + test.start, test.size); TEST("Vector grew", as_vec(lvec)->size > size);
printf("[%lu/%lu] -> ", vec->size, vec->capacity); TEST("Vector's substring is equivalent to the actual substring",
printf("`%.*s`\n", (int)vec->size, (char *)vec_data(vec)); strncmp(vec_data(as_vec(lvec)), substr.data, substr.size) == 0);
} }
printf("[vec_test2]: Pass\n");
sys_cleanup(&system); sys_cleanup(&system);
} }
@@ -147,8 +198,7 @@ void cons_test(void)
sys_t system = {0}; sys_t system = {0};
sys_init(&system); sys_init(&system);
// Iterate through each "word" in words, make a large contiguous list which is // Let's make a list of words using `cons`
// its reverse
lisp_t *lisp = NIL; lisp_t *lisp = NIL;
for (u64 i = 0; i < ARRSIZE(words); ++i) for (u64 i = 0; i < ARRSIZE(words); ++i)
{ {
@@ -157,28 +207,32 @@ void cons_test(void)
lisp = cons(&system, lword, lisp); lisp = cons(&system, lword, lisp);
} }
// Then iterate through it // Make sure we've essentially reversed the `words` array
printf("[cons_test]: "); u64 i = ARRSIZE(words);
for (lisp_t *iter = lisp; iter; iter = cdr(iter)) for (lisp_t *iter = lisp; iter; iter = cdr(iter))
{ {
lisp_t *item = car(iter); lisp_t *item = car(iter);
printf("%s ", as_sym(item)); TEST("we've reversed the array",
strncmp(words[i - 1], as_sym(item), strlen(words[i - 1])) == 0);
i -= 1;
} }
printf("\n");
TEST_PASSED();
sys_cleanup(&system); sys_cleanup(&system);
} }
typedef void (*test_fn)(void);
const test_fn TESTS[] = {
int_test, sym_test, vec_test1, vec_test2, cons_test,
};
int main(void) int main(void)
{ {
symtable_test(); for (u64 i = 0; i < ARRSIZE(TESTS); ++i)
printf("\n"); {
make_int_test(); TESTS[i]();
printf("\n"); }
intern_test();
printf("\n");
make_vec_test();
printf("\n");
cons_test();
return 0; return 0;
} }