Compare commits
3 Commits
270d4a4d6a
...
2d7adf595f
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2d7adf595f | ||
|
|
ce7185f923 | ||
|
|
52a56c27f6 |
21
Makefile
21
Makefile
@@ -2,6 +2,7 @@ CC=cc
|
|||||||
|
|
||||||
DIST=build
|
DIST=build
|
||||||
OUT=$(DIST)/alisp.out
|
OUT=$(DIST)/alisp.out
|
||||||
|
TEST=$(DIST)/test.out
|
||||||
|
|
||||||
LDFLAGS=
|
LDFLAGS=
|
||||||
GFLAGS=-Wall -Wextra -Wpedantic -std=c23 -I./include/
|
GFLAGS=-Wall -Wextra -Wpedantic -std=c23 -I./include/
|
||||||
@@ -16,21 +17,30 @@ CFLAGS=$(GFLAGS) $(DFLAGS)
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
# Units to compile
|
# Units to compile
|
||||||
UNITS=src/main.c src/sv.c src/vec.c src/stream.c src/symtable.c src/tag.c src/lisp.c src/reader.c
|
UNITS=src/sv.c src/vec.c src/stream.c src/symtable.c src/tag.c src/lisp.c
|
||||||
OBJECTS:=$(patsubst src/%.c, $(DIST)/%.o, $(UNITS))
|
OBJECTS:=$(patsubst src/%.c, $(DIST)/%.o, $(UNITS))
|
||||||
|
|
||||||
# Dependency generation
|
# Dependency generation
|
||||||
DEPFLAGS=-MT $@ -MMD -MP -MF
|
DEPFLAGS=-MT $@ -MMD -MP -MF
|
||||||
DEPDIR=$(DIST)/deps
|
DEPDIR=$(DIST)/deps
|
||||||
|
|
||||||
$(OUT): $(OBJECTS) | $(DIST)
|
all: $(OUT) $(TEST)
|
||||||
|
|
||||||
|
$(OUT): $(OBJECTS) $(DIST)/main.o | $(DIST)
|
||||||
|
$(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS)
|
||||||
|
|
||||||
|
$(TEST): $(OBJECTS) $(DIST)/test/test.o | $(DIST)
|
||||||
$(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS)
|
$(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS)
|
||||||
|
|
||||||
$(DIST)/%.o: src/%.c | $(DIST) $(DEPDIR)
|
$(DIST)/%.o: src/%.c | $(DIST) $(DEPDIR)
|
||||||
$(CC) $(CFLAGS) $(DEPFLAGS) $(DEPDIR)/$*.d -c -o $@ $<
|
$(CC) $(CFLAGS) $(DEPFLAGS) $(DEPDIR)/$*.d -c -o $@ $<
|
||||||
|
|
||||||
|
$(DIST)/test/%.o: test/%.c | $(DIST) $(DEPDIR)
|
||||||
|
$(CC) $(CFLAGS) $(DEPFLAGS) $(DEPDIR)/$*.d -c -o $@ $<
|
||||||
|
|
||||||
$(DIST):
|
$(DIST):
|
||||||
mkdir -p $(DIST)
|
mkdir -p $(DIST)
|
||||||
|
mkdir -p $(DIST)/test
|
||||||
|
|
||||||
$(DEPDIR):
|
$(DEPDIR):
|
||||||
mkdir -p $(DEPDIR)
|
mkdir -p $(DEPDIR)
|
||||||
@@ -39,13 +49,16 @@ clangd: compile_commands.json
|
|||||||
compile_commands.json: Makefile
|
compile_commands.json: Makefile
|
||||||
bear -- $(MAKE) -B MODE=debug
|
bear -- $(MAKE) -B MODE=debug
|
||||||
|
|
||||||
.PHONY: run clean examples
|
.PHONY: run test clean examples
|
||||||
ARGS=
|
ARGS=
|
||||||
run: $(OUT)
|
run: $(OUT)
|
||||||
./$^ $(ARGS)
|
./$^ $(ARGS)
|
||||||
|
|
||||||
|
test: $(TEST)
|
||||||
|
./$^
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -rf $(DIST)
|
rm -rf $(DIST)
|
||||||
|
|
||||||
DEPS:=$(patsubst src/%.c,$(DEPDIR)/%.d, $(UNITS))
|
DEPS:=$(patsubst src/%.c,$(DEPDIR)/%.d, $(UNITS)) $(DEPDIR)/main.d $(DEPDIR)/test.d
|
||||||
include $(wildcard $(DEPS))
|
include $(wildcard $(DEPS))
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
#include <alisp/stream.h>
|
#include <alisp/stream.h>
|
||||||
#include <alisp/sv.h>
|
#include <alisp/sv.h>
|
||||||
#include <alisp/symtable.h>
|
#include <alisp/symtable.h>
|
||||||
|
#include <alisp/tag.h>
|
||||||
#include <alisp/vec.h>
|
#include <alisp/vec.h>
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
64
test/test.c
64
test/test.c
@@ -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
47
test/test.h
Normal 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/>.
|
||||||
|
|
||||||
|
*/
|
||||||
Reference in New Issue
Block a user