diff --git a/v0/test.c b/v0/test.c index 512a5b8..b8cd999 100644 --- a/v0/test.c +++ b/v0/test.c @@ -1,10 +1,12 @@ #include "test.h" + +#include "util.h" +#include "parser.h" + #include #include #include #include -#include "util.h" -#include "parser.h" static jmp_buf s_testJmp; static const char* s_failMsg; @@ -12,6 +14,9 @@ static char* s_logOutput = NULL; static const char* s_currentTestName = NULL; static char* s_testSource = NULL; +static Module* s_currentModule = NULL; +static TokenStream* s_currentTokenStream = NULL; + void fail(const char* msg) { s_failMsg = msg; longjmp(s_testJmp, 1); @@ -56,32 +61,34 @@ void assert_str(const char* expected, const char* actual, const char* msg) { } } -TokenStream* tokenstream_get_test(void) { - char* filepath = NULL; - TokenStream* ts = NULL; +TokenStream* test_get_tokenstream(void) { + if (s_currentTokenStream == NULL) { + char* filepath = NULL; - filepath = format_string("v0/tests/%s.c2", s_currentTestName); - if (!filepath) { - fail("out of memory"); - return NULL; - } - - if (s_testSource) free(s_testSource); - s_testSource = read_file_content(filepath); - if (!s_testSource) { - fail("could not read test source file"); + filepath = format_string("v0/tests/%s.c2", s_currentTestName); + if (!filepath) { + fail("out of memory"); + return NULL; + } + + if (s_testSource) free(s_testSource); + s_testSource = read_file_content(filepath); + if (!s_testSource) { + fail("could not read test source file"); + free(filepath); + return NULL; + } + s_currentTokenStream = tokenstream_open(filepath, s_testSource); free(filepath); - return NULL; } - ts = tokenstream_open(filepath, s_testSource); - free(filepath); - return ts; + return s_currentTokenStream; } Module* test_get_ast(void) { - TokenStream* ts = tokenstream_get_test(); - if (!ts) return NULL; - return parser_parse(ts); + if (s_currentModule == NULL) { + s_currentModule = parser_parse(test_get_tokenstream()); + } + return s_currentModule; } void assert_log(const char* expected, const char* msg) { @@ -240,6 +247,15 @@ int main(int argc, char** argv) { printf(" [FAIL]: %s\n", s_failMsg ? s_failMsg : ""); failedTests[failedCount++] = s_tests[i].name; } + + if (s_currentModule) { + parser_free(s_currentModule); + s_currentModule = NULL; + } + if (s_currentTokenStream) { + tokenstream_close(s_currentTokenStream); + s_currentTokenStream = NULL; + } fflush(stdout); } diff --git a/v0/test_parser.c b/v0/test_parser.c index b5e563b..da99cf3 100644 --- a/v0/test_parser.c +++ b/v0/test_parser.c @@ -4,58 +4,34 @@ #include static void test_parser_module_name(void) { - TokenStream* ts = tokenstream_open("test.c", "module my_module;"); - Module* m = parser_parse(ts); + Module* m = test_get_ast(); assert_not_null(m, "expected module to be parsed"); assert_str("my_module", m->name, "expected name 'my_module'"); - parser_free(m); - tokenstream_close(ts); } static void test_parser_bad_module_name(void) { - TokenStream* ts = tokenstream_get_test(); - Module* m = parser_parse(ts); - + test_get_ast(); 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_get_test(); - Module* m = parser_parse(ts); - + test_get_ast(); 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_get_test(); - Module* m = parser_parse(ts); - + test_get_ast(); 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_get_test(); - Module* m = parser_parse(ts); - + test_get_ast(); assert_log_file("expected error for bad import name"); - - parser_free(m); - tokenstream_close(ts); } static void test_parser_imports(void) { - TokenStream* ts = tokenstream_open("test.c", "module my_module; import other_module;"); - Module* m = parser_parse(ts); + Module* m = test_get_ast(); assert_not_null(m, "expected module to be parsed"); assert_str("my_module", m->name, "expected name 'my_module'"); @@ -64,13 +40,10 @@ static void test_parser_imports(void) { assert_int(1, (int)m->import_count, "expected one import"); assert_str("other_module", m->imports[0].module_name, "expected import name 'other_module'"); assert_false(m->imports[0].is_public, "expected import to not be public"); - parser_free(m); - tokenstream_close(ts); } static void test_parser_public_imports(void) { - TokenStream* ts = tokenstream_open("test.c", "module my_module; import public other_module;"); - Module* m = parser_parse(ts); + Module* m = test_get_ast(); assert_not_null(m, "expected module to be parsed"); assert_str("my_module", m->name, "expected name 'my_module'"); @@ -79,8 +52,6 @@ static void test_parser_public_imports(void) { assert_int(1, (int)m->import_count, "expected one import"); assert_str("other_module", m->imports[0].module_name, "expected import name 'other_module'"); assert_true(m->imports[0].is_public, "expected import to be public"); - parser_free(m); - tokenstream_close(ts); } static void test_parser_alias_simple(void) { @@ -110,7 +81,6 @@ static void test_parser_alias_array(void) { assert_true(valueType->builtin.isSigned, "expected signed"); } - static void test_parser_alias_and_import_mix(void) { Module* m = test_get_ast(); @@ -122,5 +92,4 @@ static void test_parser_alias_and_import_mix(void) { assert_str("bar", m->imports[1].module_name, "expected import 2 name 'bar'"); assert_str("myalias", m->aliases[0].name, "expected alias 1 name 'myalias'"); assert_str("otheralias", m->aliases[1].name, "expected alias 2 name 'otheralias'"); - parser_free(m); } diff --git a/v0/test_token.c b/v0/test_token.c index 8b7ae5e..f425e84 100644 --- a/v0/test_token.c +++ b/v0/test_token.c @@ -9,23 +9,19 @@ static void test_tokenstream_open_fail(void) { } static void test_tokenstream_simple_keyword(void) { - TokenStream* ts; + TokenStream* ts = test_get_tokenstream(); Token t; Token eof; - ts = tokenstream_open("test.c", "module"); - t = tokenstream_next(ts); if (t.token != TOKEN_MODULE) fail("expected TOKEN_MODULE"); eof = tokenstream_next(ts); if (eof.token != TOKEN_EOF) fail("expected EOF"); - - tokenstream_close(ts); } static void test_tokenstream_keywords_and_symbols(void) { - TokenStream* ts = tokenstream_open("test.c", "module main; import stdio;"); + TokenStream* ts = test_get_tokenstream(); if (tokenstream_next(ts).token != TOKEN_MODULE) fail("expected TOKEN_MODULE"); if (tokenstream_next(ts).token != TOKEN_IDENTIFIER) fail("expected TOKEN_IDENTIFIER (main)"); @@ -34,24 +30,20 @@ static void test_tokenstream_keywords_and_symbols(void) { if (tokenstream_next(ts).token != TOKEN_IDENTIFIER) fail("expected TOKEN_IDENTIFIER (stdio)"); if (tokenstream_next(ts).token != TOKEN_SEMICOLON) fail("expected TOKEN_SEMICOLON"); if (tokenstream_next(ts).token != TOKEN_EOF) fail("expected EOF"); - - tokenstream_close(ts); } static void test_tokenstream_parentheses_and_brackets(void) { - TokenStream* ts = tokenstream_open("test.c", "()[]"); + TokenStream* ts = test_get_tokenstream(); if (tokenstream_next(ts).token != TOKEN_PARENT_OPEN) fail("expected TOKEN_PARENT_OPEN"); if (tokenstream_next(ts).token != TOKEN_PARENT_CLOSE) fail("expected TOKEN_PARENT_CLOSE"); if (tokenstream_next(ts).token != TOKEN_BRACKET_OPEN) fail("expected TOKEN_BRACKET_OPEN"); if (tokenstream_next(ts).token != TOKEN_BRACKET_CLOSE) fail("expected TOKEN_BRACKET_CLOSE"); if (tokenstream_next(ts).token != TOKEN_EOF) fail("expected EOF"); - - tokenstream_close(ts); } static void test_tokenstream_comma(void) { - TokenStream* ts = tokenstream_open("test.c", "a,b,c"); + TokenStream* ts = test_get_tokenstream(); if (tokenstream_next(ts).token != TOKEN_IDENTIFIER) fail("expected a"); if (tokenstream_next(ts).token != TOKEN_COMMA) fail("expected comma"); @@ -59,75 +51,49 @@ static void test_tokenstream_comma(void) { if (tokenstream_next(ts).token != TOKEN_COMMA) fail("expected comma"); if (tokenstream_next(ts).token != TOKEN_IDENTIFIER) fail("expected c"); if (tokenstream_next(ts).token != TOKEN_EOF) fail("expected EOF"); - - tokenstream_close(ts); } static void test_tokenstream_whitespace_ignored(void) { - TokenStream* ts = tokenstream_open("test.c", " module \n\t import ; "); + TokenStream* ts = test_get_tokenstream(); if (tokenstream_next(ts).token != TOKEN_MODULE) fail("expected TOKEN_MODULE"); if (tokenstream_next(ts).token != TOKEN_IMPORT) fail("expected TOKEN_IMPORT"); if (tokenstream_next(ts).token != TOKEN_SEMICOLON) fail("expected TOKEN_SEMICOLON"); if (tokenstream_next(ts).token != TOKEN_EOF) fail("expected EOF"); - - tokenstream_close(ts); } static void test_tokenstream_void_function_signature(void) { - TokenStream* ts = tokenstream_open("test.c", "void main()"); + TokenStream* ts = test_get_tokenstream(); if (tokenstream_next(ts).token != TOKEN_VOID) fail("expected TOKEN_VOID"); if (tokenstream_next(ts).token != TOKEN_IDENTIFIER) fail("expected TOKEN_IDENTIFIER"); if (tokenstream_next(ts).token != TOKEN_PARENT_OPEN) fail("expected TOKEN_PARENT_OPEN"); if (tokenstream_next(ts).token != TOKEN_PARENT_CLOSE) fail("expected TOKEN_PARENT_CLOSE"); if (tokenstream_next(ts).token != TOKEN_EOF) fail("expected EOF"); - - tokenstream_close(ts); } static void test_tokenstream_unknown_token(void) { - TokenStream* ts = tokenstream_get_test(); + TokenStream* ts = test_get_tokenstream(); if (tokenstream_next(ts).token != TOKEN_UNKNOWN) fail("expected TOKEN_UNKNOWN"); - - assert_log_file("expected error message for unknown token"); - tokenstream_close(ts); + assert_log_file("expected error message for unknown token"); } static void test_tokenstream_info(void) { - TokenStream* ts; + TokenStream* ts = test_get_tokenstream(); Token t1; Token t2; - char* buf1; - char* buf2; - - ts = tokenstream_open("test.c", "module main;"); t1 = tokenstream_next(ts); if (t1.token != TOKEN_MODULE) fail("expected TOKEN_MODULE"); - - buf1 = malloc((size_t)t1.text.length + 1); - if (!buf1) fail("out of memory"); - memcpy(buf1, t1.text.data, t1.text.length); - buf1[t1.text.length] = '\0'; - assert_str("module", buf1, "info: expected 'module'"); + assert_string("module", t1.text, "info: expected 'module'"); if (t1.location.line != 1) fail("expected line 1"); if (t1.location.column_start != 1) fail("expected column 1"); t2 = tokenstream_next(ts); if (t2.token != TOKEN_IDENTIFIER) fail("expected TOKEN_IDENTIFIER"); - - buf2 = malloc((size_t)t2.text.length + 1); - if (!buf2) { free(buf1); fail("out of memory"); } - memcpy(buf2, t2.text.data, t2.text.length); - buf2[t2.text.length] = '\0'; - assert_str("main", buf2, "info: expected 'main'"); + assert_string("main", t2.text, "info: expected 'main'"); if (t2.location.line != 1) fail("expected line 1"); if (t2.location.column_start != 8) fail("expected column 8"); - - free(buf1); - free(buf2); - tokenstream_close(ts); } diff --git a/v0/tests/parser_imports.c2 b/v0/tests/parser_imports.c2 new file mode 100644 index 0000000..e3a89d6 --- /dev/null +++ b/v0/tests/parser_imports.c2 @@ -0,0 +1,2 @@ +module my_module; +import other_module; diff --git a/v0/tests/parser_module_name.c2 b/v0/tests/parser_module_name.c2 new file mode 100644 index 0000000..9aca53f --- /dev/null +++ b/v0/tests/parser_module_name.c2 @@ -0,0 +1 @@ +module my_module; diff --git a/v0/tests/parser_public_imports.c2 b/v0/tests/parser_public_imports.c2 new file mode 100644 index 0000000..fe81561 --- /dev/null +++ b/v0/tests/parser_public_imports.c2 @@ -0,0 +1,2 @@ +module my_module; +import public other_module; diff --git a/v0/tests/tokenstream_comma.c2 b/v0/tests/tokenstream_comma.c2 new file mode 100644 index 0000000..b2ffb02 --- /dev/null +++ b/v0/tests/tokenstream_comma.c2 @@ -0,0 +1 @@ +a,b,c diff --git a/v0/tests/tokenstream_info.c2 b/v0/tests/tokenstream_info.c2 new file mode 100644 index 0000000..8bffabe --- /dev/null +++ b/v0/tests/tokenstream_info.c2 @@ -0,0 +1 @@ +module main; diff --git a/v0/tests/tokenstream_keywords_and_symbols.c2 b/v0/tests/tokenstream_keywords_and_symbols.c2 new file mode 100644 index 0000000..526db8c --- /dev/null +++ b/v0/tests/tokenstream_keywords_and_symbols.c2 @@ -0,0 +1 @@ +module main; import stdio; diff --git a/v0/tests/tokenstream_parentheses_and_brackets.c2 b/v0/tests/tokenstream_parentheses_and_brackets.c2 new file mode 100644 index 0000000..4512531 --- /dev/null +++ b/v0/tests/tokenstream_parentheses_and_brackets.c2 @@ -0,0 +1 @@ +()[] diff --git a/v0/tests/tokenstream_simple_keyword.c2 b/v0/tests/tokenstream_simple_keyword.c2 new file mode 100644 index 0000000..0cca093 --- /dev/null +++ b/v0/tests/tokenstream_simple_keyword.c2 @@ -0,0 +1 @@ +module diff --git a/v0/tests/tokenstream_void_function_signature.c2 b/v0/tests/tokenstream_void_function_signature.c2 new file mode 100644 index 0000000..5a17181 --- /dev/null +++ b/v0/tests/tokenstream_void_function_signature.c2 @@ -0,0 +1 @@ +void main() diff --git a/v0/tests/tokenstream_whitespace_ignored.c2 b/v0/tests/tokenstream_whitespace_ignored.c2 new file mode 100644 index 0000000..a868249 --- /dev/null +++ b/v0/tests/tokenstream_whitespace_ignored.c2 @@ -0,0 +1,2 @@ + module + import ;