Worked on tests

This commit is contained in:
Kyler Olsen 2025-11-06 00:54:52 -07:00
parent 6aad733263
commit 389890a7e7
5 changed files with 131 additions and 95 deletions

View File

@ -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)

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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