kit

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

rv64.sh (6065B)


      1 #!/usr/bin/env bash
      2 # test/smoke/rv64.sh — end-to-end smoke test for the rv64 podman/qemu path, on
      3 # the shared Type-K mode-P kit (test/lib/kit_sh_kit.sh).
      4 #
      5 # Phase-2 of the multi-arch bring-up: prove the test/lib/exec_target.sh helper
      6 # can build, queue, and run a riscv64-linux ELF before any kit-emitted rv64
      7 # bytes exist. Builds a tiny freestanding static executable with
      8 # clang --target=riscv64-linux-gnu and pushes it through
      9 # exec_target_run / exec_target_queue+flush, asserting exit code 42 on both
     10 # paths. This is one inline program, so it is a single-scenario procedural
     11 # suite (build, exec, assert rc) rather than a file-glob corpus.
     12 #
     13 # Skipped if clang lacks the riscv64-linux-gnu target, ld.lld is missing, or no
     14 # runner (podman or qemu-riscv64) is available. Skip is treated as failure
     15 # unless KIT_TEST_ALLOW_SKIP=1 (the shared kit_exit honors it).
     16 
     17 set -u
     18 
     19 ROOT="$(cd "$(dirname "$0")/../.." && pwd)"
     20 BUILD_DIR="$ROOT/build/test/smoke-rv64"
     21 mkdir -p "$BUILD_DIR"
     22 
     23 KIT_KIT_DIR="$ROOT/test/lib"
     24 # shellcheck source=../lib/kit_sh_kit.sh
     25 . "$ROOT/test/lib/kit_sh_kit.sh"
     26 kit_report_init
     27 
     28 # This harness's convention (preserved from the original smoke runner): a SKIP
     29 # is a failure unless KIT_TEST_ALLOW_SKIP=1, so CI catches a degraded run.
     30 KIT_SKIP_IS_FAILURE=1
     31 
     32 # Mode-P suites are SERIAL and share one $work sandbox.
     33 work="$BUILD_DIR"
     34 
     35 # ---- detect prerequisites --------------------------------------------------
     36 #
     37 # Delegated to test/lib/check_rv64_env.sh (the kit-rv64 doctor). It
     38 # probes clang/lld/qemu/podman/native, prints a per-tool ok/MISSING
     39 # line with install hints, and populates RV64_* globals plus a single
     40 # READY/BLOCKED summary. The smoke script reuses those globals below
     41 # and never re-implements the detection.
     42 # shellcheck source=../lib/check_rv64_env.sh
     43 . "$(cd "$(dirname "$0")/.." && pwd)/lib/check_rv64_env.sh"
     44 check_rv64_env
     45 
     46 have_clang_rv64="$RV64_HAVE_CLANG_TARGET"
     47 have_lld="$RV64_HAVE_LLD"
     48 
     49 CLANG_TARGET="--target=riscv64-linux-gnu"
     50 
     51 # Variables expected by exec_target.sh. The aarch64 helper expects
     52 # these names regardless of target arch — they describe the host
     53 # detection rather than the target. For rv64-only smoke we don't need
     54 # QEMU_BIN (that's the aarch64 user-mode qemu); rv64 picks up
     55 # qemu-riscv64 automatically inside _exec_target_qemu (which honors
     56 # QEMU_RV64_BIN from the doctor as well).
     57 have_qemu=0
     58 QEMU_BIN=""
     59 have_podman="$RV64_HAVE_PODMAN"
     60 QEMU_RV64_BIN="$RV64_QEMU_BIN"
     61 arch_raw="$(uname -m 2>/dev/null || true)"
     62 is_aarch64=0
     63 { [ "$arch_raw" = "aarch64" ] || [ "$arch_raw" = "arm64" ]; } && is_aarch64=1
     64 export have_qemu QEMU_BIN have_podman is_aarch64 QEMU_RV64_BIN
     65 
     66 EXEC_TARGET_MOUNT_ROOT="$BUILD_DIR"
     67 export EXEC_TARGET_MOUNT_ROOT
     68 # shellcheck source=../lib/exec_target.sh
     69 . "$ROOT/test/lib/exec_target.sh"
     70 
     71 if [ "$have_clang_rv64" -eq 0 ]; then
     72     skip_test "build" "clang --target=riscv64-linux-gnu unavailable — install: $(_rv64_hint_clang)"
     73     kit_summary test-smoke-rv64; kit_exit
     74 fi
     75 if [ "$have_lld" -eq 0 ]; then
     76     skip_test "build" "ld.lld unavailable — install: $(_rv64_hint_lld)"
     77     kit_summary test-smoke-rv64; kit_exit
     78 fi
     79 if ! exec_target_supported rv64; then
     80     # No runner: pick the most actionable hint. qemu is the lightest
     81     # to install on a contributor box; podman is the second-best.
     82     skip_test "exec" "no rv64 runner — easiest fix: $(_rv64_hint_qemu); or set up podman ($(_rv64_hint_podman_riscv64))"
     83     kit_summary test-smoke-rv64; kit_exit
     84 fi
     85 
     86 # ---- build a tiny freestanding riscv64 ELF ----------------------------------
     87 
     88 # Direct syscall in _start: SYS_exit_group on rv64 is 94 (a7), exit
     89 # code 42 (a0). No libc, no relocations, no PIE. The point is to
     90 # exercise the harness pipeline (clang cross-compile -> podman/qemu
     91 # run -> recorded rc), not to build a complete program.
     92 SRC="$BUILD_DIR/smoke.c"
     93 cat >"$SRC" <<'EOF'
     94 __attribute__((noreturn)) void _start(void) {
     95   register long a7 __asm__("a7") = 94; /* sys_exit_group */
     96   register long a0 __asm__("a0") = 42;
     97   __asm__ volatile("ecall" : : "r"(a7), "r"(a0) : "memory");
     98   __builtin_unreachable();
     99 }
    100 EOF
    101 
    102 EXE="$BUILD_DIR/smoke.exe"
    103 if ! clang $CLANG_TARGET -march=rv64gc -fuse-ld=lld \
    104         -O1 -ffreestanding -fno-stack-protector \
    105         -fno-PIC -fno-pie -nostdlib -static \
    106         -Wl,-e,_start \
    107         "$SRC" -o "$EXE" 2>"$BUILD_DIR/build.err"; then
    108     not_ok "build" "$BUILD_DIR/build.err"
    109     kit_summary test-smoke-rv64; kit_exit
    110 fi
    111 ok "build"
    112 
    113 # Classify the recorded rc on a non-42 result. 125/126/127 are podman/shell
    114 # "couldn't execute" rcs — treat those as setup failures and run the podman
    115 # classifier so the contributor sees one line saying *which* podman issue it
    116 # is. ERRFILE / NAME / RC are passed in.
    117 note_run_fail() {
    118     local name="$1" rc="$2" errfile="$3" diag="$BUILD_DIR/$4.diag"
    119     if [ "${RV64_HAVE_PODMAN:-0}" -eq 1 ] && \
    120        { [ "$rc" -eq 125 ] || [ "$rc" -eq 126 ] || [ "$rc" -eq 127 ]; }; then
    121         printf '(rc=%s) — %s\n' "$rc" "$(classify_podman_rv64_error "$errfile")" > "$diag"
    122     else
    123         printf 'expected 42 got %s; see %s\n' "$rc" "$errfile" > "$diag"
    124     fi
    125     not_ok "$name" "$diag"
    126 }
    127 
    128 # ---- exec_target_run ---------------------------------------------------------
    129 
    130 exec_target_run rv64 "$EXE" "$BUILD_DIR/run.out" "$BUILD_DIR/run.err"
    131 if [ "$RUN_RC" -eq 42 ]; then
    132     ok "exec_target_run rv64 (rc=42)"
    133 else
    134     note_run_fail "exec_target_run rv64" "$RUN_RC" "$BUILD_DIR/run.err" "run"
    135 fi
    136 
    137 # ---- exec_target_queue + flush ----------------------------------------------
    138 
    139 exec_target_queue rv64 smoke "$EXE" \
    140     "$BUILD_DIR/q.out" "$BUILD_DIR/q.err" "$BUILD_DIR/q.rc"
    141 exec_target_flush
    142 if [ ! -f "$BUILD_DIR/q.rc" ]; then
    143     echo "no rc file produced" > "$BUILD_DIR/q.diag"
    144     not_ok "exec_target_queue+flush rv64" "$BUILD_DIR/q.diag"
    145 else
    146     Q_RC="$(cat "$BUILD_DIR/q.rc")"
    147     if [ "$Q_RC" -eq 42 ]; then
    148         ok "exec_target_queue+flush rv64 (rc=42)"
    149     else
    150         note_run_fail "exec_target_queue+flush rv64" "$Q_RC" "$BUILD_DIR/q.err" "q"
    151     fi
    152 fi
    153 
    154 kit_summary test-smoke-rv64
    155 kit_exit