. "$BST_LIB" # BST-TIMEOUT: 600 # ~30 execs of two 2.9 MB wasm modules, plus ~12 full MD5 # # passes over a 411 KB fixture. Measured on the x86-64 # # control at 3 s; the bound is for a loaded guest. # # isomd5sum 1.2.4 (meta-oe recipes-extended, git 3f4c9bd3 plus meta-oe's two # build patches) -- implantisomd5 writes an MD5 of an ISO 9660 image into the # image's own Application Use area, and checkisomd5 reads it back and verifies # it. Nothing here touches optical hardware: both programs open a FILE, so the # whole package is exercisable against the fixture beside this suite. # # CALIBRATED AGAINST AN x86-64 CONTROL, not against the ticket. The control is # isomd5sum-native from THIS build's own sysroot -- the same source, the same # two patches, the same recipe, built by the same bitbake run -- so every value # pinned below was read off a working arm before it was asserted here, and a red # is a target-only divergence rather than an assertion written wrong. Recorded # 2026-08-27. # # THE FIXTURE IS THE ORACLE. data/isomd5sum-fixture.iso is 411648 bytes (201 # sectors) of genisoimage output, committed as a blob, so the MD5 the target # computes is a FIXED STRING that the x86-64 control produced first: # # md5 = 7e05c4177a1f9b41f658f43e9f025276 # fragmd5 = ac5cc82c9e565575b7888e3e8799a43be19d35968194fac74f29f975b # # That is the strongest case in this file. The package ships its OWN MD5 (md5.c, # not OpenSSL -- see UPSTREAM FACT 3), so a wasm32 miscompile of the hash would # show up here as a wrong 32-character string and nowhere else. # # FOUR THINGS THE TICKET ASKED FOR THAT THIS PACKAGE DOES NOT HAVE OR DO. Each # is asserted in its corrected form rather than dropped, because "this is # missing" is a finding and the opposite would mean the wrong binary answered: # # --version : neither program has one. popt rejects it as an unknown # option, rc 1, "bad option --version: unknown option". # --help : exists, but prints USAGE ON STDERR and exits 1. It is # not an error path that returns 0. # pyisomd5sum : NOT BUILT AND NOT SHIPPED. The -shared link this arm # refuses (brintos/hwjs-cc#76), and a CPython built # MODULE_BUILDTYPE=static that could not import an # out-of-tree .so even if it linked. Asserted as an # absence, from the filesystem AND from the interpreter. # openssl / curl : the recipe DEPENDS and RDEPENDS on both and the code # links neither -- see UPSTREAM FACT 3. # # TWO UPSTREAM BUGS ARE PINNED HERE RATHER THAN PATCHED. Both are third-party # (rhinstaller/isomd5sum), both reproduce identically on the x86-64 control, and # we file nothing against a third-party public repository -- see # docs/conventions/no-public-upstream-reports.md. # # UPSTREAM BUG 1 -- ANY FILE THAT IS NOT AN ISO 9660 HANGS BOTH PROGRAMS # FOREVER. read_primary_volume_descriptor() treats read(2) == 0 (EOF) as # success and re-reads a STALE buffer, and advances its offset with # `nbyte *= SECTOR_SIZE' where it means `+='. On an empty file, a short file, # a zero-filled file or random bytes it spins with no output and never # returns. Measured on the x86-64 control: rc 124 under `timeout 5', four # inputs out of four. # # IT IS NOT EXERCISED ON TARGET, AND THAT IS NOT A JUDGEMENT ABOUT # THOROUGHNESS. There was no way to bound it here when this was written: # alarm(2) was ENOSYS (a kernel without the brintos/linux#77 fix) and # relative timers do not elapse (brintos/linux-in-the-browser#120), so # timeout(1) never fired and sleep is a no-op -- which brintos-selftest # states in its own BST_SUITE_TIMEOUT comment as the reason IT did not use # timeout either. So `timeout 15 checkisomd5 empty' did not give a bounded # red -- it gave TWO hangs, and a spinning process grows the HOST # guest until brintos_local_verify's rss-rate guard ends the boot. Measured # 2026-08-27: 3915 MiB/min, 4130 MiB, boot ended -- and because the runner # buffers a suite's whole output to a file and emits it only at the end, ALL # 127 cases were lost, not just the two. The witnesses below are therefore # skips naming the control that did establish the hang. # NOTHING IN THIS FILE MAY USE timeout(1), FOR THE SAME REASON. # # The clean half of that same code path IS exercised: a Volume Descriptor Set # Terminator at sector 16 ends the walk, and both programs then give their # documented answer. That is the `term-*' group, and it is what a fix to the # EOF handling would have to keep working. # # UPSTREAM BUG 2 -- THE FRAGMENT-SUM FIELD IS WRITTEN 57 CHARACTERS WIDE AND # READ 60. implantISOFD's loop stops at fragment 19 (19 x 3 = 57 chars); # parsepvd memcpy's a fixed 60, so it takes three characters of the NEXT field # with it and `checkisomd5 --md5sumonly' prints "...f975b;FR". It is harmless # -- fragment 20 is never validated, so the three stray characters are never # compared -- and it is pinned by exact string below so a fix is visible. # # UPSTREAM FACT 3 -- THE RECIPE'S openssl AND curl DEPENDENCIES ARE STALE. Every # hash in this package comes from its own bundled md5.c (MD5_Init/Update/Final # in md5.h); grep finds no , no EVP_, and no libcurl anywhere in # the sources, and both programs link `-lpopt' and nothing else. The RDEPENDS # is left as upstream writes it -- openssl and curl are both on this image # already, so it costs nothing and diverging from meta-oe would need a reason # better than tidiness. It is recorded so the next reader does not conclude from # the recipe that this package does crypto or networking. It does neither. # # TWO PLATFORM HABITS THIS FILE OBEYS. `[ -x ]' is a false oracle on the # virtiofs root -- the files are owned 1000:1001, the guest runs as root, and # getgroups(2) is ENOSYS (brintos/linux#19) -- so the mode cases read `ls -l'. # And checkisomd5 calls tcgetattr/tcsetattr on fd 0 and getchar()s it looking # for Esc, so an unredirected run would take the console away from the run that # is testing it: every invocation goes through _run, which redirects &1); _rc=$?; } _has() { case "$_out" in *"$2"*) bst_ok "$1" ;; *) if bst_execfail "$_out"; then bst_unrun "$1" "$_out" else bst_notok "$1" "want:'$2' got:'$(_bst_1line "$_out")'"; fi ;; esac } _hasnt() { case "$_out" in *"$2"*) bst_notok "$1" "unexpectedly present: '$2' in '$(_bst_1line "$_out")'" ;; *) bst_ok "$1" ;; esac } W=${TMPDIR:-/tmp}/bst-isomd5sum.$$ rm -rf "$W"; mkdir -p "$W" || { bst_notok isomd5sum/scratch "cannot mkdir $W"; return 2>/dev/null || exit 0; } # ---- 1. the installed artifacts ------------------------------------------------ check_eq isomd5sum/implant-which "$IMP" "$(command -v implantisomd5)" check_eq isomd5sum/check-which "$CHK" "$(command -v checkisomd5)" check isomd5sum/implant-is-file test -f "$IMP" check isomd5sum/check-is-file test -f "$CHK" check_eq isomd5sum/implant-mode "-rwxr-xr-x" "$(ls -l "$IMP" | awk '{print $1}')" check_eq isomd5sum/check-mode "-rwxr-xr-x" "$(ls -l "$CHK" | awk '{print $1}')" # \0asm -- both programs are WebAssembly, and neither is an ELF. Read the same # four bytes twice and compare against different constants, so no artifact can # satisfy both. _magic() { od -An -N4 -tx1 "$1" 2>/dev/null | tr -d ' \n'; } check_eq isomd5sum/implant-is-wasm "0061736d" "$(_magic "$IMP")" check_eq isomd5sum/check-is-wasm "0061736d" "$(_magic "$CHK")" check_eq isomd5sum/implant-not-elf "no" "$([ "$(_magic "$IMP")" = "7f454c46" ] && echo yes || echo no)" check_eq isomd5sum/check-not-elf "no" "$([ "$(_magic "$CHK")" = "7f454c46" ] && echo yes || echo no)" # -doc, -dev and -staticdev: everything else install-bin/install-devel writes. check isomd5sum/man-implant test -f /usr/share/man/man1/implantisomd5.1 check isomd5sum/man-check test -f /usr/share/man/man1/checkisomd5.1 check isomd5sum/hdr-implant test -f /usr/include/libimplantisomd5.h check isomd5sum/hdr-check test -f /usr/include/libcheckisomd5.h check isomd5sum/lib-implant test -f /usr/lib/libimplantisomd5.a check isomd5sum/lib-check test -f /usr/lib/libcheckisomd5.a check isomd5sum/pc-present test -f /usr/share/pkgconfig/isomd5sum.pc check_out isomd5sum/pc-name "Name: isomd5sum" cat /usr/share/pkgconfig/isomd5sum.pc check_out isomd5sum/pc-version "Version: 1.2.4" cat /usr/share/pkgconfig/isomd5sum.pc # the archives are real ar payload, not empty stubs. `!\n' plus a floor # that holds on BOTH arms -- x86-64 gives 17962/16096, wasm32 74046/69924 -- so # the case says the same thing about the control as about the target. check_eq isomd5sum/lib-implant-is-ar "213c617263683e0a" \ "$(dd if=/usr/lib/libimplantisomd5.a bs=1 count=8 2>/dev/null | od -An -tx1 | tr -d ' \n')" check_eq isomd5sum/lib-check-is-ar "213c617263683e0a" \ "$(dd if=/usr/lib/libcheckisomd5.a bs=1 count=8 2>/dev/null | od -An -tx1 | tr -d ' \n')" check_eq isomd5sum/lib-implant-nonempty "yes" \ "$([ "$(wc -c < /usr/lib/libimplantisomd5.a)" -gt 10000 ] && echo yes || echo no)" check_eq isomd5sum/lib-check-nonempty "yes" \ "$([ "$(wc -c < /usr/lib/libcheckisomd5.a)" -gt 10000 ] && echo yes || echo no)" # The man pages are the oracle for the option vocabulary asserted further down. check_out isomd5sum/man-implant-force "\-\-force" cat /usr/share/man/man1/implantisomd5.1 check_out isomd5sum/man-implant-supported "\-\-supported-iso" cat /usr/share/man/man1/implantisomd5.1 check_out isomd5sum/man-check-md5sumonly "\-\-md5sumonly" cat /usr/share/man/man1/checkisomd5.1 check_out isomd5sum/man-check-exit-status "exit status 0 if the checksum is correct" \ cat /usr/share/man/man1/checkisomd5.1 # ---- 2. usage, --help and the --version the ticket asked for -------------------- _run "$IMP" check_eq isomd5sum/implant-noargs-rc 1 "$_rc" _has isomd5sum/implant-noargs-usage "implantisomd5 [--force] [--supported-iso] " _run "$CHK" check_eq isomd5sum/check-noargs-rc 1 "$_rc" _has isomd5sum/check-noargs-usage "Usage: checkisomd5 [--md5sumonly] [--verbose] [--gauge] |" # a usage line naming --output/--json/--noheadings would be a different program _hasnt isomd5sum/check-usage-no-version "--version" _run "$IMP" --help check_eq isomd5sum/implant-help-rc 1 "$_rc" _has isomd5sum/implant-help-usage "implantisomd5 [--force] [--supported-iso] " _run "$IMP" -h check_eq isomd5sum/implant-help-short-rc 1 "$_rc" _run "$CHK" --help check_eq isomd5sum/check-help-rc 1 "$_rc" _has isomd5sum/check-help-usage "Usage: checkisomd5" _run "$CHK" -h check_eq isomd5sum/check-help-short-rc 1 "$_rc" # THE TICKET ASKED FOR --version ON BOTH. Neither has one; popt rejects it. _run "$IMP" --version check_eq isomd5sum/implant-version-rc 1 "$_rc" _has isomd5sum/implant-version-rejected "bad option --version: unknown option" _run "$CHK" --version check_eq isomd5sum/check-version-rc 1 "$_rc" _has isomd5sum/check-version-rejected "bad option --version: unknown option" # ...and the rejection is popt's generic one, not a --version-specific path _run "$IMP" --zzznosuchoption check_eq isomd5sum/implant-badopt-rc 1 "$_rc" _has isomd5sum/implant-badopt-msg "bad option --zzznosuchoption: unknown option" _run "$CHK" --zzznosuchoption check_eq isomd5sum/check-badopt-rc 1 "$_rc" _has isomd5sum/check-badopt-msg "bad option --zzznosuchoption: unknown option" # ---- 3. a file that is not there ------------------------------------------------ _run "$IMP" "$W/absent.iso" check_eq isomd5sum/implant-missing-rc 1 "$_rc" _has isomd5sum/implant-missing-msg "ERROR: Error - Unable to open file $W/absent.iso" _run "$CHK" "$W/absent.iso" check_eq isomd5sum/check-missing-rc 1 "$_rc" _has isomd5sum/check-missing-na "the result is: NA." _has isomd5sum/check-missing-msg "File not found." # ---- 4. the fixture ------------------------------------------------------------ F=$W/fixture.iso if cp "$BST_DATA/isomd5sum-fixture.iso" "$F" 2>/dev/null; then bst_ok isomd5sum/fixture-staged else bst_notok isomd5sum/fixture-staged "cannot copy $BST_DATA/isomd5sum-fixture.iso to $F" return 2>/dev/null || exit 0 fi check_eq isomd5sum/fixture-size 411648 "$(wc -c < "$F")" check_eq isomd5sum/fixture-md5 "cedd6efaf930801eb5ce283d63436ed3" "$(md5sum < "$F" | awk '{print $1}')" # ISO 9660: descriptor type 1 ("primary") + the CD001 identifier at sector 16 check_eq isomd5sum/fixture-pvd-type "01" \ "$(dd if="$F" bs=1 skip=32768 count=1 2>/dev/null | od -An -tx1 | tr -d ' \n')" check_eq isomd5sum/fixture-pvd-id "CD001" \ "$(dd if="$F" bs=1 skip=32769 count=5 2>/dev/null)" check_eq isomd5sum/fixture-volid "BRINTOSFIX" \ "$(dd if="$F" bs=1 skip=32808 count=32 2>/dev/null | sed 's/ *$//')" # the two bytes the corruption cases flip -- pinned so a changed fixture fires # HERE rather than as an inexplicable green further down check_eq isomd5sum/fixture-byte-40960 "01" \ "$(dd if="$F" bs=1 skip=40960 count=1 2>/dev/null | od -An -tx1 | tr -d ' \n')" check_eq isomd5sum/fixture-byte-409600 "00" \ "$(dd if="$F" bs=1 skip=409600 count=1 2>/dev/null | od -An -tx1 | tr -d ' \n')" # ECMA-119 8.4.32 Application Use: 512 bytes at PVD offset 883. Blank on a fresh # image, which is exactly what implantisomd5 refuses to overwrite without --force. _appdata() { dd if="$1" bs=1 skip=33651 count=512 2>/dev/null; } check_eq isomd5sum/fixture-appdata-blank "" "$(_appdata "$F" | tr -d ' ')" # ---- 5. an image that was never implanted -------------------------------------- _run "$CHK" "$F" check_eq isomd5sum/fresh-check-rc 1 "$_rc" _has isomd5sum/fresh-check-na "the result is: NA." _has isomd5sum/fresh-check-msg "No checksum information available, unable to verify media." _hasnt isomd5sum/fresh-check-not-pass "It is OK to use this media." _run "$CHK" --md5sumonly "$F" check_eq isomd5sum/fresh-md5sumonly-rc 1 "$_rc" _has isomd5sum/fresh-md5sumonly-na "No checksum information available, unable to verify media." # ---- 6. implant ---------------------------------------------------------------- _run "$IMP" "$F" check_eq isomd5sum/implant-rc 0 "$_rc" _has isomd5sum/implant-msg-inserting "Inserting md5sum into iso image..." _has isomd5sum/implant-msg-fragments "Inserting fragment md5sums into iso image..." _has isomd5sum/implant-msg-frags "frags = 20" _has isomd5sum/implant-msg-supported0 "Setting supported flag to 0" IMPOUT=$_out MD5=$(printf '%s\n' "$IMPOUT" | awk '/^md5 = /{print $3}') FRAG=$(printf '%s\n' "$IMPOUT" | awk '/^fragmd5 = /{print $3}') # THE CROSS-ARM ASSERTION: the same fixture bytes through this package's own # md5.c must give the string the x86-64 control gave. check_eq isomd5sum/implant-md5-matches-x86 "7e05c4177a1f9b41f658f43e9f025276" "$MD5" check_eq isomd5sum/implant-fragmd5-matches-x86 "ac5cc82c9e565575b7888e3e8799a43be19d35968194fac74f29f975b" "$FRAG" # UPSTREAM BUG 2, from the writing side: 19 fragments x 3 characters, not 20. check_eq isomd5sum/implant-fragmd5-len-57 57 "${#FRAG}" AD=$(_appdata "$F") _out=$AD _has isomd5sum/appdata-md5 "ISO MD5SUM = 7e05c4177a1f9b41f658f43e9f025276;" _has isomd5sum/appdata-skipsectors "SKIPSECTORS = 15;" _has isomd5sum/appdata-status-0 "RHLISOSTATUS=0;" _has isomd5sum/appdata-fragcount "FRAGMENT COUNT = 20;" _has isomd5sum/appdata-warning "THIS IS NOT THE SAME AS RUNNING MD5SUM ON THIS ISO!!" # ---- 7. verify ----------------------------------------------------------------- _run "$CHK" "$F" check_eq isomd5sum/check-pass-rc 0 "$_rc" _has isomd5sum/check-pass-result "the result is: PASS." _has isomd5sum/check-pass-msg "It is OK to use this media." _has isomd5sum/check-press-esc "Press [Esc] to abort check." _run "$CHK" --md5sumonly "$F" check_eq isomd5sum/md5sumonly-rc 0 "$_rc" _has isomd5sum/md5sumonly-md5 "$F: 7e05c4177a1f9b41f658f43e9f025276" # UPSTREAM BUG 2, from the reading side: 60 characters copied where 57 were # written, so the field ends in three characters of "FRAGMENT COUNT". _has isomd5sum/md5sumonly-fragsums "Fragment sums: ac5cc82c9e565575b7888e3e8799a43be19d35968194fac74f29f975b;FR" _has isomd5sum/md5sumonly-fragcount "Fragment count: 20" _has isomd5sum/md5sumonly-supported "Supported ISO: no" # --gauge: the callback reports offset against total_size, and the LAST call # passes isosize instead -- so it overshoots to 108. Pinned, not smoothed over. _run "$CHK" --gauge "$F" check_eq isomd5sum/gauge-rc 0 "$_rc" GAUGE=$(printf '%s\n' "$_out" | awk '/^[0-9]+$/{print}') check_eq isomd5sum/gauge-first "4" "$(printf '%s\n' "$GAUGE" | head -1)" check_eq isomd5sum/gauge-last "108" "$(printf '%s\n' "$GAUGE" | tail -1)" _out=$GAUGE _has isomd5sum/gauge-reaches-100 "100" _run "$CHK" --verbose "$F" check_eq isomd5sum/verbose-rc 0 "$_rc" _has isomd5sum/verbose-md5 "7e05c4177a1f9b41f658f43e9f025276" _has isomd5sum/verbose-progress "Checking: 100.0%" _has isomd5sum/verbose-overshoot "Checking: 108.1%" # ---- 8. the second implant is refused ------------------------------------------ BEFORE=$(_appdata "$F") _run "$IMP" "$F" check_eq isomd5sum/reimplant-rc 1 "$_rc" _has isomd5sum/reimplant-msg "ERROR: Application data has been used - not implanting md5sum!" check_eq isomd5sum/reimplant-appdata-untouched "$BEFORE" "$(_appdata "$F")" # ---- 9. --force --supported-iso ------------------------------------------------- _run "$IMP" --force --supported-iso "$F" check_eq isomd5sum/force-rc 0 "$_rc" _has isomd5sum/force-msg-supported1 "Setting supported flag to 1" # the md5 is UNCHANGED, because --force blanks the application area before # hashing -- which is the whole reason the sum can live inside the image it sums check_eq isomd5sum/force-md5-unchanged "7e05c4177a1f9b41f658f43e9f025276" \ "$(printf '%s\n' "$_out" | awk '/^md5 = /{print $3}')" _out=$(_appdata "$F") _has isomd5sum/force-appdata-status-1 "RHLISOSTATUS=1;" _run "$CHK" "$F" check_eq isomd5sum/force-check-rc 0 "$_rc" _has isomd5sum/force-check-pass "the result is: PASS." _run "$CHK" --md5sumonly "$F" _has isomd5sum/force-supported-yes "Supported ISO: yes" # ---- 10. one flipped byte inside the checked range ------------------------------ cp "$F" "$W/bad.iso" printf '\377' | dd of="$W/bad.iso" bs=1 seek=40960 count=1 conv=notrunc 2>/dev/null check_eq isomd5sum/corrupt-byte-flipped "ff" \ "$(dd if="$W/bad.iso" bs=1 skip=40960 count=1 2>/dev/null | od -An -tx1 | tr -d ' \n')" _run "$CHK" "$W/bad.iso" check_eq isomd5sum/corrupt-check-rc 1 "$_rc" _has isomd5sum/corrupt-check-fail "the result is: FAIL." _has isomd5sum/corrupt-check-msg "It is not recommended to use this media." _hasnt isomd5sum/corrupt-check-not-pass "It is OK to use this media." # --md5sumonly reads the PVD and nothing else, so it CANNOT see the corruption: # it still exits 0 and still prints the implanted sum. Asserted so the two # options are not mistaken for each other. _run "$CHK" --md5sumonly "$W/bad.iso" check_eq isomd5sum/corrupt-md5sumonly-rc 0 "$_rc" _has isomd5sum/corrupt-md5sumonly-md5 "7e05c4177a1f9b41f658f43e9f025276" # ---- 11. SKIPSECTORS: the last 15 sectors are not summed ------------------------ cp "$F" "$W/tail.iso" printf '\377' | dd of="$W/tail.iso" bs=1 seek=409600 count=1 conv=notrunc 2>/dev/null _run "$CHK" "$W/tail.iso" check_eq isomd5sum/skiptail-check-rc 0 "$_rc" _has isomd5sum/skiptail-check-pass "the result is: PASS." # ---- 12. an input that is not an ISO 9660 --------------------------------------- # The clean half: a Volume Descriptor Set Terminator (type 255) at sector 16 ends # the descriptor walk, so both programs give a documented answer. dd if=/dev/zero of="$W/term.bin" bs=2048 count=32 2>/dev/null printf '\377CD001\001' | dd of="$W/term.bin" bs=1 seek=32768 conv=notrunc 2>/dev/null _run "$CHK" "$W/term.bin" check_eq isomd5sum/term-check-rc 1 "$_rc" _has isomd5sum/term-check-na "No checksum information available, unable to verify media." _run "$IMP" "$W/term.bin" check_eq isomd5sum/term-implant-rc 1 "$_rc" _has isomd5sum/term-implant-msg "ERROR: Could not find primary volume!" # UPSTREAM BUG 1 IS NOT RUN HERE -- see the header. An empty file spins both # programs forever, this runtime had no working bound for it when it was run # (timeout(1) never fired before the brintos/linux#77 fix), and running it once # cost every case in this file. The two witnesses stay skips carrying the # control that did establish the hang, so the finding is on the record where a # reader of the run will meet it. On a kernel with the #77 fix timeout(1) # fires, but no bounded run of this spin has been measured on target yet; once # one has, they can become the red witnesses they were written as. _eofskip="upstream read(2)==0 loop in read_primary_volume_descriptor(): an input that is not an ISO 9660 spins forever, and this runtime had no bound for it when measured -- alarm(2) was ENOSYS before the brintos/linux#77 fix and relative timers do not elapse (brintos/linux-in-the-browser#120), so timeout(1) never fired. Established on the x86-64 control instead: rc 124 under timeout 5, on empty, short, zero-filled and random inputs, 4 of 4" bst_skip isomd5sum/eof-loop-check "$_eofskip" bst_skip isomd5sum/eof-loop-implant "$_eofskip" # ---- 13. the Python extension is absent, from both directions ------------------- # The ticket expected python3-isomd5sum to ship and pyisomd5sum to import. It # does not and it cannot, and BOTH halves are asserted from the filesystem -- # the object's absence, and the absence of the mechanism that would have loaded # it. No interpreter is started: 99-python3 owns CPython's own behaviour and # records its start-up as minutes on a loaded guest, so an `import' here would # buy a restatement of the two facts below at the price of this suite's margin. PYD=/usr/lib/python3.12 # (a) the exact path the recipe's install-python would have written to. check isomd5sum/no-pyext-sitepkg test ! -e "$PYD/site-packages/pyisomd5sum.so" # (b) nothing else in site-packages answers to the name either. One directory # read rather than a walk -- and the read's own success is asserted first, # since an absence produced by a listing that did not happen is not one. check isomd5sum/sitepkg-readable test -d "$PYD/site-packages" check_eq isomd5sum/no-pyext-in-sitepkg "" "$(ls "$PYD/site-packages" 2>/dev/null | grep isomd5sum)" # (c) THE MECHANISM. lib-dynload is where CPython keeps the extension modules it # dlopen's, and here it is empty BY CONSTRUCTION: configure's wasm32 case # selects MODULE_BUILDTYPE=static and compiles every stdlib extension into # the one interpreter binary. An out-of-tree .so has nothing to load it, # which is why this port drops pyisomd5sum rather than deferring it. check isomd5sum/lib-dynload-present test -d "$PYD/lib-dynload" check_eq isomd5sum/lib-dynload-empty "" "$(ls "$PYD/lib-dynload" 2>/dev/null)" rm -rf "$W"