#!/bin/sh
# Run binary tests.
# Usage: test/run [<test.rad>...]
#
# If no arguments are provided, runs all tests in `test/tests/`.
#
# For each test:
#   - If a `.ril` file exists alongside it, the IL output is checked
#     against it via the runner binary.
#   - If `//! returns: N` appears in the file, the test is compiled to
#     a binary and executed; the exit code must match N.

RUNNER="test/runner.rv64"
TEST_DIR="test/tests"
EMU="${RAD_EMULATOR:-emulator} -stack-size=1024 -run"
EMU_RUN="${RAD_EMULATOR:-emulator} -run"

if [ ! -f "$RUNNER" ]; then
  echo "error: runner binary not found: $RUNNER" >&2
  echo "hint: run 'make test' first" >&2
  exit 1
fi

# Disable core dumps for tests.
ulimit -c 0

# Collect tests.
if [ $# -eq 0 ]; then
  tests=$(find "$TEST_DIR" -name '*.rad' | sort)
else
  tests="$*"
fi

if [ -z "$tests" ]; then
  echo "error: no tests found" >&2
  exit 1
fi

passed=0
failed=0

for test in $tests; do
  ril="${test%.rad}.ril"
  bin="${test%.rad}.rv64"

  # IL check: run the runner if a .ril file exists.
  if [ -f "$ril" ]; then
    if $EMU "$RUNNER" -- "$test"; then
      passed=$((passed + 1))
    else
      failed=$((failed + 1))
    fi
  fi

  # Execution check: run the binary if //! returns: is present.
  returns=$(grep -m1 '^//! returns:' "$test" | sed 's/^\/\/! returns: *//')
  if [ -n "$returns" ]; then
    echo -n "test $test ... "

    if [ ! -f "$bin" ]; then
      echo "FAILED (binary not found: $bin)"
      failed=$((failed + 1))
      continue
    fi

    $EMU_RUN "$bin" >/dev/null 2>&1
    ret=$?

    if [ "$ret" -eq "$returns" ]; then
      echo "ok"
      passed=$((passed + 1))
    else
      echo "FAILED (expected: $returns, got: $ret)"
      failed=$((failed + 1))
    fi
  fi
done
echo

if [ "$failed" -eq 0 ]; then
  echo "test result: ok. $passed passed; $failed failed"
  exit 0
else
  echo "test result: FAILED. $passed passed; $failed failed"
  exit 1
fi
