Improved tests.
h3rald h3rald@h3rald.com
Mon, 03 Aug 2026 16:16:11 +0200
1 files changed,
117 insertions(+),
38 deletions(-)
jump to
M
test.sh
→
test.sh
@@ -2,16 +2,20 @@ #!/usr/bin/env bash
set -euo pipefail ### Test cases -TEST_CASES=( - "run_test helloworld.xyw assert_output_equals \$'Hello, World!\\n'" - "run_test d6.xyw assert_output_in_range 1 6" - "run_test on-error.xyw assert_output_equals \$'Error: Division by zero.\\n'" - "run_test print-args.xyw test1 test2 -- assert_output_equals \$'print-args.xim, test1, test2\\n'" - "run_test factorial8.xyw assert_output_equals \$'120\\n'" - "run_test factorial16.xyw assert_output_equals \$'5040\\n'" - "run_test fileops.xyw assert_output_equals \$'This is a test file.\\nIt has multiple lines.\\n'" - "run_test launcher.xyw assert_output_equals \$'Executing: print-args.xim hello world\\nprint-args.xim, hello, world\\nExecuting: helloworld.xim\\nHello, World!\\nDone!\\n'" -) +# +run_all_tests() { + run_test helloworld.xyw -- assert_output_equals $'Hello, World!\n' + run_test d6.xyw -- assert_output_in_range 1 6 + run_test on-error.xyw -- assert_output_equals $'Error: Division by zero.\n' + run_test print-args.xyw test1 test2 -- assert_output_equals $'print-args.xim, test1, test2\n' + run_test factorial8.xyw -- assert_output_equals $'120\n' + run_test factorial16.xyw -- assert_output_equals $'5040\n' + run_test fileops.xyw -- assert_output_equals $'This is a test file.\nIt has multiple lines.\n' + # Cleanup test file + rm -f "$EXAMPLES_DIR/test.txt" + run_test launcher.xyw -- assert_output_equals $'Executing: print-args.xim hello world\nprint-args.xim, hello, world\nExecuting: helloworld.xim\nHello, World!\nDone!\n' + run_test cmdexec.xyw -- assert_output_matches $'MINGW|Linux|BSD|Darwin' +} ### Helper functions@@ -89,6 +93,18 @@ need_file "$EXAMPLES_DIR/$img_basename"
echo "$img_basename" } +# Set by run_image_capture_stdout after each run, for assertions that +# care about the process exit code (e.g. assert_exit_code) or stderr +# (e.g. assert_stderr_contains-style checks). +LAST_EXIT_CODE=0 +LAST_STDERR_FILE="" + +# Set to "1" by run_test before calling run_image_capture_stdout when the +# chosen assertion function is expected to handle a non-zero exit code +# itself (e.g. assert_exit_code). Otherwise a non-zero exit is treated as +# a hard failure, same as before. +ALLOW_NONZERO_EXIT="0" + run_image_capture_stdout() { local xyw_bin="$1" local img_basename="$2" # e.g. helloworld.xim@@ -99,27 +115,16 @@
need_file "$EXAMPLES_DIR/$img_basename" local run_log="$TMPDIR/run.${img_basename}.log" + local rc=0 + (cd "$EXAMPLES_DIR" && "$xyw_bin" "$img_basename" "${run_args[@]}" >"$out_file" 2>"$run_log") || rc=$? - if ((${#run_args[@]})); then - if ! ( - cd "$EXAMPLES_DIR" && - "$xyw_bin" "$img_basename" "${run_args[@]}" \ - >"$out_file" 2>"$run_log" - ); then - dump_file_if_exists "Runtime stderr" "$run_log" - dump_file_if_exists "Runtime stdout" "$out_file" - fail "Execution failed for $img_basename" - fi - else - if ! ( - cd "$EXAMPLES_DIR" && - "$xyw_bin" "$img_basename" \ - >"$out_file" 2>"$run_log" - ); then - dump_file_if_exists "Runtime stderr" "$run_log" - dump_file_if_exists "Runtime stdout" "$out_file" - fail "Execution failed for $img_basename" - fi + LAST_EXIT_CODE="$rc" + LAST_STDERR_FILE="$run_log" + + if [[ "$rc" -ne 0 && "$ALLOW_NONZERO_EXIT" != "1" ]]; then + dump_file_if_exists "Runtime stderr" "$run_log" + dump_file_if_exists "Runtime stdout" "$out_file" + fail "Execution failed for $img_basename (exit code $rc)" fi }@@ -177,6 +182,80 @@ fail "Output out of range (expected ${min_value}..${max_value}): $value"
fi } +assert_output_in_set() { + local stdout_file="$1" + shift + local candidates=("$@") + + if ((${#candidates[@]} == 0)); then + fail "assert_output_in_set requires at least one candidate string" + fi + + local candidate expected_file + for candidate in "${candidates[@]}"; do + expected_file="$TMPDIR/expected_set.$$.${RANDOM}.txt" + printf '%s' "$candidate" >"$expected_file" + if cmp -s "$stdout_file" "$expected_file"; then + rm -f "$expected_file" + return 0 + fi + rm -f "$expected_file" + done + + echo "--- Actual (cat -v) ---" >&2 + cat -v "$stdout_file" >&2 || true + echo "--- Expected one of ---" >&2 + for candidate in "${candidates[@]}"; do + printf '%s\n' "$candidate" | cat -v >&2 || true + echo "---" >&2 + done + fail "Output did not match any candidate." +} + +assert_output_matches() { + local stdout_file="$1" + local pattern="$2" + + local content + content="$(cat "$stdout_file")" + + if [[ ! "$content" =~ $pattern ]]; then + echo "--- Actual (cat -v) ---" >&2 + cat -v "$stdout_file" >&2 || true + fail "Output did not match pattern: $pattern" + fi +} + +assert_exit_code() { + local stdout_file="$1" + local expected_code="$2" + + if [[ "$LAST_EXIT_CODE" -ne "$expected_code" ]]; then + echo "--- Actual stdout (cat -v) ---" >&2 + dump_file_if_exists "stdout" "$stdout_file" + dump_file_if_exists "stderr" "$LAST_STDERR_FILE" + fail "Exit code mismatch: expected $expected_code, got $LAST_EXIT_CODE" + fi +} + +assert_output_equals_file() { + local stdout_file="$1" + local expected_path="$2" + + local resolved="" + if [[ "$expected_path" == /* && -f "$expected_path" ]]; then + resolved="$expected_path" + elif [[ -f "$EXAMPLES_DIR/$expected_path" ]]; then + resolved="$EXAMPLES_DIR/$expected_path" + elif [[ -f "$ROOT_DIR/$expected_path" ]]; then + resolved="$ROOT_DIR/$expected_path" + else + fail "Expected output file not found: $expected_path" + fi + + assert_file_equals "$stdout_file" "$resolved" +} + ### Test runner # Usage: run_test src.xyw [run_args...] -- assert_fn [assert_args...]@@ -226,12 +305,14 @@ img_basename="$(assemble_in_examples_dir "$XYW_BIN" "$src_basename")"
local raw_out="$TMPDIR/${src_basename%.xyw}.raw" local norm_out="$TMPDIR/${src_basename%.xyw}.norm" - - if ((${#run_args[@]})); then - run_image_capture_stdout "$XYW_BIN" "$img_basename" "$raw_out" "${run_args[@]}" + + if [[ "$assert_fn" == "assert_exit_code" ]]; then + ALLOW_NONZERO_EXIT="1" else - run_image_capture_stdout "$XYW_BIN" "$img_basename" "$raw_out" + ALLOW_NONZERO_EXIT="0" fi + + run_image_capture_stdout "$XYW_BIN" "$img_basename" "$raw_out" "${run_args[@]}" normalize_crlf "$raw_out" "$norm_out" "$assert_fn" "$norm_out" "${assert_args[@]}"@@ -254,11 +335,9 @@ XYW_BIN="$(find_xyw_bin)"
echo "" - for tc in "${TEST_CASES[@]}"; do - eval "$tc" - done + run_all_tests echo -e "\n=> All tests passed." } -main "$@" +main "$@"