diff options
Diffstat (limited to 'tests')
-rw-r--r-- | tests/errors/closure_no_lhs.amal | 1 | ||||
-rw-r--r-- | tests/errors/duplicate_declaration.amal | 2 | ||||
-rw-r--r-- | tests/errors/pub_in_closure.amal | 3 | ||||
-rw-r--r-- | tests/main.amal | 3 | ||||
-rw-r--r-- | tests/main.c | 127 |
5 files changed, 128 insertions, 8 deletions
diff --git a/tests/errors/closure_no_lhs.amal b/tests/errors/closure_no_lhs.amal new file mode 100644 index 0000000..d903c3c --- /dev/null +++ b/tests/errors/closure_no_lhs.amal @@ -0,0 +1 @@ +fn {}
\ No newline at end of file diff --git a/tests/errors/duplicate_declaration.amal b/tests/errors/duplicate_declaration.amal new file mode 100644 index 0000000..a97b507 --- /dev/null +++ b/tests/errors/duplicate_declaration.amal @@ -0,0 +1,2 @@ +const main = fn {} +const main = fn {}
\ No newline at end of file diff --git a/tests/errors/pub_in_closure.amal b/tests/errors/pub_in_closure.amal new file mode 100644 index 0000000..881bbd4 --- /dev/null +++ b/tests/errors/pub_in_closure.amal @@ -0,0 +1,3 @@ +const main = fn { + pub const num = 45; +}
\ No newline at end of file diff --git a/tests/main.amal b/tests/main.amal index f778a14..ae37816 100644 --- a/tests/main.amal +++ b/tests/main.amal @@ -10,15 +10,12 @@ const main = fn { } const value = "hello"; - // fn {} // error, function declaration can't be by itself. Needs left-hand side print(value, "world", 356, 13.37); var num1: i64; const num2 = 23232; const num3 = num1 + num2 * 30; //const num4 = (num1 + num2) * num3 * ((34 + 32) / 234.345); const num4 = (num1 + num2) * num3 * ((34 + 32) / 2); - // pub cost num34 = 45; // error, only declarations in global scope can be public - //const num4 = 23; // error, variable redeclaration /* episfjpseifipesf */ diff --git a/tests/main.c b/tests/main.c index 0dfd878..bc2fbb1 100644 --- a/tests/main.c +++ b/tests/main.c @@ -5,6 +5,7 @@ #include "../include/std/hash.h" #include <stdio.h> #include <stdlib.h> +#include <unistd.h> #define REQUIRE_EQ_INT(expected, actual) do{\ if((expected) != (actual)) {\ @@ -41,25 +42,141 @@ static CHECK_RESULT int test_hash_map() { return 0; } -/* TODO: Restrict variables in global scope to const */ -int main() { +#define FAIL_TEST(name) do { fprintf(stderr, "Test failed: %s\n", (name)); exit(1); } while(0) + +typedef struct { + char *filepath; + char *expected_error; + bool got_expected_error; +} ErrorExpectedData; + +static void error_callback_assert(const char *err_msg, int err_msg_len, void *userdata) { + ErrorExpectedData *expected_data; + expected_data = userdata; + int expected_err_msg_len; + expected_err_msg_len = strlen(expected_data->expected_error); + + if(expected_data->got_expected_error) { + fprintf(stderr, "We got the error we expected but also got additional error:\n%.*s\n", err_msg_len, err_msg); + FAIL_TEST(expected_data->filepath); + } + + if(err_msg_len != expected_err_msg_len || strncmp(err_msg, expected_data->expected_error, expected_err_msg_len) != 0) { + fprintf(stderr, "Expected error message:\n%.*s\n", expected_err_msg_len, expected_data->expected_error); + fprintf(stderr, "Actual error message:\n%.*s\n", err_msg_len, err_msg); + fprintf(stderr, "a: %d, b: %d\n", expected_err_msg_len, err_msg_len); + FAIL_TEST(expected_data->filepath); + } + + expected_data->got_expected_error = bool_true; +} + +static char* get_full_path(const char *filepath) { + #define PATH_LEN 4096 + char *buf; + int len; + int filepath_len; + + buf = malloc(PATH_LEN); + buf[PATH_LEN - 1] = '\0'; + getcwd(buf, PATH_LEN); + + len = strlen(buf); + filepath_len = strlen(filepath); + + buf[len++] = '/'; + memcpy(buf + len, filepath, filepath_len); + buf[len + filepath_len] = '\0'; + return buf; +} + +static char* join_str(const char *str1, const char *str2, char delimiter) { + char *buf; + int len1; + int len2; + + len1 = strlen(str1); + len2 = strlen(str2); + buf = malloc(len1 + 1 + len2 + 1); + + memcpy(buf, str1, len1); + buf[len1] = delimiter; + memcpy(buf + len1 + 1, str2, len2); + buf[len1 + 1 + len2] = '\0'; + return buf; +} + +static void test_load_error(const char *filepath, const char *expected_error) { amal_compiler compiler; - FileScopeReference *file_scope; + amal_compiler_options options; int result; + amal_compiler_options_init(&options); + options.error_callback = error_callback_assert; + ErrorExpectedData expected_data; + expected_data.filepath = get_full_path(filepath); + expected_data.expected_error = join_str(expected_data.filepath, expected_error, ':'); + expected_data.got_expected_error = bool_false; + options.error_callback_userdata = &expected_data; + + result = amal_compiler_init(&compiler, &options); + if(result != AMAL_COMPILER_OK) { + fprintf(stderr, "Failed to initialize compiler, error code: %d\n", result); + FAIL_TEST(expected_data.filepath); + } + + result = amal_compiler_load_file(&compiler, filepath); + if(result == AMAL_COMPILER_OK) { + fprintf(stderr, "Expected to fail loading file\n"); + FAIL_TEST(expected_data.filepath); + } + + if(amal_compiler_deinit(&compiler) != 0) { + fprintf(stderr, "Failed to deinitialize compiler.\n"); + FAIL_TEST(expected_data.filepath); + } + + if(!expected_data.got_expected_error) { + fprintf(stderr, "Didn't get expected error message:\n%s\n", expected_error); + FAIL_TEST(expected_data.filepath); + } + free(expected_data.filepath); + free(expected_data.expected_error); +} + +/* TODO: Restrict variables in global scope to const */ +int main() { + /*amal_compiler compiler; + int result;*/ + return_if_error(test_hash_map()); - result = amal_compiler_init(&compiler); + /* + result = amal_compiler_init(&compiler, NULL); if(result != AMAL_COMPILER_OK) { fprintf(stderr, "Failed to initialize compiler, error code: %d\n", result); return 1; } - result = amal_compiler_load_file(&compiler, "tests/main.amal", &file_scope); + result = amal_compiler_load_file(&compiler, "tests/main.amal"); if(result != AMAL_COMPILER_OK) { fprintf(stderr, "Failed to load file, error code: %d\n", result); return 1; } return amal_compiler_deinit(&compiler); + */ + test_load_error("tests/errors/duplicate_declaration.amal", + "2:7: error: Variable with the name main was declared twice in the same scope\n" + "const main = fn {}\n" + " ^\n"); + test_load_error("tests/errors/pub_in_closure.amal", + "2:5: error: Only declarations in structs can be public\n" + " pub const num = 45;\n" + " ^\n"); + test_load_error("tests/errors/closure_no_lhs.amal", + "1:1: error: Expected variable declaration, string, variable or function call\n" + "fn {}\n" + "^\n"); + return 0; } |