diff options
Diffstat (limited to 'scripts')
| -rwxr-xr-x | scripts/docker_test.sh | 14 | ||||
| -rwxr-xr-x | scripts/run_suite.sh | 35 | ||||
| -rwxr-xr-x | scripts/test_examples.sh | 77 |
3 files changed, 92 insertions, 34 deletions
diff --git a/scripts/docker_test.sh b/scripts/docker_test.sh index 93f0bca..2ded903 100755 --- a/scripts/docker_test.sh +++ b/scripts/docker_test.sh @@ -2,17 +2,15 @@ # Convenience wrapper: build hdass and run the full test suite (unit tests plus # the end-to-end example tests) inside the amd64 Linux Docker environment. # Run this from the host; it brings the container up if it is not already. +# +# Colours are on by default; set NO_COLOR to disable them. set -euo pipefail root="$(cd "$(dirname "$0")/.." && pwd)" cd "$root" -docker compose up -d +docker compose up -d >/dev/null -docker compose exec -T hdass bash -c ' - set -e - premake5 gmake - make config=debug - ./bin/debug-linux/tests - ./scripts/test_examples.sh -' +# stdin is redirected from /dev/null so `docker compose exec -T` does not hang +# waiting on the stream after the suite finishes. +docker compose exec -T -e "NO_COLOR=${NO_COLOR:-}" hdass bash /hdass/scripts/run_suite.sh </dev/null diff --git a/scripts/run_suite.sh b/scripts/run_suite.sh new file mode 100755 index 0000000..9d40e24 --- /dev/null +++ b/scripts/run_suite.sh @@ -0,0 +1,35 @@ +#!/usr/bin/env bash +# Build hdass and run the full test suite (unit tests plus the end-to-end +# example tests). Expects the amd64 Linux environment; it is invoked inside the +# container by scripts/docker_test.sh, but can also be run directly there. +# +# Colours are on by default; set NO_COLOR to disable them. +set -euo pipefail + +cd "$(cd "$(dirname "$0")/.." && pwd)" + +if [ -z "${NO_COLOR:-}" ]; then + bold=$'\033[1m'; red=$'\033[31m'; green=$'\033[32m'; reset=$'\033[0m' +else + bold=; red=; green=; reset= +fi + +printf '%s━━ building compiler ━━%s\n' "$bold" "$reset" +if ! build=$(premake5 gmake 2>&1 && make config=debug 2>&1); then + printf '%s\n' "$build" + printf ' %s✘ build failed%s\n' "$red" "$reset" + exit 1 +fi +printf ' %s✔ compiler built%s\n\n' "$green" "$reset" + +printf '%s━━ unit tests ━━%s\n' "$bold" "$reset" +if units=$(./bin/debug-linux/tests 2>/dev/null); then + printf ' %s✔%s %s\n\n' "$green" "$reset" "$(printf '%s' "$units" | tail -1)" +else + printf '%s\n' "$units" + ./bin/debug-linux/tests || true + printf ' %s✘ unit tests failed%s\n' "$red" "$reset" + exit 1 +fi + +exec bash ./scripts/test_examples.sh diff --git a/scripts/test_examples.sh b/scripts/test_examples.sh index d5b5491..5ebba65 100755 --- a/scripts/test_examples.sh +++ b/scripts/test_examples.sh @@ -5,21 +5,29 @@ # # The generated programs use Linux x86-64 syscalls, so this must run in the # amd64 Linux environment (see the Docker setup in the README), not on macOS. +# +# Colours are on by default; set NO_COLOR to disable them. set -u root="$(cd "$(dirname "$0")/.." && pwd)" cd "$root" +if [ -z "${NO_COLOR:-}" ]; then + bold=$'\033[1m'; dim=$'\033[2m'; red=$'\033[31m'; green=$'\033[32m'; reset=$'\033[0m' +else + bold=; dim=; red=; green=; reset= +fi + hdass="${HDASS:-./bin/debug-linux/hdass}" if [ ! -x "$hdass" ]; then - echo "error: '$hdass' not found; build it first with:" >&2 + echo "${red}error:${reset} '$hdass' not found; build it first with:" >&2 echo " premake5 gmake && make config=debug" >&2 exit 1 fi for tool in nasm ld; do if ! command -v "$tool" >/dev/null 2>&1; then - echo "error: '$tool' not found; run this inside the Docker environment" >&2 + echo "${red}error:${reset} '$tool' not found; run this inside the Docker environment" >&2 exit 1 fi done @@ -30,47 +38,59 @@ trap 'rm -rf "$work"' EXIT pass=0 fail=0 -# check <name> <source> <expected_exit> <expected_stdout> +# check <name> <description> <source> <expected_exit> <expected_stdout> # expected_stdout is compared after trailing newlines are stripped (as $() does). check() { - local name="$1" source="$2" expected_exit="$3" expected_stdout="$4" - local asm="$work/$name.asm" obj="$work/$name.o" bin="$work/$name" + local name="$1" desc="$2" source="$3" expected_exit="$4" expected_stdout="$5" + local asm="$work/$name.asm" obj="$work/$name.o" bin="$work/$name" stage="" if ! "$hdass" "$source" -o "$asm" 2>"$work/err"; then - echo "FAIL $name (transpile)"; cat "$work/err"; fail=$((fail + 1)); return + stage="transpile" + elif ! nasm -f elf64 "$asm" -o "$obj" 2>"$work/err"; then + stage="assemble" + elif ! ld -e main "$obj" -o "$bin" 2>"$work/err"; then + stage="link" fi - if ! nasm -f elf64 "$asm" -o "$obj" 2>"$work/err"; then - echo "FAIL $name (assemble)"; cat "$work/err"; fail=$((fail + 1)); return - fi - if ! ld "$obj" -o "$bin" 2>"$work/err"; then - echo "FAIL $name (link)"; cat "$work/err"; fail=$((fail + 1)); return + + if [ -n "$stage" ]; then + printf ' %s✘%s %-12s %s%s%s\n' "$red" "$reset" "$name" "$dim" "$desc" "$reset" + printf ' %sfailed to %s%s\n' "$red" "$stage" "$reset" + sed 's/^/ /' "$work/err" + fail=$((fail + 1)) + return fi local actual_stdout actual_exit - actual_stdout="$("$bin")" + actual_stdout="$(timeout 10 "$bin")" actual_exit=$? if [ "$actual_exit" != "$expected_exit" ] || [ "$actual_stdout" != "$expected_stdout" ]; then - echo "FAIL $name" - echo " expected: exit=$expected_exit stdout=$(printf '%q' "$expected_stdout")" - echo " actual: exit=$actual_exit stdout=$(printf '%q' "$actual_stdout")" + printf ' %s✘%s %-12s %s%s%s\n' "$red" "$reset" "$name" "$dim" "$desc" "$reset" + if [ "$actual_exit" = 124 ]; then + printf ' %stimed out (likely an infinite loop)%s\n' "$red" "$reset" + fi + printf ' expected: exit %s stdout=%s\n' "$expected_exit" "$(printf '%q' "$expected_stdout")" + printf ' actual: exit %s stdout=%s\n' "$actual_exit" "$(printf '%q' "$actual_stdout")" fail=$((fail + 1)) return fi - echo "PASS $name" + printf ' %s✔%s %-12s %s%-42s%s %sexit %s%s\n' \ + "$green" "$reset" "$name" "$dim" "$desc" "$reset" "$dim" "$expected_exit" "$reset" pass=$((pass + 1)) } -check hello_world examples/hello_world.hdass 0 "Hello, World!" -check greet examples/greet.hdass 0 "hdass works!" -check exit_code examples/exit_code.hdass 42 "" -check arithmetic examples/arithmetic.hdass 15 "" -check loop_sum examples/loop_sum.hdass 15 "" -check branch examples/branch.hdass 8 "" -check call examples/call.hdass 21 "" -check fibonacci examples/fibonacci.hdasm 0 "0 +printf '%s━━ example programs ━━%s\n' "$bold" "$reset" + +check hello_world "writes a greeting to stdout" examples/hello_world.hdass 0 "Hello, World!" +check greet "writes a fixed string" examples/greet.hdass 0 "hdass works!" +check exit_code "exits with a status code" examples/exit_code.hdass 42 "" +check arithmetic "integer compound-assignment math" examples/arithmetic.hdass 15 "" +check loop_sum "sums 1..5 with a countdown loop" examples/loop_sum.hdass 15 "" +check branch "selects the larger of two values" examples/branch.hdass 8 "" +check call "passes an argument through a proc" examples/call.hdass 21 "" +check fibonacci "prints the first ten Fibonacci numbers" examples/fibonacci.hdasm 0 "0 1 1 2 @@ -81,6 +101,11 @@ check fibonacci examples/fibonacci.hdasm 0 "0 21 34" -echo -echo "$pass passed, $fail failed" +printf '\n' +if [ "$fail" -eq 0 ]; then + printf ' %s✔ all %d examples passed%s\n' "$green" "$pass" "$reset" +else + printf ' %s✘ %d of %d examples failed%s\n' "$red" "$fail" "$((pass + fail))" "$reset" +fi + [ "$fail" -eq 0 ] |
