Split off testing API into header, separate from source

This is so I could generate new test units using the same API.
This commit is contained in:
2026-02-04 20:06:04 +00:00
parent 52a56c27f6
commit ce7185f923
2 changed files with 80 additions and 31 deletions

View File

@@ -8,18 +8,7 @@
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include "../alisp.h" #include "./test.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[] = { const char *unique_words[] = {
@@ -84,8 +73,11 @@ void symtable_test(void)
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]))); sym_table_find(&table, SV(words[i], strlen(words[i])));
TEST("|table|=|set(words)|", table.count == ARRSIZE(unique_words)); TEST(table.count == ARRSIZE(unique_words), "%lu == %lu", table.count,
TEST("|table| < |words|", table.count < ARRSIZE(words)); ARRSIZE(unique_words));
TEST(table.count < ARRSIZE(unique_words), "%lu < %lu", table.count,
ARRSIZE(unique_words));
TEST_PASSED(); TEST_PASSED();
@@ -104,7 +96,7 @@ void 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);
TEST("in == out", in == out); TEST(in == out, "%ld == %ld", in, out);
} }
TEST_PASSED(); TEST_PASSED();
@@ -119,9 +111,9 @@ void sym_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);
TEST("unique pointers when interning a symbol", in != out); TEST(in != out, "%p != %p", in, out);
TEST("same size", strlen(in) == strlen(out)); TEST(strlen(in) == strlen(out), "%zu == %zu", strlen(in), strlen(out));
TEST("same string", strncmp(in, out, strlen(in)) == 0); TEST(strncmp(in, out, strlen(in)) == 0, "%d", strncmp(in, out, strlen(in)));
} }
TEST_PASSED(); TEST_PASSED();
sys_cleanup(&system); sys_cleanup(&system);
@@ -145,9 +137,10 @@ void vec_test1(void)
vec_t *vec = as_vec(lvec); vec_t *vec = as_vec(lvec);
TEST("same size vector", vec->size == ARRSIZE(words_text)); TEST(vec->size == ARRSIZE(words_text), "%lu == %lu", vec->size,
TEST("same as actually concatenated string", ARRSIZE(words_text));
strncmp(vec_data(vec), words_text, vec->size) == 0); TEST(strncmp((char *)vec_data(vec), words_text, vec->size) == 0, "%d",
strncmp((char *)vec_data(vec), words_text, vec->size));
TEST_PASSED(); TEST_PASSED();
sys_cleanup(&system); sys_cleanup(&system);
@@ -176,12 +169,13 @@ void vec_test2(void)
lisp_t *lvec = make_vec(&system, size); lisp_t *lvec = make_vec(&system, size);
vec_append(as_vec(lvec), text + test.start, test.size); vec_append(as_vec(lvec), text + test.start, test.size);
TEST("Vector grew", as_vec(lvec)->size > size); TEST(as_vec(lvec)->size > size, "%lu > %lu", as_vec(lvec)->size, size);
TEST("Vector's substring is equivalent to the actual substring", TEST(strncmp((char *)vec_data(as_vec(lvec)), substr.data, substr.size) == 0,
strncmp(vec_data(as_vec(lvec)), substr.data, substr.size) == 0); "%d",
strncmp((char *)vec_data(as_vec(lvec)), substr.data, substr.size));
} }
printf("[vec_test2]: Pass\n"); TEST_PASSED();
sys_cleanup(&system); sys_cleanup(&system);
} }
@@ -204,8 +198,8 @@ void cons_test(void)
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);
TEST("we've reversed the array", TEST(strncmp(words[i - 1], as_sym(item), strlen(words[i - 1])) == 0, "%d",
strncmp(words[i - 1], as_sym(item), strlen(words[i - 1])) == 0); strncmp(words[i - 1], as_sym(item), strlen(words[i - 1])));
i -= 1; i -= 1;
} }
@@ -214,17 +208,25 @@ void cons_test(void)
sys_cleanup(&system); sys_cleanup(&system);
} }
typedef void (*test_fn)(void); struct TestFn
{
const char *name;
void (*fn)(void);
};
const test_fn TESTS[] = { #define MAKE_TEST_FN(NAME) {.name = #NAME, .fn = NAME}
int_test, sym_test, vec_test1, vec_test2, cons_test,
const struct TestFn TESTS[] = {
MAKE_TEST_FN(int_test), MAKE_TEST_FN(sym_test), MAKE_TEST_FN(vec_test1),
MAKE_TEST_FN(vec_test2), MAKE_TEST_FN(cons_test),
}; };
int main(void) int main(void)
{ {
for (u64 i = 0; i < ARRSIZE(TESTS); ++i) for (u64 i = 0; i < ARRSIZE(TESTS); ++i)
{ {
TESTS[i](); printf("[%s]: Running...\n", TESTS[i].name);
TESTS[i].fn();
} }
return 0; return 0;
} }

47
test/test.h Normal file
View File

@@ -0,0 +1,47 @@
/* test.h: Unit test API
* Created: 2026-02-04
* Author: Aryadev Chavali
* License: See end of file
* Commentary:
*/
#ifndef TEST_H
#define TEST_H
#include <alisp/alisp.h>
#define TEST_PASSED() printf("[%s]: Passed\n", __func__)
#define TEST(COND, ...) \
do \
{ \
bool cond = (COND); \
if (!cond) \
{ \
printf("\tFAIL: "); \
} \
else \
{ \
printf("\tPASS: "); \
} \
printf("%s => ", #COND); \
printf(__VA_ARGS__); \
printf("\n"); \
if (!cond) \
{ \
assert(0); \
} \
} while (0)
#endif
/* Copyright (C) 2026 Aryadev Chavali
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the Unlicense for details.
* You may distribute and modify this code under the terms of the Unlicense,
* which you should have received a copy of along with this program. If not,
* please go to <https://unlicense.org/>.
*/