Compare commits

...

21 Commits

Author SHA1 Message Date
Aryadev Chavali
61efa91403 alisp.org: add TODOs for all the tests required for streams 2026-02-05 06:32:26 +00:00
Aryadev Chavali
3add9beb59 sv: fix possible runtime issue with NULL SV's in sv_copy 2026-02-05 06:17:52 +00:00
Aryadev Chavali
df1076f7d7 tests: enable STREAM_SUITE 2026-02-05 06:17:31 +00:00
Aryadev Chavali
a809d9de25 test_stream: Enable only stream_test_string 2026-02-05 06:17:21 +00:00
Aryadev Chavali
3b14144ccc test_stream: implement stream_test_string 2026-02-05 06:17:13 +00:00
Aryadev Chavali
bd838c02ab test_stream: basic skeleton 2026-02-05 06:06:03 +00:00
Aryadev Chavali
54e9edcba6 test_lisp_api: added sys_test 2026-02-05 05:48:00 +00:00
Aryadev Chavali
b32f420cb9 lisp: split off lisp_free as it's own function
lisp_free will do a shallow clean of any object, freeing its
associated memory.  It won't recur through any containers, nor will it
freakout if you give it something that is constant (symbols, small
integers, NIL, etc).
2026-02-05 05:39:35 +00:00
Aryadev Chavali
34d3417e74 symtable: sym_table_cleanup -> sym_table_free 2026-02-05 05:39:22 +00:00
Aryadev Chavali
66770f22d9 alisp.org: Added some tasks 2026-02-05 05:35:51 +00:00
Aryadev Chavali
3d0e373862 test_lisp_api: added sym_unique_test 2026-02-05 05:34:54 +00:00
Aryadev Chavali
0e8cdd7507 test_lisp_api: sym_test -> sym_fresh_test 2026-02-05 05:34:39 +00:00
Aryadev Chavali
4d693c8a92 test_lisp_api: int_test -> smi_test, added smi_oob_test 2026-02-05 05:24:34 +00:00
Aryadev Chavali
1c88253b3c tests: fix size of LISP_API_SUITE tests 2026-02-05 05:23:38 +00:00
Aryadev Chavali
de6fcd17ee Makefile: added mode flag for full logs
MODE=full will initialise a debug build with all logs, including test
logs.  Otherwise, MODE=debug just sets up standard debug build with
main logs but no testing logs.  MODE=release optimises and strips all
logs.
2026-02-05 05:17:25 +00:00
Aryadev Chavali
91264d96e4 test: Added definition to make default testing less verbose
TEST_VERBOSE is a preprocesser directive which TEST is dependent on.
By default it is 0, in which case TEST simply fails if the condition
is not true.  Otherwise, a full log (as done previously) is made.
2026-02-05 05:16:11 +00:00
Aryadev Chavali
d88d7f7f23 tests: c23 allows you to inline stack allocated arrays in struct decls 2026-02-05 05:10:19 +00:00
Aryadev Chavali
16be3392b0 tests: slight cleanliness 2026-02-05 05:10:12 +00:00
Aryadev Chavali
2705ef9bb7 tests: Meaningful and pretty logging for tests 2026-02-05 04:56:11 +00:00
Aryadev Chavali
45ef1fa01a tests: Added string view suite
sv_copy is the only function, but we may have others later.
2026-02-05 04:48:42 +00:00
Aryadev Chavali
9095b118fd tests: split of symtable testing into its own suite
makes sense to be there, not in the lisp API
2026-02-05 04:48:42 +00:00
14 changed files with 477 additions and 94 deletions

View File

@@ -12,8 +12,10 @@ RFLAGS=-O3
MODE=release
ifeq ($(MODE), release)
CFLAGS=$(GFLAGS) $(RFLAGS)
else
else ifeq ($(MODE), debug)
CFLAGS=$(GFLAGS) $(DFLAGS)
else ifeq ($(MODE), full)
CFLAGS=$(GFLAGS) $(DFLAGS) -DTEST_VERBOSE=1
endif
# Units to compile

View File

@@ -45,11 +45,61 @@ i.e. no parsing.
*** DONE Design what a "parser function" would look like
The general function is something like ~stream -> T | Err~. What
other state do we need to encode?
*** WIP Write a parser for integers
*** TODO Write a parser for integers
*** TODO Write a parser for symbols
*** TODO Write a parser for lists
*** TODO Write a parser for vectors
*** TODO Write the general parser
** WIP Unit tests :tests:
*** TODO Test streams
**** TODO Test file init
[[file:test/test_stream.c::void stream_test_file(void)]]
***** TODO Test successful init from real files
Ensure stream_size is 0 i.e. we don't read anything on creation.
Also ensure stream_eoc is false.
***** TODO Test failed init from fake files
**** TODO Test peeking and next
[[file:test/test_stream.c::void stream_test_peek_next(void)]]
- Peeking with bad streams ('\0' return)
- Peeking with good streams (no effect on position)
- Next with bad streams ('\0' return, no effect on position)
- Next with good streams (effects position)
- Peeking after next (should just work)
**** TODO Test seeking
[[file:test/test_stream.c::void stream_test_seek(void)]]
- Seeking forward/backward on a bad stream (should stop at 0)
- Seeking forward/backward too far (should clamp)
- Seeking forward/backward zero sum via relative index (stream_seek)
**** TODO Test substring
[[file:test/test_stream.c::void stream_test_substr(void)]]
- Substr on bad stream (NULL sv)
- Substr on bad position/size (NULL sv)
- Substr relative/absolute (good SV)
**** TODO Test till
[[file:test/test_stream.c::void stream_test_till(void)]]
- till on a bad stream (NULL SV)
- till on an ended stream (NULL SV)
- till on a stream with no items in search string (eoc)
- till on a stream with all items in search string (no effect)
- till on a stream with prefix being all search string (no effect)
- till on a stream with suffix being all search string (stops at
suffix)
**** TODO Test while
[[file:test/test_stream.c::void stream_test_while(void)]]
- while on a bad stream (NULL SV)
- while on an ended stream (NULL SV)
- while on a stream with no items in search string (no effect)
- while on a stream with all items in search string (eoc)
- while on a stream with prefix being all search string (effect)
- while on a stream with suffix being all search string (no effect)
**** TODO Test line_col
[[file:test/test_stream.c::void stream_test_line_col(void)]]
- line_col on bad stream (no effect on args)
- line_col on eoc stream (should go right to the end)
- line_col on random points in a stream
*** DONE Test system registration of allocated units
In particular, does clean up work as we expect? Do we have situations
where we may double free or not clean up something we should've?
** Backlog
*** TODO Design Big Integers
We currently have 62 bit integers implemented via immediate values
@@ -139,9 +189,6 @@ Latter approach time complexity:
Former approach is better time complexity wise, but latter is way
better in terms of simplicity of code. Must deliberate.
*** TODO Test system registration of allocated units :test:
In particular, does clean up work as we expect? Do we have situations
where we may double free or not clean up something we should've?
*** TODO Design Strings
We have ~sv_t~ so our basic C API is done. We just need pluggable
functions to construct and deconstruct strings as lisps.
@@ -160,4 +207,4 @@ Test if ~make_vec~ works with ~as_vec~, ~cons~ with ~as_cons~ AND
We may need to think of effective ways to deal with NILs in ~car~ and
~cdr~. Maybe make functions as well as the macros so I can choose
between them?
**** DONE Write more tests
*** DONE Write more tests

View File

@@ -49,6 +49,8 @@ vec_t *as_vec(lisp_t *);
lisp_t *car(lisp_t *);
lisp_t *cdr(lisp_t *);
void lisp_free(lisp_t *);
#endif
/* Copyright (C) 2026 Aryadev Chavali

View File

@@ -22,7 +22,7 @@ typedef struct
void sym_table_init(sym_table_t *);
char *sym_table_find(sym_table_t *, sv_t);
void sym_table_cleanup(sym_table_t *);
void sym_table_free(sym_table_t *);
#endif

View File

@@ -26,7 +26,7 @@ void sys_free(sys_t *sys)
{
static_assert(NUM_TAGS == 5);
sym_table_cleanup(&sys->symtable);
sym_table_free(&sys->symtable);
if (sys->memory.size == 0)
return;
@@ -34,26 +34,7 @@ void sys_free(sys_t *sys)
for (size_t i = 0; i < VEC_SIZE(&sys->memory, lisp_t **); ++i)
{
lisp_t *allocated = VEC_GET(&sys->memory, i, lisp_t *);
switch (get_tag(allocated))
{
case TAG_CONS:
// Delete the cons
free(as_cons(allocated));
break;
case TAG_VEC:
{
vec_t *vec = as_vec(allocated);
vec_free(vec);
free(vec);
break;
}
case TAG_NIL:
case TAG_INT:
case TAG_SYM:
case NUM_TAGS:
// shouldn't be dealt with (either constant or dealt with elsewhere)
break;
}
lisp_free(allocated);
}
// Free the container
@@ -110,6 +91,30 @@ lisp_t *cdr(lisp_t *lsp)
return CDR(lsp);
}
void lisp_free(lisp_t *item)
{
switch (get_tag(item))
{
case TAG_CONS:
// Delete the cons
free(as_cons(item));
break;
case TAG_VEC:
{
vec_t *vec = as_vec(item);
vec_free(vec);
free(vec);
break;
}
case TAG_NIL:
case TAG_INT:
case TAG_SYM:
case NUM_TAGS:
// shouldn't be dealt with (either constant or dealt with elsewhere)
break;
}
}
/* Copyright (C) 2025, 2026 Aryadev Chavali
* This program is distributed in the hope that it will be useful, but WITHOUT

View File

@@ -12,6 +12,10 @@
sv_t sv_copy(sv_t old)
{
if (old.size == 0)
return SV(old.data, 0);
else if (old.data == NULL)
return SV(NULL, old.size);
char *newstr = calloc(1, (old.size + 1) * sizeof(*newstr));
memcpy(newstr, old.data, old.size);
newstr[old.size] = '\0';

View File

@@ -54,7 +54,7 @@ char *sym_table_find(sym_table_t *table, sv_t sv)
return ENTRY_GET(table, index).data;
}
void sym_table_cleanup(sym_table_t *table)
void sym_table_free(sym_table_t *table)
{
// Iterate through the strings and free each of them.
sv_t current = {0};

View File

@@ -12,11 +12,13 @@
#include "./test.h"
#include "./test_lisp_api.c"
#include "./test_stream.c"
#include "./test_sv.c"
#include "./test_symtable.c"
#include "./test_vec.c"
test_suite_t SUITES[] = {
LISP_API_SUITE,
VEC_SUITE,
VEC_SUITE, SV_SUITE, SYMTABLE_SUITE, STREAM_SUITE, LISP_API_SUITE,
};
int main(void)
@@ -27,7 +29,7 @@ int main(void)
printf("Suite [%s]\n", suite.name);
for (u64 j = 0; j < suite.size; ++j)
{
printf("[%s]: Running...\n", suite.tests[j].name);
printf("\t[%s]: Running...\n", suite.tests[j].name);
suite.tests[j].fn();
}
}

View File

@@ -10,27 +10,41 @@
#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); \
} \
#ifndef TEST_VERBOSE
#define TEST_VERBOSE 0
#endif
#define TEST_PASSED() printf("\t[%s]: Passed\n", __func__)
#if TEST_VERBOSE
#define TEST(COND, ...) \
do \
{ \
bool cond = (COND); \
if (!cond) \
{ \
printf("\t\tFAIL: "); \
} \
else \
{ \
printf("\t\tPASS: "); \
} \
printf(__VA_ARGS__); \
printf("\n\t\t [%s]\n", #COND); \
if (!cond) \
{ \
assert(0); \
} \
} while (0)
#else
#define TEST(COND, ...) \
do \
{ \
if (!(COND)) \
{ \
assert(0); \
} \
} while (0)
#endif
typedef struct TestFn
{

View File

@@ -10,8 +10,10 @@
#include <alisp/lisp.h>
void int_test(void)
void smi_test(void)
{
// Standard old testing, checking both sides of the number line and our set
// bounds.
i64 ints[] = {
1, -1, (1 << 10) - 1, (-1) * ((1 << 10) - 1), INT_MIN, INT_MAX,
};
@@ -28,28 +30,36 @@ void int_test(void)
TEST_PASSED();
}
void symtable_test(void)
void smi_oob_test(void)
{
sym_table_t table = {0};
sym_table_init(&table);
for (u64 i = 0; i < ARRSIZE(words); ++i)
sym_table_find(&table, SV((char *)words[i], strlen(words[i])));
// These are integers that are completely out of the bounds of our standard
// tagging system due to their size. We need to use big integers for this.
i64 ints[] = {
INT_MIN - 1,
INT_MAX + 1,
INT64_MIN,
INT64_MAX,
};
TEST(table.count == ARRSIZE(unique_words), "%lu == %lu", table.count,
ARRSIZE(unique_words));
for (u64 i = 0; i < ARRSIZE(ints); ++i)
{
i64 in = ints[i];
lisp_t *lisp = make_int(in);
i64 out = as_int(lisp);
TEST(table.count < ARRSIZE(unique_words), "%lu < %lu", table.count,
ARRSIZE(unique_words));
TEST(in != out, "%ld != %ld", in, out);
}
TEST_PASSED();
sym_table_cleanup(&table);
}
void sym_test(void)
void sym_fresh_test(void)
{
sys_t system = {0};
sys_init(&system);
// We expect every interned symbol to get a fresh allocation, but still be a
// valid representation of the original symbol.
for (u64 i = 0; i < ARRSIZE(words); ++i)
{
const char *in = words[i];
@@ -57,10 +67,42 @@ void sym_test(void)
char *out = as_sym(lisp);
TEST(in != out, "%p != %p", in, out);
TEST(strlen(in) == strlen(out), "%zu == %zu", strlen(in), strlen(out));
TEST(strncmp(in, out, strlen(in)) == 0, "%d", strncmp(in, out, strlen(in)));
TEST(strncmp(in, out, strlen(in)) == 0, "`%s` == `%s`", in, out);
}
TEST_PASSED();
sys_free(&system);
TEST_PASSED();
}
void sym_unique_test(void)
{
sys_t system = {0};
sys_init(&system);
sv_t symbols[] = {
SV("hello", 5),
SV("goodbye", 7),
SV("display", 7),
SV("@xs'a_sh;d::a-h]", 16),
};
lisp_t *ptrs[ARRSIZE(symbols)];
for (u64 i = 0; i < ARRSIZE(symbols); ++i)
{
ptrs[i] = intern(&system, symbols[i]);
TEST(ptrs[i] != 0, "%p (derived from `" PR_SV "`) is not NIL",
(void *)ptrs[i], SV_FMT(symbols[i]));
}
for (u64 i = 0; i < ARRSIZE(symbols); ++i)
{
lisp_t *newptr = intern(&system, symbols[i]);
TEST(newptr == ptrs[i], "interning again (%p) gives us the same (%p)",
(void *)newptr, (void *)ptrs[i]);
}
sys_free(&system);
TEST_PASSED();
}
void cons_test(void)
@@ -77,7 +119,13 @@ void cons_test(void)
lisp = cons(&system, lword, lisp);
}
// Make sure we've essentially reversed the `words` array
/*
As we've cons'd each word, we'd expect the order to be reversed. This test
will allow us to verify:
1) words have actually been added to the linked list.
2) words are in the order we expect.
in one go.
*/
u64 i = ARRSIZE(words);
for (lisp_t *iter = lisp; iter; iter = cdr(iter), --i)
{
@@ -89,21 +137,67 @@ void cons_test(void)
TEST(strncmp(expected, got, size) == 0, "%s == %s", expected, got);
}
TEST_PASSED();
sys_free(&system);
TEST_PASSED();
}
const test_fn TESTS_LISP_API[] = {
MAKE_TEST_FN(int_test),
MAKE_TEST_FN(sym_test),
MAKE_TEST_FN(cons_test),
};
void sys_test(void)
{
sys_t sys = {0};
sys_init(&sys);
u64 old_memory_size = sys.memory.size;
// Creating integers doesn't affect memory size
(void)make_int(2000);
TEST(sys.memory.size == old_memory_size,
"Making integers doesn't affect system memory size");
// Creating symbols won't affect memory size, but does affect the symbol table
(void)intern(&sys, SV("hello world!", 12));
TEST(sys.memory.size == old_memory_size,
"Interning doesn't affect system memory size");
TEST(sys.symtable.count > 0, "Interning affects symbol table");
// Creating cons' do affect memory size
(void)cons(&sys, make_int(1), make_int(2));
TEST(sys.memory.size > 0, "Creating cons' affects memory size");
old_memory_size = sys.memory.size;
(void)cons(&sys, intern(&sys, SV("test", 4)), NIL);
TEST(sys.memory.size > old_memory_size,
"Creating cons' back to back affects memory size");
old_memory_size = sys.memory.size;
// Creating vectors does affect memory size
(void)make_vec(&sys, 8);
TEST(sys.memory.size > old_memory_size,
"Creating vectors (size 8) affects memory size");
old_memory_size = sys.memory.size;
(void)make_vec(&sys, 1000);
TEST(sys.memory.size > old_memory_size,
"Creating vectors (size 1000) affects memory size");
old_memory_size = sys.memory.size;
sys_free(&sys);
TEST(sys.memory.size == 0, "sys_free cleans up memory (shallow check)");
TEST(sys.symtable.count == 0, "sys_free cleans up symtable (shallow check)");
TEST_PASSED();
}
const test_suite_t LISP_API_SUITE = {
.name = "Lisp API Tests",
.tests = TESTS_LISP_API,
.size = ARRSIZE(TESTS_LISP_API),
.name = "Lisp API Tests",
.tests =
(test_fn[]){
MAKE_TEST_FN(smi_test),
MAKE_TEST_FN(smi_oob_test),
MAKE_TEST_FN(sym_fresh_test),
MAKE_TEST_FN(sym_unique_test),
MAKE_TEST_FN(cons_test),
MAKE_TEST_FN(sys_test),
},
.size = 6,
};
/* Copyright (C) 2026 Aryadev Chavali

117
test/test_stream.c Normal file
View File

@@ -0,0 +1,117 @@
/* test_stream.c: Stream tests
* Created: 2026-02-05
* Author: Aryadev Chavali
* License: See end of file
* Commentary:
*/
#include <malloc.h>
#include "./data.h"
#include "./test.h"
#include <alisp/stream.h>
void stream_test_string(void)
{
sv_t test_strings[] = {
SV("hello, world!", 13),
SV("another string", 14),
SV((char *)text, ARRSIZE(text) / 2),
};
for (u64 i = 0; i < ARRSIZE(test_strings); ++i)
{
sv_t copy = sv_copy(test_strings[i]);
stream_t stream = {0};
stream_err_t err = stream_init_string(&stream, NULL, test_strings[i]);
TEST(err == STREAM_ERR_OK, "Stream initialising did not fail: %s",
stream_err_to_cstr(err));
TEST(stream_size(&stream) == test_strings[i].size,
"Stream size is always string size (%lu == %lu)", stream_size(&stream),
test_strings[i].size);
TEST(!stream_eoc(&stream), "Not end of content already");
stream_stop(&stream);
TEST(strncmp(copy.data, test_strings[i].data, copy.size) == 0,
"Freeing a stream does not free the underlying memory it was derived "
"from");
free(copy.data);
}
stream_t stream = {0};
stream_err_t err = stream_init_string(&stream, NULL, SV(NULL, 0));
TEST(err == STREAM_ERR_OK, "NULL stream initialising did not fail: %s",
stream_err_to_cstr(err));
TEST(stream_size(&stream) == 0, "NULL stream size is 0");
TEST(stream_eoc(&stream), "NULL stream is always at end of content");
stream_stop(&stream);
TEST_PASSED();
}
void stream_test_file(void)
{
TODO("Not implemented");
}
void stream_test_peek_next(void)
{
TODO("Not implemented");
}
void stream_test_seek(void)
{
TODO("Not implemented");
}
void stream_test_substr(void)
{
TODO("Not implemented");
}
void stream_test_till(void)
{
TODO("Not implemented");
}
void stream_test_while(void)
{
TODO("Not implemented");
}
void stream_test_line_col(void)
{
TODO("Not implemented");
}
const test_suite_t STREAM_SUITE = {
.name = "Stream Tests",
.tests =
(test_fn[]){
MAKE_TEST_FN(stream_test_string),
// MAKE_TEST_FN(stream_test_file),
// MAKE_TEST_FN(stream_test_peek_next),
// MAKE_TEST_FN(stream_test_seek),
// MAKE_TEST_FN(stream_test_substr),
// MAKE_TEST_FN(stream_test_till),
// MAKE_TEST_FN(stream_test_while),
// MAKE_TEST_FN(stream_test_line_col),
},
.size = 1,
};
/* 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 GNU General Public License Version 2 for
* details.
* You may distribute and modify this code under the terms of the GNU General
* Public License Version 2, which you should have received a copy of along with
* this program. If not, please go to <https://www.gnu.org/licenses/>.
*/

51
test/test_sv.c Normal file
View File

@@ -0,0 +1,51 @@
/* test_sv.c: String View tests
* Created: 2026-02-05
* Author: Aryadev Chavali
* License: See end of file
* Commentary:
*/
#include <assert.h>
#include <malloc.h>
#include "./data.h"
#include "./test.h"
void sv_copy_test(void)
{
static_assert(ARRSIZE(unique_words) > 3, "Expected at least 3 unique words");
for (u64 i = 0; i < 3; ++i)
{
sv_t word = SV((char *)unique_words[i], strlen(unique_words[i]));
sv_t copy = sv_copy(word);
TEST(word.data != copy.data, "%p != %p", word.data, copy.data);
TEST(word.size == copy.size, "%lu == %lu", word.size, copy.size);
TEST(strncmp(word.data, copy.data, copy.size) == 0, "`%s` == `%s`",
word.data, copy.data);
// Obviously we can't just have this lying around.
free(copy.data);
}
}
const test_suite_t SV_SUITE = {
.name = "String View Tests",
.tests =
(test_fn[]){
MAKE_TEST_FN(sv_copy_test),
},
.size = 1,
};
/* 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 GNU General Public License Version 2 for
* details.
* You may distribute and modify this code under the terms of the GNU General
* Public License Version 2, which you should have received a copy of along with
* this program. If not, please go to <https://www.gnu.org/licenses/>.
*/

45
test/test_symtable.c Normal file
View File

@@ -0,0 +1,45 @@
/* test_symtable.c: Symbol table tests
* Created: 2026-02-05
* Author: Aryadev Chavali
* License: See end of file
* Commentary:
*/
#include "./data.h"
#include "./test.h"
void symtable_test(void)
{
sym_table_t table = {0};
sym_table_init(&table);
for (u64 i = 0; i < ARRSIZE(words); ++i)
sym_table_find(&table, SV((char *)words[i], strlen(words[i])));
TEST(table.count == ARRSIZE(unique_words), "%lu == %lu", table.count,
ARRSIZE(unique_words));
sym_table_free(&table);
TEST_PASSED();
}
const test_suite_t SYMTABLE_SUITE = {
.name = "Symbol Table Tests",
.tests =
(test_fn[]){
MAKE_TEST_FN(symtable_test),
},
.size = 1,
};
/* 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 GNU General Public License Version 2 for
* details.
* You may distribute and modify this code under the terms of the GNU General
* Public License Version 2, which you should have received a copy of along with
* this program. If not, please go to <https://www.gnu.org/licenses/>.
*/

View File

@@ -8,7 +8,7 @@
#include "./data.h"
#include "./test.h"
void vec_test1(void)
void vec_test_concat(void)
{
sys_t system = {0};
sys_init(&system);
@@ -28,14 +28,15 @@ void vec_test1(void)
TEST(vec->size == ARRSIZE(words_text), "%lu == %lu", vec->size,
ARRSIZE(words_text));
TEST(strncmp((char *)vec_data(vec), words_text, vec->size) == 0, "%d",
strncmp((char *)vec_data(vec), words_text, vec->size));
TEST(strncmp((char *)vec_data(vec), words_text, vec->size) == 0,
"%p@%lu == %p@%lu", (char *)vec_data(vec), vec->size, words_text,
strlen(words_text));
TEST_PASSED();
sys_free(&system);
TEST_PASSED();
}
void vec_test2(void)
void vec_test_substr(void)
{
sys_t system = {0};
sys_init(&system);
@@ -60,23 +61,22 @@ void vec_test2(void)
vec_append(as_vec(lvec), text + test.start, test.size);
TEST(as_vec(lvec)->size > size, "%lu > %lu", as_vec(lvec)->size, size);
TEST(strncmp((char *)vec_data(as_vec(lvec)), substr.data, substr.size) == 0,
"%d",
strncmp((char *)vec_data(as_vec(lvec)), substr.data, substr.size));
"%p@%lu == %p@%lu", (char *)vec_data(as_vec(lvec)), as_vec(lvec)->size,
substr.data, substr.size);
}
TEST_PASSED();
sys_free(&system);
TEST_PASSED();
}
const test_fn TESTS_VEC[] = {
MAKE_TEST_FN(vec_test1),
MAKE_TEST_FN(vec_test2),
};
const test_suite_t VEC_SUITE = {
.name = "Vector Tests",
.tests = TESTS_VEC,
.size = ARRSIZE(TESTS_VEC),
.name = "Vector Tests",
.tests =
(test_fn[]){
MAKE_TEST_FN(vec_test_concat),
MAKE_TEST_FN(vec_test_substr),
},
.size = 2,
};
/* Copyright (C) 2026 Aryadev Chavali