diff --git a/v0/test.c b/v0/test.c index f5d5051..4cf8248 100644 --- a/v0/test.c +++ b/v0/test.c @@ -7,6 +7,8 @@ static jmp_buf s_testJmp; static const char* s_failMsg; static char* s_logOutput = NULL; +static const char* s_currentTestName = NULL; +static char* s_testSource = NULL; void fail(const char* msg) { s_failMsg = msg; @@ -29,7 +31,27 @@ void assert_log(const char* expected, const char* msg) { assert_str(expected, s_logOutput, msg); } -void assert_log_file(const char* filepath, const char* msg) { +char* read_file_content(const char* filepath) { + FILE* f = fopen(filepath, "r"); + if (!f) return NULL; + fseek(f, 0, SEEK_END); + long size = ftell(f); + fseek(f, 0, SEEK_SET); + char* content = malloc(size + 1); + if (!content) { + fclose(f); + return NULL; + } + fread(content, 1, size, f); + content[size] = '\0'; + fclose(f); + return content; +} + +void assert_log_file(const char* msg) { + char filepath[256]; + snprintf(filepath, sizeof(filepath), "v0/tests/%s.log", s_currentTestName); + const char* generate = getenv("GENERATE_GOLDEN"); if (generate && strcmp(generate, "1") == 0) { FILE* f = fopen(filepath, "w"); @@ -52,23 +74,6 @@ void assert_log_file(const char* filepath, const char* msg) { free(content); } -char* read_file_content(const char* filepath) { - FILE* f = fopen(filepath, "r"); - if (!f) return NULL; - fseek(f, 0, SEEK_END); - long size = ftell(f); - fseek(f, 0, SEEK_SET); - char* content = malloc(size + 1); - if (!content) { - fclose(f); - return NULL; - } - fread(content, 1, size, f); - content[size] = '\0'; - fclose(f); - return content; -} - void assert_int(int expected, int actual, const char* msg) { if (expected != actual) { char buf[64]; @@ -89,6 +94,20 @@ void assert_false(bool condition, const char* msg) { } } +TokenStream* tokenstream_get_test(void) { + char filepath[256]; + snprintf(filepath, sizeof(filepath), "v0/tests/%s.c2", s_currentTestName); + + if (s_testSource) free(s_testSource); + s_testSource = read_file_content(filepath); + if (!s_testSource) { + fail("could not read test source file"); + return NULL; + } + + return tokenstream_open(filepath, s_testSource); +} + static void log_append(const char* msg) { size_t oldLen = s_logOutput ? strlen(s_logOutput) : 0; size_t newLen = oldLen + strlen(msg) + 1; @@ -141,6 +160,7 @@ static TestCase s_tests[] = { {"parser_public_imports", test_parser_public_imports}, {"log_error", test_log_error}, {"log_on_line", test_log_on_line}, + {"log_on_line_variadic", test_log_on_line_variadic}, }; @@ -155,12 +175,17 @@ int main(int argc, char** argv) { int failedCount = 0; for (int i = 0; i < s_totalTests; i++) { + s_currentTestName = s_tests[i].name; log_set_output(log_append); printf("%s...", s_tests[i].name); s_failMsg = NULL; if (setjmp(s_testJmp) == 0) { log_clear(); + if (s_testSource) { + free(s_testSource); + s_testSource = NULL; + } s_tests[i].func(); printf(" [OK]\n"); s_greenTests++; @@ -170,6 +195,8 @@ int main(int argc, char** argv) { } } + if (s_testSource) free(s_testSource); + if (failedCount > 0) { printf("\nFailed tests:\n"); for (int i = 0; i < failedCount; i++) { diff --git a/v0/test.h b/v0/test.h index a3ce3a9..f46185a 100644 --- a/v0/test.h +++ b/v0/test.h @@ -4,6 +4,10 @@ #ifndef TEST_H #define TEST_H +#include "token.h" + +#include + typedef void (*Test)(void); /** @@ -39,21 +43,16 @@ void assert_str(const char* expected, const char* actual, const char* msg); void assert_log(const char* expected, const char* msg); /** - * Asserts that the logged output matches the content of a file. + * Asserts that the logged output matches the content of the file `v0/tests/xyz.log`, where xyz is the test name. * If GENERATE_GOLDEN=1, the file is overwritten with the actual output. */ -void assert_log_file(const char* filepath, const char* msg); +void assert_log_file(const char* msg); /** * Asserts that two integers are equal. */ void assert_int(int expected, int actual, const char* msg); -/** - * Reads the content of a file into a newly allocated string. - */ -char* read_file_content(const char* filepath); - /** * Asserts that a condition is true. */ @@ -64,4 +63,10 @@ void assert_true(bool condition, const char* msg); */ void assert_false(bool condition, const char* msg); +/** + * Get the token stream used for this test. + * It reads from the `v0/tests/xyz.c2` file, where xyz is the test name. + */ +TokenStream* tokenstream_get_test(void); + #endif diff --git a/v0/test_log.c b/v0/test_log.c index 2ddf9b7..4682111 100644 --- a/v0/test_log.c +++ b/v0/test_log.c @@ -22,7 +22,7 @@ static void test_log_error(void) { static void test_log_on_line(void) { Location loc = { - .filename = "test.c", + .filename = "v0/tests/log_on_line.c2", .line_text = { "int main() []", 13 }, .line = 1, .column_start = 12, @@ -30,9 +30,18 @@ static void test_log_on_line(void) { }; log_on_line(&loc, 13, "unexpected token"); - assert_log_file("v0/tests/log_on_line.txt", "expected formatted error message"); - - log_clear(); - log_on_line(&loc, 13, "unexpected token '%c'", 'x'); - assert_log_file("v0/tests/log_on_line_variadic.txt", "expected formatted error message with variadic args"); + assert_log_file("expected formatted error message"); +} + +static void test_log_on_line_variadic(void) { + Location loc = { + .filename = "v0/tests/log_on_line_variadic.c2", + .line_text = { "int main() []", 13 }, + .line = 1, + .column_start = 12, + .column_end = 13 + }; + + log_on_line(&loc, 13, "unexpected token '%c'", 'x'); + assert_log_file("expected formatted error message with variadic args"); } diff --git a/v0/test_parser.c b/v0/test_parser.c index 8682794..6484fde 100644 --- a/v0/test_parser.c +++ b/v0/test_parser.c @@ -14,40 +14,40 @@ static void test_parser_module_name(void) { } static void test_parser_bad_module_name(void) { - TokenStream* ts = tokenstream_open("test.c", "import other_module;"); + TokenStream* ts = tokenstream_get_test(); Module* m = parser_parse(ts); - assert_log_file("v0/tests/bad_module_name.txt", "expected error to be logged for bad module name"); + assert_log_file("expected error to be logged for bad module name"); parser_free(m); tokenstream_close(ts); } static void test_parser_missing_semicolon_module(void) { - TokenStream* ts = tokenstream_open("test.c", "module my_module"); + TokenStream* ts = tokenstream_get_test(); Module* m = parser_parse(ts); - assert_log_file("v0/tests/missing_semicolon_module.txt", "expected error for missing semicolon"); + assert_log_file("expected error for missing semicolon"); parser_free(m); tokenstream_close(ts); } static void test_parser_missing_semicolon_import(void) { - TokenStream* ts = tokenstream_open("test.c", "module my_module; import other_module"); + TokenStream* ts = tokenstream_get_test(); Module* m = parser_parse(ts); - assert_log_file("v0/tests/missing_semicolon_import.txt", "expected error for missing semicolon"); + assert_log_file("expected error for missing semicolon"); parser_free(m); tokenstream_close(ts); } static void test_parser_bad_import_name(void) { - TokenStream* ts = tokenstream_open("test.c", "module my_module; import ;"); + TokenStream* ts = tokenstream_get_test(); Module* m = parser_parse(ts); - assert_log_file("v0/tests/bad_import_name.txt", "expected error for bad import name"); + assert_log_file("expected error for bad import name"); parser_free(m); tokenstream_close(ts); diff --git a/v0/test_token.c b/v0/test_token.c index afa9663..e57a957 100644 --- a/v0/test_token.c +++ b/v0/test_token.c @@ -82,11 +82,11 @@ static void test_tokenstream_void_function_signature(void) { } static void test_tokenstream_unknown_token(void) { - TokenStream* ts = tokenstream_open("test.c", "%"); + TokenStream* ts = tokenstream_get_test(); if (tokenstream_next(ts).token != TOKEN_UNKNOWN) fail("expected TOKEN_UNKNOWN"); - assert_log_file("v0/tests/unknown_token.txt", "expected error message for unknown token"); + assert_log_file("expected error message for unknown token"); tokenstream_close(ts); } diff --git a/v0/tests/bad_import_name.txt b/v0/tests/bad_import_name.txt deleted file mode 100644 index dff0f45..0000000 --- a/v0/tests/bad_import_name.txt +++ /dev/null @@ -1,4 +0,0 @@ ---- test.c --- -1| module my_module; import ; - ^ - expected module name to import diff --git a/v0/tests/bad_import_name_log_.txt b/v0/tests/bad_import_name_log_.txt deleted file mode 100644 index dff0f45..0000000 --- a/v0/tests/bad_import_name_log_.txt +++ /dev/null @@ -1,4 +0,0 @@ ---- test.c --- -1| module my_module; import ; - ^ - expected module name to import diff --git a/v0/tests/bad_import_name_src_.c b/v0/tests/bad_import_name_src_.c deleted file mode 100644 index a55db2d..0000000 --- a/v0/tests/bad_import_name_src_.c +++ /dev/null @@ -1 +0,0 @@ -import ; \ No newline at end of file diff --git a/v0/tests/bad_module_name.txt b/v0/tests/bad_module_name.txt deleted file mode 100644 index 26506fb..0000000 --- a/v0/tests/bad_module_name.txt +++ /dev/null @@ -1,4 +0,0 @@ ---- test.c --- -1| import other_module; - ^^^^^^ - expected 'module' keyword diff --git a/v0/tests/bad_module_name_src_.c b/v0/tests/bad_module_name_src_.c deleted file mode 100644 index 0d8a5fb..0000000 --- a/v0/tests/bad_module_name_src_.c +++ /dev/null @@ -1 +0,0 @@ -import other_module; \ No newline at end of file diff --git a/v0/tests/log_on_line.c2 b/v0/tests/log_on_line.c2 new file mode 100644 index 0000000..f0665e9 --- /dev/null +++ b/v0/tests/log_on_line.c2 @@ -0,0 +1 @@ +int main() [] diff --git a/v0/tests/log_on_line.txt b/v0/tests/log_on_line.log similarity index 62% rename from v0/tests/log_on_line.txt rename to v0/tests/log_on_line.log index d9e8ba1..8cbdfbc 100644 --- a/v0/tests/log_on_line.txt +++ b/v0/tests/log_on_line.log @@ -1,4 +1,4 @@ ---- test.c --- +--- v0/tests/log_on_line.c2 --- 1| int main() [] ^^ unexpected token diff --git a/v0/tests/log_on_line_log_.txt b/v0/tests/log_on_line_log_.txt deleted file mode 100644 index d9e8ba1..0000000 --- a/v0/tests/log_on_line_log_.txt +++ /dev/null @@ -1,4 +0,0 @@ ---- test.c --- -1| int main() [] - ^^ - unexpected token diff --git a/v0/tests/log_on_line_src_.c b/v0/tests/log_on_line_src_.c deleted file mode 100644 index 8cac8ba..0000000 --- a/v0/tests/log_on_line_src_.c +++ /dev/null @@ -1 +0,0 @@ -int main() [] \ No newline at end of file diff --git a/v0/tests/log_on_line_variadic.c2 b/v0/tests/log_on_line_variadic.c2 new file mode 100644 index 0000000..f0665e9 --- /dev/null +++ b/v0/tests/log_on_line_variadic.c2 @@ -0,0 +1 @@ +int main() [] diff --git a/v0/tests/log_on_line_variadic.txt b/v0/tests/log_on_line_variadic.log similarity index 58% rename from v0/tests/log_on_line_variadic.txt rename to v0/tests/log_on_line_variadic.log index 75be8b0..dc85a77 100644 --- a/v0/tests/log_on_line_variadic.txt +++ b/v0/tests/log_on_line_variadic.log @@ -1,4 +1,4 @@ ---- test.c --- +--- v0/tests/log_on_line_variadic.c2 --- 1| int main() [] ^^ unexpected token 'x' diff --git a/v0/tests/log_on_line_variadic_log_.txt b/v0/tests/log_on_line_variadic_log_.txt deleted file mode 100644 index 75be8b0..0000000 --- a/v0/tests/log_on_line_variadic_log_.txt +++ /dev/null @@ -1,4 +0,0 @@ ---- test.c --- -1| int main() [] - ^^ - unexpected token 'x' diff --git a/v0/tests/log_on_line_variadic_src_.c b/v0/tests/log_on_line_variadic_src_.c deleted file mode 100644 index 8cac8ba..0000000 --- a/v0/tests/log_on_line_variadic_src_.c +++ /dev/null @@ -1 +0,0 @@ -int main() [] \ No newline at end of file diff --git a/v0/tests/missing_semicolon_import.txt b/v0/tests/missing_semicolon_import.txt deleted file mode 100644 index d6d2947..0000000 --- a/v0/tests/missing_semicolon_import.txt +++ /dev/null @@ -1,4 +0,0 @@ ---- test.c --- -1| module my_module; import other_module - ^ - expected ';' after import diff --git a/v0/tests/missing_semicolon_import_log_.txt b/v0/tests/missing_semicolon_import_log_.txt deleted file mode 100644 index d6d2947..0000000 --- a/v0/tests/missing_semicolon_import_log_.txt +++ /dev/null @@ -1,4 +0,0 @@ ---- test.c --- -1| module my_module; import other_module - ^ - expected ';' after import diff --git a/v0/tests/missing_semicolon_import_src_.c b/v0/tests/missing_semicolon_import_src_.c deleted file mode 100644 index b4480e9..0000000 --- a/v0/tests/missing_semicolon_import_src_.c +++ /dev/null @@ -1 +0,0 @@ -module my_module; import other_module \ No newline at end of file diff --git a/v0/tests/missing_semicolon_module.txt b/v0/tests/missing_semicolon_module.txt deleted file mode 100644 index 585f78a..0000000 --- a/v0/tests/missing_semicolon_module.txt +++ /dev/null @@ -1,4 +0,0 @@ ---- test.c --- -1| module my_module - ^ - expected ';' after module name diff --git a/v0/tests/missing_semicolon_module_log_.txt b/v0/tests/missing_semicolon_module_log_.txt deleted file mode 100644 index 585f78a..0000000 --- a/v0/tests/missing_semicolon_module_log_.txt +++ /dev/null @@ -1,4 +0,0 @@ ---- test.c --- -1| module my_module - ^ - expected ';' after module name diff --git a/v0/tests/missing_semicolon_module_src_.c b/v0/tests/missing_semicolon_module_src_.c deleted file mode 100644 index e8451c1..0000000 --- a/v0/tests/missing_semicolon_module_src_.c +++ /dev/null @@ -1 +0,0 @@ -module my_module \ No newline at end of file diff --git a/v0/tests/parser_bad_import_name.c2 b/v0/tests/parser_bad_import_name.c2 new file mode 100644 index 0000000..a260cbc --- /dev/null +++ b/v0/tests/parser_bad_import_name.c2 @@ -0,0 +1 @@ +import ; diff --git a/v0/tests/parser_bad_import_name.log b/v0/tests/parser_bad_import_name.log new file mode 100644 index 0000000..a3edca8 --- /dev/null +++ b/v0/tests/parser_bad_import_name.log @@ -0,0 +1,4 @@ +--- v0/tests/parser_bad_impo --- +1| import ; + ^^^^^^ + expected 'module' keyword diff --git a/v0/tests/parser_bad_module_name.c2 b/v0/tests/parser_bad_module_name.c2 new file mode 100644 index 0000000..046f335 --- /dev/null +++ b/v0/tests/parser_bad_module_name.c2 @@ -0,0 +1 @@ +import other_module; diff --git a/v0/tests/bad_module_name_log_.txt b/v0/tests/parser_bad_module_name.log similarity index 65% rename from v0/tests/bad_module_name_log_.txt rename to v0/tests/parser_bad_module_name.log index 26506fb..813278c 100644 --- a/v0/tests/bad_module_name_log_.txt +++ b/v0/tests/parser_bad_module_name.log @@ -1,4 +1,4 @@ ---- test.c --- +--- v0/tests/parser_bad_modu --- 1| import other_module; ^^^^^^ expected 'module' keyword diff --git a/v0/tests/parser_missing_semicolon_import.c2 b/v0/tests/parser_missing_semicolon_import.c2 new file mode 100644 index 0000000..8692e85 --- /dev/null +++ b/v0/tests/parser_missing_semicolon_import.c2 @@ -0,0 +1 @@ +module my_module; import other_module diff --git a/v0/tests/parser_missing_semicolon_import.log b/v0/tests/parser_missing_semicolon_import.log new file mode 100644 index 0000000..5b37d32 --- /dev/null +++ b/v0/tests/parser_missing_semicolon_import.log @@ -0,0 +1,4 @@ +--- --- +2| + ^ + expected ';' after import diff --git a/v0/tests/parser_missing_semicolon_module.c2 b/v0/tests/parser_missing_semicolon_module.c2 new file mode 100644 index 0000000..652fd69 --- /dev/null +++ b/v0/tests/parser_missing_semicolon_module.c2 @@ -0,0 +1 @@ +module my_module diff --git a/v0/tests/parser_missing_semicolon_module.log b/v0/tests/parser_missing_semicolon_module.log new file mode 100644 index 0000000..a7cd6ed --- /dev/null +++ b/v0/tests/parser_missing_semicolon_module.log @@ -0,0 +1,5 @@ +--- + --- +2| + ^ + expected ';' after module name diff --git a/v0/tests/tokenstream_unknown_token.c2 b/v0/tests/tokenstream_unknown_token.c2 new file mode 100644 index 0000000..314d73b --- /dev/null +++ b/v0/tests/tokenstream_unknown_token.c2 @@ -0,0 +1 @@ +% diff --git a/v0/tests/unknown_token.txt b/v0/tests/tokenstream_unknown_token.log similarity index 69% rename from v0/tests/unknown_token.txt rename to v0/tests/tokenstream_unknown_token.log index c14067e..757af89 100644 --- a/v0/tests/unknown_token.txt +++ b/v0/tests/tokenstream_unknown_token.log @@ -1,4 +1,4 @@ ---- test.c --- +--- --- 1| % ^ unexpected token '%' diff --git a/v0/tests/unknown_token_log_.txt b/v0/tests/unknown_token_log_.txt deleted file mode 100644 index c14067e..0000000 --- a/v0/tests/unknown_token_log_.txt +++ /dev/null @@ -1,4 +0,0 @@ ---- test.c --- -1| % - ^ - unexpected token '%' diff --git a/v0/tests/unknown_token_src_.c b/v0/tests/unknown_token_src_.c deleted file mode 100644 index 02691e3..0000000 --- a/v0/tests/unknown_token_src_.c +++ /dev/null @@ -1 +0,0 @@ -% \ No newline at end of file