Compare commits

...

5 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
4 changed files with 100 additions and 14 deletions

View File

@@ -45,13 +45,58 @@ i.e. no parsing.
*** DONE Design what a "parser function" would look like *** DONE Design what a "parser function" would look like
The general function is something like ~stream -> T | Err~. What The general function is something like ~stream -> T | Err~. What
other state do we need to encode? 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 symbols
*** TODO Write a parser for lists *** TODO Write a parser for lists
*** TODO Write a parser for vectors *** TODO Write a parser for vectors
*** TODO Write the general parser *** TODO Write the general parser
** WIP Unit tests :tests: ** WIP Unit tests :tests:
*** TODO Test streams *** 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 *** DONE Test system registration of allocated units
In particular, does clean up work as we expect? Do we have situations 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? where we may double free or not clean up something we should've?

View File

@@ -12,6 +12,10 @@
sv_t sv_copy(sv_t old) 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)); char *newstr = calloc(1, (old.size + 1) * sizeof(*newstr));
memcpy(newstr, old.data, old.size); memcpy(newstr, old.data, old.size);
newstr[old.size] = '\0'; newstr[old.size] = '\0';

View File

@@ -12,15 +12,13 @@
#include "./test.h" #include "./test.h"
#include "./test_lisp_api.c" #include "./test_lisp_api.c"
#include "./test_stream.c"
#include "./test_sv.c" #include "./test_sv.c"
#include "./test_symtable.c" #include "./test_symtable.c"
#include "./test_vec.c" #include "./test_vec.c"
test_suite_t SUITES[] = { test_suite_t SUITES[] = {
VEC_SUITE, VEC_SUITE, SV_SUITE, SYMTABLE_SUITE, STREAM_SUITE, LISP_API_SUITE,
SV_SUITE,
SYMTABLE_SUITE,
LISP_API_SUITE,
}; };
int main(void) int main(void)

View File

@@ -5,12 +5,51 @@
* Commentary: * Commentary:
*/ */
#include <malloc.h>
#include "./data.h" #include "./data.h"
#include "./test.h" #include "./test.h"
#include <alisp/stream.h>
void stream_test_string(void) void stream_test_string(void)
{ {
TODO("Not implemented"); 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) void stream_test_file(void)
@@ -53,15 +92,15 @@ const test_suite_t STREAM_SUITE = {
.tests = .tests =
(test_fn[]){ (test_fn[]){
MAKE_TEST_FN(stream_test_string), MAKE_TEST_FN(stream_test_string),
MAKE_TEST_FN(stream_test_file), // MAKE_TEST_FN(stream_test_file),
MAKE_TEST_FN(stream_test_peek_next), // MAKE_TEST_FN(stream_test_peek_next),
MAKE_TEST_FN(stream_test_seek), // MAKE_TEST_FN(stream_test_seek),
MAKE_TEST_FN(stream_test_substr), // MAKE_TEST_FN(stream_test_substr),
MAKE_TEST_FN(stream_test_till), // MAKE_TEST_FN(stream_test_till),
MAKE_TEST_FN(stream_test_while), // MAKE_TEST_FN(stream_test_while),
MAKE_TEST_FN(stream_test_line_col), // MAKE_TEST_FN(stream_test_line_col),
}, },
.size = 8, .size = 1,
}; };
/* Copyright (C) 2026 Aryadev Chavali /* Copyright (C) 2026 Aryadev Chavali