#!/bin/bash
#
#   SmokeParallel — Run smoke tests in parallel isolated workspaces.
#
#   Usage: cd testcases && ./tools/SmokeParallel [-j JOBS] [test_name ...]
#
set -euo pipefail

SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd)
TC=$(cd "$SCRIPT_DIR/.." && pwd)
JOBS=2
TEST_NAMES=()
TMP_ROOT=$(mktemp -d "${TMPDIR:-/tmp}/tinymux-smoke-parallel.XXXXXX")

cleanup() {
    rm -rf "$TMP_ROOT"
}

discover_tests() {
    find "$TC" -maxdepth 1 -name '*.mux' -print \
        | sed "s#^$TC/##" \
        | sed 's/\.mux$//' \
        | sort \
        | grep -vx '0upload' \
        | grep -vx 'smoke'
}

run_one() {
    local test_name="$1"
    local workspace="$TMP_ROOT/$test_name"
    local run_log="$workspace/run.log"

    mkdir -p "$workspace"
    {
        echo "=== $test_name: Makesmoke ==="
        "$SCRIPT_DIR/Makesmoke" --workspace "$workspace" --output "$workspace/smoke.flat" "$test_name"
        echo "=== $test_name: Smoke ==="
        "$SCRIPT_DIR/Smoke" --workspace "$workspace" --flatfile "$workspace/smoke.flat"
    } >"$run_log" 2>&1
}

trap cleanup EXIT

while [ $# -gt 0 ]; do
    case "$1" in
        -j|--jobs)
            JOBS="$2"
            shift 2
            ;;
        --)
            shift
            while [ $# -gt 0 ]; do
                TEST_NAMES+=("$1")
                shift
            done
            ;;
        *)
            TEST_NAMES+=("$1")
            shift
            ;;
    esac
done

if [ ${#TEST_NAMES[@]} -eq 0 ]; then
    mapfile -t TEST_NAMES < <(discover_tests)
fi

if [ ${#TEST_NAMES[@]} -eq 0 ]; then
    echo "ERROR: no smoke tests selected."
    exit 1
fi

FAILURES=0
for test_name in "${TEST_NAMES[@]}"; do
    while [ "$(jobs -pr | wc -l)" -ge "$JOBS" ]; do
        wait -n || FAILURES=1
    done
    run_one "$test_name" &
done

while [ "$(jobs -pr | wc -l)" -gt 0 ]; do
    wait -n || FAILURES=1
done

for test_name in "${TEST_NAMES[@]}"; do
    run_log="$TMP_ROOT/$test_name/run.log"
    if [ -r "$run_log" ]; then
        cat "$run_log"
    fi
done

exit "$FAILURES"
