summaryrefslogtreecommitdiffhomepage
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/CMakeLists.txt6
-rw-r--r--tests/cram/CMakeLists.txt27
-rw-r--r--tests/cram/test_basic.t59
-rw-r--r--tests/custom/00_syntax/00_single_line_comments (renamed from tests/00_syntax/00_single_line_comments)0
-rw-r--r--tests/custom/00_syntax/01_unterminated_comment (renamed from tests/00_syntax/01_unterminated_comment)0
-rw-r--r--tests/custom/00_syntax/02_multi_line_comments (renamed from tests/00_syntax/02_multi_line_comments)0
-rw-r--r--tests/custom/00_syntax/03_expression_blocks (renamed from tests/00_syntax/03_expression_blocks)0
-rw-r--r--tests/custom/00_syntax/04_statement_blocks (renamed from tests/00_syntax/04_statement_blocks)0
-rw-r--r--tests/custom/00_syntax/05_block_nesting (renamed from tests/00_syntax/05_block_nesting)0
-rw-r--r--tests/custom/00_syntax/06_open_statement_block (renamed from tests/00_syntax/06_open_statement_block)0
-rw-r--r--tests/custom/00_syntax/07_embedded_single_line_comments (renamed from tests/00_syntax/07_embedded_single_line_comments)0
-rw-r--r--tests/custom/00_syntax/08_embedded_multi_line_comments (renamed from tests/00_syntax/08_embedded_multi_line_comments)0
-rw-r--r--tests/custom/00_syntax/09_string_literals (renamed from tests/00_syntax/09_string_literals)0
-rw-r--r--tests/custom/00_syntax/10_numeric_literals (renamed from tests/00_syntax/10_numeric_literals)0
-rw-r--r--tests/custom/00_syntax/11_misc_literals (renamed from tests/00_syntax/11_misc_literals)0
-rw-r--r--tests/custom/00_syntax/12_block_whitespace_control (renamed from tests/00_syntax/12_block_whitespace_control)0
-rw-r--r--tests/custom/00_syntax/13_object_literals (renamed from tests/00_syntax/13_object_literals)0
-rw-r--r--tests/custom/00_syntax/14_array_literals (renamed from tests/00_syntax/14_array_literals)0
-rw-r--r--tests/custom/00_syntax/15_function_declarations (renamed from tests/00_syntax/15_function_declarations)0
-rw-r--r--tests/custom/00_syntax/16_for_loop (renamed from tests/00_syntax/16_for_loop)0
-rw-r--r--tests/custom/00_syntax/17_while_loop (renamed from tests/00_syntax/17_while_loop)0
-rw-r--r--tests/custom/00_syntax/18_if_condition (renamed from tests/00_syntax/18_if_condition)0
-rw-r--r--tests/custom/00_syntax/19_arrow_functions (renamed from tests/00_syntax/19_arrow_functions)0
-rw-r--r--tests/custom/00_syntax/20_list_expressions (renamed from tests/00_syntax/20_list_expressions)0
-rw-r--r--tests/custom/00_syntax/21_regex_literals (renamed from tests/00_syntax/21_regex_literals)2
-rw-r--r--tests/custom/01_arithmetic/00_value_conversion (renamed from tests/01_arithmetic/00_value_conversion)0
-rw-r--r--tests/custom/01_arithmetic/01_division (renamed from tests/01_arithmetic/01_division)0
-rw-r--r--tests/custom/01_arithmetic/02_modulo (renamed from tests/01_arithmetic/02_modulo)0
-rw-r--r--tests/custom/01_arithmetic/03_bitwise (renamed from tests/01_arithmetic/03_bitwise)0
-rw-r--r--tests/custom/01_arithmetic/04_inc_dec (renamed from tests/01_arithmetic/04_inc_dec)0
-rw-r--r--tests/custom/02_runtime/00_scoping (renamed from tests/02_runtime/00_scoping)0
-rw-r--r--tests/custom/02_runtime/01_break_continue (renamed from tests/02_runtime/01_break_continue)0
-rw-r--r--tests/custom/02_runtime/02_this (renamed from tests/02_runtime/02_this)0
-rw-r--r--tests/custom/02_runtime/03_try_catch (renamed from tests/02_runtime/03_try_catch)0
-rw-r--r--tests/custom/02_runtime/04_switch_case (renamed from tests/02_runtime/04_switch_case)0
-rw-r--r--tests/custom/02_runtime/05_closure_scope (renamed from tests/02_runtime/05_closure_scope)0
-rw-r--r--tests/custom/02_runtime/06_recursion (renamed from tests/02_runtime/06_recursion)0
-rw-r--r--tests/custom/03_bugs/01_try_catch_stack_mismatch (renamed from tests/03_bugs/01_try_catch_stack_mismatch)0
-rw-r--r--tests/custom/03_bugs/02_array_pop_use_after_free (renamed from tests/03_bugs/02_array_pop_use_after_free)0
-rw-r--r--tests/custom/03_bugs/03_switch_fallthrough_miscompilation (renamed from tests/03_bugs/03_switch_fallthrough_miscompilation)0
-rw-r--r--tests/custom/03_bugs/04_property_set_abort (renamed from tests/03_bugs/04_property_set_abort)0
-rw-r--r--tests/custom/03_bugs/05_duplicate_ressource_type (renamed from tests/03_bugs/05_duplicate_ressource_type)0
-rw-r--r--tests/custom/03_bugs/06_lexer_escape_at_boundary (renamed from tests/03_bugs/06_lexer_escape_at_boundary)0
-rw-r--r--tests/custom/03_bugs/07_lexer_overlong_lines (renamed from tests/03_bugs/07_lexer_overlong_lines)0
-rw-r--r--tests/custom/03_bugs/08_compiler_arrow_fn_expressions (renamed from tests/03_bugs/08_compiler_arrow_fn_expressions)0
-rw-r--r--tests/custom/03_bugs/09_reject_invalid_array_indexes (renamed from tests/03_bugs/09_reject_invalid_array_indexes)0
-rw-r--r--tests/custom/03_bugs/10_break_stack_mismatch (renamed from tests/03_bugs/10_break_stack_mismatch)0
-rw-r--r--tests/custom/03_bugs/11_switch_stack_mismatch (renamed from tests/03_bugs/11_switch_stack_mismatch)0
-rw-r--r--tests/custom/03_bugs/12_altblock_stack_mismatch (renamed from tests/03_bugs/12_altblock_stack_mismatch)0
-rw-r--r--tests/custom/CMakeLists.txt22
-rwxr-xr-xtests/custom/run_tests.sh187
-rw-r--r--tests/fuzz/CMakeLists.txt16
-rw-r--r--tests/fuzz/corpus/.keep0
-rw-r--r--tests/fuzz/test-fuzz.c9
54 files changed, 327 insertions, 1 deletions
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
new file mode 100644
index 0000000..aed0100
--- /dev/null
+++ b/tests/CMakeLists.txt
@@ -0,0 +1,6 @@
+ADD_SUBDIRECTORY(cram)
+ADD_SUBDIRECTORY(custom)
+
+IF(CMAKE_C_COMPILER_ID STREQUAL "Clang")
+ ADD_SUBDIRECTORY(fuzz)
+ENDIF()
diff --git a/tests/cram/CMakeLists.txt b/tests/cram/CMakeLists.txt
new file mode 100644
index 0000000..a93add5
--- /dev/null
+++ b/tests/cram/CMakeLists.txt
@@ -0,0 +1,27 @@
+FIND_PACKAGE(PythonInterp 3 REQUIRED)
+FILE(GLOB test_cases "test_*.t")
+
+SET(PYTHON_VENV_DIR "${CMAKE_CURRENT_BINARY_DIR}/.venv")
+SET(PYTHON_VENV_PIP "${PYTHON_VENV_DIR}/bin/pip")
+SET(PYTHON_VENV_CRAM "${PYTHON_VENV_DIR}/bin/cram")
+
+ADD_CUSTOM_COMMAND(
+ OUTPUT ${PYTHON_VENV_CRAM}
+ COMMAND ${PYTHON_EXECUTABLE} -m venv ${PYTHON_VENV_DIR}
+ COMMAND ${PYTHON_VENV_PIP} install cram
+)
+ADD_CUSTOM_TARGET(prepare-cram-venv ALL DEPENDS ${PYTHON_VENV_CRAM})
+
+ADD_TEST(
+ NAME cram
+ COMMAND ${PYTHON_VENV_CRAM} ${test_cases} ${test_cases_san}
+ WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
+)
+
+SET_PROPERTY(TEST cram APPEND PROPERTY ENVIRONMENT "BUILD_BIN_DIR=$<TARGET_FILE_DIR:ucode>")
+
+IF(CMAKE_C_COMPILER_ID STREQUAL "Clang")
+ SET_PROPERTY(TEST cram APPEND PROPERTY ENVIRONMENT "UCODE_BIN=$<TARGET_FILE:ucode-san>")
+ELSE()
+ SET_PROPERTY(TEST cram APPEND PROPERTY ENVIRONMENT "UCODE_BIN=valgrind --quiet --leak-check=full $<TARGET_FILE:ucode>")
+ENDIF()
diff --git a/tests/cram/test_basic.t b/tests/cram/test_basic.t
new file mode 100644
index 0000000..3d4cd9e
--- /dev/null
+++ b/tests/cram/test_basic.t
@@ -0,0 +1,59 @@
+setup common environment:
+
+ $ [ -n "$BUILD_BIN_DIR" ] && export PATH="$BUILD_BIN_DIR:$PATH"
+ $ alias ucode="$UCODE_BIN"
+
+ $ for m in $BUILD_BIN_DIR/*.so; do
+ > ln -s "$m" "$(pwd)/$(basename $m)"; \
+ > done
+
+check that ucode provides exepected help:
+
+ $ ucode | sed 's/ucode-san/ucode/'
+ == Usage ==
+
+ # ucode [-d] [-l] [-r] [-S] [-e '[prefix=]{"var": ...}'] [-E [prefix=]env.json] {-i <file> | -s "ucode script..."}
+ -h, --help\tPrint this help (esc)
+ -i file\tSpecify an ucode script to parse (esc)
+ -s "ucode script..."\tSpecify an ucode fragment to parse (esc)
+ -d Instead of executing the script, dump the resulting AST as dot
+ -l Do not strip leading block whitespace
+ -r Do not trim trailing block newlines
+ -S Enable strict mode
+ -e Set global variables from given JSON object
+ -E Set global variables from given JSON file
+ -m Preload given module
+
+check that ucode prints greetings:
+
+ $ ucode -s "{% print('hello world') %}"
+ hello world (no-eol)
+
+check that ucode provides proper error messages:
+
+ $ ucode -m foo
+ One of -i or -s is required
+ [1]
+
+ $ ucode -m foo -s ' '
+ Runtime error: No module named 'foo' could be found
+ At start of program
+
+ [1]
+
+ $ touch moo; ucode -m foo -i moo
+ Runtime error: No module named 'foo' could be found
+ At start of program
+
+ [1]
+
+check that ucode can load fs module:
+
+ $ ucode -m fs
+ One of -i or -s is required
+ [1]
+
+ $ ucode -m fs -s ' '
+ (no-eol)
+
+ $ touch moo; ucode -m fs -i moo
diff --git a/tests/00_syntax/00_single_line_comments b/tests/custom/00_syntax/00_single_line_comments
index 24a32a2..24a32a2 100644
--- a/tests/00_syntax/00_single_line_comments
+++ b/tests/custom/00_syntax/00_single_line_comments
diff --git a/tests/00_syntax/01_unterminated_comment b/tests/custom/00_syntax/01_unterminated_comment
index 1d3669c..1d3669c 100644
--- a/tests/00_syntax/01_unterminated_comment
+++ b/tests/custom/00_syntax/01_unterminated_comment
diff --git a/tests/00_syntax/02_multi_line_comments b/tests/custom/00_syntax/02_multi_line_comments
index 99fc37e..99fc37e 100644
--- a/tests/00_syntax/02_multi_line_comments
+++ b/tests/custom/00_syntax/02_multi_line_comments
diff --git a/tests/00_syntax/03_expression_blocks b/tests/custom/00_syntax/03_expression_blocks
index 3568016..3568016 100644
--- a/tests/00_syntax/03_expression_blocks
+++ b/tests/custom/00_syntax/03_expression_blocks
diff --git a/tests/00_syntax/04_statement_blocks b/tests/custom/00_syntax/04_statement_blocks
index 920ed71..920ed71 100644
--- a/tests/00_syntax/04_statement_blocks
+++ b/tests/custom/00_syntax/04_statement_blocks
diff --git a/tests/00_syntax/05_block_nesting b/tests/custom/00_syntax/05_block_nesting
index fcfd7da..fcfd7da 100644
--- a/tests/00_syntax/05_block_nesting
+++ b/tests/custom/00_syntax/05_block_nesting
diff --git a/tests/00_syntax/06_open_statement_block b/tests/custom/00_syntax/06_open_statement_block
index 9c2d142..9c2d142 100644
--- a/tests/00_syntax/06_open_statement_block
+++ b/tests/custom/00_syntax/06_open_statement_block
diff --git a/tests/00_syntax/07_embedded_single_line_comments b/tests/custom/00_syntax/07_embedded_single_line_comments
index 43f188c..43f188c 100644
--- a/tests/00_syntax/07_embedded_single_line_comments
+++ b/tests/custom/00_syntax/07_embedded_single_line_comments
diff --git a/tests/00_syntax/08_embedded_multi_line_comments b/tests/custom/00_syntax/08_embedded_multi_line_comments
index 75aba5f..75aba5f 100644
--- a/tests/00_syntax/08_embedded_multi_line_comments
+++ b/tests/custom/00_syntax/08_embedded_multi_line_comments
diff --git a/tests/00_syntax/09_string_literals b/tests/custom/00_syntax/09_string_literals
index 0967850..0967850 100644
--- a/tests/00_syntax/09_string_literals
+++ b/tests/custom/00_syntax/09_string_literals
diff --git a/tests/00_syntax/10_numeric_literals b/tests/custom/00_syntax/10_numeric_literals
index 3e367d0..3e367d0 100644
--- a/tests/00_syntax/10_numeric_literals
+++ b/tests/custom/00_syntax/10_numeric_literals
diff --git a/tests/00_syntax/11_misc_literals b/tests/custom/00_syntax/11_misc_literals
index 372741c..372741c 100644
--- a/tests/00_syntax/11_misc_literals
+++ b/tests/custom/00_syntax/11_misc_literals
diff --git a/tests/00_syntax/12_block_whitespace_control b/tests/custom/00_syntax/12_block_whitespace_control
index 911171c..911171c 100644
--- a/tests/00_syntax/12_block_whitespace_control
+++ b/tests/custom/00_syntax/12_block_whitespace_control
diff --git a/tests/00_syntax/13_object_literals b/tests/custom/00_syntax/13_object_literals
index 18fbbed..18fbbed 100644
--- a/tests/00_syntax/13_object_literals
+++ b/tests/custom/00_syntax/13_object_literals
diff --git a/tests/00_syntax/14_array_literals b/tests/custom/00_syntax/14_array_literals
index 941ee4a..941ee4a 100644
--- a/tests/00_syntax/14_array_literals
+++ b/tests/custom/00_syntax/14_array_literals
diff --git a/tests/00_syntax/15_function_declarations b/tests/custom/00_syntax/15_function_declarations
index 4257dd6..4257dd6 100644
--- a/tests/00_syntax/15_function_declarations
+++ b/tests/custom/00_syntax/15_function_declarations
diff --git a/tests/00_syntax/16_for_loop b/tests/custom/00_syntax/16_for_loop
index 67edc21..67edc21 100644
--- a/tests/00_syntax/16_for_loop
+++ b/tests/custom/00_syntax/16_for_loop
diff --git a/tests/00_syntax/17_while_loop b/tests/custom/00_syntax/17_while_loop
index 1e68d6b..1e68d6b 100644
--- a/tests/00_syntax/17_while_loop
+++ b/tests/custom/00_syntax/17_while_loop
diff --git a/tests/00_syntax/18_if_condition b/tests/custom/00_syntax/18_if_condition
index 9e02767..9e02767 100644
--- a/tests/00_syntax/18_if_condition
+++ b/tests/custom/00_syntax/18_if_condition
diff --git a/tests/00_syntax/19_arrow_functions b/tests/custom/00_syntax/19_arrow_functions
index 102c527..102c527 100644
--- a/tests/00_syntax/19_arrow_functions
+++ b/tests/custom/00_syntax/19_arrow_functions
diff --git a/tests/00_syntax/20_list_expressions b/tests/custom/00_syntax/20_list_expressions
index d5ba459..d5ba459 100644
--- a/tests/00_syntax/20_list_expressions
+++ b/tests/custom/00_syntax/20_list_expressions
diff --git a/tests/00_syntax/21_regex_literals b/tests/custom/00_syntax/21_regex_literals
index 3af53bb..6d85e97 100644
--- a/tests/00_syntax/21_regex_literals
+++ b/tests/custom/00_syntax/21_regex_literals
@@ -23,7 +23,7 @@ regular expression engine.
Testing regular expression type.
-- Expect stdout --
-object
+regexp
-- End --
-- Testcase --
diff --git a/tests/01_arithmetic/00_value_conversion b/tests/custom/01_arithmetic/00_value_conversion
index c44ad00..c44ad00 100644
--- a/tests/01_arithmetic/00_value_conversion
+++ b/tests/custom/01_arithmetic/00_value_conversion
diff --git a/tests/01_arithmetic/01_division b/tests/custom/01_arithmetic/01_division
index d4a2adb..d4a2adb 100644
--- a/tests/01_arithmetic/01_division
+++ b/tests/custom/01_arithmetic/01_division
diff --git a/tests/01_arithmetic/02_modulo b/tests/custom/01_arithmetic/02_modulo
index 244d624..244d624 100644
--- a/tests/01_arithmetic/02_modulo
+++ b/tests/custom/01_arithmetic/02_modulo
diff --git a/tests/01_arithmetic/03_bitwise b/tests/custom/01_arithmetic/03_bitwise
index faf4ffd..faf4ffd 100644
--- a/tests/01_arithmetic/03_bitwise
+++ b/tests/custom/01_arithmetic/03_bitwise
diff --git a/tests/01_arithmetic/04_inc_dec b/tests/custom/01_arithmetic/04_inc_dec
index ae50ceb..ae50ceb 100644
--- a/tests/01_arithmetic/04_inc_dec
+++ b/tests/custom/01_arithmetic/04_inc_dec
diff --git a/tests/02_runtime/00_scoping b/tests/custom/02_runtime/00_scoping
index 5fadf43..5fadf43 100644
--- a/tests/02_runtime/00_scoping
+++ b/tests/custom/02_runtime/00_scoping
diff --git a/tests/02_runtime/01_break_continue b/tests/custom/02_runtime/01_break_continue
index a27d072..a27d072 100644
--- a/tests/02_runtime/01_break_continue
+++ b/tests/custom/02_runtime/01_break_continue
diff --git a/tests/02_runtime/02_this b/tests/custom/02_runtime/02_this
index d8e85d2..d8e85d2 100644
--- a/tests/02_runtime/02_this
+++ b/tests/custom/02_runtime/02_this
diff --git a/tests/02_runtime/03_try_catch b/tests/custom/02_runtime/03_try_catch
index 751ca1d..751ca1d 100644
--- a/tests/02_runtime/03_try_catch
+++ b/tests/custom/02_runtime/03_try_catch
diff --git a/tests/02_runtime/04_switch_case b/tests/custom/02_runtime/04_switch_case
index 4c1fc57..4c1fc57 100644
--- a/tests/02_runtime/04_switch_case
+++ b/tests/custom/02_runtime/04_switch_case
diff --git a/tests/02_runtime/05_closure_scope b/tests/custom/02_runtime/05_closure_scope
index c59a433..c59a433 100644
--- a/tests/02_runtime/05_closure_scope
+++ b/tests/custom/02_runtime/05_closure_scope
diff --git a/tests/02_runtime/06_recursion b/tests/custom/02_runtime/06_recursion
index 470fc3a..470fc3a 100644
--- a/tests/02_runtime/06_recursion
+++ b/tests/custom/02_runtime/06_recursion
diff --git a/tests/03_bugs/01_try_catch_stack_mismatch b/tests/custom/03_bugs/01_try_catch_stack_mismatch
index f6e5a0a..f6e5a0a 100644
--- a/tests/03_bugs/01_try_catch_stack_mismatch
+++ b/tests/custom/03_bugs/01_try_catch_stack_mismatch
diff --git a/tests/03_bugs/02_array_pop_use_after_free b/tests/custom/03_bugs/02_array_pop_use_after_free
index 22f63ff..22f63ff 100644
--- a/tests/03_bugs/02_array_pop_use_after_free
+++ b/tests/custom/03_bugs/02_array_pop_use_after_free
diff --git a/tests/03_bugs/03_switch_fallthrough_miscompilation b/tests/custom/03_bugs/03_switch_fallthrough_miscompilation
index 3e6410e..3e6410e 100644
--- a/tests/03_bugs/03_switch_fallthrough_miscompilation
+++ b/tests/custom/03_bugs/03_switch_fallthrough_miscompilation
diff --git a/tests/03_bugs/04_property_set_abort b/tests/custom/03_bugs/04_property_set_abort
index 8af477f..8af477f 100644
--- a/tests/03_bugs/04_property_set_abort
+++ b/tests/custom/03_bugs/04_property_set_abort
diff --git a/tests/03_bugs/05_duplicate_ressource_type b/tests/custom/03_bugs/05_duplicate_ressource_type
index 21166b2..21166b2 100644
--- a/tests/03_bugs/05_duplicate_ressource_type
+++ b/tests/custom/03_bugs/05_duplicate_ressource_type
diff --git a/tests/03_bugs/06_lexer_escape_at_boundary b/tests/custom/03_bugs/06_lexer_escape_at_boundary
index e80b0a1..e80b0a1 100644
--- a/tests/03_bugs/06_lexer_escape_at_boundary
+++ b/tests/custom/03_bugs/06_lexer_escape_at_boundary
diff --git a/tests/03_bugs/07_lexer_overlong_lines b/tests/custom/03_bugs/07_lexer_overlong_lines
index d2dd3be..d2dd3be 100644
--- a/tests/03_bugs/07_lexer_overlong_lines
+++ b/tests/custom/03_bugs/07_lexer_overlong_lines
diff --git a/tests/03_bugs/08_compiler_arrow_fn_expressions b/tests/custom/03_bugs/08_compiler_arrow_fn_expressions
index 5cd8960..5cd8960 100644
--- a/tests/03_bugs/08_compiler_arrow_fn_expressions
+++ b/tests/custom/03_bugs/08_compiler_arrow_fn_expressions
diff --git a/tests/03_bugs/09_reject_invalid_array_indexes b/tests/custom/03_bugs/09_reject_invalid_array_indexes
index a7e5272..a7e5272 100644
--- a/tests/03_bugs/09_reject_invalid_array_indexes
+++ b/tests/custom/03_bugs/09_reject_invalid_array_indexes
diff --git a/tests/03_bugs/10_break_stack_mismatch b/tests/custom/03_bugs/10_break_stack_mismatch
index ae16dac..ae16dac 100644
--- a/tests/03_bugs/10_break_stack_mismatch
+++ b/tests/custom/03_bugs/10_break_stack_mismatch
diff --git a/tests/03_bugs/11_switch_stack_mismatch b/tests/custom/03_bugs/11_switch_stack_mismatch
index cc3b41a..cc3b41a 100644
--- a/tests/03_bugs/11_switch_stack_mismatch
+++ b/tests/custom/03_bugs/11_switch_stack_mismatch
diff --git a/tests/03_bugs/12_altblock_stack_mismatch b/tests/custom/03_bugs/12_altblock_stack_mismatch
index e350660..e350660 100644
--- a/tests/03_bugs/12_altblock_stack_mismatch
+++ b/tests/custom/03_bugs/12_altblock_stack_mismatch
diff --git a/tests/custom/CMakeLists.txt b/tests/custom/CMakeLists.txt
new file mode 100644
index 0000000..c8007a0
--- /dev/null
+++ b/tests/custom/CMakeLists.txt
@@ -0,0 +1,22 @@
+ADD_TEST(
+ NAME custom
+ COMMAND run_tests.sh
+ WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
+)
+SET_PROPERTY(TEST custom APPEND PROPERTY ENVIRONMENT
+ "UCODE_BIN=valgrind --quiet --leak-check=full $<TARGET_FILE:ucode>"
+ "UCODE_LIB=${CMAKE_BINARY_DIR}"
+)
+
+IF(CMAKE_C_COMPILER_ID STREQUAL "Clang")
+ ADD_TEST(
+ NAME custom-san
+ COMMAND run_tests.sh
+ WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
+ )
+
+ SET_PROPERTY(TEST custom-san APPEND PROPERTY ENVIRONMENT
+ "UCODE_BIN=$<TARGET_FILE:ucode-san>"
+ "UCODE_LIB=${CMAKE_BINARY_DIR}"
+ )
+ENDIF()
diff --git a/tests/custom/run_tests.sh b/tests/custom/run_tests.sh
new file mode 100755
index 0000000..61b116f
--- /dev/null
+++ b/tests/custom/run_tests.sh
@@ -0,0 +1,187 @@
+#!/usr/bin/env bash
+
+testdir=$(dirname "$0")
+topdir=$(readlink -f "$testdir/../..")
+
+line='........................................'
+ucode_bin=${UCODE_BIN:-"$topdir/ucode"}
+ucode_lib=${UCODE_LIB:-"$topdir"}
+
+extract_sections() {
+ local file=$1
+ local dir=$2
+ local count=0
+ local tag line outfile
+
+ while IFS= read -r line; do
+ case "$line" in
+ "-- Testcase --")
+ tag="test"
+ count=$((count + 1))
+ outfile=$(printf "%s/%03d.in" "$dir" $count)
+ printf "" > "$outfile"
+ ;;
+ "-- Expect stdout --"|"-- Expect stderr --"|"-- Expect exitcode --")
+ tag="${line#-- Expect }"
+ tag="${tag% --}"
+ count=$((count + 1))
+ outfile=$(printf "%s/%03d.%s" "$dir" $count "$tag")
+ printf "" > "$outfile"
+ ;;
+ "-- End --")
+ tag=""
+ outfile=""
+ ;;
+ *)
+ if [ -n "$tag" ]; then
+ printf "%s\\n" "$line" >> "$outfile"
+ fi
+ ;;
+ esac
+ done < "$file"
+
+ return $(ls -l "$dir/"*.in 2>/dev/null | wc -l)
+}
+
+run_testcase() {
+ local num=$1
+ local dir=$2
+ local in=$3
+ local out=$4
+ local err=$5
+ local code=$6
+ local fail=0
+
+ (
+ cd "$topdir"
+ $ucode_bin -e '{ "REQUIRE_SEARCH_PATH": [ "'"$ucode_lib"'/*.so" ] }' -i - <"$in" >"$dir/res.out" 2>"$dir/res.err"
+ )
+
+ touch "$dir/empty"
+ printf "%d\n" $? > "$dir/res.code"
+
+ if ! cmp -s "$dir/res.err" "${err:-$dir/empty}"; then
+ [ $fail = 0 ] && printf "!\n"
+ printf "Testcase #%d: Expected stderr did not match:\n" $num
+ diff -u --color=always --label="Expected stderr" --label="Resulting stderr" "${err:-$dir/empty}" "$dir/res.err"
+ printf -- "---\n"
+ fail=1
+ fi
+
+ if ! cmp -s "$dir/res.out" "${out:-$dir/empty}"; then
+ [ $fail = 0 ] && printf "!\n"
+ printf "Testcase #%d: Expected stdout did not match:\n" $num
+ diff -u --color=always --label="Expected stdout" --label="Resulting stdout" "${out:-$dir/empty}" "$dir/res.out"
+ printf -- "---\n"
+ fail=1
+ fi
+
+ if [ -n "$code" ] && ! cmp -s "$dir/res.code" "$code"; then
+ [ $fail = 0 ] && printf "!\n"
+ printf "Testcase #%d: Expected exit code did not match:\n" $num
+ diff -u --color=always --label="Expected code" --label="Resulting code" "$code" "$dir/res.code"
+ printf -- "---\n"
+ fail=1
+ fi
+
+ return $fail
+}
+
+run_test() {
+ local file=$1
+ local name=${file##*/}
+ local res ecode eout eerr ein tests
+ local testcase_first=0 failed=0 count=0
+
+ printf "%s %s " "$name" "${line:${#name}}"
+
+ mkdir "/tmp/test.$$"
+
+ extract_sections "$file" "/tmp/test.$$"
+ tests=$?
+
+ [ -f "/tmp/test.$$/001.in" ] && testcase_first=1
+
+ for res in "/tmp/test.$$/"[0-9]*; do
+ case "$res" in
+ *.in)
+ count=$((count + 1))
+
+ if [ $testcase_first = 1 ]; then
+ # Flush previous test
+ if [ -n "$ein" ]; then
+ run_testcase $count "/tmp/test.$$" "$ein" "$eout" "$eerr" "$ecode" || failed=$((failed + 1))
+ eout=""
+ eerr=""
+ ecode=""
+ fi
+
+ ein=$res
+ else
+ run_testcase $count "/tmp/test.$$" "$res" "$eout" "$eerr" "$ecode" || failed=$((failed + 1))
+
+ eout=""
+ eerr=""
+ ecode=""
+ fi
+
+ ;;
+ *.stdout) eout=$res ;;
+ *.stderr) eerr=$res ;;
+ *.exitcode) ecode=$res ;;
+ esac
+ done
+
+ # Flush last test
+ if [ $testcase_first = 1 ] && [ -n "$eout$eerr$ecode" ]; then
+ run_testcase $count "/tmp/test.$$" "$ein" "$eout" "$eerr" "$ecode" || failed=$((failed + 1))
+ fi
+
+ rm -r "/tmp/test.$$"
+
+ if [ $failed = 0 ]; then
+ printf "OK\n"
+ else
+ printf "%s %s FAILED (%d/%d)\n" "$name" "${line:${#name}}" $failed $tests
+ fi
+
+ return $failed
+}
+
+
+n_tests=0
+n_fails=0
+
+select_tests="$@"
+
+use_test() {
+ local input="$(readlink -f "$1")"
+ local test
+
+ [ -f "$input" ] || return 1
+ [ -n "$select_tests" ] || return 0
+
+ for test in "$select_tests"; do
+ test="$(readlink -f "$test")"
+
+ [ "$test" != "$input" ] || return 0
+ done
+
+ return 1
+}
+
+for catdir in "$testdir/"[0-9][0-9]_*; do
+ [ -d "$catdir" ] || continue
+
+ printf "\n##\n## Running %s tests\n##\n\n" "${catdir##*/[0-9][0-9]_}"
+
+ for testfile in "$catdir/"[0-9][0-9]_*; do
+ use_test "$testfile" || continue
+
+ n_tests=$((n_tests + 1))
+ run_test "$testfile" || n_fails=$((n_fails + 1))
+ done
+done
+
+printf "\nRan %d tests, %d okay, %d failures\n" $n_tests $((n_tests - n_fails)) $n_fails
+exit $n_fails
diff --git a/tests/fuzz/CMakeLists.txt b/tests/fuzz/CMakeLists.txt
new file mode 100644
index 0000000..384e7e0
--- /dev/null
+++ b/tests/fuzz/CMakeLists.txt
@@ -0,0 +1,16 @@
+MACRO(ADD_FUZZER_TEST name)
+ ADD_EXECUTABLE(${name} ${name}.c)
+ TARGET_COMPILE_OPTIONS(${name} PRIVATE -g -O1 -fno-omit-frame-pointer -fsanitize=fuzzer,address,leak,undefined)
+ TARGET_INCLUDE_DIRECTORIES(${name} PRIVATE ${PROJECT_SOURCE_DIR})
+ TARGET_LINK_OPTIONS(${name} PRIVATE -stdlib=libc++ -fsanitize=fuzzer,address,leak,undefined)
+ ADD_TEST(
+ NAME ${name}
+ COMMAND ${name} -max_len=256 -timeout=10 -max_total_time=300 ${CMAKE_CURRENT_SOURCE_DIR}/corpus
+ )
+ENDMACRO(ADD_FUZZER_TEST)
+
+FILE(GLOB test_cases "test-*.c")
+FOREACH(test_case ${test_cases})
+ GET_FILENAME_COMPONENT(test_case ${test_case} NAME_WE)
+ ADD_FUZZER_TEST(${test_case})
+ENDFOREACH(test_case)
diff --git a/tests/fuzz/corpus/.keep b/tests/fuzz/corpus/.keep
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/fuzz/corpus/.keep
diff --git a/tests/fuzz/test-fuzz.c b/tests/fuzz/test-fuzz.c
new file mode 100644
index 0000000..40649e2
--- /dev/null
+++ b/tests/fuzz/test-fuzz.c
@@ -0,0 +1,9 @@
+#include <stdio.h>
+#include <stdint.h>
+#include <stddef.h>
+#include <limits.h>
+
+int LLVMFuzzerTestOneInput(const uint8_t *input, size_t size)
+{
+ return 0;
+}