. "$BST_LIB" require perl libxml-perl/present # BST-TIMEOUT: 600 # # Set from a measurement rather than guessed. This suite starts perl about a # dozen times -- one payload, six `prove' children, and a handful of one-liners # -- against 36-libtest-warnings-perl.test's fourteen `perl -e' plus 27 files at # 311 s. A perl process costs seconds rather than milliseconds on this arm # (linux-in-the-browser#117 measured 46-68x native), so the count is what sets # the bound. 600 leaves ~2x headroom on a loaded host and stays well under the # runner's BST_SUITE_TIMEOUT_MAX. # # libxml-perl 0.08 (POKY meta/recipes-devtools/perl/libxml-perl_0.08.bb -- NOT # meta-oe, which the ticket names; the same correction libmodule-build-perl, # libtest-fatal-perl, libtest-needs-perl and libtest-warnings-perl each had to # make). Twentieth Perl module on this image under BRINTOS-999. # # WHAT THE DISTRIBUTION IS. libxml-perl is the older Perl XML helper collection # that predates XML::SAX: XML::Parser::PerlSAX, the XML::Handler::* SAX # handlers, the XML::PatAct::* pattern/action engine, Data::Grove, and the # XML::Perl2SAX / XML::SAX2Perl translators between the Perl-style and # Java-style SAX1 calling conventions. Sixteen .pm files, all pure Perl. # # THE ONE FACT THAT SHAPES THIS SUITE. The ticket's criterion is the # distribution's own `prove -r t/', and all six of its .t files open with # `use XML::Parser::PerlSAX', which loads XML::Parser -- an XS module that # CANNOT LOAD on this arm. The glibc interpreter is built -Uusedl -Uuseshrplib, # so there is no DynaLoader and no Expat.so, only Expat.a; that is BRINTOS-881, # already recorded by 36-libxml-parser-perl.test, and it is OURS (--disable-shared # is distro policy) rather than a brintos.io defect -- which is why it is named # in prose and not as a BRINTOS-WORKAROUND: marker, whose # grammar a # JIRA key does not satisfy. Same treatment as 36-libxml-parser-perl.test and # 90-intltool.test. # # SO THE CRITERION IS EXPECTED RED, AND THE PORT IS STILL MEASURED. Sixteen # modules ship and exactly ONE -- XML::Parser::PerlSAX -- sits behind that gap. # Measured, not assumed: each module was required in isolation on x86-64 with # XML/Parser.pm shadowed by a stub dying with the target's own diagnostic, and # fifteen of sixteen loaded clean. Section 3's payload therefore feeds the # handlers the PerlSAX event stream PerlSAX ITSELF would have emitted -- the # call shapes read off XML/Parser/PerlSAX.pm's _handle_* subs -- and asserts the # same outputs the distribution's own t/amsterdam.t and t/schema.t assert. That # recovers the semantics the criterion cannot reach here, instead of reporting # the whole port unmeasurable behind one XS gap. # # THE CONTROL. The same 0.08 sources on x86-64 (perl 5.38.2, XML::Parser 2.47 -- # the same version this image carries): `prove -rb t/' gives `All tests # successful.', Files=6, Tests=45, Result: PASS. The payload is green on that # host BOTH with XML::Parser available and with it blocked, differing only in # R11 -- which is the case written to flip. # # THE PAYLOAD IS A GUARD, NOT A RUBBER STAMP, and that was demonstrated rather # than claimed. Four mutations of the shipped sources were run against it and # each was caught by the case that should catch it: CanonXMLWriter emitting # attributes unsorted (R3-canon), XML::Handler::Subs dropping the # non-word-character mangling that routes `non-null' to e_non_null # (R2-subs-mangled-name), MatchName returning the raw pattern index instead of # index/2 (R5-match-second, R5-match-path), and Amsterdam dropping the `[attr]' # substitution (R6-amsterdam, R6-amsterdam-attr). # # Four 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 XS gap that blocks the criterion, classified on THIS boot's own # diagnostic, and written in the direction that flips when 881 lands. # 3. the value battery -- 43 measurements over the fifteen reachable modules. # 4. the criterion itself: prove -r t/ over the installed suite. # perl prints a multi-line locale-warning preamble on EVERY invocation on this # image, on stderr (linux-in-the-browser#179: setlocale SUCCEEDS and perl # reports it as failed). Sections 2-4 capture 2>&1 -- they must, since 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, which is the # wrong diagnosis in the one place a later reader attributes by. Same strip as # 36-libtest-warnings-perl.test, 36-libtest-fatal-perl.test and # 36-libtest-needs-perl.test. _lxp_clean() { printf '%s\n' "$1" | awk '/^perl: warning/ { skip=1; next } /^[ \t]/ && skip { next } { skip=0; print }' } # Does this transcript show the BRINTOS-881 XS gap? ONE predicate, used by every # classifier below, because the two that had their own copies drifted apart on # the first target run and one of them misattributed the criterion. # # The diagnostic is NOT the one an x86-64 rehearsal produces. Shadowing # XML/Parser.pm with a stub gives "Can't locate loadable object for module # XML::Parser::Expat", because a host perl HAS DynaLoader and gets as far as # looking for the .so. This arm has no DynaLoader at all, so XML/Parser.pm dies # one step earlier, at its own `require DynaLoader', with "Can't locate # DynaLoader.pm in @INC". Both forms are the same gap and both are matched here. _lxp_xsgap() { printf '%s\n' "$1" | grep -qE "locate loadable object|DynaLoader" } V=$(ls -d /usr/lib/perl5/vendor_perl/* 2>/dev/null | head -1) VA=$(ls -d /usr/lib/perl5/vendor_perl/*/*-linux 2>/dev/null | head -1) PT=/usr/lib/libxml-perl/ptest # ------------------------- 1. what the port SHIPS: filesystem facts ---------- # The VERSION directory, not the arch directory. libxml-perl is pure Perl in # full, so cpan installs every .pm to vendor_perl// and none to the # vendor_perl//-linux/ an XS module lands in. That placement is the # packaging's own statement that this distribution has no compiled half -- which # is why BRINTOS-881 blocks its CRITERION (through XML::Parser) without blocking # the port itself. # # vendor-dir IS THE FIRST CASE THIS FILE EMITS, AND THAT IS DELIBERATE. The # guest loses a suite's first BST result line between its own printf and the # host's read -- linux-in-the-browser#177, reproduced and filed by BRINTOS-1149, # with the fleet-wide `brintos-selftest' filler-line mitigation held open as # BRINTOS-1210 because it re-signs every image. So one case per suite is going # to be dropped until #177 lands, and the only thing a suite author controls is # WHICH one. This is the right casualty: it is a precondition rather than a # measurement, it asserts something every one of the sixteen pm-* cases below # would red on anyway if it were false, and losing it costs the report nothing. # Do not move a real assertion above it. check libxml-perl/vendor-dir test -n "$V" # All sixteen: by directory count where the directory is this package's alone, # and then every file by name. The names alone would not notice a split that # ADDED a file; a count alone would not say which one went missing. # # The counts are scoped to directories libxml-perl owns outright rather than # taken over $V/XML as a whole -- that tree is shared with libxml-sax-perl, # libxml-namespacesupport-perl and libxml-parser-perl's pure-Perl half, so a # whole-tree count would move whenever an unrelated port lands and would read as # this package's regression. check_eq libxml-perl/patact-count 5 "$(ls "$V"/XML/PatAct/*.pm 2>/dev/null | wc -l | tr -d ' ')" check_eq libxml-perl/handler-count 4 "$(ls "$V"/XML/Handler/*.pm 2>/dev/null | wc -l | tr -d ' ')" check_eq libxml-perl/grove-count 3 "$(find "$V/Data" -name '*.pm' 2>/dev/null | wc -l | tr -d ' ')" for m in XML/Parser/PerlSAX XML/Handler/CanonXMLWriter XML/Handler/XMLWriter \ XML/Handler/Subs XML/Handler/Sample XML/ESISParser \ XML/PatAct/MatchName XML/PatAct/Amsterdam XML/PatAct/ToObjects \ XML/PatAct/ActionTempl XML/PatAct/PatternTempl \ XML/Perl2SAX XML/SAX2Perl \ Data/Grove Data/Grove/Parent Data/Grove/Visitor; do id=$(printf '%s' "$m" | tr '/' '-') check "libxml-perl/pm-$id" test -f "$V/$m.pm" done # No XS half at all: a recipe that started shipping an auto/ tree here would # mean this distribution had acquired a compiled extension, which is the one # change that would put the PORT (not merely its criterion) under BRINTOS-881. check libxml-perl/no-xs-object test ! -d "$VA/auto/XML/PatAct" check libxml-perl/no-xs-arch test -z "$(find "$VA" -path '*/XML/Handler/*' -name '*.a' 2>/dev/null)" # THE INSTALLED SUITE -- the deliverable the ticket's criterion runs on. poky's # recipe already inherits ptest-perl, but the class deletes its own # do_install_ptest_perl task unless PTEST_ENABLED is 1, and this distro's # DISTRO_FEATURES has no `ptest'. These three cases are what says this layer's # bbappend took effect. check libxml-perl/ptest-dir test -d "$PT/t" check libxml-perl/ptest-runptest test -f "$PT/run-ptest" check_eq libxml-perl/ptest-count 6 "$(ls "$PT"/t/*.t 2>/dev/null | wc -l | tr -d ' ')" # The six by name. The x86-64 control ran exactly these and no others, and the # recipe prunes none of them. for t in amsterdam canon_xml_writer schema stream subs xp_sax; do check "libxml-perl/ptest-$t" test -f "$PT/t/$t.t" done check libxml-perl/payload-installed test -f "$BST_DATA/libxml-perl-selftest.pl" # --------- 2. the XS gap that blocks the criterion, measured on THIS boot ----- # Not cited -- taken from this interpreter, so section 4's attribution rests on # evidence from the same boot rather than on a comment. The two filesystem cases # are written in the direction that FLIPS: each asserts what must become TRUE, # so both go green by themselves the day BRINTOS-881 lands shared libraries, # rather than going red and reading as a regression. Asserting the absence would # pass today and fail on success, which is the wrong way round for a pin whose # whole purpose is to notice the fix. This is the same pair # 36-libxml-parser-perl.test carries; it is repeated here because THIS port's # criterion is what they block, and a reader of this suite's report should not # have to find another suite to learn why. if [ -n "$(find /usr/lib/perl5 -name 'Expat.so' 2>/dev/null)" ]; then bst_ok libxml-perl/xs-shared-object else bst_notok libxml-perl/xs-shared-object \ "no XML/Parser/Expat/Expat.so anywhere under /usr/lib/perl5 -- the glibc arm is built -Uusedl -Uuseshrplib, so XML::Parser cannot load and every one of this distribution's six .t files opens with use XML::Parser::PerlSAX (BRINTOS-881); flips green when 881 lands" fi if [ -n "$(find /usr/lib/perl5 -name 'DynaLoader.pm' 2>/dev/null)" ]; then bst_ok libxml-perl/dynaloader-present else bst_notok libxml-perl/dynaloader-present \ "no DynaLoader.pm in any perl package on this image -- there is nothing to load an XS object with even if one were built (BRINTOS-881); flips green when 881 lands" fi # And the load itself, classified on the diagnostic rather than reported as a # bare failure. Three outcomes are distinguishable and they mean different # things: the XS gap (expected today), an interpreter abort (a platform defect # of a different kind), and success (881 has landed and section 4's criterion # should now be reachable). pl=$(perl -e 'require XML::Parser::PerlSAX; print "LOADED\n"' 2>&1); plrc=$? pl=$(_lxp_clean "$pl") case "$pl" in *LOADED*) bst_ok libxml-perl/perlsax-load ;; *"invalid pointer"*|*"panic: "*|*Abort*) bst_notok libxml-perl/perlsax-load \ "rc=$plrc an interpreter ABORT, not the XS gap -- this is NOT BRINTOS-881 and wants a brintos.io issue: $(_bst_1line "$pl")" ;; *) if _lxp_xsgap "$pl"; then bst_notok libxml-perl/perlsax-load "rc=$plrc BRINTOS-881 -- $(_bst_1line "$pl")" else bst_notok libxml-perl/perlsax-load "rc=$plrc unclassified -- $(_bst_1line "$pl")" fi ;; esac # The fifteen modules that are NOT behind the gap must load. This is the case # that separates "the criterion is blocked by one XS dependency" from "this port # does not work": a red here is THIS PORT'S, whatever XML::Parser is doing. lm=$(perl -e 'my $n=0; for my $m (qw(Data::Grove Data::Grove::Parent Data::Grove::Visitor XML::ESISParser XML::Handler::CanonXMLWriter XML::Handler::Sample XML::Handler::Subs XML::Handler::XMLWriter XML::PatAct::ActionTempl XML::PatAct::Amsterdam XML::PatAct::MatchName XML::PatAct::PatternTempl XML::PatAct::ToObjects XML::Perl2SAX XML::SAX2Perl)) { $n++ if eval "require $m; 1" } print "$n\n"' 2>&1) check_eq libxml-perl/pure-modules-load 15 "$(printf '%s\n' "$(_lxp_clean "$lm")" | tail -1 | tr -d ' ')" # ------------------------- 3. the value battery ------------------------------ # One perl invocation. The payload prints one `R- ' line per # measurement and a final ALL-LIBXML-PERL-OK when every internal comparison # held; the whole-suite gate below is the cheap answer and the per-value cases # after it are what makes a red say WHICH property moved. out=$(perl "$BST_DATA/libxml-perl-selftest.pl" 2>&1); orc=$? out=$(_lxp_clean "$out") case "$out" in *ALL-LIBXML-PERL-OK*) bst_ok libxml-perl/battery-all-ok ;; *) bst_notok libxml-perl/battery-all-ok "rc=$orc $(_bst_1line "$out")" ;; esac _r() { printf '%s\n' "$out" | awk -v k="$1" '$1==k { $1=""; sub(/^ /,""); print; exit }'; } # 3a. the module set, and one version across all of it. check_eq libxml-perl/battery-loaded 15 "$(_r R1-loaded)" check_eq libxml-perl/battery-versions 0.08 "$(_r R1-versions)" # 3b. XML::Handler::Subs -- the s_/e_ dispatch, the Names stack read at depth, # in_element/within_element, and the name mangling. The log pins the ORDER as # well as the membership: a handler that fired e_outer before e_inner would # satisfy a set comparison and fail this. check_eq libxml-perl/subs-dispatch "s:outer(1) s:inner(outer/inner) in:1 within-outer:1 e:outer" "$(_r R2-subs-log)" check_eq libxml-perl/subs-stack-cleared yes "$(_r R2-subs-stack-cleared)" check_eq libxml-perl/subs-mangled-name 1 "$(_r R2-subs-mangled-name)" # 3c. XML::Handler::CanonXMLWriter -- canonical XML. Attributes sorted whatever # the hash order, the escape table applied, and comments/PIs handled per option. check_eq libxml-perl/canon 'text&<>"' "$(_r R3-canon)" check_eq libxml-perl/canon-attr-escape '' "$(_r R3-canon-attr-escape)" check_eq libxml-perl/canon-ws ' ' "$(_r R3-canon-ws)" check_eq libxml-perl/canon-nocomment '' "$(_r R3-canon-nocomment)" check_eq libxml-perl/canon-comment '' "$(_r R3-canon-comment)" # 3d. XML::PatAct::MatchName -- match() is a pure function of the name path and # returns the pattern's index/2, undef for no match. check_eq libxml-perl/match-first 0 "$(_r R5-match-first)" check_eq libxml-perl/match-second 1 "$(_r R5-match-second)" check_eq libxml-perl/match-path 2 "$(_r R5-match-path)" check_eq libxml-perl/match-none undef "$(_r R5-match-none)" # 3e. t/amsterdam.t's own assertion, recovered without the parser -- same # patterns, same document shape, same expected string. A red here is the finding # the distribution's own file would have reported if it could run. check_eq libxml-perl/amsterdam-attr "" "$(_r R6-amsterdam-attr)" am=$(printf '%s\n' "$out" | sed -n '/^R6-amsterdam /,/^R6-amsterdam-attr/p' | sed '1s/^R6-amsterdam //; $d') if [ "$am" = "Outer-before, 'an attr' Inner Outer-after" ]; then bst_ok libxml-perl/amsterdam else bst_notok libxml-perl/amsterdam "t/amsterdam.t's expected string not reproduced: $(_bst_1line "$am")"; fi # 3f. t/schema.t's own assertion, likewise: -holder, -make, -field/-as-string, # -push-field and -value, checked at values on the built object graph rather # than as the single boolean the .t reduces them to. check_eq libxml-perl/toobj-class Schema::Table "$(_r R7-toobj-class)" check_eq libxml-perl/toobj-name MyTable "$(_r R7-toobj-name)" check_eq libxml-perl/toobj-summary "A short summary" "$(_r R7-toobj-summary)" check_eq libxml-perl/toobj-colclass Schema::Column "$(_r R7-toobj-colclass)" check_eq libxml-perl/toobj-colname MyColumn1 "$(_r R7-toobj-colname)" check_eq libxml-perl/toobj-unique 1 "$(_r R7-toobj-unique)" check_eq libxml-perl/toobj-default 42 "$(_r R7-toobj-default)" # 3g. Data::Grove and its two extension modules. check_eq libxml-perl/grove-class Data::Grove::Characters "$(_r R8-grove-class)" check_eq libxml-perl/grove-shallow-copy hi "$(_r R8-grove-shallow-copy)" check_eq libxml-perl/parent-class BSTNode "$(_r R8-parent-class)" check_eq libxml-perl/parent-parent root "$(_r R8-parent-parent)" check_eq libxml-perl/parent-raw-clean clean "$(_r R8-parent-raw)" check_eq libxml-perl/parent-rewrap root "$(_r R8-parent-rewrap-parent)" check_eq libxml-perl/visitor-accept "visited:n1:x,y" "$(_r R8-visitor-accept)" # 3h. the two SAX1 translators, in both directions. check_eq libxml-perl/perl2sax "sd s:a(k=v) c:txt@0+3 pi:tgt=d=1 e:a ed" "$(_r R9-perl2sax)" check_eq libxml-perl/sax2perl "sd s:a(k=v) c:t&t pi:tgt=d=1 e:a ed" "$(_r R9-sax2perl)" # 3i. XML::ESISParser loads but drives an external nsgmls this image does not # ship. Reported as a value, not as a red: a missing external tool is not a # defect in this port, and the class surface is what can honestly be asserted. check_eq libxml-perl/esis-loaded yes "$(_r R10-esis-loaded)" ns=$(_r R10-nsgmls-present) if [ "$ns" = yes ]; then bst_ok libxml-perl/esis-nsgmls else bst_skip libxml-perl/esis-nsgmls "nsgmls is not on this image, so XML::ESISParser cannot be driven end to end; the module itself loads (esis-loaded)"; fi # ------------------------- 4. THE CRITERION: prove -r t/ --------------------- # Run from a WRITABLE COPY, not in place. Two reasons, and both are load-bearing # here: the deployed rootfs is read-only at browser runtime, and t/xp_sax.t # WRITES a file (`open(ZOE, '>zoe.ent')') into the current directory as part of # its external-entity case. CWD is the directory that HOLDS t/, which is how # run-ptest invokes it too. WD=${TMPDIR:-/tmp}/bst-libxml-perl.$$ PW=$WD/ptest mkdir -p "$PW" && cp -r "$PT/t" "$PW/t" 2>/dev/null check libxml-perl/suite-staged test -f "$PW/t/xp_sax.t" # 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 # 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 criterion 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=$(_lxp_clean "$smoke") case "$smoke" in *"Result: PASS"*) bst_ok libxml-perl/prove-smoke ;; *) bst_notok libxml-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=$(_lxp_clean "$cout") # `Result: PASS' is prove's own verdict over the whole run and is the ticket's # "reporting zero failures" verbatim. It is EXPECTED RED here and the red # carries its attribution: every one of the six files opens with # `use XML::Parser::PerlSAX', so all six die before their first assertion. case "$cout" in *"Result: PASS"*) bst_ok libxml-perl/prove-result ;; *) if _lxp_xsgap "$cout"; then why="BRINTOS-881 -- XML::Parser is XS and this arm's perl is -Uusedl -Uuseshrplib, so all six .t files die at their opening use XML::Parser::PerlSAX; the identical tree is Result: PASS with Files=6 Tests=45 on x86-64" elif printf '%s\n' "$cout" | grep -q 'panic: '; then why="a perl interpreter panic, which is NOT the XS gap -- read prove-failing-files and file it" else why="no XS-load diagnostic and no interpreter panic -- this is a genuine test failure and is THIS PORT'S to answer" fi bst_notok libxml-perl/prove-result "rc=$crc $(_bst_1line "$cout") -- $why" ;; 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 verdict cannot show. This case holds TODAY, blocked # criterion or not: prove ran all six, they simply all died. files=$(printf '%s\n' "$cout" | sed -n 's/^Files=\([0-9]*\),.*/\1/p' | tail -1) check_eq libxml-perl/prove-files 6 "$files" # The assertion total, bounded from below at the x86-64 control's 45. This is # the case that will carry the criterion the day BRINTOS-881 lands: today the # six files die before printing a plan, so the total is 0 and this reds with the # same attribution as prove-result. Bounded rather than pinned so a later 0.09 # with an extra case does not read 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 libxml-perl/prove-tests "no Tests= total in prove's summary -- $(_bst_1line "$cout")" ;; *) if [ "$tests" -ge 45 ]; then bst_ok libxml-perl/prove-tests else bst_notok libxml-perl/prove-tests "Tests=$tests, want >= 45 (the x86-64 control ran 45 with nothing skipped); today this is BRINTOS-881 -- the six files die at use XML::Parser::PerlSAX before printing a plan"; fi ;; esac # 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 # printed first. It also bounds the blast radius of the XS gap: today the answer # must be ALL SIX, and a run where only some die means something else is going # on -- the gap is a property of the interpreter, not of a file. bad=$(printf '%s\n' "$cout" | sed -n 's/^\(t\/[A-Za-z0-9_.-]*\.t\) *(Wstat:.*/\1/p' | sort | tr '\n' ' ') nbad=$(printf '%s\n' "$cout" | sed -n 's/^t\/[A-Za-z0-9_.-]*\.t *(Wstat:.*/x/p' | wc -l | tr -d ' ') if [ -z "$bad" ]; then bst_ok libxml-perl/prove-failing-files elif [ "$nbad" = 6 ]; then bst_notok libxml-perl/prove-failing-files \ "all six files failed, which is what BRINTOS-881 predicts (the XS gap is a property of the interpreter, not of any one file): $bad" else bst_notok libxml-perl/prove-failing-files \ "$nbad of 6 files failed -- a PARTIAL failure is NOT the XS gap, which would take all six: $bad" fi # THE PLANNED TOTAL, WHICH IS WHERE THE PORT IS ACTUALLY MEASURED TODAY. Each # of these six files opens with `BEGIN { $| = 1; print "1..N\n"; }' -- the # 1999-era black magic that prints the plan BEFORE the `use' line -- and closes # with `END { print "not ok 1\n" unless $loaded; }'. So on this arm every file # still announces its plan, fails at `use XML::Parser::PerlSAX', and its own END # guard reports that as `not ok 1'. prove therefore says `Bad plan. You planned # N tests but ran 1' six times, and those six N sum to exactly 45 -- the x86-64 # control's Tests total. # # That sum is worth a case of its own, because it is the sharpest thing this # blocked criterion can still say: all six files were reached, all six parsed # and ran, and everything lost was lost at ONE import. A file that had been # pruned from the package, or that died before its BEGIN block, would move this # number while leaving Files=6 and the six reds looking identical. planned=$(printf '%s\n' "$cout" | sed -n 's/.*You planned \([0-9]*\) tests but ran.*/\1/p' \ | awk '{ n += $1 } END { print n+0 }') if [ "$planned" = 0 ]; then # no `Bad plan' lines at all: either the criterion passed (planned is then # not reported) or the files did not reach their BEGIN plan. case "$cout" in *"Result: PASS"*) bst_ok libxml-perl/prove-planned-total ;; *) bst_notok libxml-perl/prove-planned-total \ "prove reported no plan at all and did not pass -- the six files did not reach their BEGIN plan line, which is NOT the import gap: $(_bst_1line "$cout")" ;; esac else check_eq libxml-perl/prove-planned-total 45 "$planned" fi # HOW MANY ASSERTIONS ACTUALLY FAILED, as distinct from how the run ENDED, and # WHY. A non-zero failed-subtest count is normally THIS PORT'S -- but here the # six failures are the distribution's OWN `not ok 1' load sentinel firing # exactly as its authors intended, which is a different finding from a wrong # answer. The two are told apart by whether the transcript carries the XS-load # diagnostic, not by the count. fail=$(printf '%s\n' "$cout" | sed -n 's/.*Failed \([0-9]*\)\/[0-9]* subtests.*/\1/p' | tr '\n' ' ') nfail=$(printf '%s\n' "$cout" | sed -n 's/^ *Failed test: *[0-9].*/x/p' | wc -l | tr -d ' ') if [ -z "$fail" ]; then bst_ok libxml-perl/prove-no-failed-subtests elif _lxp_xsgap "$cout"; then bst_notok libxml-perl/prove-no-failed-subtests \ "$nfail failures, all of them the distribution's own END-block sentinel (\`not ok 1 unless \$loaded') firing because use XML::Parser::PerlSAX did not load -- BRINTOS-881, not a wrong answer; expect one per file" else bst_notok libxml-perl/prove-no-failed-subtests \ "prove reported failed subtests ($fail) with NO XS-load diagnostic -- these are genuine assertion failures and are THIS PORT'S" fi # A perl INTERPRETER PANIC is not a test failure and must not be reported as # one. 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 bst_notok libxml-perl/perl-no-panic \ "$(_bst_1line "$pan") -- an interpreter panic on a run whose expected failure is a missing XS object; unattributed, and worth a brintos.io issue" else bst_ok libxml-perl/perl-no-panic fi # THE LOCALE PREAMBLE, REPORTED RATHER THAN ONLY STRIPPED. _lxp_clean removes it # from every detail field in this file, which is what every brintOS Perl # selftest does -- and that private, repeated workaround is precisely why # nothing tracked the defect until BRINTOS-1323 filed # linux-in-the-browser#179. This case makes the strip visible: it reports # whether the preamble is still being emitted, so the day #179 lands the suite # says so instead of silently continuing to filter it. lp=$(perl -e 'print "X\n"' 2>&1) case "$lp" in *"Setting locale failed"*) bst_notok libxml-perl/no-locale-preamble \ "linux-in-the-browser#179 -- perl prints a locale-warning preamble on stderr on EVERY invocation although setlocale() succeeds; every Perl suite here strips it by hand" ;; *) bst_ok libxml-perl/no-locale-preamble ;; esac rm -rf "$WD"