boot2

Playing with the boostrap
git clone https://git.ryansepassi.com/git/boot2.git
Log | Files | Refs | README

run.sh (6670B)


      1 #!/bin/sh
      2 ## tests/run.sh — host-side dispatcher for the unified test runner.
      3 ##
      4 ## All build/run/diff work happens inside the container via
      5 ## tests/run-suite.sh: this script just starts one podman
      6 ## process per requested arch and aggregates the per-arch
      7 ## PASS/FAIL totals. Prior versions of this runner re-entered the
      8 ## container per fixture (and per build/run within a fixture); now
      9 ## a whole arch's suite is one podman invocation.
     10 ##
     11 ## The one bit of work that stays on the host is the lint preflight
     12 ## for the m1pp and p1 suites: tools/lint.sh runs python, which the
     13 ## busybox container doesn't carry. Names that fail lint are reported
     14 ## here (FAIL + diagnostic) and excluded from the in-container batch.
     15 ##
     16 ## Suites:
     17 ##   m1pp     tests/M1pp/<name>.M1pp   — m1pp expander parity test.
     18 ##   p1       tests/P1/<name>.P1pp     — built via tests/build-p1pp.sh
     19 ##                                       and run; stdout diffed.
     20 ##            tests/P1/<name>.P1       — raw P1, built via
     21 ##                                       tests/build-p1.sh (no expander).
     22 ##   scheme1  tests/scheme1/<name>.scm — run by per-arch scheme1.
     23 ##   cc-util  tests/cc-util/<name>.scm — scheme1 prelude+util byte-diff.
     24 ##   cc-lex   tests/cc-lex/<name>.c    — lex pipeline byte-diff.
     25 ##   cc-pp    tests/cc-pp/<name>.c     — pp pipeline byte-diff (+ .scm).
     26 ##   cc-cg    tests/cc-cg/<name>.scm   — cg emit -> P1pp -> ELF -> run.
     27 ##   cc       tests/cc/<name>.c        — cc -> P1pp -> ELF -> run.
     28 ##   cc-ext   vendor/c-testsuite/single-exec/<name>.c — broad subset
     29 ##                                       coverage from the upstream
     30 ##                                       c-testsuite. needs-libc tests
     31 ##                                       link the mes-libc chain (same
     32 ##                                       as cc-libc); plain tests use
     33 ##                                       the bare cc pipeline. Any
     34 ##                                       compile/assemble/runtime error
     35 ##                                       counts as FAIL.
     36 ##   tcc-cc   tests/cc/<name>.c        — tcc-boot2 -> ELF -> run.
     37 ##   tcc-libc tests/cc-libc/<name>.c   — tcc-boot2 builds mes-libc into
     38 ##                                       libc.o, then compiles + links
     39 ##                                       each fixture against it -> run.
     40 ##
     41 ## All three arches by default; --arch restricts to one.
     42 ##
     43 ## Usage: tests/run.sh --suite <suite> [--arch ARCH] [name ...]
     44 
     45 set -eu
     46 
     47 SUITE=
     48 ARCH=
     49 NAMES=
     50 STAGE=
     51 
     52 while [ "$#" -gt 0 ]; do
     53     case "$1" in
     54         --suite)   shift; SUITE=$1 ;;
     55         --suite=*) SUITE=${1#--suite=} ;;
     56         --arch)    shift; ARCH=$1 ;;
     57         --arch=*)  ARCH=${1#--arch=} ;;
     58         --stage)   shift; STAGE=$1 ;;
     59         --stage=*) STAGE=${1#--stage=} ;;
     60         --) shift; while [ "$#" -gt 0 ]; do NAMES="$NAMES $1"; shift; done; break ;;
     61         -*) echo "$0: unknown flag '$1'" >&2; exit 2 ;;
     62         *) NAMES="$NAMES $1" ;;
     63     esac
     64     shift
     65 done
     66 
     67 case "$SUITE" in
     68     m1pp|p1|scheme1|cc-util|cc-lex|cc-pp|cc-cg|cc|cc-libc|cc-ext|tcc-cc|tcc-libc) ;;
     69     "") echo "$0: --suite required (m1pp | p1 | scheme1 | cc-util | cc-lex | cc-pp | cc-cg | cc | cc-libc | cc-ext | tcc-cc | tcc-libc)" >&2; exit 2 ;;
     70     *) echo "$0: unknown suite '$SUITE'" >&2; exit 2 ;;
     71 esac
     72 
     73 REPO=$(cd "$(dirname "$0")/.." && pwd)
     74 cd "$REPO"
     75 
     76 platform_of() {
     77     case "$1" in
     78         aarch64) echo linux/arm64 ;;
     79         amd64)   echo linux/amd64 ;;
     80         riscv64) echo linux/riscv64 ;;
     81         *) echo "$0: unknown arch '$1'" >&2; return 1 ;;
     82     esac
     83 }
     84 
     85 run_in_container() {
     86     arch=$1; shift
     87     podman run --rm --pull=never --platform "$(platform_of "$arch")" \
     88         --tmpfs /tmp:size=512M \
     89         -e "ARCH=$arch" \
     90         -e "CC_TRACE_EMIT=${CC_TRACE_EMIT:-0}" \
     91         -e "CC_DEBUG=${CC_DEBUG:-0}" \
     92         -e "STAGE=${STAGE:-}" \
     93         -v "$REPO":/work -w /work \
     94         "boot2-busybox-test:$arch" "$@"
     95 }
     96 
     97 if [ -z "$ARCH" ]; then
     98     ARCHES="aarch64 amd64 riscv64"
     99 else
    100     ARCHES=$ARCH
    101 fi
    102 
    103 PASS=0
    104 FAIL=0
    105 
    106 # Lint preflight: lint.sh uses python (host-only). Discover the
    107 # fixture set if --names was empty, lint each raw fixture (.M1pp / .P1),
    108 # emit a host-side FAIL + diagnostic for any miss, write the kept name
    109 # list to $keep_file. FAIL line goes to stdout to interleave with the
    110 # container's PASS/FAIL output; the FAIL counter updates in-scope.
    111 #
    112 # Suite layout:
    113 #   m1pp: tests/M1pp/<name>.M1pp   (no raw .M1 fixtures any more)
    114 #   p1:   tests/P1/<name>.P1pp     (lint skipped — expander output)
    115 #         tests/P1/<name>.P1       (lint runs)
    116 lint_preflight() {
    117     arch=$1; keep_file=$2; dir=$3; raw_ext=$4; pp_ext=$5
    118     : > "$keep_file"
    119     if [ -z "$NAMES" ]; then
    120         raw=$(ls "$dir" 2>/dev/null \
    121              | sed -n "s/^\([^_][^.]*\)\.${raw_ext}\$/\1/p")
    122         pp=$(ls "$dir" 2>/dev/null \
    123              | sed -n "s/^\([^_][^.]*\)\.${pp_ext}\$/\1/p")
    124         all=$(printf '%s\n%s\n' "$raw" "$pp" | sort -u | tr '\n' ' ')
    125     else
    126         all=$NAMES
    127     fi
    128     for name in $all; do
    129         raw_src=$dir/$name.$raw_ext
    130         if [ -e "$raw_src" ] \
    131            && ! ARCH=$arch sh tools/lint.sh "$raw_src" >/dev/null 2>&1; then
    132             echo "  FAIL [$arch] $name"
    133             ARCH=$arch sh tools/lint.sh "$raw_src" 2>&1 \
    134                 | sed 's/^/    /' >&2 || true
    135             FAIL=$((FAIL + 1))
    136         else
    137             printf '%s ' "$name" >> "$keep_file"
    138         fi
    139     done
    140 }
    141 
    142 for arch in $ARCHES; do
    143     case "$SUITE" in
    144         m1pp) preflight_args="tests/M1pp M1 M1pp" ;;
    145         p1)   preflight_args="tests/P1 P1 P1pp" ;;
    146         *)    preflight_args= ;;
    147     esac
    148     if [ -n "$preflight_args" ]; then
    149         keep_file=$(mktemp)
    150         # shellcheck disable=SC2086 # $preflight_args is intentionally word-split.
    151         lint_preflight "$arch" "$keep_file" $preflight_args
    152         names=$(cat "$keep_file")
    153         rm -f "$keep_file"
    154         # Skip the container call only when the user gave names AND
    155         # all of them failed lint. With no names, an empty kept set
    156         # would mean nothing to run anyway.
    157         names_trimmed=$(echo "$names" | tr -d ' \t\n')
    158         if [ -z "$names_trimmed" ]; then
    159             continue
    160         fi
    161     else
    162         names=$NAMES
    163     fi
    164 
    165     out=$(mktemp)
    166     # shellcheck disable=SC2086 # $names is intentionally word-split.
    167     run_in_container "$arch" sh tests/run-suite.sh \
    168         --suite="$SUITE" $names | tee "$out"
    169     p=$(grep -c '^  PASS ' "$out" 2>/dev/null || true)
    170     f=$(grep -c '^  FAIL ' "$out" 2>/dev/null || true)
    171     PASS=$((PASS + ${p:-0}))
    172     FAIL=$((FAIL + ${f:-0}))
    173     rm -f "$out"
    174 done
    175 
    176 echo "$PASS passed, $FAIL failed"
    177 [ "$FAIL" -eq 0 ]