kit

kit
git clone https://git.ryansepassi.com/git/kit.git
Log | Files | Refs | README

run.sh (5858B)


      1 #!/usr/bin/env bash
      2 # test/hosted/run.sh — the hosted test suite: build each C case for every
      3 # (target, link-mode) config in the support set with scripts/hosted.sh, run it
      4 # through the shared seam test/lib/exec_target.sh, and check exit code + stdout
      5 # against the oracle (<name>.expected / <name>.stdout). The first principled
      6 # cross-OS hosted-exec suite; seed case is cases/hello.c.
      7 #
      8 # Full matrix (15 configs):
      9 #   linux {aa64,x64,rv64} x {musl-static, musl-dynamic, glibc}   (podman: alpine
     10 #       for musl, debian for glibc; each routed by its exec tag)
     11 #   macos-aarch64                                                (native)
     12 #   windows {x64,aarch64}                                        (VM)
     13 #   freebsd {amd64,aarch64,riscv64}                              (VM)
     14 #
     15 # Two verdicts per (case, config): ":build" (cc+link ok) and ":run" (right exit
     16 # code + stdout). A target whose sysroot is absent SKIPs build; a config with no
     17 # runner here SKIPs run. The tag carries the libc, so one flush routes every
     18 # config to its runner.
     19 #
     20 # Default config set: Linux + macOS (fast). FreeBSD + Windows (VMs) are added by
     21 # KIT_HOSTED_VM=1. env: KIT, HOSTED_CONFIGS (override the list), KIT_HOSTED_VM,
     22 # EXEC_VM_KEEP_UP.
     23 
     24 set -u
     25 
     26 ROOT="$(cd "$(dirname "$0")/../.." && pwd)"
     27 KIT="${KIT:-$ROOT/build/kit}"
     28 HOSTED="$ROOT/scripts/hosted.sh"
     29 CASES="$ROOT/test/hosted/cases"
     30 BUILD_DIR="$ROOT/build/test/hosted"
     31 
     32 # shellcheck source=../lib/kit_sh_report.sh
     33 . "$ROOT/test/lib/kit_sh_report.sh"
     34 # shellcheck source=../lib/exec_target.sh
     35 . "$ROOT/test/lib/exec_target.sh"
     36 kit_report_init
     37 trap exec_target_teardown_all EXIT
     38 
     39 [ -x "$KIT" ] || { echo "hosted: kit not found at $KIT (run 'make bin')" >&2; exit 2; }
     40 
     41 # exec_target's caller contract for the linux/macos runners (VM tags ignore these).
     42 have_podman=0; command -v podman >/dev/null 2>&1 && have_podman=1
     43 QEMU_BIN="${QEMU_BIN:-$(command -v qemu-aarch64 2>/dev/null || true)}"
     44 QEMU_RV64_BIN="${QEMU_RV64_BIN:-$(command -v qemu-riscv64 2>/dev/null || true)}"
     45 have_qemu=0; [ -n "$QEMU_BIN" ] && have_qemu=1
     46 case "$(uname -m 2>/dev/null)" in aarch64|arm64) is_aarch64=1 ;; *) is_aarch64=0 ;; esac
     47 export have_podman QEMU_BIN QEMU_RV64_BIN have_qemu is_aarch64
     48 mkdir -p "$BUILD_DIR"
     49 EXEC_TARGET_MOUNT_ROOT="$BUILD_DIR"; export EXEC_TARGET_MOUNT_ROOT
     50 
     51 # ---- config list -----------------------------------------------------------
     52 # A config is "<target>[:<mode>]". mode (static|dynamic) only varies for musl;
     53 # glibc is dynamic-only, freebsd is static, windows/macos have one shape.
     54 LINUX_CONFIGS=""
     55 for a in aa64 x64 rv64; do
     56   LINUX_CONFIGS="$LINUX_CONFIGS linux-musl-$a:static linux-musl-$a:dynamic linux-glibc-$a"
     57 done
     58 DEFAULT_CONFIGS="$LINUX_CONFIGS macos-aarch64"
     59 VM_CONFIGS="freebsd-amd64 freebsd-aarch64 freebsd-riscv64 windows-x64 windows-aarch64"
     60 if [ -n "${HOSTED_CONFIGS:-}" ]; then
     61   CONFIGS="$HOSTED_CONFIGS"
     62 else
     63   CONFIGS="$DEFAULT_CONFIGS"
     64   [ "${KIT_HOSTED_VM:-0}" = 1 ] && CONFIGS="$CONFIGS $VM_CONFIGS"
     65 fi
     66 
     67 # Link flags for a (target, mode): musl honors the mode; freebsd is self-contained
     68 # static; glibc/windows/macos use their default shape (glibc is dynamic-only).
     69 link_flags_for() {
     70   local target="$1" mode="$2"
     71   case "$target" in
     72     linux-musl-*) [ "$mode" = static ] && echo -static ;;
     73     freebsd-*)    echo -static ;;
     74     *)            echo ;;
     75   esac
     76 }
     77 
     78 # ---- build + queue ---------------------------------------------------------
     79 H_NAME=(); H_OUT=(); H_RC=(); H_EXP=(); H_STDOUT=()
     80 
     81 printf 'hosted: configs=%s\n' "$CONFIGS"
     82 
     83 for case_src in "$CASES"/*.c; do
     84   cbase="$(basename "${case_src%.c}")"
     85   exp=0; [ -f "${case_src%.c}.expected" ] && exp="$(cat "${case_src%.c}.expected")"
     86   want_out=""; [ -f "${case_src%.c}.stdout" ] && want_out="$(cat "${case_src%.c}.stdout")"
     87   for config in $CONFIGS; do
     88     target="${config%%:*}"; mode="${config#*:}"; [ "$mode" = "$config" ] && mode=""
     89     os="${target%%-*}"
     90     label="$cbase/$config"
     91     sr="$("$HOSTED" path "$target" 2>/dev/null)"
     92     if [ "$os" != macos ] && { [ -z "$sr" ] || [ ! -d "$sr" ]; }; then
     93       kit_skip "$label:build" "missing sysroot (scripts/hosted.sh prepare $target)"
     94       continue
     95     fi
     96     cdir="$BUILD_DIR/$(printf '%s' "$config" | tr ':/' '__')"; mkdir -p "$cdir"
     97     ext=""; [ "$os" = windows ] && ext=".exe"
     98     exe="$cdir/$cbase$ext"
     99     # shellcheck disable=SC2046
    100     if ! "$HOSTED" cc "$target" $(link_flags_for "$target" "$mode") "$case_src" -o "$exe" \
    101           > "$cdir/$cbase.cc.out" 2> "$cdir/$cbase.cc.err"; then
    102       kit_fail "$label:build" "hosted.sh cc failed"
    103       sed 's/^/    | /' "$cdir/$cbase.cc.err" | head -20
    104       continue
    105     fi
    106     kit_pass "$label:build"
    107 
    108     tag="$("$HOSTED" tag "$target")"
    109     if ! exec_target_supported "$tag"; then
    110       kit_skip "$label:run" "no runner for $tag"
    111       continue
    112     fi
    113     exec_target_queue "$tag" "$label" "$exe" \
    114       "$cdir/$cbase.out" "$cdir/$cbase.err" "$cdir/$cbase.rc"
    115     H_NAME+=("$label:run"); H_OUT+=("$cdir/$cbase.out")
    116     H_RC+=("$cdir/$cbase.rc"); H_EXP+=("$exp"); H_STDOUT+=("$want_out")
    117   done
    118 done
    119 
    120 # ---- execute + check -------------------------------------------------------
    121 exec_target_flush
    122 
    123 i=0; n="${#H_NAME[@]}"
    124 while [ "$i" -lt "$n" ]; do
    125   name="${H_NAME[$i]}"; exp=$(( ${H_EXP[$i]} & 255 ))
    126   rc="$(cat "${H_RC[$i]}" 2>/dev/null || echo 127)"
    127   got_out="$(cat "${H_OUT[$i]}" 2>/dev/null || true)"
    128   if ! case "$rc" in ''|*[!0-9-]*) false ;; *) true ;; esac; then
    129     kit_fail "$name" "did not run (rc=$rc)"
    130   elif [ "$(( rc & 255 ))" -ne "$exp" ]; then
    131     kit_fail "$name" "expected rc $exp, got $rc"
    132   elif [ -n "${H_STDOUT[$i]}" ] && [ "$got_out" != "${H_STDOUT[$i]}" ]; then
    133     kit_fail "$name" "stdout mismatch"
    134     printf '    want: %s\n    got:  %s\n' "${H_STDOUT[$i]}" "$got_out"
    135   else
    136     kit_pass "$name"
    137   fi
    138   i=$((i + 1))
    139 done
    140 
    141 KIT_SKIP_IS_FAILURE=0
    142 kit_summary test-hosted
    143 kit_exit