#!/bin/sh
# Verify test discovery, package selection, and descriptor capacity.
set -eu
ulimit -c 0
work=$(mktemp -d)
trap 'rm -rf "$work"' EXIT HUP INT TERM
mkdir "$work/selected"

# The dependency test must not enter the selected package's runner.
printf '%s\n' '/// Test outside the entry package.' '@test fn excluded() { assert false; }' > "$work/dependency.rad"
printf '%s\n' 'use std::testing;' '/// Test in a child module.' \
    '@test fn childTest() throws (testing::TestError) { assert true; }' > "$work/selected/child.rad"

# Compile through Make so the driver uses the standard memory settings.
compile() {
    timeout 300 "${MAKE:-make}" --no-print-directory driver-test-image \
        RAD_BIN="${RAD_BIN:-bin/radiance.rv64.dev}" \
        RAD_EMULATOR="${RAD_EMULATOR:-emulator}" \
        DRIVER_TEST_INPUTS="-pkg dependency -mod $work/dependency.rad -pkg selected -mod $work/selected.rad $1" \
        DRIVER_TEST_FLAGS="${2:-}" \
        DRIVER_TEST_OUTPUT="$work/result.rv64" > "$work/compile.log" 2>&1
}

# Check one successful runner and its exact number of executed tests.
run() {
    if ! compile "$1"; then
        cat "$work/compile.log"
        exit 1
    fi
    if ! timeout 10 "${RAD_EMULATOR:-emulator}" -run "$work/result.rv64" > "$work/run.log" 2>&1; then
        cat "$work/run.log"
        exit 1
    fi
    grep -Fq "test result: ok. $2 passed; 0 failed" "$work/run.log"
    test "$(grep -c '^test selected::' "$work/run.log")" -eq "$2"
}

printf '%s\n' 'use std::testing;' 'mod child;' \
    '/// Test in the package root.' '@test fn rootTest() throws (testing::TestError) { assert true; }' > "$work/selected.rad"
run "-mod $work/selected/child.rad" 2
grep -Fq 'test selected::rootTest ... ok' "$work/run.log"
grep -Fq 'test selected::child::childTest ... ok' "$work/run.log"

printf '%s\n' 'use std::testing;' > "$work/selected.rad"
if compile ''; then
    echo 'driver: empty test discovery unexpectedly succeeded'
    exit 1
fi
grep -Fq 'no test functions found' "$work/compile.log"

# MAX_TESTS is the compiler's supported discovery capacity.
for count in 1024 1025; do
    awk -v count="$count" -v directory="$work/selected" 'BEGIN {
        print "use std::testing;"
        for (i = 0; i < count; i++) {
            part = int(i / 256)
            path = directory "/part" part ".rad"
            if (i % 256 == 0) {
                printf "/// Capacity test group.\nmod part%d;\n", part
                print "use std::testing;" > path
            }
            print "/// Generated capacity test." > path
            printf "@test fn test%d() throws (testing::TestError) { assert true; }\n", i > path
        }
    }' > "$work/selected.rad"
    inputs=''
    for path in "$work/selected"/part*.rad; do
        inputs="$inputs -mod $path"
    done
    if [ "$count" -eq 1024 ]; then
        if ! compile "$inputs" '-dump il'; then
            cat "$work/compile.log"
            exit 1
        fi
        grep -Fq 'selected: found 1024 test(s)' "$work/compile.log"
        test "$(grep -c 'call.*std::testing::test' "$work/compile.log")" -eq "$count"
        run "$inputs" "$count"
    else
        if compile "$inputs"; then
            echo 'driver: test discovery overflow unexpectedly succeeded'
            exit 1
        fi
        grep -Fq 'Runtime error (EBREAK)' "$work/compile.log"
    fi
done
echo 'driver tests: 4 passed'
