# BST-TIMEOUT: 1200 . "$BST_LIB" # xmlsec1 (XML Security Library 1.3.5) -- a port whose acceptance evidence is # UPSTREAM'S OWN SUITE. OpenEmbedded packages xmlsec1's examples/ tree as a # ptest, so what closes BRINTOS-556 is the set of signature and encryption # round-trips upstream itself ships: thirteen cases over fixed documents, bundled # RSA keys, a DES key and a two-level X.509 CA chain. No clock, no network peer, # no device node, no TTY. # # THE SUITE IS DRIVEN BY UPSTREAM'S OWN run-ptest, IN THE FOREGROUND. That is the # ticket's stated gate and it is what runs here: `cd $p && sh ./run-ptest`, whose # thirteen `PASS:`/`FAIL:` lines are then asserted BY NAME, plus its exit status. # Nothing is re-implemented and nothing is re-scored. # # THIS REPLACES A WORKAROUND, AND THE REASON IT COULD BE REMOVED IS WORTH KEEPING. # The first version of this suite ran the thirteen programs by hand, each one # BACKGROUNDED with its output polled out of a file, because # brintos/linux-in-the-browser#148 symptom 1 said a foreground child whose stdout # is a REDIRECTED FILE completes and writes byte-correct output but is never # reaped -- the parent's wait(2) never returns. run-ptest is built entirely out # of foreground redirects: # # ./sign1 sign1-tmpl.xml rsakey.pem > sign1-res.xml # ./verify1 sign1-res.xml rsapub.pem # check_return sign-tmpl # # so on that platform it wedged on its FIRST command. Measured again on # superproject b0b2dac it does not: run-ptest runs all thirteen cases to # `PASS:` and exits 0, having reaped 23 such children. Symptom 1 no longer # reproduces, so the workaround is deleted rather than carried -- keeping a poll # loop that exists for a defect that no longer fires is how a suite comes to # report a platform's old behaviour instead of its current one. If a future # platform regresses here, the failure is loud: run-ptest never returns and this # suite hits its own BST-TIMEOUT. # # SYMPTOM 2 DOES NOT REPRODUCE HERE EITHER, and is still probed below. # ptest-runner had been recorded as trapping in glibc's __uflow reading the child # back off a non-tty stream -- exit 132, no suite output at all -- but that was # measured on a hand-assembled rootfs, not on the image. On the image it runs all # thirteen cases and exits 0, and the reading was withdrawn on #148. The issue # stays open: it also covers cunit, which has not been re-measured. # `xmlsec1/ptest-runner-cases` is therefore ASSERTED rather than skipped, as a # live tripwire -- if the platform regresses here, this case goes red on its own. # # SPAWN BUDGET. Every exec is a fresh instantiation of a ~51 MB wasm module -- # the examples statically carry libxmlsec1-openssl and libcrypto since the crypto # dl path had to be configured out (see xmlsec1_%.bbappend) -- and run-ptest # execs 23 of them. Measured elapsed for the whole run is ~3 min against the # 1200 s bound. The payload checks below use `test`, an ash builtin, for the same # reason. p=/usr/lib/xmlsec1/ptest runner=/usr/bin/ptest-runner tmp=${TMPDIR:-/tmp}/bst-xmlsec1.$$ mkdir -p "$tmp" 2>/dev/null || tmp=/tmp # The scratch directory is asserted, not assumed. A first run of this suite lost # every case to "can't open $tmp/…: no such file" while still reporting each one # as an ordinary red, which reads exactly like the port failing — so the one # thing every case below depends on gets its own case, and run_prog re-creates # the directory rather than trusting that this line held. check_rc xmlsec1/scratch-dir 0 test -d "$tmp" POLL_TICKS=40 # x 3 s = 120 s per program, well inside the 1200 s bound POLL_BUF='' # slurp -> POLL_BUF. Builtin-only: `read` is an ash builtin and the # redirect costs no process, so a poll tick is free apart from its sleep. slurp() { POLL_BUF='' while read -r _l; do POLL_BUF="$POLL_BUF$_l "; done < "$1" 2>/dev/null } # run_prog [args...] # Launch the program with stdout+stderr on , never wait for it, and poll # the file until appears. Returns 0 with the output in POLL_BUF, # or 1 on timeout with whatever arrived. # # The suite proper no longer needs this -- run-ptest is driven in the foreground # below. It is kept for the two probes that must not block the bound: the tool # banner, and ptest-runner. ptest-runner completes on the current platform, but # it re-runs all thirteen cases to do so, and #148 is still open against the # shape that once left it trapped -- so it is polled rather than waited on. run_prog() { _out=$1; _want=$2 shift 2 mkdir -p "${_out%/*}" 2>/dev/null : > "$_out" ( "$@" > "$_out" 2>&1 ) & _i=0 while [ "$_i" -lt "$POLL_TICKS" ]; do slurp "$_out" case "$POLL_BUF" in *"$_want"*) return 0 ;; esac sleep 3 _i=$((_i + 1)) done return 1 } # ------------------------------------------------------ what shipped ---------- check_rc xmlsec1/ptest-dir 0 test -d "$p" check_rc xmlsec1/ptest-runptest 0 test -x "$p/run-ptest" check_rc xmlsec1/tool 0 test -x /usr/bin/xmlsec1 check_rc xmlsec1/tool-config 0 test -x /usr/bin/xmlsec1-config check_rc xmlsec1/ar 0 test -s /usr/lib/libxmlsec1.a check_rc xmlsec1/ar-openssl 0 test -s /usr/lib/libxmlsec1-openssl.a check_rc xmlsec1/hdr-xmlsec 0 test -s /usr/include/xmlsec1/xmlsec/xmlsec.h check_rc xmlsec1/hdr-openssl 0 test -s /usr/include/xmlsec1/xmlsec/openssl/crypto.h # The four backends this arm does NOT carry. PACKAGECONFIG names openssl alone # because gnutls, nss and nspr are built for wasm32-hwjs by nothing at all, and # libgcrypt -- which this image does have -- would add a second backend library # that nothing here can reach, xmlSecCryptoDLLoadLibrary being a dlopen path on a # --disable-shared distro. Asserting their ABSENCE is what makes that a decision # rather than an accident: a stray libxmlsec1-gcrypt.a means the PACKAGECONFIG # override stopped binding. for b in gcrypt gnutls nss mscrypto; do check_rc "xmlsec1/no-backend-$b" 1 test -e "/usr/lib/libxmlsec1-$b.a" done # The thirteen example programs run-ptest drives, plus xmldsigverify which it # does not. Each is ~51 MB, which is why they are counted rather than globbed. for b in sign1 sign2 sign3 verify1 verify2 verify3 verify4 \ encrypt1 encrypt2 encrypt3 decrypt1 decrypt2 decrypt3 xmldsigverify; do check_rc "xmlsec1/prog-$b" 0 test -x "$p/$b" done # The keys, certificates and documents the cases key on. A missing one would turn # a case red for want of a file rather than for anything the platform did. for d in rsakey.pem rsapub.pem rsacert.pem cacert.pem ca2cert.pem deskey.bin \ sign1-tmpl.xml sign2-doc.xml sign3-doc.xml \ encrypt1-tmpl.xml encrypt2-doc.xml encrypt3-doc.xml verify4-res.xml; do check_rc "xmlsec1/data-$d" 0 test -s "$p/$d" done # ------------------------------------------------- the shipped tool runs ------ # The examples are static binaries of their own; /usr/bin/xmlsec1 is the package's # actual command-line tool and nothing in run-ptest touches it. Its --version # also states which crypto backend it was linked against, which is the same # PACKAGECONFIG decision asserted from the other side above. if run_prog "$tmp/version.out" "xmlsec1 " /usr/bin/xmlsec1 --version; then case "$POLL_BUF" in *1.3.5*) check_eq xmlsec1/tool-version 1.3.5 1.3.5 ;; *) check_eq xmlsec1/tool-version 1.3.5 "$POLL_BUF" ;; esac case "$POLL_BUF" in *openssl*) check_eq xmlsec1/tool-backend openssl openssl ;; *) check_eq xmlsec1/tool-backend openssl "$POLL_BUF" ;; esac else check_eq xmlsec1/tool-version 1.3.5 NO-OUTPUT check_eq xmlsec1/tool-backend openssl NO-OUTPUT fi # ---------------------------------------------- upstream's suite, driven ------ # run-ptest in the FOREGROUND, from its own directory, on its own data. Its # thirteen verdict lines ARE this ticket's acceptance evidence; the only thing # added here is the assertion that each one is present and says PASS, plus the # driver's own exit status. Nothing is re-implemented and nothing is re-scored. if ! cd "$p"; then bst_notok xmlsec1/suite-cwd "cannot cd to $p -- run-ptest cannot be driven" return 0 2>/dev/null || exit 0 fi sh ./run-ptest > "$tmp/runptest.out" 2>&1 rc=$? check_rc xmlsec1/run-ptest-exit 0 test "$rc" -eq 0 slurp "$tmp/runptest.out" PTEST_OUT=$POLL_BUF NL=' ' # Every case run-ptest declares, in its own order. A case that printed neither # word is reported ABSENT rather than as the absence of PASS: run-ptest stopping # early and a case genuinely failing are different findings, and only the first # of them means the platform rather than the port. The verdict is matched with # its trailing newline so no case id can be read as the prefix of another. n=0 for c in sign-tmpl sign-dynamic-templ sign-x509 \ verify-single-key verify-keys-manager verify-x509 verify-res \ encrypt-tmpl encrypt-dynamic-tmpl encrypt-session-key \ encrypt-single-key encrypt-keys-manager write-keys-manager; do case "$PTEST_OUT" in *"PASS: $c$NL"*) _got=PASS ;; *"FAIL: $c$NL"*) _got=FAIL ;; *) _got=ABSENT ;; esac check_eq "xmlsec1/ptest-$c" PASS "$_got" n=$((n + 1)) done # End-of-suite sentinel, and the expected case total in one line. It prints only # if every case above was reached, so a suite killed by its own bound (or by a # starved guest) is missing THIS line rather than merely being short -- which is # the difference between "13 green cases" and "13 green cases out of 13". check_eq xmlsec1/suite-end 13 "$n" # ------------------------------------------------ the preferred route -------- # ptest-runner, the ticket's PREFERRED route, probed LAST and deliberately so. # What is asserted is that the harness produced the suite's own PASS/FAIL # vocabulary; it does, on the image, for all thirteen cases. # # IT RUNS AFTER THE GATE BECAUSE IT SHARES THE WORKING DIRECTORY. run_prog # backgrounds it and never waits. That was written when #148 symptom 2 left it # trapped, and it is more load-bearing now that it completes: a ptest-runner that # actually runs drives xmlsec1's ptest out of the same directory run-ptest uses, # writing the same result files. Probed before the gate it made `ptest-sign-tmpl` # flake FAIL against a clean PASS from the same binaries run alone -- the race, # not the port. A diagnostic that shares a working directory with the measurement # goes after it. if [ -x "$runner" ]; then bst_ok xmlsec1/ptest-runner-present run_prog "$tmp/runner.out" "PASS: " "$runner" xmlsec1 slurp "$tmp/runner.out" case "$POLL_BUF" in *"PASS: "*|*"FAIL: "*) _got=cases ;; *) _got=no-cases ;; esac check_eq xmlsec1/ptest-runner-cases cases "$_got" else bst_skip xmlsec1/ptest-runner-present "this image ships no ptest-runner" bst_skip xmlsec1/ptest-runner-cases "no ptest-runner to run" fi rm -rf "$tmp"