. "$BST_LIB" require perl libtest-fatal-perl/present # BST-TIMEOUT: 600 # # Set from a measurement, not guessed -- see the elapsed figure this suite's own # `==BST-SUITE` line reports. 600 leaves the headroom the packager README asks # for; without a marker the runner applies its 60 s default and every perl # subprocess here costs seconds rather than milliseconds # (linux-in-the-browser#117). # # Test::Fatal 0.017 (POKY meta/recipes-devtools/perl/libtest-fatal-perl_0.017.bb # -- NOT meta-oe, which the ticket names; see the design doc) -- `exception`, # `dies_ok` and `lives_ok`, the helpers a Perl test suite uses to assert that # code does or does not throw. Seventeenth Perl module on this image under # BRINTOS-999. Pure Perl over Try::Tiny, so BRINTOS-881 -- the -Uusedl # -Uuseshrplib arm that stops every XS module here -- does not apply. # # THIS SUITE'S PASS CRITERION IS THE DISTRIBUTION'S OWN t/, NOT A HAND-WRITTEN # BATTERY -- the ticket's own wording. The port therefore installs the suite # (libtest-fatal-perl-ptest, from PTEST_ENABLED = "1" for this recipe alone) and # section 5 runs `prove -r t/` over it. # # WHY THIS ONE CAN PASS WHERE libmodule-build-perl AND libdev-checklib-perl # COULD NOT, stated up front because it is the port's one real risk and it was # settled by reading the four .t files rather than by hoping. Both of those ports # lost their whole-run verdict to linux-in-the-browser#93 -- a # `panic: magic_killbackrefs` use-after-free in Test2::Hub's teardown -- and # 36-libdev-checklib-perl.test isolated the trigger to ONE of Test::More's two # plan forms: `plan tests => N` works on this arm, `plan skip_all` panics. All # four of Test::Fatal's files use `tests => N` (7, 6, 4 and 1) and NONE of them # contains a skip_all or a done_testing. Section 4b re-measures that pair on the # boot rather than citing it, so a criterion that goes red is attributed to the # right mechanism by evidence from the same interpreter. # # EVERY REFERENCE BELOW WAS MEASURED, NOT READ OFF THE TARBALL. The control is # the same 0.017 tree on x86-64 (perl 5.38.2), driven exactly as section 5 # drives it, and run BOTH with and without CPAN::Meta on @INC -- CPAN::Meta is a # *recommends* of t/00-report-prereqs.t and is not on this image, so the # unblocked control would have been the wrong reference. Both give # `All tests successful.`, Files=4, Tests=18, Result: PASS, exit 0. # # Five layers: # 1. filesystem facts -- what the port SHIPS, asserted before anything starts # perl, so they hold on a boot where the interpreter cannot load a module. # 2. the harness the criterion names, and the Test::* core modules it needs. # 3. can perl load the module on this boot, classified on the diagnostic. # 4. the SEMANTICS, at values, against the x86-64 control: both directions the # ticket names (raised-and-caught, and completed), plus the TAP that # dies_ok/lives_ok actually emit -- in both the passing and failing # direction, so a helper that always says `ok` is caught. # 5. the criterion: prove -r t/ over the installed suite. # perl prints a four-line locale-warning preamble on EVERY invocation on this # image, on stderr. Sections 3-5 capture 2>&1 (they must: a prove that died has # said so on stderr), so without this strip every red would report "Setting # locale failed" in the 100-char detail field -- the wrong diagnosis in the one # place a later reader attributes by. Same strip as 36-libparse-yapp-perl.test. _tf_clean() { printf '%s\n' "$1" | awk '/^perl: warning/ { skip=1; next } /^[ \t]/ && skip { next } { skip=0; print }' } V=$(ls -d /usr/lib/perl5/vendor_perl/* 2>/dev/null | head -1) CORE=$(ls -d /usr/lib/perl5/5.* 2>/dev/null | head -1) PT=/usr/lib/libtest-fatal-perl/ptest # ------------------------- 1. what the port SHIPS: filesystem facts ---------- # The VERSION dir, not the arch dir: Test::Fatal is pure Perl, so cpan installs # it to vendor_perl// and NOT to the vendor_perl//-linux/ that # 36-libdbi-perl.test globs for its XS module. check libtest-fatal-perl/vendor-dir test -n "$V" check libtest-fatal-perl/module-installed test -f "$V/Test/Fatal.pm" # Try::Tiny is the ENGINE, not a neighbour: Test::Fatal::exception IS a # try/catch, so a missing Try::Tiny turns every case in sections 3-5 into a load # failure. It is the one non-perl-module name in the recipe's RDEPENDS:${PN}, # and it reached this image under its own port (BRINTOS-999's second module). check libtest-fatal-perl/trytiny-installed test -f "$V/Try/Tiny.pm" # THE INSTALLED SUITE -- the deliverable the ticket's criterion runs on. poky's # recipe already inherits ptest-perl, but the class deletes its own task unless # PTEST_ENABLED is 1, and this distro's DISTRO_FEATURES has no `ptest`. These # cases are what says this layer's one-line bbappend took effect. check libtest-fatal-perl/ptest-dir test -d "$PT/t" check libtest-fatal-perl/ptest-runptest test -f "$PT/run-ptest" for t in 00-report-prereqs basic like-exception todo; do check "libtest-fatal-perl/ptest-$t" test -f "$PT/t/$t.t" done # 4 -- the whole of the distribution's t/. This recipe prunes none of them, so # the count is the tarball's and a recipe that started dropping files reds here. # The x86-64 control ran exactly these 4. check_eq libtest-fatal-perl/ptest-count 4 "$(ls "$PT"/t/*.t 2>/dev/null | wc -l | tr -d ' ')" # The .dd is a DATA file, not a test, and it is the one thing ptest-perl's bare # `cp -r ${B}/t` could plausibly have left behind. t/00-report-prereqs.t reads it # as `do './t/00-report-prereqs.dd'` -- a path relative to CWD, which is why # section 5 runs prove from the ptest root rather than from anywhere else. # # THE CRITERION CANNOT SEE THIS ONE, WHICH IS THE REASON IT IS ASSERTED HERE. # Deleting the .dd was expected to kill that file and was measured instead: # 00-report-prereqs.t still reports `ok`, Result: PASS, Tests=1. Its single # assertion is a pass() at the end, and $static_prereqs simply comes back undef, # so the prereq table it exists to print silently empties out. A green run is # therefore compatible with the file being gone -- so the filesystem case is the # only thing that would notice a recipe that stopped shipping it. check libtest-fatal-perl/ptest-dd test -f "$PT/t/00-report-prereqs.dd" # ------------------- 2. the harness the criterion names ---------------------- # `prove` reached this image under libdbi-perl (perl-misc + perl-module-app-prove) # and WORKS only because libdev-checklib-perl added the 43 perl-module-tap-* # splits. Asserted as ordinary reds, not as a `require`: their absence is a # regression to report, not a reason to skip this port's criterion. check libtest-fatal-perl/prove-installed test -x /usr/bin/prove check libtest-fatal-perl/prove-lib test -f "$CORE/App/Prove.pm" # The three Test::* core modules poky's recipe names in RDEPENDS, each on its own # case. All three are perl-module-* splits of this image's 1146-way perl, and the # distribution's four .t files divide across them: Test::More (all four), # Test::Builder (Test::Fatal itself, for dies_ok/lives_ok), Test::Builder::Tester # (like-exception.t and todo.t). A missing one is a specific finding, not "the # criterion failed". check libtest-fatal-perl/tb-installed test -f "$CORE/Test/Builder.pm" check libtest-fatal-perl/tbt-installed test -f "$CORE/Test/Builder/Tester.pm" check libtest-fatal-perl/testmore-installed test -f "$CORE/Test/More.pm" # ------------------ 3. can perl LOAD this module on this boot? --------------- # Pure Perl, so BRINTOS-881 does not apply and no .so is wanted. A clean import # is the expected -- and the only passing -- outcome. Failure is classified on # the diagnostic so a red says WHOSE defect it is rather than quoting 100 # characters of transcript. pout=$(perl -e ' eval { require Test::Fatal }; if ($@) { print "LOAD-FAILED: $@"; exit 1 } print "LOAD-OK $Test::Fatal::VERSION\n";' 2>&1) pout=$(_tf_clean "$pout") case "$pout" in *"LOAD-OK"*) bst_ok libtest-fatal-perl/require-loads ;; *"Can't locate Try/Tiny.pm"*) bst_notok libtest-fatal-perl/require-loads \ "Try::Tiny is absent -- the engine, declared in RDEPENDS:\${PN}: $(_bst_1line "$pout")" ;; *"Can't locate"*) bst_notok libtest-fatal-perl/require-loads \ "a module in the closure is not on the image: $(_bst_1line "$pout")" ;; *"panic:"*) bst_notok libtest-fatal-perl/require-loads \ "perl PANICKED loading a pure-Perl module -- a platform defect, not this port's: $(_bst_1line "$pout")" ;; *) bst_notok libtest-fatal-perl/require-loads "$(_bst_1line "$pout")" ;; esac check_out libtest-fatal-perl/import-load "TF-OK" perl -MTest::Fatal -e 'print "TF-OK\n"' # ------------------ 4. THE SEMANTICS, at values, vs the x86-64 control ------- # The payload measures; this file names and compares, so a single wrong answer # is one red case rather than one red suite. out=$(perl "$BST_DATA/libtest-fatal-perl-selftest.pl" 2>&1); rc=$? out=$(_tf_clean "$out") case "$out" in *ALL-TEST-FATAL-OK*) all=1 ;; *) all=0 ;; esac if [ "$rc" -eq 0 ] && [ "$all" -eq 1 ]; then bst_ok libtest-fatal-perl/all-ok else bst_notok libtest-fatal-perl/all-ok "rc=$rc $(_bst_1line "$out")"; fi val() { printf '%s\n' "$out" | awk -v t="$1" '$1==t{ $1=""; sub(/^ /,""); print; exit }'; } # --- identity, and that it came from the image ------------------------------ check_eq libtest-fatal-perl/version 0.017 "$(val R1-version)" case "$(val R2-inc-path)" in /usr/*) bst_ok libtest-fatal-perl/installed-path ;; *) bst_notok libtest-fatal-perl/installed-path "Test/Fatal.pm resolved to $(val R2-inc-path)" ;; esac check_eq libtest-fatal-perl/export-default exception "$(val R3-export-default)" check_eq libtest-fatal-perl/export-ok 'exception,success,dies_ok,lives_ok' "$(val R4-export-ok)" # The prototypes are load-bearing, not decoration: `exception { ... }` parses as # a block call only because exception is (&), and the `try {} catch {} success {}` # chain only because success is (&;@). A module that lost them would `require` # cleanly and fail at every call site in every caller's t/. check_eq libtest-fatal-perl/proto-exception '&' "$(val R5-proto-exception)" check_eq libtest-fatal-perl/proto-success '&;@' "$(val R6-proto-success)" check_eq libtest-fatal-perl/proto-dies-ok '&;$' "$(val R7-proto-dies-ok)" check_eq libtest-fatal-perl/proto-lives-ok '&;$' "$(val R8-proto-lives-ok)" # Try::Tiny resolved through the closure rather than by luck of @INC check_eq libtest-fatal-perl/trytiny-version 0.31 "$(val R9-trytiny-version)" case "$(val R9b-trytiny-path)" in /usr/*) bst_ok libtest-fatal-perl/trytiny-path ;; *) bst_notok libtest-fatal-perl/trytiny-path "Try/Tiny.pm resolved to $(val R9b-trytiny-path)" ;; esac # --- THE TICKET'S TWO DIRECTIONS ------------------------------------------- # "an exception raised and caught, and a block that completes". Four values, # because the three no-exception forms fail differently: a block returning true, # an empty block, and a block returning FALSE -- the last is the one a naive # implementation gets wrong, since 0 and "no exception" look alike. check_eq libtest-fatal-perl/exception-msg boom "$(val R10-exception-msg)" check_eq libtest-fatal-perl/exception-undef '' "$(val R11-exception-undef)" check_eq libtest-fatal-perl/exception-empty-block '' "$(val R12-exception-empty-block)" check_eq libtest-fatal-perl/exception-zero-return '' "$(val R13-exception-zero-return)" # a die with no trailing newline gets perl's " at FILE line N." appended. The # SHAPE is asserted before the message is stripped, because a Test::Fatal that # returned a truncated message is indistinguishable from a correct one once the # tail is gone -- and this is also the one case in the suite that reads perl's # own die-message construction on this arm. check_eq libtest-fatal-perl/die-noeol-shape 1 "$(val R14-die-noeol-shape)" check_eq libtest-fatal-perl/die-noeol-token nonl "$(val R15-die-noeol-token)" # a thrown object arrives as the SAME reference, not a stringification of one check_eq libtest-fatal-perl/obj-class My::Err "$(val R16-obj-class)" check_eq libtest-fatal-perl/obj-field 42 "$(val R17-obj-field)" check_eq libtest-fatal-perl/obj-identity SAME "$(val R18-obj-identity)" # WHAT THE MODULE IS FOR, as a pair. An exception object that is FALSE in # boolean context cannot be RETURNED by exception() -- a false return means "no # exception" -- so Test::Fatal confesses instead, which is still a report rather # than a silent miss. The bare `eval {}; if ($@)` idiom it replaces misses the # same exception outright. Needs the overload pragma to construct, so both cases # skip together where the image has no perl-module-overload; the skip fires only # on a POSITIVE statement that the payload got that far. if [ -z "$(val R19-false-exception)" ] && [ "$all" = 0 ]; then bst_skip libtest-fatal-perl/false-exception "payload did not reach the overload cases" bst_skip libtest-fatal-perl/eval-idiom-misses "payload did not reach the overload cases" else check_eq libtest-fatal-perl/false-exception \ 'false exception caught by Test::Fatal::exception' "$(val R19-false-exception)" check_eq libtest-fatal-perl/eval-idiom-misses MISSED "$(val R20-eval-idiom-misses)" fi # --- $@ is not clobbered: Try::Tiny's promise, inherited by exception() ----- check_eq libtest-fatal-perl/inner-token inner "$(val R21-inner-token)" check_eq libtest-fatal-perl/at-preserved sentinel "$(val R22-at-preserved)" # --- success blocks, in the block syntax every caller writes ---------------- # The order strings are Try::Tiny's own unwind order, pinned against the control # rather than assumed: success() is implemented AS a finally that returns early # when handed arguments, and Try::Tiny unwinds its finally handlers in reverse # declaration order -- which is why `finally` precedes `success` here even though # it is written after it. The substantive assertion is the pair: on the success # path the success block runs, on the failure path it does not. check_eq libtest-fatal-perl/order-success 'try,finally,success' "$(val R23-order-success)" check_eq libtest-fatal-perl/order-failure 'try,catch,finally' "$(val R24-order-failure)" check_eq libtest-fatal-perl/success-not-on-failure 'not-on-failure' "$(val R24b-success-ran-once)" # --- nesting: exception() inside exception() is what callers' t/ lean on ---- check_eq libtest-fatal-perl/nested-inner '' "$(val R25-nested-inner)" check_eq libtest-fatal-perl/nested-outer-undef '' "$(val R26-nested-outer-undef)" check_eq libtest-fatal-perl/rethrow one "$(val R27-rethrow)" check_eq libtest-fatal-perl/list-block-undef '' "$(val R28-list-block-undef)" check_eq libtest-fatal-perl/test-builder 1.302194 "$(val R29-test-builder)" check_eq libtest-fatal-perl/test-builder-tester 1.302194 "$(val R30-test-builder-tester)" # ---------- 4a. dies_ok / lives_ok EMIT TAP, in both directions ------------- # The ticket names these two by name. They are not value-returning like # exception(): their whole output is a TAP line through Test::Builder, so they # are driven in their own perl and the TAP is read back. BOTH directions are # asserted -- a helper hard-wired to print `ok` passes the happy cases and is # exactly what the failing pair catches. tap=$(perl -MTest::More -e ' use Test::Fatal qw(dies_ok lives_ok); plan tests => 2; dies_ok { die "x\n" } "d"; lives_ok { 1 } "l";' 2>&1) tap=$(_tf_clean "$tap") case "$tap" in *"ok 1 - d"*) bst_ok libtest-fatal-perl/dies-ok-tap ;; *) bst_notok libtest-fatal-perl/dies-ok-tap "$(_bst_1line "$tap")" ;; esac case "$tap" in *"ok 2 - l"*) bst_ok libtest-fatal-perl/lives-ok-tap ;; *) bst_notok libtest-fatal-perl/lives-ok-tap "$(_bst_1line "$tap")" ;; esac case "$tap" in *"not ok"*) bst_notok libtest-fatal-perl/tap-no-false-red "$(_bst_1line "$tap")" ;; *) bst_ok libtest-fatal-perl/tap-no-false-red ;; esac # the failing direction: a block that does NOT die must make dies_ok say so, and # say WHY on the diagnostic channel. Without this pair the three cases above # would pass against a stub. ntap=$(perl -MTest::More -e ' use Test::Fatal qw(dies_ok lives_ok); plan tests => 2; dies_ok { 1 } "nd"; lives_ok { die "y\n" } "nl";' 2>&1) ntap=$(_tf_clean "$ntap") case "$ntap" in *"not ok 1 - nd"*) bst_ok libtest-fatal-perl/dies-ok-negative ;; *) bst_notok libtest-fatal-perl/dies-ok-negative "dies_ok did not fail on a block that returned -- $(_bst_1line "$ntap")" ;; esac case "$ntap" in *"not ok 2 - nl"*) bst_ok libtest-fatal-perl/lives-ok-negative ;; *) bst_notok libtest-fatal-perl/lives-ok-negative "lives_ok did not fail on a block that died -- $(_bst_1line "$ntap")" ;; esac case "$ntap" in *"expected an exception but none was raised"*) bst_ok libtest-fatal-perl/dies-ok-diag ;; *) bst_notok libtest-fatal-perl/dies-ok-diag "$(_bst_1line "$ntap")" ;; esac case "$ntap" in *"expected return but an exception was raised"*) bst_ok libtest-fatal-perl/lives-ok-diag ;; *) bst_notok libtest-fatal-perl/lives-ok-diag "$(_bst_1line "$ntap")" ;; esac # ---------- 4b. THE PLAN FORM THE CRITERION USES, measured on this boot ------ # 36-libdev-checklib-perl.test isolated linux-in-the-browser#93 to ONE of # Test::More's two plan forms: `plan tests => N` works on this arm, `plan # skip_all` panics in Test2::Hub's teardown. All four of this distribution's # files use `tests => N`, so the criterion below is expected to survive where # libmodule-build-perl's and libdev-checklib-perl's did not. That expectation is # re-measured here rather than cited, so a red in section 5 is attributed from # evidence taken on the SAME interpreter, on the same boot. pt=$(perl -MTest::More -e 'plan tests => 1; ok(1, "ab");' 2>&1) pt=$(_tf_clean "$pt") case "$pt" in *"panic:"*) bst_notok libtest-fatal-perl/plan-tests-no-panic \ "plan tests => N panics on this boot, so the criterion cannot pass either -- $(_bst_1line "$pt")" ;; *"ok 1"*) bst_ok libtest-fatal-perl/plan-tests-no-panic ;; *) bst_notok libtest-fatal-perl/plan-tests-no-panic "$(_bst_1line "$pt")" ;; esac # and that none of the four files reaches the form that DOES panic -- a property # of the shipped tarball, asserted on the target so a future 0.018 that adds a # skip_all cannot quietly turn the criterion red without saying why. sa=$(grep -l 'skip_all\|done_testing' "$PT"/t/*.t 2>/dev/null | tr '\n' ' ') if [ -z "$sa" ]; then bst_ok libtest-fatal-perl/no-skipall-in-suite else bst_notok libtest-fatal-perl/no-skipall-in-suite \ "these files reach a plan form #93 panics on: $sa"; fi # ------------------------- 5. THE CRITERION: prove -r t/ --------------------- # Run from a WRITABLE COPY, not in place: the deployed rootfs is read-only at # browser runtime. Cheap here (4 files) and it removes a whole class of false # red. CWD matters beyond writability: t/00-report-prereqs.t reads its data as # `do './t/00-report-prereqs.dd'`, relative to CWD, so prove has to run from the # directory that HOLDS t/ -- which is also how run-ptest invokes it. WD=${TMPDIR:-/tmp}/bst-libtest-fatal-perl.$$ PW=$WD/ptest mkdir -p "$PW" && cp -r "$PT/t" "$PW/t" 2>/dev/null check libtest-fatal-perl/suite-staged test -f "$PW/t/basic.t" check libtest-fatal-perl/suite-staged-dd test -f "$PW/t/00-report-prereqs.dd" # THE HARNESS ITSELF, BEFORE THE CRITERION THAT RIDES ON IT. `prove` resolving # and parsing is not the same as `prove` running: TAP::Harness names its five # collaborators as bare strings and loads them at run time, so poky's # use-scanning RDEPENDS generator never saw them and an image can carry a # /usr/bin/prove that dies on first invocation. Asserted on a trivial # self-contained test so a broken harness reds HERE, by name, instead of turning # the cases below into an unreadable heap. A .t file is a PROGRAM prove executes, # not a TAP transcript it reads -- so the smoke file is perl that PRINTS the # plan, not the plan itself. cat > "$PW/smoke.t" <<'SMOKE' print "1..1\nok 1 - smoke\n"; SMOKE smoke=$(cd "$PW" && prove smoke.t 2>&1); srn=$? smoke=$(_tf_clean "$smoke") case "$smoke" in *"Result: PASS"*) bst_ok libtest-fatal-perl/prove-smoke ;; *) bst_notok libtest-fatal-perl/prove-smoke \ "rc=$srn prove cannot run a 1-line passing test -- $(_bst_1line "$smoke")" ;; esac rm -f "$PW/smoke.t" cout=$(cd "$PW" && prove -r t/ 2>&1); crc=$? cout=$(_tf_clean "$cout") # `Result: PASS` is prove's own verdict over the whole run and is the ticket's # "reporting zero failures" verbatim; the exit status is asserted beside it # because a harness that died before printing a verdict leaves neither. The red # carries its ATTRIBUTION rather than just the transcript. case "$cout" in *"Result: PASS"*) bst_ok libtest-fatal-perl/prove-result ;; *) if printf '%s\n' "$cout" | grep -q '^panic: magic_killbackrefs'; then why="linux-in-the-browser#93 -- perl's magic_killbackrefs use-after-free in Test2 teardown; the identical tree is Result: PASS on x86-64" elif printf '%s\n' "$cout" | grep -q '^panic: '; then why="a perl interpreter panic that is NOT #93's magic_killbackrefs -- read perl-no-panic's detail" else why="no interpreter panic -- this is a genuine test failure and is THIS PORT'S to answer" fi bst_notok libtest-fatal-perl/prove-result "rc=$crc $(_bst_1line "$cout") -- $why" ;; esac check_eq libtest-fatal-perl/prove-rc 0 "$crc" case "$cout" in *"All tests successful."*) bst_ok libtest-fatal-perl/prove-all-successful ;; *) bst_notok libtest-fatal-perl/prove-all-successful "$(_bst_1line "$cout")" ;; esac # The file count is pinned EXACTLY -- it is a property of the package, already # asserted on the rootfs in section 1, and a harness that silently ran fewer # files is the failure a green verdict cannot show. files=$(printf '%s\n' "$cout" | sed -n 's/^Files=\([0-9]*\),.*/\1/p' | tail -1) check_eq libtest-fatal-perl/prove-files 4 "$files" # The assertion count is bounded from BELOW, not pinned. 18 is what the x86-64 # control ran (1 + 7 + 6 + 4), both with and without CPAN::Meta on @INC; none of # the four files skips anything on this arm, so a lower number means a file died # part-way and prove still counted it. Bounding from below rather than pinning # keeps a future 0.018 with an extra case from reading as a regression. tests=$(printf '%s\n' "$cout" | sed -n 's/^Files=[0-9]*, Tests=\([0-9]*\),.*/\1/p' | tail -1) case "$tests" in ''|*[!0-9]*) bst_notok libtest-fatal-perl/prove-tests "no Tests= total in prove's summary -- $(_bst_1line "$cout")" ;; *) if [ "$tests" -ge 18 ]; then bst_ok libtest-fatal-perl/prove-tests else bst_notok libtest-fatal-perl/prove-tests "Tests=$tests, want >= 18 (x86-64 control ran 18)"; fi ;; esac # THE FOUR FILES, PINNED BY NAME. A skip and a pass are both green to prove, so # without this a regression that turned all four into skips would still report # Result: PASS -- the exact false green the criterion is meant to exclude. None # of the four can legitimately skip here: all are self-contained, needing only # Test::Fatal, Try::Tiny and the three Test::* core modules section 2 asserted. for t in 00-report-prereqs basic like-exception todo; do line=$(printf '%s\n' "$cout" | grep -m1 "^t/$t\.t ") case "$line" in '') bst_notok "libtest-fatal-perl/ran-$t" "t/$t.t has no line in prove's transcript -- it did not run at all" ;; *skipped*) bst_notok "libtest-fatal-perl/ran-$t" "t/$t.t skipped; it is self-contained and must run -- $(_bst_1line "$line")" ;; *ok*) bst_ok "libtest-fatal-perl/ran-$t" ;; *) bst_notok "libtest-fatal-perl/ran-$t" "$(_bst_1line "$line")" ;; esac done # WHICH FILES FAILED, BY NAME. Without this a non-zero prove is one red carrying # 100 characters of transcript, and the file that actually broke is whichever one # happened to print first. prove's Test Summary Report names each on a line of # the form `t/.t (Wstat: ...)`, so the names are recoverable and belong in # the report rather than in a later reader's guess. bad=$(printf '%s\n' "$cout" | sed -n 's/^\(t\/[A-Za-z0-9_.-]*\.t\) *(Wstat:.*/\1/p' | sort | tr '\n' ' ') if [ -z "$bad" ]; then bst_ok libtest-fatal-perl/prove-failing-files else bst_notok libtest-fatal-perl/prove-failing-files "failing files: $bad"; fi # A perl INTERPRETER PANIC is not a test failure and must not be reported as one. # perl prints `panic: ` from its own guts when an internal invariant # breaks; on this arm that is a platform fact about perl-on-wasm32, not a # statement about Test::Fatal. Named separately so it is attributable instead of # being buried in whichever red quoted the transcript first. pan=$(printf '%s\n' "$cout" | grep -m1 '^panic: ') if [ -n "$pan" ]; then case "$pan" in *magic_killbackrefs*) pwhy="linux-in-the-browser#93 -- the magic_killbackrefs use-after-free this arm already carries a warnings.pm workaround for" ;; *) pwhy="an interpreter panic #93 does not cover -- unattributed, and worth a brintos.io issue" ;; esac bst_notok libtest-fatal-perl/perl-no-panic "$(_bst_1line "$pan") -- $pwhy" else bst_ok libtest-fatal-perl/perl-no-panic fi rm -rf "$WD"