From 389890a7e7cf63d81f6b6094efd351d584bed854 Mon Sep 17 00:00:00 2001 From: Kyler Date: Thu, 6 Nov 2025 00:54:52 -0700 Subject: [PATCH] Worked on tests --- SLS_C/Makefile | 5 ++- SLS_C/tests/lexer_test_helpers.c | 18 +++++--- SLS_C/tests/lexer_tests.c | 63 +++++++++----------------- SLS_C/tests/tests.c | 77 ++++++++++++++++++++++++++------ SLS_Tests/cases.yaml | 63 ++++++++++++-------------- 5 files changed, 131 insertions(+), 95 deletions(-) diff --git a/SLS_C/Makefile b/SLS_C/Makefile index e8fffd9..034b76b 100644 --- a/SLS_C/Makefile +++ b/SLS_C/Makefile @@ -47,12 +47,15 @@ run: $(TARGET) @echo "Running $(TARGET)..." ./$(TARGET) +test_cases: ../SLS_Tests/yaml_to_c_tests.py ../SLS_Tests/cases.yaml + python3 ../SLS_Tests/yaml_to_c_tests.py ../SLS_Tests/cases.yaml ./tests/lexer_tests.c + # Build test runner executable $(TEST_TARGET): $(TEST_OBJECTS) $(NON_MAIN_OBJECTS) | $(BINDIR) $(CC) $(LDFLAGS) $^ -o $@ -lm # Run tests -test: $(TEST_TARGET) +test: test_cases $(TEST_TARGET) @echo "Running tests..." ./$(TEST_TARGET) diff --git a/SLS_C/tests/lexer_test_helpers.c b/SLS_C/tests/lexer_test_helpers.c index f63c257..03eba37 100644 --- a/SLS_C/tests/lexer_test_helpers.c +++ b/SLS_C/tests/lexer_test_helpers.c @@ -33,38 +33,44 @@ void clean_up_test(LexerResult result) { } TestResult error_test(LexerTest *test, LexerResult result, SlsError error) { - clean_up_test(result); test->result.status = TEST_ERROR; test->result.error = error; + clean_up_test(result); return test->result; } TestResult logic_fail_test(LexerTest *test, LexerResult result, char *message) { if (message == 0) return error_test(test, result, (SlsError) { .message = "Out of Memory Error!", .code = 1, }); - clean_up_test(result); test->result.status = TEST_LOGIC_FAIL; test->result.message = message; + clean_up_test(result); return test->result; } TestResult logic_error_fail_test(LexerTest *test, LexerResult result, SlsError error) { - clean_up_test(result); test->result.status = TEST_LOGIC_ERROR_FAIL; test->result.error = error; + + size_t message_length = strlen(error.message) + 1; + const char *message = (char *)malloc(sizeof(char) * message_length); + strncpy(message, error.message, message_length); + test->result.error.message = message; + + clean_up_test(result); return test->result; } TestResult error_fail_test(LexerTest *test, LexerResult result, SlsError error) { - clean_up_test(result); test->result.status = TEST_ERROR_FAIL; test->result.error = error; + clean_up_test(result); return test->result; } TestResult skip_test(LexerTest *test, LexerResult result) { - clean_up_test(result); test->result.status = TEST_NOT_IMPLEMENTED; + clean_up_test(result); return test->result; } @@ -74,8 +80,8 @@ TestResult skip_test_no_result(LexerTest *test) { } TestResult pass_test(LexerTest *test, LexerResult result) { - clean_up_test(result); test->result.status = TEST_PASS; + clean_up_test(result); return test->result; } diff --git a/SLS_C/tests/lexer_tests.c b/SLS_C/tests/lexer_tests.c index 39b7224..c909818 100644 --- a/SLS_C/tests/lexer_tests.c +++ b/SLS_C/tests/lexer_tests.c @@ -16,7 +16,7 @@ #include "tests/tests.h" -static const size_t NUM_OF_TESTS = 22; +static const size_t NUM_OF_TESTS = 20; static TestResult test_Empty_Statement() { LexerTest test = start_up_test("test_Empty_Statement", ""); @@ -37,8 +37,8 @@ static TestResult test_Integer_Default_Decimal_0() { return pass_test(&test, result); } -static TestResult test_Integer_Default_Decimal_1_neg() { - LexerTest test = start_up_test("test_Integer_Default_Decimal_1_neg", "-1"); +static TestResult test_Integer_Default_Decimal_1() { + LexerTest test = start_up_test("test_Integer_Default_Decimal_1", "-1"); LexerResult result = lexical_analysis(&test.lexer_info); if (result.type == SLS_ERROR) return error_fail_test(&test, result, result.error); size_t i = 0; @@ -47,16 +47,6 @@ static TestResult test_Integer_Default_Decimal_1_neg() { return pass_test(&test, result); } -static TestResult test_Integer_Default_Decimal_1_pos() { - LexerTest test = start_up_test("test_Integer_Default_Decimal_1_pos", "+1"); - LexerResult result = lexical_analysis(&test.lexer_info); - if (result.type == SLS_ERROR) return error_fail_test(&test, result, result.error); - size_t i = 0; - if (test_integer_value(&test, result, i++, &(TestIntegerValue){INTEGER_I64, 1})) return test.result; - if (test_eof_value(&test, result, i++, 0)) return test.result; - return pass_test(&test, result); -} - static TestResult test_Integer_Default_Decimal_Leading_Zeros() { LexerTest test = start_up_test("test_Integer_Default_Decimal_Leading_Zeros", "00042"); LexerResult result = lexical_analysis(&test.lexer_info); @@ -108,7 +98,7 @@ static TestResult test_Integer_Default_Octal_0o755() { } static TestResult test_Integer_i8_Decimal_127() { - LexerTest test = start_up_test("test_Integer_i8_Decimal_127", "127i8"); + LexerTest test = start_up_test("test_Integer_i8_Decimal_127", "127:i8"); LexerResult result = lexical_analysis(&test.lexer_info); if (result.type == SLS_ERROR) return error_fail_test(&test, result, result.error); size_t i = 0; @@ -118,7 +108,7 @@ static TestResult test_Integer_i8_Decimal_127() { } static TestResult test_Integer_i8_Decimal_128() { - LexerTest test = start_up_test("test_Integer_i8_Decimal_128", "-128i8"); + LexerTest test = start_up_test("test_Integer_i8_Decimal_128", "-128:i8"); LexerResult result = lexical_analysis(&test.lexer_info); if (result.type == SLS_ERROR) return error_fail_test(&test, result, result.error); size_t i = 0; @@ -128,7 +118,7 @@ static TestResult test_Integer_i8_Decimal_128() { } static TestResult test_Integer_u8_Decimal_255() { - LexerTest test = start_up_test("test_Integer_u8_Decimal_255", "255u8"); + LexerTest test = start_up_test("test_Integer_u8_Decimal_255", "255:u8"); LexerResult result = lexical_analysis(&test.lexer_info); if (result.type == SLS_ERROR) return error_fail_test(&test, result, result.error); size_t i = 0; @@ -152,12 +142,12 @@ static TestResult test_Integer_Default_Decimal_with_Commas_Invalid() { LexerResult result = lexical_analysis(&test.lexer_info); if (result.type == SLS_ERROR) return error_fail_test(&test, result, result.error); size_t i = 0; - if (test_for_error(&test, result, i++, &(TestErrorMessage){52, "Invalid numeric literal: unexpected ',' in integer."})) return test.result; + if (test_for_error(&test, result, i++, &(TestErrorMessage){60, "Invalid decimal literal: unexpected ',' in decimal integer."})) return test.result; return pass_test(&test, result); } static TestResult test_Integer_i8_Overflow() { - LexerTest test = start_up_test("test_Integer_i8_Overflow", "128i8"); + LexerTest test = start_up_test("test_Integer_i8_Overflow", "128:i8"); LexerResult result = lexical_analysis(&test.lexer_info); if (result.type == SLS_ERROR) return error_fail_test(&test, result, result.error); size_t i = 0; @@ -166,7 +156,7 @@ static TestResult test_Integer_i8_Overflow() { } static TestResult test_Integer_i8_Underflow() { - LexerTest test = start_up_test("test_Integer_i8_Underflow", "-129i8"); + LexerTest test = start_up_test("test_Integer_i8_Underflow", "-129:i8"); LexerResult result = lexical_analysis(&test.lexer_info); if (result.type == SLS_ERROR) return error_fail_test(&test, result, result.error); size_t i = 0; @@ -179,7 +169,7 @@ static TestResult test_Integer_Default_Invalid_Characters() { LexerResult result = lexical_analysis(&test.lexer_info); if (result.type == SLS_ERROR) return error_fail_test(&test, result, result.error); size_t i = 0; - if (test_for_error(&test, result, i++, &(TestErrorMessage){51, "Invalid numeric literal: unexpected character 'a'."})) return test.result; + if (test_for_error(&test, result, i++, &(TestErrorMessage){60, "Invalid decimal literal: unexpected 'a' in decimal integer."})) return test.result; return pass_test(&test, result); } @@ -198,34 +188,27 @@ static TestResult test_Integer_Default_Invalid_Prefix() { LexerResult result = lexical_analysis(&test.lexer_info); if (result.type == SLS_ERROR) return error_fail_test(&test, result, result.error); size_t i = 0; - if (test_for_error(&test, result, i++, &(TestErrorMessage){47, "Invalid binary literal: digit '2' not allowed."})) return test.result; + if (test_for_error(&test, result, i++, &(TestErrorMessage){58, "Invalid binary literal: unexpected '2' in binary integer."})) return test.result; return pass_test(&test, result); } -static TestResult test_Integer_Default_Invalid_Underscore_Start() { - LexerTest test = start_up_test("test_Integer_Default_Invalid_Underscore_Start", "_42"); +static TestResult test_Integer_Default_Underscore_End() { + LexerTest test = start_up_test("test_Integer_Default_Underscore_End", "42_"); LexerResult result = lexical_analysis(&test.lexer_info); if (result.type == SLS_ERROR) return error_fail_test(&test, result, result.error); size_t i = 0; - if (test_for_error(&test, result, i++, &(TestErrorMessage){55, "Invalid numeric literal: cannot start with underscore."})) return test.result; + if (test_integer_value(&test, result, i++, &(TestIntegerValue){INTEGER_I64, 42})) return test.result; + if (test_eof_value(&test, result, i++, 0)) return test.result; return pass_test(&test, result); } -static TestResult test_Integer_Default_Invalid_Underscore_End() { - LexerTest test = start_up_test("test_Integer_Default_Invalid_Underscore_End", "42_"); +static TestResult test_Integer_Default_Underscore_Double() { + LexerTest test = start_up_test("test_Integer_Default_Underscore_Double", "4__2"); LexerResult result = lexical_analysis(&test.lexer_info); if (result.type == SLS_ERROR) return error_fail_test(&test, result, result.error); size_t i = 0; - if (test_for_error(&test, result, i++, &(TestErrorMessage){53, "Invalid numeric literal: cannot end with underscore."})) return test.result; - return pass_test(&test, result); -} - -static TestResult test_Integer_Default_Invalid_Underscore_Double() { - LexerTest test = start_up_test("test_Integer_Default_Invalid_Underscore_Double", "4__2"); - LexerResult result = lexical_analysis(&test.lexer_info); - if (result.type == SLS_ERROR) return error_fail_test(&test, result, result.error); - size_t i = 0; - if (test_for_error(&test, result, i++, &(TestErrorMessage){62, "Invalid numeric literal: consecutive underscores not allowed."})) return test.result; + if (test_integer_value(&test, result, i++, &(TestIntegerValue){INTEGER_I64, 42})) return test.result; + if (test_eof_value(&test, result, i++, 0)) return test.result; return pass_test(&test, result); } @@ -240,8 +223,7 @@ TestsReport run_lexer_tests() { test_report.tests[i++] = test_Empty_Statement(); test_report.tests[i++] = test_Integer_Default_Decimal_0(); - test_report.tests[i++] = test_Integer_Default_Decimal_1_neg(); - test_report.tests[i++] = test_Integer_Default_Decimal_1_pos(); + test_report.tests[i++] = test_Integer_Default_Decimal_1(); test_report.tests[i++] = test_Integer_Default_Decimal_Leading_Zeros(); test_report.tests[i++] = test_Integer_Default_Hex_0xFF(); test_report.tests[i++] = test_Integer_Default_Hex_0xdeadbeef(); @@ -257,9 +239,8 @@ TestsReport run_lexer_tests() { test_report.tests[i++] = test_Integer_Default_Invalid_Characters(); test_report.tests[i++] = test_Integer_Default_Whitespace(); test_report.tests[i++] = test_Integer_Default_Invalid_Prefix(); - test_report.tests[i++] = test_Integer_Default_Invalid_Underscore_Start(); - test_report.tests[i++] = test_Integer_Default_Invalid_Underscore_End(); - test_report.tests[i++] = test_Integer_Default_Invalid_Underscore_Double(); + test_report.tests[i++] = test_Integer_Default_Underscore_End(); + test_report.tests[i++] = test_Integer_Default_Underscore_Double(); return test_report; } diff --git a/SLS_C/tests/tests.c b/SLS_C/tests/tests.c index fe962da..1962e78 100644 --- a/SLS_C/tests/tests.c +++ b/SLS_C/tests/tests.c @@ -11,43 +11,94 @@ const char *TEST_FILE_NAME = "TEST_FILE.SLS"; -int main(void) { - TestsReport lexer_reports = run_lexer_tests(); +typedef struct { + uint16_t errored; + uint16_t error_failed; + uint16_t logic_error_failed; + uint16_t logic_failed; + uint16_t passed; + uint16_t not_implemented; + uint16_t total; +} TestCounts; - for (size_t i = 0; i < lexer_reports.count; i++) { - switch (lexer_reports.tests[i].status) { +static void lexer_test_report(TestsReport reports, TestCounts *counts) { + counts->total += reports.count; + for (size_t i = 0; i < reports.count; i++) { + switch (reports.tests[i].status) { case TEST_ERROR: // Bright Red - printf("\x1b[91mTest errored: %s\n\t%s\n\x1b[0m", lexer_reports.tests[i].name, lexer_reports.tests[i].error.message); + printf("\x1b[91mTest errored: %s\n\t%s\n\x1b[0m", reports.tests[i].name, reports.tests[i].error.message); + counts->errored += 1; break; case TEST_ERROR_FAIL: // Magenta - printf("\x1b[35mLexing errored: %s\n\t%s\n\x1b[0m", lexer_reports.tests[i].name, lexer_reports.tests[i].error.message); + printf("\x1b[35mLexing errored: %s\n\t%s\n\x1b[0m", reports.tests[i].name, reports.tests[i].error.message); + counts->error_failed += 1; break; case TEST_LOGIC_ERROR_FAIL: // Red - printf("\x1b[31mTest failed with error: %s\n\t%s\n\x1b[0m", lexer_reports.tests[i].name, lexer_reports.tests[i].error.message); - free(lexer_reports.tests[i].message); + printf("\x1b[31mTest failed with lexical error: %s\n\t%s\n\x1b[0m", reports.tests[i].name, reports.tests[i].error.message); + counts->logic_error_failed += 1; + free(reports.tests[i].message); break; case TEST_LOGIC_FAIL: // Red - printf("\x1b[31mTest failed: %s\n\t%s\n\x1b[0m", lexer_reports.tests[i].name, lexer_reports.tests[i].message); - free(lexer_reports.tests[i].message); + printf("\x1b[31mTest failed: %s\n\t%s\n\x1b[0m", reports.tests[i].name, reports.tests[i].message); + counts->logic_failed += 1; + free(reports.tests[i].message); break; case TEST_PASS: // Green - printf("\x1b[32mTest passed: %s\n\x1b[0m", lexer_reports.tests[i].name); + printf("\x1b[32mTest passed: %s\n\x1b[0m", reports.tests[i].name); + counts->passed += 1; break; case TEST_NOT_IMPLEMENTED: // Blue - printf("\x1b[34mTest not implemented: %s\n\x1b[0m", lexer_reports.tests[i].name); + printf("\x1b[34mTest not implemented: %s\n\x1b[0m", reports.tests[i].name); + counts->not_implemented += 1; break; default: // Bright Red - printf("\x1b[91mTest errored: %s\n\tUnknown test result status.\n\x1b[0m", lexer_reports.tests[i].name); + printf("\x1b[91mTest errored: %s\n\tUnknown test result status.\n\x1b[0m", reports.tests[i].name); + counts->errored += 1; break; } } +} + +int main(void) { + TestCounts counts = { + .errored = 0, + .error_failed = 0, + .logic_error_failed = 0, + .logic_failed = 0, + .passed = 0, + .not_implemented = 0, + .total = 0, + }; + + TestsReport lexer_reports = run_lexer_tests(); + lexer_test_report(lexer_reports, &counts); + + printf(" ===== Tests Overview =====\n"); + if (counts.errored > 0) + // Bright Red + printf("\x1b[91m%d of %d tests encountered an error.\n\x1b[0m", counts.errored, counts.total); + if (counts.error_failed > 0) + // Magenta + printf("\x1b[35m%d of %d tests failed because of an interpreter error.\n\x1b[0m", counts.error_failed, counts.total); + if (counts.logic_error_failed > 0) + // Red + printf("\x1b[31m%d of %d tests failed because of a lexical, parsing, or runtime error.\n\x1b[0m", counts.logic_error_failed, counts.total); + if (counts.logic_failed > 0) + // Red + printf("\x1b[31m%d of %d tests failed because of a logical error.\n\x1b[0m", counts.logic_failed, counts.total); + if (counts.passed > 0) + // Green + printf("\x1b[32m%d of %d tests passed.\n\x1b[0m", counts.passed, counts.total); + if (counts.not_implemented > 0) + // Blue + printf("\x1b[34m%d of %d tests are not implemented.\n\x1b[0m", counts.not_implemented, counts.total); return 0; } diff --git a/SLS_Tests/cases.yaml b/SLS_Tests/cases.yaml index efa7023..f8a0f30 100644 --- a/SLS_Tests/cases.yaml +++ b/SLS_Tests/cases.yaml @@ -41,7 +41,7 @@ - type: i64 value: 0 -- name: Integer Default Decimal -1 neg +- name: Integer Default Decimal -1 code: "-1" tokens: - type: i64 @@ -54,19 +54,6 @@ - type: i64 value: -1 -- name: Integer Default Decimal +1 pos - code: "+1" - tokens: - - type: i64 - value: 1 - operations: - - function: push - type: i64 - value: 1 - stack_final: - - type: i64 - value: 1 - - name: Integer Default Decimal Leading Zeros code: "00042" tokens: @@ -133,7 +120,7 @@ value: 493 - name: Integer i8 Decimal 127 - code: "127i8" + code: "127:i8" tokens: - type: i8 value: 127 @@ -146,7 +133,7 @@ value: 127 - name: Integer i8 Decimal -128 - code: "-128i8" + code: "-128:i8" tokens: - type: i8 value: -128 @@ -159,7 +146,7 @@ value: -128 - name: Integer u8 Decimal 255 - code: "255u8" + code: "255:u8" tokens: - type: u8 value: 255 @@ -188,15 +175,15 @@ code: "1,000,000" tokens: - type: error - value: "Invalid numeric literal: unexpected ',' in integer." + value: "Invalid decimal literal: unexpected ',' in decimal integer." - name: Integer i8 Overflow - code: "128i8" + code: "128:i8" runtime_error: message: "Integer overflow: 128 exceeds range for i8." - name: Integer i8 Underflow - code: "-129i8" + code: "-129:i8" runtime_error: message: "Integer underflow: -129 exceeds range for i8." @@ -204,7 +191,7 @@ code: "12a3" tokens: - type: error - value: "Invalid numeric literal: unexpected character 'a'." + value: "Invalid decimal literal: unexpected 'a' in decimal integer." - name: Integer Default Whitespace code: " 42 " @@ -223,25 +210,33 @@ code: "0b2" tokens: - type: error - value: "Invalid binary literal: digit '2' not allowed." + value: "Invalid binary literal: unexpected '2' in binary integer." -- name: Integer Default Invalid Underscore Start - code: "_42" - tokens: - - type: error - value: "Invalid numeric literal: cannot start with underscore." - -- name: Integer Default Invalid Underscore End +- name: Integer Default Underscore End code: "42_" tokens: - - type: error - value: "Invalid numeric literal: cannot end with underscore." + - type: i64 + value: 42 + operations: + - function: push + type: i64 + value: 42 + stack_final: + - type: i64 + value: 42 -- name: Integer Default Invalid Underscore Double +- name: Integer Default Underscore Double code: "4__2" tokens: - - type: error - value: "Invalid numeric literal: consecutive underscores not allowed." + - type: i64 + value: 42 + operations: + - function: push + type: i64 + value: 42 + stack_final: + - type: i64 + value: 42 # Basic Floats # Basic Strings