diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml index 2d0c72907..a2ec10a0a 100644 --- a/.github/workflows/linux.yml +++ b/.github/workflows/linux.yml @@ -88,7 +88,7 @@ jobs: - name: Install deps run: | source ./util/ci/common.sh - install_linux_deps clang-7 llvm + install_linux_deps clang-7 llvm-7 - name: Build run: | @@ -102,6 +102,11 @@ jobs: run: | ./bin/minetest --run-unittests + # Do this here because we have ASan and error paths are sensitive to dangling pointers + - name: Test error cases + run: | + ./util/test_error_cases.sh + # Current clang version clang_18: runs-on: ubuntu-24.04 diff --git a/util/helper_mod/error.lua b/util/helper_mod/error.lua new file mode 100644 index 000000000..2a4b3e355 --- /dev/null +++ b/util/helper_mod/error.lua @@ -0,0 +1 @@ +error("intentional") diff --git a/util/helper_mod/init.lua b/util/helper_mod/init.lua index 4da832ed7..b2ed3b29d 100644 --- a/util/helper_mod/init.lua +++ b/util/helper_mod/init.lua @@ -48,4 +48,24 @@ elseif mode == "mapgen" then end core.after(0, next_, 1) +elseif mode == "error" then + + local n = tonumber(core.settings:get("error_type")) + local error_lua = core.get_modpath(core.get_current_modname()) .. "/error.lua" + if n == 1 then + print("=> error during startup <=") + error("intentional") + elseif n == 2 then + print("=> error on first step <=") + core.after(0, error, "intentional") + elseif n == 3 then + print("=> error in async script <=") + core.register_async_dofile(error_lua) + elseif n == 4 then + print("=> error in mapgen script <=") + core.register_mapgen_script(error_lua) + else + assert(false) + end + end diff --git a/util/test_error_cases.sh b/util/test_error_cases.sh new file mode 100755 index 000000000..801e097a3 --- /dev/null +++ b/util/test_error_cases.sh @@ -0,0 +1,46 @@ +#!/bin/bash +dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +gameid=${gameid:-devtest} +minetest=$dir/../bin/minetest +testspath=$dir/../tests +conf_server=$testspath/server.conf +worldpath=$testspath/world + +[ -e "$minetest" ] || { echo "executable $minetest missing"; exit 1; } + +write_config () { + printf '%s\n' >"$conf_server" \ + helper_mode=error mg_name=singlenode "$@" +} + +run () { + timeout 10 "$@" + r=$? + echo "Exit status: $r" + [ $r -eq 124 ] && echo "(timed out)" + if [ $r -ne 1 ]; then + echo "-> Test failed" + exit 1 + fi +} + +rm -rf "$worldpath" +mkdir -p "$worldpath/worldmods" + +ln -s "$dir/helper_mod" "$worldpath/worldmods/" + +args=(--server --config "$conf_server" --world "$worldpath" --gameid $gameid) + +# make sure we can tell apart sanitizer and minetest errors +export ASAN_OPTIONS="exitcode=42" +export MSAN_OPTIONS="exitcode=42" + +# see helper_mod/init.lua for the different types +for n in $(seq 1 4); do + write_config error_type=$n + run "$minetest" "${args[@]}" + echo "---------------" +done + +echo "All done." +exit 0