#!/bin/sh # brintOS wasm32-hwjs replacement for elfutils' upstream run-ptest. # # Upstream runs the suite as `make -k installcheck-local`, and automake's # serial-tests check-TESTS recipe execs ONE `sh -c` carrying the whole TESTS list # plus TESTS_ENVIRONMENT. On this arm that argv block is 10,787 bytes against an # 8,192-byte __wasm32_args_buf, and an execve that exceeds it never returns -- # the child is lost and the parent waits forever (brintos/hardwarejs#15). # The suite therefore produced NO output at all under make, and was only ever # stopped by an outer wall-clock bound. # # So the drivers are run one at a time instead, which is what automake's serial # harness does anyway -- the difference is only that the list never becomes a # single argv. Everything else is upstream's: the same TESTS list read from # upstream's own Makefile, the same test-wrapper.sh, the same environment # TESTS_ENVIRONMENT sets, and the same PASS/FAIL/SKIP-by-exit-status contract # (0 pass, 77 skip, anything else fail). No test is skipped, reordered or # reinterpreted here. # # BRINTOS-WORKAROUND: hardwarejs#15 revisit -- restore upstream's # `make -k installcheck-local` once an execve whose argv exceeds # __wasm32_args_buf fails with E2BIG instead of losing the child. set -u cd "$(dirname "$0")/tests" || exit 1 # TESTS_ENVIRONMENT, verbatim from the generated Makefile, minus the valgrind # arm (VALGRIND_CMD is empty here, as it is in the recipe's own build). abs_srcdir=$PWD abs_builddir=$PWD abs_top_builddir=$(cd .. && pwd) export abs_srcdir abs_builddir abs_top_builddir # srcdir/top_srcdir are NOT in TESTS_ENVIRONMENT: upstream's run-ptest passes # them on make's command line, and make exports command-line variables to every # recipe's environment. Every driver's line 19 is `. $srcdir/test-subr.sh`, so # without them each one dies on `can't open '/test-subr.sh'` -- and, because the # failure is in the sourced setup, exits 0 and would be scored a PASS. They must # be absolute: the drivers cd into a per-test subdirectory before using them. srcdir=$PWD top_srcdir=$abs_top_builddir export srcdir top_srcdir LC_ALL=C LANG=C VALGRIND_CMD='' export LC_ALL LANG VALGRIND_CMD unset DEBUGINFOD_URLS 2>/dev/null || true NM=eu-nm CC=gcc export NM CC # What run-ptest's own `make` line passed, and what test-wrapper.sh needs. libdir=/usr/lib bindir=/usr/bin export libdir bindir # The TESTS list, read from upstream's Makefile and written one name per line so # it is never expanded into an argument list. Handles the `TESTS = ` assignment # and any `TESTS += ` blocks, both of which use backslash continuations. # # EXPANDING MAKE'S VARIABLES IS NOT A NICETY HERE. automake writes every # compiled test program into TESTS as `newfile$(EXEEXT)`, groups nine of them # behind `$(am__EXEEXT_1)`, and every conditional group behind # `$(am__append_N)`. Read literally, none of those names exists on disk -- so a # driver that only checks `[ -e "$t" ]` reports each of them SKIP and runs # nothing. That is 36 of the 244 tests: the 35 compiled C programs (asm-tst1-9, # update1-4, the dwfl-* set, newfile/newdata/newscn, test-nlist and the rest -- # the whole libelf/libdw/libasm API surface, which no run-*.sh driver covers) # plus the one conditional driver this build enables. They read as # "legitimately absent" while nothing had executed. Five of the six am__append # groups are empty (their configure conditionals are off), and those must vanish # rather than become phantom skips. Substituting one $(VAR) at a time until # none is left, with an undefined or empty variable expanding to nothing, is # exactly what make does with the same text: the list this produces was checked # name-for-name against `make print-tests` on the installed Makefile and is # equal to it -- 244 names, no duplicates, every one present on disk. list=${TMPDIR:-/tmp}/eu-ptest-tests.$$ awk ' function trim(s) { sub(/^[ \t]+/, "", s); sub(/[ \t]+$/, "", s); return s } { line = $0 sub(/\r$/, "", line) if (cont) { more = line cont = (more ~ /\\$/) sub(/[ \t]*\\$/, "", more) val[curr] = val[curr] " " more next } # A variable assignment starts in column 1; a recipe line is tab-indented, # so this cannot mistake a command containing `=` for one. if (match(line, /^[A-Za-z_][A-Za-z0-9_]*[ \t]*\+?=/)) { eq = index(line, "=") lhs = substr(line, 1, eq - 1) append = (lhs ~ /\+[ \t]*$/) sub(/\+[ \t]*$/, "", lhs) name = trim(lhs) rhs = substr(line, eq + 1) cont = (rhs ~ /\\$/) sub(/[ \t]*\\$/, "", rhs) if (append && (name in val)) val[name] = val[name] " " rhs else val[name] = rhs if (cont) curr = name next } } END { s = ("TESTS" in val) ? val["TESTS"] : "" # Bounded: a self-referential variable would otherwise spin here, and a # truncated list is a better failure than a hung one. guard = 0 while (match(s, /\$\([A-Za-z_][A-Za-z0-9_]*\)/) && guard++ < 1000) { v = substr(s, RSTART + 2, RLENGTH - 3) s = substr(s, 1, RSTART - 1) ((v in val) ? val[v] : "") \ substr(s, RSTART + RLENGTH) } n = split(s, a, /[ \t]+/) for (i = 1; i <= n; i++) if (a[i] != "") print a[i] } ' Makefile > "$list" pass=0 fail=0 skip=0 echo "BEGIN: $abs_top_builddir" while IFS= read -r t; do [ -n "$t" ] || continue if [ ! -e "$t" ]; then # A test whose program was not built (the dlopen-only fixture is dropped in # an all-static build) is reported, never silently omitted. echo "SKIP: $t" skip=$((skip + 1)) continue fi ./test-wrapper.sh installed no 's,^,eu-,' "./$t" > /dev/null 2>&1 rc=$? case $rc in 0) echo "PASS: $t"; pass=$((pass + 1)) ;; 77) echo "SKIP: $t"; skip=$((skip + 1)) ;; *) echo "FAIL: $t"; fail=$((fail + 1)) ;; esac done < "$list" rm -f "$list" echo "END: $abs_top_builddir" echo "TOTAL: $((pass + fail + skip)) PASS: $pass FAIL: $fail SKIP: $skip" [ "$fail" -eq 0 ]