# BST-TIMEOUT: 900 # eleven perl starts; run-mailcap and update-mime ARE perl # # mime-support 3.62 -- Debian's mime.types and mailcap tables plus THE PROGRAMS # THAT USE THEM: run-mailcap (aliased see/edit/compose/print) and update-mime. # # THIS IS THE ROUND'S ONE EXECUTABLE DELIVERABLE, so the suite drives the # programs rather than asserting the payload. Every other package in round 23 # ships bytes that something else must read; this one ships perl scripts that # run on target, which means what is really under test is the ported perl # runtime (BRINTOS-34) driving a real workload -- and, through run-mailcap's own # type oracle, the ported file(1) as well. A port being driven by two other # ports is the strongest statement this round can make about its own data. # # WHAT IT READS, AND WHOSE. run-mailcap consults TWO tables and they come from # TWO DIFFERENT PACKAGES on this image: # # /etc/mime.types -- an update-alternatives link. mime-support declares # ALTERNATIVE_PRIORITY 90 and mailcap (BRINTOS-1189) takes # the class default of 10, so THIS package wins the link # and its 24,512-byte table is what the link resolves to. # mailcap's 74,869-byte table stays on disk beside it as # /etc/mime.types.mailcap, untouched. # /etc/mailcap -- NOT ours. mime-support installs its own mailcap to # /usr/lib/mime/mailcap (a skeleton, see update-mime # below) and never to /etc/mailcap, so the six-entry Red # Hat table mailcap ships is what run-mailcap resolves # types through. There is no collision on this path. # # Both halves are asserted, and this package's own table is read by its REAL # INSTALLED PATH (/etc/mime.types.mime-support) rather than through the link, so # the content cases stay true whichever package holds it. # # THE EXPECTATIONS ARE AN x86-64 RUN OF THE SAME VERSION, byte for byte, with # exactly TWO normalisations, both mechanical and both applied to the target's # output as well: the staging directory (which is $$-suffixed and cannot be # equal on two hosts) and nothing else -- run-mailcap is invoked here by the # absolute path /usr/bin/run-mailcap precisely so that the $0 it interpolates # into a copiousoutput pipeline is the same string on both sides rather than a # third thing to normalise away. # # WRITTEN TO EXEC AS LITTLE AS THE SUBJECT ALLOWS. On this arm a process's # memory is not returned when it exits and /bin/sh is a 16 MB wasm module, so a # suite's cost is how many programs it starts. Eleven of these are perl and are # irreducible -- each is a distinct CLI contract. The rest is one find, one # sha256sum, one gawk and one sed; the six-file resolution spread is ONE # run-mailcap invocation, not six, because run-mailcap takes a file list. . "$BST_LIB" S=mime-support # THE CANARY, which is not an assertion about mime-support at all. # # brintos_local_verify.py loses a suite's FIRST BST result line before the host # parser ever sees it -- BRINTOS-1149, a defect in our own host-side tooling and # not in the runner, the guest or any package. The harness reports the deficit # but computes its pass count as total-minus-failures, so THE DROPPED LINE IS # COUNTED AS A PASS: a suite whose first case is a genuine `not ok` loses the # one line that mattered, silently. A case that asserts nothing stands in that # position so the eaten line costs nothing. It sits ahead of the `require` # guards deliberately -- a `require` that skips emits its skip as the first line # and that line would be eaten too. # # Remove this case when 1149 is fixed. Same idiom and reason as 99-mailcap. bst_ok $S/suite-canary D=$BST_DATA tmp=${TMPDIR:-/tmp} W=$tmp/bst-mime-support.$$ require /usr/bin/run-mailcap $S/run-mailcap-present require /usr/sbin/update-mime $S/update-mime-present require perl $S/perl-present require file $S/file-present require gawk $S/gawk-present require sha256sum $S/sha256sum-present require find $S/find-present require sed $S/sed-present RM=/usr/bin/run-mailcap UM=/usr/sbin/update-mime MTREAL=/etc/mime.types.mime-support MTLINK=/etc/mime.types MTMAILCAP=/etc/mime.types.mailcap MAILCAP=/etc/mailcap SKEL=/usr/lib/mime/mailcap PKGENT=/usr/lib/mime/packages/mime-support ORDER=/etc/mailcap.order mkdir -p "$W/home" 2>/dev/null # --------------------------------------------------------------- payload shape # One find over every path this suite has an opinion about, including the two # that belong to mailcap: /etc/mime.types.mailcap has to be OBSERVED unchanged, # not assumed, because this package taking the alternatives link is exactly the # event that could have moved it. find "$MTREAL" "$MTLINK" "$MTMAILCAP" "$MAILCAP" "$ORDER" "$SKEL" "$PKGENT" \ /usr/bin/see /usr/bin/edit /usr/bin/compose /usr/bin/print "$RM" "$UM" \ /usr/lib/mime/debian-view /usr/lib/mime/playaudio /usr/lib/mime/playdsp \ -maxdepth 0 -printf '%p %y %s %l\n' 2>/dev/null > "$W.inv" sha256sum "$MTREAL" "$MTLINK" "$MTMAILCAP" "$MAILCAP" "$ORDER" "$SKEL" "$PKGENT" \ "$RM" "$UM" /usr/lib/mime/debian-view /usr/lib/mime/playaudio \ /usr/lib/mime/playdsp 2>/dev/null > "$W.sums" for pair in "mime-types:$MTREAL" "run-mailcap:$RM" "update-mime:$UM" \ "skeleton:$SKEL" "pkg-entries:$PKGENT" "order:$ORDER" "mailcap:$MAILCAP"; do nm=${pair%%:*}; f=${pair#*:} if [ -f "$f" ]; then bst_ok "$S/present-$nm" else bst_notok "$S/present-$nm" "$f is not a regular file"; fi done if [ ! -f "$MTREAL" ] || [ ! -x "$RM" ] || [ ! -x "$UM" ] || [ ! -f "$MAILCAP" ]; then bst_notok $S/prereq "a payload file is missing; the drive batches cannot run" return 2>/dev/null || exit 0 fi # ------------------------------------------------------------ the table itself gawk -v LOOKUPS='pdf,html,png,tar,json,mp3,ogg,ics,wasm,deb,bst-no-such-ext' \ -v RLOOKUPS='application/pdf,text/html,application/wasm,image/png,application/json,application/x-tar' \ -v DUPS='ttf,otf,sh,csh,tcl,deb,udeb,m3u,woff,wrl' \ -v CORE="$MTREAL,$MTLINK,$MTMAILCAP,$MAILCAP,$RM,$UM,$SKEL,$PKGENT" \ -f "$D/mime-support-mimetypes.awk" "$MTREAL" "$W.sums" "$W.inv" > "$W.mt" . "$W.mt" # The inventory pass saw all eight paths. This is the case that names the cause # when the find above produces nothing -- which is what a find without -printf # does, silently, leaving every size and type assertion below reading ''. check_eq $S/inventory-core 8 "$MS_INV_CORE" # These pin the table by the SAME rules 99-mailcap pins the other one by, so the # two are directly comparable. mime-support's table is the SMALLER of the pair # and that is the point: this package wins /etc/mime.types at priority 90, so # after this port lands the link resolves to 798 types where it used to resolve # to 2151. That is a real consequence of the port and is asserted, not glossed. check_eq $S/mimetypes-types 798 "$MS_TYPES" check_eq $S/mimetypes-extensions 549 "$MS_EXTS" check_eq $S/mimetypes-ext-slots 570 "$MS_SLOTS" check_eq $S/mimetypes-dup-type 0 "$MS_DUPTYPE" check_eq $S/mimetypes-bad-top 0 "$MS_BADTOP" check_eq $S/mimetypes-comments 47 "$MS_COMMENTS" # 376 of the 798 types carry no extension at all. The header says "zero or # more", so this is legal and is the single largest structural difference from # mailcap's table -- pinned because a table that lost its extension column # entirely would still parse and would still count 798 types. check_eq $S/mimetypes-no-ext 376 "$MS_NOEXT" check_eq $S/mimetypes-toplevel \ 'application:491,audio:45,chemical:54,font:6,image:53,inode:6,message:8,model:13,multipart:13,text:73,video:33,x-conference:1,x-epoc:1,x-world:1' \ "$MS_TOPLEVEL" # ------------------------------------------------- duplicate extensions, and # ------------------------------------------------- who wins them # mailcap's table has ZERO duplicate extensions; this one has 21 slots over 17 # distinct extensions, so "first definition wins" is a rule that matters here and # does not there. The list is asserted as well as the count: a table that gained # one duplicate and lost another would keep the count and change the data. check_eq $S/mimetypes-dup-ext-slots 21 "$MS_DUPEXT" check_eq $S/mimetypes-dup-ext-n 17 "$MS_DUPN" check_eq $S/mimetypes-dup-ext-list \ 'otf,ttf,woff,spl,cpt,deb,udeb,sdf,csh,sh,tcl,m3u,ra,asn,ent,wrl,vrml' "$MS_DUPLIST" check_eq $S/dup-ttf 'application/font-sfnt|4' "$MS_D_ttf" check_eq $S/dup-otf 'application/font-sfnt|4' "$MS_D_otf" check_eq $S/dup-sh 'application/x-sh|2' "$MS_D_sh" check_eq $S/dup-csh 'application/x-csh|2' "$MS_D_csh" check_eq $S/dup-tcl 'application/x-tcl|2' "$MS_D_tcl" check_eq $S/dup-deb 'application/vnd.debian.binary-package|2' "$MS_D_deb" check_eq $S/dup-udeb 'application/vnd.debian.binary-package|2' "$MS_D_udeb" check_eq $S/dup-m3u 'audio/mpegurl|2' "$MS_D_m3u" check_eq $S/dup-woff 'application/font-woff|2' "$MS_D_woff" check_eq $S/dup-wrl 'model/vrml|2' "$MS_D_wrl" # ------------------------------------------------------------ extension lookups check_eq $S/ext-pdf 'application/pdf' "$MS_E_pdf" check_eq $S/ext-html 'text/html' "$MS_E_html" check_eq $S/ext-png 'image/png' "$MS_E_png" check_eq $S/ext-tar 'application/x-tar' "$MS_E_tar" check_eq $S/ext-json 'application/json' "$MS_E_json" check_eq $S/ext-mp3 'audio/mpeg' "$MS_E_mp3" check_eq $S/ext-ogg 'audio/ogg' "$MS_E_ogg" check_eq $S/ext-ics 'text/calendar' "$MS_E_ics" check_eq $S/ext-wasm 'application/wasm' "$MS_E_wasm" check_eq $S/ext-deb 'application/vnd.debian.binary-package' "$MS_E_deb" check_eq $S/ext-absent 'none' "$MS_E_bst_no_such_ext" # The reverse direction, only where the table is unambiguous. text/html carries # the qualifier here for the same reason it does in 99-mailcap -- and answers # ambiguous:3 against that table's ambiguous:2, which is the two tables being # genuinely different rather than one being a subset of the other. check_eq $S/type-application-pdf 'pdf' "$MS_T_application_pdf" check_eq $S/type-image-png 'png' "$MS_T_image_png" check_eq $S/type-application-json 'json' "$MS_T_application_json" check_eq $S/type-application-wasm 'wasm' "$MS_T_application_wasm" check_eq $S/type-application-x-tar 'tar' "$MS_T_application_x_tar" check_eq $S/type-text-html-ambig 'ambiguous:3' "$MS_T_text_html" # ------------------------------------------------ sizes and content, vs x86-64 # Every one of these is byte-identical to the upstream tarball, which is also # what an x86-64 install of 3.62 produces: mime-support has no do_compile (there # is no Makefile in the tarball) so do_install copies the payload verbatim. That # makes agreement expected rather than surprising -- and it is asserted anyway, # because the failure it catches is a TRUNCATED or partially-installed payload, # which is neither expected nor visible any other way. check_eq $S/size-mime-types 24512 "$MS_SZ__etc_mime_types_mime_support" check_eq $S/size-run-mailcap 18161 "$MS_SZ__usr_bin_run_mailcap" check_eq $S/size-update-mime 9053 "$MS_SZ__usr_sbin_update_mime" check_eq $S/size-skeleton 1022 "$MS_SZ__usr_lib_mime_mailcap" check_eq $S/size-pkg-entries 257 "$MS_SZ__usr_lib_mime_packages_mime_support" check_eq $S/size-order 449 "$MS_SZ__etc_mailcap_order" check_eq $S/sha-mime-types \ 'd76bd92cf6e5f593cab2824e7774eaca544838ef8d358db5a0df5c200d74f3b2' "$MS_SHA__etc_mime_types_mime_support" check_eq $S/sha-run-mailcap \ '67b14b98ba2f54d30d3d862d3bec4cf16cde06f5f93e1dc8a66f400246e21ea8' "$MS_SHA__usr_bin_run_mailcap" check_eq $S/sha-update-mime \ '690c0d715fa6814dd894f724cdaee93bcc0dc38f14b3d4d1ce9d95826df10633' "$MS_SHA__usr_sbin_update_mime" check_eq $S/sha-skeleton \ '542d195f98f06edd6ec7d01838e24b013816e1e83fec1c19814281bbf4bfea03' "$MS_SHA__usr_lib_mime_mailcap" check_eq $S/sha-pkg-entries \ 'b138dd1e5d6a6f950ec695f0f4a4ca436af0fbee735c13281959bbb52db7e9bd' "$MS_SHA__usr_lib_mime_packages_mime_support" check_eq $S/sha-debian-view \ 'a7fb8973354234bc7366d4900fd4930b7119cc67d486e754c6b4a761711ca75a' "$MS_SHA__usr_lib_mime_debian_view" # --------------------------------------------------------- the alternatives link # THIS package wins /etc/mime.types at ALTERNATIVE_PRIORITY 90 against mailcap's # class default of 10. Both sides are asserted and so is the loser: mailcap's # table has to be present, a regular file, and byte-identical to what # 99-mailcap pins -- because this port taking the link is precisely the event # that could have disturbed it, and "mailcap still passes" is an obligation this # ticket owes rather than a thing to hope for. check_eq $S/alt-real-is-file 'f' "$MS_TY__etc_mime_types_mime_support" check_eq $S/alt-link-is-link 'l' "$MS_TY__etc_mime_types" check_eq $S/alt-winner 'mime.types.mime-support' "$MS_LN__etc_mime_types" # What the link RESOLVES to, not just what it says: sha256sum follows symlinks, # so this reads the table the way anything on the image would read it. check_eq $S/alt-link-resolves \ 'd76bd92cf6e5f593cab2824e7774eaca544838ef8d358db5a0df5c200d74f3b2' "$MS_SHA__etc_mime_types" check_eq $S/alt-loser-is-file 'f' "$MS_TY__etc_mime_types_mailcap" check_eq $S/alt-loser-size 74869 "$MS_SZ__etc_mime_types_mailcap" check_eq $S/alt-loser-intact \ '6d89583307fd2941a32039b9d8f392195c6e9a2fc89c681e693a06a714b3a23d' "$MS_SHA__etc_mime_types_mailcap" # ------------------------------------------------------------------ the aliases # Four symlinks, asserted as symlinks with their target, before any of them is # driven. run-mailcap derives its ACTION from $0, so the link target is what # makes `see` a viewer -- see the four drive cases below. check_eq $S/alias-see-link 'run-mailcap' "$MS_LN__usr_bin_see" check_eq $S/alias-edit-link 'run-mailcap' "$MS_LN__usr_bin_edit" check_eq $S/alias-compose-link 'run-mailcap' "$MS_LN__usr_bin_compose" check_eq $S/alias-print-link 'run-mailcap' "$MS_LN__usr_bin_print" check_eq $S/alias-see-is-link 'l' "$MS_TY__usr_bin_see" check_eq $S/alias-edit-is-link 'l' "$MS_TY__usr_bin_edit" check_eq $S/alias-compose-is-link 'l' "$MS_TY__usr_bin_compose" check_eq $S/alias-print-is-link 'l' "$MS_TY__usr_bin_print" # ------------------------------- #154 NO LONGER REPRODUCES, AND THIS IS THE GUARD # EVERY PROGRAM THIS PACKAGE SHIPS IS PERL, and on the image this suite was # FIRST written against perl aborted in glibc's allocator on every module load # -- linux-in-the-browser#154. That is no longer true here, and the change is # measured rather than assumed. The same 20-runs-of-each probe, run twice on two # images that differ only in the layer: # # was now # perl -e 'print' 0/20 0/20 <- interpreter always fine # perl -e 'use I18N::Langinfo' 0/20 0/20 # perl -e 'use Encode' 20/20 0/20 <- run-mailcap's first use # perl -e 'use File::Spec' 20/20 0/20 # run-mailcap --norun --action=view 20/20 0/20 <- so the battery now runs # update-mime 7/20 0/20 <- was INTERMITTENT # # THE BASE DID NOT MOVE. Both images pin base a60034d50dbb (superproject # 2556832a2ef3). The only change on this arm between them is BRINTOS-738 # staging empty stub archives into external-brintos-glibc.bb -- a TOOLCHAIN-LEVEL # recipe, so it re-signed the graph and glibc and everything above it rebuilt. # 738 documents itself as inert at link time (wasmld short-circuits the nine # integrated -l names above the file probe), so whether it FIXED anything or # merely forced a genuine rebuild in place of a stale sstate object is not # something this suite can distinguish, and it does not claim to. What is # reported upstream is the measurement, not a cause. # # THE CLASSIFIER STAYS, and that is the point of this block. #154 is still OPEN # upstream and nothing here fixed it deliberately, so a regression would come # back through exactly these programs. ms_try/ms_is154 cost one attempt each # when nothing aborts -- the battery below now takes the first branch on attempt # 1 -- and buy an ATTRIBUTED red instead of a bare want/got the day it returns. # The pattern set is deliberately wide: update-mime alone produced FOUR glibc # spellings in its 7 aborts (mremap_chunk(): invalid pointer / corrupted size # vs. prev_size / free(): invalid pointer / double free or corruption (!prev)). # It is 36-libperlio-gzip-perl's set, adopted rather than re-derived, and # BRINTOS-1011 widened it after a narrower one reported an attributed red as a # new defect. # # BRINTOS-WORKAROUND: linux-in-the-browser#154 remove -- ms_try/ms_is154 exist # only against this defect. When #154 is CLOSED upstream, delete them and let # every case below run once, unconditionally; the assertions are already written # and now pass on target rather than only against x86-64. # ms_diag : the real diagnostic, with perl's locale preamble stripped. # SEVEN lines, not the four this comment used to claim -- measured on target: # two "perl: warning:" lines, three indented "LANGUAGE/LC_ALL/LANG = (unset)" # lines, an indented "are supported and installed" line, then a third # "perl: warning: Falling back" line. The awk below already handled all seven # (it skips a warning line and any indented continuation of one); only the count # in this comment was wrong. Without the strip the 100-char detail field of # every red reads "Setting locale failed", which is the WRONG diagnosis in the # one field a later reader attributes by -- the warning is on every perl run on # this image, including the ones that succeed. It is also why the byte-exact # comparisons in the battery below strip it from stderr before comparing. ms_diag() { printf '%s\n' "$1" | awk '/^perl: warning/{s=1;next} /^[ \t]/&&s{next} {s=0;print}'; } ms_is154() { case "$1" in *mremap_chunk*|*munmap_chunk*|*"corrupted size"*|*"corrupted double-linked list"*|\ *"double free or corruption"*|*"free(): "*|*"malloc(): "*|*"realloc(): "*) return 0 ;; *) return 1 ;; esac } # ms_try : run up to times, stopping at the first attempt # that is NOT a #154 abort. Sets ms_out / ms_rc / ms_aborts. # # The retry is deliberate and is not a way of hiding the defect: a case whose # command was killed by the allocator never ran, so it has no verdict to report # -- the same reasoning bst_unrun applies to an exec the kernel refused to # stage. What the retry buys is that update-mime's 35% is not re-rolled into a # random red on every verify. It cannot rescue run-mailcap, whose rate is 100%, # and the gate below reports that as the block it is rather than retrying at it. ms_try() { _n=$1; shift ms_aborts=0; _i=0 while [ "$_i" -lt "$_n" ]; do ms_out=$("$@" 2>&1); ms_rc=$? ms_d=$(ms_diag "$ms_out") ms_is154 "$ms_d" || return 0 ms_aborts=$((ms_aborts+1)); _i=$((_i+1)) done return 1 } MS154='linux-in-the-browser#154 -- perl aborts in glibc allocator on wasm32-hwjs' # ------------------------------------------------------- file(1) as the oracle # run-mailcap falls back to `file -b --mime-type -e tokens -L -z` when the # filename carries no extension it recognises. Asserted DIRECTLY first, so that # a magic-resolution failure below separates "run-mailcap did not consult file" # from "file answered differently" -- the two have different owners. cp "$D/mime-support-magic.png" "$W/magicprobe" 2>/dev/null check_out $S/file-oracle-direct 'image/png' file -b --mime-type -e tokens -L -z "$W/magicprobe" # run-mailcap guards that fallback with a bare `which file`, so which(1) is a # HIDDEN RUNTIME DEPENDENCY of this package -- the recipe's RDEPENDS names only # perl. When which is missing the guard is simply false: run-mailcap never # consults file, silently falls back to application/octet-stream, and the type # resolution goes wrong in a way that reads like a bad table rather than a # missing tool. Asserted on its own so that failure names itself. (Observed for # real while developing this suite, in a sandbox whose /etc/alternatives was not # present -- the symptom was exactly the octet-stream fallback and nothing else.) check_out $S/which-resolves-file '/usr/bin/file' which file # ------------------------------------------------------------ driving run-mailcap # THE GATE, AND IT IS OPEN. This battery was written blind: run-mailcap aborted # 20/20 when the suite was authored, so every case below was unreachable and the # expectations came from an x86-64 run of this same version through these same # two tables. #154 stopped reproducing (see the block above) and the battery now # runs on target -- and it asserted, on the first boot that reached it, exactly # what was written down for x86-64. That is the strongest statement this suite # makes: the expectations were not adjusted to fit the target, they were # recorded ahead of it and then met, with the ONE exception documented at the # transcript below (perl's locale preamble on stderr, which is the image's and # not this package's). ms_try still wraps the first call as a regression guard. : > "$W/probe.pdf"; : > "$W/probe.png"; : > "$W/probe.html" : > "$W/probe.tar"; : > "$W/probe.txt" if ms_try 3 "$RM" --norun --action=view "$W/probe.pdf"; then bst_ok $S/run-mailcap-runs # ONE invocation, six files, --norun so nothing is executed: run-mailcap takes # a file list and processes it in order, which is what lets the whole # resolution spread cost one perl start instead of six. stdout and stderr are # captured SEPARATELY -- stderr is unbuffered and stdout is not, so a combined # capture interleaves by buffer-flush order and is not reproducible. "$RM" --norun --action=view \ "$W/probe.pdf" "$W/probe.png" "$W/probe.html" "$W/probe.tar" "$W/probe.txt" \ "$W/magicprobe" > "$W/rm.out" 2> "$W/rm.err" rc=$? # The aggregate status of a batch is the WORST case in it: two of the six have # no rule, and run-mailcap raises $retcode to 3 for those and never lowers it. check_eq $S/run-mailcap-batch-rc 3 "$rc" # THE PREAMBLE IS STRIPPED FROM STDERR AND NOTHING ELSE IS. Every perl start # on this image emits a seven-line locale warning before the program's own # output -- LANG, LC_ALL and LANGUAGE are all unset in the guest, so perl # falls back to C and says so. It is a property of the image's locale setup, # not of mime-support, and it is on the runs that SUCCEED as well; asserting # it here would pin an unrelated platform detail into this package's suite and # would break every one of these cases the day the image grows a locale. What # is left after the strip is byte-exact against x86-64, which is the claim. ms_diag "$(cat "$W/rm.err")" > "$W/rm.err.d" sed -e "s|$W/||g" "$W/rm.out" "$W/rm.err.d" > "$W/rm.norm" # One assertion carrying the whole normalised transcript, and it is the # byte-exact x86-64 output of the same version driven through the same two # tables. Four stdout lines then two stderr lines, in that order because sed # reads the files in that order. The third line is the one that could not be # written down from the man page: text/html is the only entry in /etc/mailcap # carrying copiousoutput, and run-mailcap honours it by APPENDING A PIPE INTO # ITSELF as a text/plain pager -- a statement about the mailcap parse made by # something other than this suite's own reading of the file. The fourth line is # magicprobe, which has no extension at all and therefore resolved through # file(1); it is what makes this one assertion span both ported oracles. want='/usr/bin/xdg-open probe.pdf /usr/bin/xdg-open probe.png /usr/bin/xdg-open probe.html | /usr/bin/run-mailcap --action=view text/plain:- /usr/bin/xdg-open magicprobe Error: no "view" mailcap rules found for type "application/x-tar" Error: no "view" mailcap rules found for type "text/plain"' check_eq $S/run-mailcap-transcript "$want" "$(cat "$W/rm.norm")" # The per-case exit statuses the batch's aggregate cannot carry. Two runs, the # two ends of the contract: a type that resolves, and one that does not. check_rc $S/run-mailcap-rc-resolved 0 "$RM" --norun --action=view "$W/probe.pdf" check_rc $S/run-mailcap-rc-no-rule 3 "$RM" --norun --action=view "$W/probe.tar" # --nopager suppresses the copiousoutput pipe. This is the one case in the file # independent of every path on either host, so it is the cleanest statement # that the flag is read: same file, same tables, pipe present above, absent here. out=$(ms_diag "$("$RM" --norun --nopager --action=view "$W/probe.html" 2>&1)") check_eq $S/run-mailcap-nopager "/usr/bin/xdg-open $W/probe.html" "$out" # --action=cat REQUIRES copiousoutput on the entry, so the same two files # split: text/html has the flag and resolves, application/pdf does not and is # refused with a DIFFERENT diagnostic from the no-rule one above ("no rule ... # passed its test case", $fail++, rather than "no rules found"). Asserting both # texts is what distinguishes the two rejection paths; a bare rc=3 cannot. check_out $S/run-mailcap-cat-ok "/usr/bin/xdg-open $W/probe.html" \ "$RM" --norun --action=cat "$W/probe.html" raw=$("$RM" --norun --action=cat "$W/probe.pdf" 2>&1); rc=$? out=$(ms_diag "$raw") check_eq $S/run-mailcap-cat-refused-rc 3 "$rc" case "$out" in *'no "cat" rule for type "application/pdf" passed its test case'*) bst_ok $S/run-mailcap-cat-refused ;; *) bst_notok $S/run-mailcap-cat-refused "$(_bst_1line "$out")" ;; esac # The action each alias implies, observed in the tool's own words. `see` views # and resolves; the other three name their action in the diagnostic, which is a # stronger statement than a bare rc=3 -- it is run-mailcap reporting which # action it selected FROM ITS OWN $0, and only the symlink can have told it. check_out $S/alias-see-views "/usr/bin/xdg-open $W/probe.pdf" \ /usr/bin/see --norun "$W/probe.pdf" for a in edit compose print; do raw=$("/usr/bin/$a" --norun "$W/probe.pdf" 2>&1); rc=$? out=$(ms_diag "$raw") if [ "$rc" -eq 3 ] && [ "$out" = "Error: no \"$a\" mailcap rules found for type \"application/pdf\"" ]; then bst_ok "$S/alias-$a-action" elif bst_execfail "$raw"; then bst_unrun "$S/alias-$a-action" "$raw" else bst_notok "$S/alias-$a-action" "rc=$rc $(_bst_1line "$out")"; fi done else # THE BLOCKED PATH. One red naming the block, then one red per requirement the # block leaves unmeasured -- named rather than silent, because a suite that # merely stopped here would report its data cases green and read as a pass on a # ticket whose whole point is that this package ships PROGRAMS. bst_notok $S/run-mailcap-runs \ "rc=$ms_rc after $ms_aborts attempt(s) -- $(_bst_1line "$(ms_diag "$ms_out")") -- $MS154" bst_notok $S/run-mailcap-selection-unverified \ "not run ($MS154): the six-type resolution spread, its byte-exact diagnostics and its per-case exit statuses are unverified on wasm32-hwjs" bst_notok $S/run-mailcap-file-oracle-unverified \ "not run ($MS154): file(1) as run-mailcap's type oracle for an extensionless file is unverified -- file itself answers image/png here, see file-oracle-direct" bst_notok $S/run-mailcap-flags-unverified \ "not run ($MS154): --nopager and --action=cat, i.e. whether the copiousoutput flag is honoured, are unverified on wasm32-hwjs" bst_notok $S/run-mailcap-aliases-unverified \ "not run ($MS154): see/edit/compose/print resolve to run-mailcap (asserted above) but which action each SELECTS is unverified on wasm32-hwjs" fi # ------------------------------------------------------------ driving update-mime # THE INPUTS FIRST, so a change in the generated table below names its own cause. # update-mime builds /etc/mailcap from /usr/lib/mime/packages/* plus any # .desktop file under /usr/share/applications that declares MimeType=. On this # image that is one package file and ZERO desktop entries (htop.desktop is the # only one and carries no MimeType), so the generated table is deterministic. # When a future port adds a MimeType-bearing .desktop, THIS case goes red and # says so, rather than the generated-table case going red and looking like a # mime-support regression. npkg=$(find /usr/lib/mime/packages -type f 2>/dev/null | wc -l) check_eq $S/update-mime-input-packages 1 "$npkg" ndesk=$(grep -l '^MimeType=' /usr/share/applications/*.desktop 2>/dev/null | wc -l) check_eq $S/update-mime-input-desktop 0 "$ndesk" # --local is the SAFE and complete path: it redirects $mailcap to $HOME/.mailcap # and leaves /etc alone, so the whole generator -- ReadEntries, ReadDesktopEntries, # ReadOrder, OrderEntries, UpdateMailcap -- runs against the image's real inputs # with nothing on the read-only rootfs written to. HOME is a tmpfs directory here # because /root is on that rootfs. # ms_try 8 rather than a bare run: update-mime aborted 7/20 on the image this was # written against (see the #154 block), so one attempt would have re-rolled a # random red on roughly a third of every verify. It measures 0/20 now and takes # the first attempt, but the retry is kept for the same reason the classifier is # -- #154 is open, and this is the one command that showed it intermittently. # The ATTEMPT COUNT is reported in the red's detail when they all abort, so a # return of the defect is visible rather than silently retried away. if ms_try 8 env HOME="$W/home" "$UM" --local; then check_eq $S/update-mime-local-rc 0 "$ms_rc" else bst_notok $S/update-mime-local-rc \ "all 8 attempts aborted -- $(_bst_1line "$(ms_diag "$ms_out")") -- $MS154" fi if [ -f "$W/home/.mailcap" ]; then bst_ok $S/update-mime-local-wrote else bst_notok $S/update-mime-local-wrote "$W/home/.mailcap was not created"; fi # The generated table, byte for byte against the x86-64 run: the skeleton up to # and including its User Section markers, then the separator update-mime appends, # then one entry -- mailcap.entries' single uncommented line with its priority # field stripped. The markers surviving is the assertion that matters most: they # are what makes the file re-generatable, and losing them is exactly the damage # the "without damaging it" half of this is about. check_eq $S/update-mime-generated-sha \ '41c0a315a5c9feef56aa8a9c582d10fa4eed9fe6c4396919008d1d1986074533' \ "$(sha256sum "$W/home/.mailcap" 2>/dev/null | cut -d' ' -f1)" if grep -q '^# ----- User Section Begins ----- #$' "$W/home/.mailcap" 2>/dev/null && grep -q '^# ----- User Section Ends ----- #$' "$W/home/.mailcap" 2>/dev/null; then bst_ok $S/update-mime-markers-kept else bst_notok $S/update-mime-markers-kept "the User Section markers are gone from the generated table"; fi if grep -qx 'application/vnd.debian.binary-package; /usr/lib/mime/debian-view %s; needsterminal; description=Debian GNU/Linux Package; nametemplate=%s.deb' "$W/home/.mailcap" 2>/dev/null; then bst_ok $S/update-mime-entry-emitted else bst_notok $S/update-mime-entry-emitted "the debian-view entry is not in the generated table"; fi # REGENERATES WITHOUT DAMAGING: the second run reads the table the first run # wrote -- a different input path, since $mailcap now exists where it did not -- # and has to produce the same bytes. This is the diff-before-and-after the ticket # asks for, and it is the property that makes update-mime safe to re-run. cp "$W/home/.mailcap" "$W/mailcap.before" 2>/dev/null if ms_try 8 env HOME="$W/home" "$UM" --local; then if cmp -s "$W/mailcap.before" "$W/home/.mailcap"; then bst_ok $S/update-mime-idempotent else bst_notok $S/update-mime-idempotent "a second --local run changed the generated table"; fi else bst_notok $S/update-mime-idempotent "all 8 attempts aborted -- $MS154" fi # AND THE COLLISION THIS IMAGE ACTUALLY HAS. Run without --local, update-mime # targets /etc/mailcap -- which on this image is MAILCAP's Red Hat table, not a # Debian one, and carries no User Section markers. UpdateMailcap's format check # fires BEFORE anything is opened for writing, so it refuses in its own words and # changes nothing. That is asserted from both ends: the refusal text, and # /etc/mailcap's sha256 re-read afterwards and compared with the one the # inventory pass took before any of this ran. if ms_try 8 "$UM"; then out=$ms_out; rc=$ms_rc else out=$ms_out; rc=$ms_rc; fi check_eq $S/update-mime-etc-rc 0 "$rc" case "$out" in *"Error: '/etc/mailcap' is not in required format -- not updated"*) bst_ok $S/update-mime-etc-refused ;; *) bst_notok $S/update-mime-etc-refused "$(_bst_1line "$out")" ;; esac check_eq $S/update-mime-etc-unharmed "$MS_SHA__etc_mailcap" \ "$(sha256sum "$MAILCAP" 2>/dev/null | cut -d' ' -f1)" check_eq $S/mailcap-table-sha \ '9e701bfd119a566cd01950a1fa4049e3d0caf8cad684228ff04afb232aa911b8' "$MS_SHA__etc_mailcap" rm -rf "$W" "$W.inv" "$W.sums" "$W.mt" 2>/dev/null