summaryrefslogtreecommitdiffhomepage
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-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)0
-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.txt7
-rwxr-xr-xtests/custom/run_tests.sh179
48 files changed, 186 insertions, 0 deletions
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..3af53bb 100644
--- a/tests/00_syntax/21_regex_literals
+++ b/tests/custom/00_syntax/21_regex_literals
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..9672fce
--- /dev/null
+++ b/tests/custom/CMakeLists.txt
@@ -0,0 +1,7 @@
+ADD_TEST(
+ NAME custom
+ COMMAND run_tests.sh
+ WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
+)
+
+SET_PROPERTY(TEST custom APPEND PROPERTY ENVIRONMENT "UCODE_BIN=$<TARGET_FILE:ucode>")
diff --git a/tests/custom/run_tests.sh b/tests/custom/run_tests.sh
new file mode 100755
index 0000000..962cd9a
--- /dev/null
+++ b/tests/custom/run_tests.sh
@@ -0,0 +1,179 @@
+#!/usr/bin/env bash
+
+line='........................................'
+ucode_bin=${UCODE_BIN:-./ucode}
+
+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
+
+ $ucode_bin -e '{ "REQUIRE_SEARCH_PATH": [ "./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 [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