diff --git a/.gitignore b/.gitignore index bd3a3a7..3cc2666 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,7 @@ !/exl !/include !/src +!/tests # Files !/.clang-format diff --git a/CMakeLists.txt b/CMakeLists.txt index f5a00e5..0ec798a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -35,108 +35,27 @@ add_executable(fz src/vm/main.c) # -# ========== Compilation tests ========== +# ========== Tests ========== # enable_testing() -add_test( - NAME compile_hw - COMMAND fzc -o "${CMAKE_CURRENT_BINARY_DIR}/hw.fzb" "${CMAKE_CURRENT_SOURCE_DIR}/exl/hw.fzs" -) -add_test( - NAME compile_print_empty - COMMAND fzc -o "${CMAKE_CURRENT_BINARY_DIR}/print_empty.fzb" "${CMAKE_CURRENT_SOURCE_DIR}/exl/print_empty.fzs" -) -add_test( - NAME compile_problematic_hw - COMMAND fzc -o "${CMAKE_CURRENT_BINARY_DIR}/problematic_hw.fzb" "${CMAKE_CURRENT_SOURCE_DIR}/exl/problematic_hw.fzs" -) -add_test( - NAME compile_base_math - COMMAND fzc -o "${CMAKE_CURRENT_BINARY_DIR}/base_math.fzb" "${CMAKE_CURRENT_SOURCE_DIR}/exl/base_math.fzs" -) -add_test( - NAME compile_variables - COMMAND fzc -o "${CMAKE_CURRENT_BINARY_DIR}/variables.fzb" "${CMAKE_CURRENT_SOURCE_DIR}/exl/variables.fzs" -) -add_test( - NAME compile_conditions - COMMAND fzc -o "${CMAKE_CURRENT_BINARY_DIR}/conditions.fzb" "${CMAKE_CURRENT_SOURCE_DIR}/exl/conditions.fzs" -) -add_test( - NAME compile_fn - COMMAND fzc -o "${CMAKE_CURRENT_BINARY_DIR}/fn.fzb" "${CMAKE_CURRENT_SOURCE_DIR}/exl/fn.fzs" -) -add_test( - NAME compile_comment - COMMAND fzc -o "${CMAKE_CURRENT_BINARY_DIR}/comment.fzb" "${CMAKE_CURRENT_SOURCE_DIR}/exl/comment.fzs" -) -add_test( - NAME compile_class - COMMAND fzc -o "${CMAKE_CURRENT_BINARY_DIR}/class.fzb" "${CMAKE_CURRENT_SOURCE_DIR}/exl/class.fzs" -) -add_test( - NAME compile_raii - COMMAND fzc -o "${CMAKE_CURRENT_BINARY_DIR}/raii.fzb" "${CMAKE_CURRENT_SOURCE_DIR}/exl/raii.fzs" -) -add_test( - NAME compile_borrow - COMMAND fzc -o "${CMAKE_CURRENT_BINARY_DIR}/borrow.fzb" "${CMAKE_CURRENT_SOURCE_DIR}/exl/borrow.fzs" -) -add_test( - NAME compile_hard_1 - COMMAND fzc -o "${CMAKE_CURRENT_BINARY_DIR}/hard-1.fzb" "${CMAKE_CURRENT_SOURCE_DIR}/exl/hard-1.fzs" -) +file(GLOB TEST_PROGS RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "tests/programs/*.fzs") +foreach (TEST_FILE IN LISTS TEST_PROGS) + get_filename_component(TEST_NAME "${TEST_FILE}" NAME_WE) + + add_test( + NAME "progs_compile_${TEST_NAME}" + COMMAND fzc -o "p_${CMAKE_CURRENT_BINARY_DIR}/${TEST_NAME}.fzb" "${CMAKE_CURRENT_SOURCE_DIR}/${TEST_FILE}" + ) + add_test( + NAME "progs_runtime_${TEST_NAME}" + COMMAND fz "${CMAKE_CURRENT_BINARY_DIR}/p_${TEST_NAME}.fzb" + ) -set_tests_properties(compile_problematic_hw PROPERTIES WILL_FAIL TRUE) - -# -# ========== Runtime tests ========== -# - -add_test( - NAME runtime_hw - COMMAND fz "${CMAKE_CURRENT_BINARY_DIR}/hw.fzb" -) -add_test( - NAME runtime_print_empty - COMMAND fz "${CMAKE_CURRENT_BINARY_DIR}/print_empty.fzb" -) -add_test( - NAME runtime_base_math - COMMAND fz "${CMAKE_CURRENT_BINARY_DIR}/base_math.fzb" -) -add_test( - NAME runtime_variables - COMMAND fz "${CMAKE_CURRENT_BINARY_DIR}/variables.fzb" -) -add_test( - NAME runtime_conditions - COMMAND fz "${CMAKE_CURRENT_BINARY_DIR}/conditions.fzb" -) -add_test( - NAME runtime_fn - COMMAND fz "${CMAKE_CURRENT_BINARY_DIR}/fn.fzb" -) -add_test( - NAME runtime_comment - COMMAND fz "${CMAKE_CURRENT_BINARY_DIR}/comment.fzb" -) -add_test( - NAME runtime_class - COMMAND fz "${CMAKE_CURRENT_BINARY_DIR}/class.fzb" -) -add_test( - NAME runtime_raii - COMMAND fz "${CMAKE_CURRENT_BINARY_DIR}/raii.fzb" -) -add_test( - NAME runtime_borrow - COMMAND fz "${CMAKE_CURRENT_BINARY_DIR}/borrow.fzb" -) -add_test( - NAME runtime_hard_1 - COMMAND fz "${CMAKE_CURRENT_BINARY_DIR}/hard-1.fzb" -) + if (TEST_NAME MATCHES "neg_") + set_tests_properties("progs_compile_${TEST_NAME}" PROPERTIES WILL_FAIL TRUE) + set_tests_properties("progs_runtime_${TEST_NAME}" PROPERTIES WILL_FAIL TRUE) + endif() +endforeach() diff --git a/tests/programs/neg_missing_operand.fzs b/tests/programs/neg_missing_operand.fzs new file mode 100644 index 0000000..5279332 --- /dev/null +++ b/tests/programs/neg_missing_operand.fzs @@ -0,0 +1,2 @@ +printline(1 + ); + diff --git a/tests/programs/neg_missing_semicolon.fzs b/tests/programs/neg_missing_semicolon.fzs new file mode 100644 index 0000000..3f84aae --- /dev/null +++ b/tests/programs/neg_missing_semicolon.fzs @@ -0,0 +1,3 @@ +int value = 42 +printline(value); + diff --git a/tests/programs/neg_unclosed_block.fzs b/tests/programs/neg_unclosed_block.fzs new file mode 100644 index 0000000..61a5439 --- /dev/null +++ b/tests/programs/neg_unclosed_block.fzs @@ -0,0 +1,4 @@ +if (true) +{ + printline("missing closing brace"); + diff --git a/tests/programs/neg_unterminated_string.fzs b/tests/programs/neg_unterminated_string.fzs new file mode 100644 index 0000000..9bcfd80 --- /dev/null +++ b/tests/programs/neg_unterminated_string.fzs @@ -0,0 +1,2 @@ +printline("unterminated string); + diff --git a/tests/programs/pos_arithmetic.fzs b/tests/programs/pos_arithmetic.fzs new file mode 100644 index 0000000..ed1907e --- /dev/null +++ b/tests/programs/pos_arithmetic.fzs @@ -0,0 +1,7 @@ +// Arithmetic precedence and operators. +printline(2 + 2 * 2); +printline(-1 + 1); +printline(2 ^ 2); +printline(4 % 2); +printline(10 / 2); + diff --git a/tests/programs/pos_class.fzs b/tests/programs/pos_class.fzs new file mode 100644 index 0000000..5e01704 --- /dev/null +++ b/tests/programs/pos_class.fzs @@ -0,0 +1,25 @@ +class Point +{ + int x; + int y; + + fn move(int dx, int dy) + { + this.x = this.x + dx; + this.y = this.y + dy; + } +} + +Point point = new Point; +point.x = 1; +point.y = 2; +point.move(9, 8); + +if (point.x == 10 && point.y == 10) + printline("class method passed"); +else +{ + printline("class method failed"); + exit(1); +} + diff --git a/tests/programs/pos_comments_strings.fzs b/tests/programs/pos_comments_strings.fzs new file mode 100644 index 0000000..7c12831 --- /dev/null +++ b/tests/programs/pos_comments_strings.fzs @@ -0,0 +1,5 @@ +// Line comments are ignored by the parser. +printline('single-quoted string');;;;; +printline(""); +printline("double-quoted string"); + diff --git a/tests/programs/pos_conditions.fzs b/tests/programs/pos_conditions.fzs new file mode 100644 index 0000000..981b441 --- /dev/null +++ b/tests/programs/pos_conditions.fzs @@ -0,0 +1,21 @@ +bool flag = true; + +if (!flag) +{ + printline("unexpected false"); + exit(1); +} +else if (2 + 2 >= 4) +{ + printline("condition passed"); +} +else +{ + printline("unexpected branch"); + exit(1); +} + +{ + printline("standalone block"); +} + diff --git a/tests/programs/pos_functions.fzs b/tests/programs/pos_functions.fzs new file mode 100644 index 0000000..7ec5cdb --- /dev/null +++ b/tests/programs/pos_functions.fzs @@ -0,0 +1,21 @@ +fn fib(int n) int +{ + if (n <= 1) + return n; + + return fib(n - 1) + fib(n - 2); +} + +fn sum(uint a, uint b) uint +{ + return a + b; +} + +if (fib(7) == 13 && sum(2, 2) == 4) + printline("functions passed"); +else +{ + printline("functions failed"); + exit(1); +} + diff --git a/tests/programs/pos_null.fzs b/tests/programs/pos_null.fzs new file mode 100644 index 0000000..877bdb2 --- /dev/null +++ b/tests/programs/pos_null.fzs @@ -0,0 +1,23 @@ +class Item +{ + int value; +} + +fn maybe_item(bool create) Item +{ + if (create) + return new Item; + + return null; +} + +Item empty = maybe_item(false); +Item present = maybe_item(true); +if (empty == null && present != null) + printline("null handling passed"); +else +{ + printline("null handling failed"); + exit(1); +} + diff --git a/tests/programs/pos_variables.fzs b/tests/programs/pos_variables.fzs new file mode 100644 index 0000000..b9d3277 --- /dev/null +++ b/tests/programs/pos_variables.fzs @@ -0,0 +1,13 @@ +uint work_it = 21 * 2 ^ 2; +int make_it = 10; +u64 do_it; +do_it = 15; +char make_us; +str floyd = "hello, Pink Floyd!"; +bool flag = true; + +printline(work_it); +printline(make_it + do_it); +printline(floyd); +printline(flag); +