# BST-TIMEOUT: 600 # FOURTEEN runs of the 7.8 MB data/freetype-probe, where # # 99-ttf-bitstream-vera does ten, 99-ttf-droid seven and # # 99-cantarell-fonts one. The bound is deliberately the SAME # # 600 all four of those carry, for the reason vera's header # # gives: all five drive the same binary, whose load cost # # dominates, and a suite whose cost is dominated by one # # binary should not claim a different bound for it. # # MEASURED on target -- read off the ==BST-SUITE elapsed= # # line, not estimated -- and recorded in the design doc and # # the test plan rather than re-edited into this comment, # # which would cost a further image build to keep the shipped # # suite byte-identical to the branch. # # source-code-pro-fonts 2.030 -- Adobe Source Code Pro, the monospace family # designed for code, under SIL OFL 1.1. meta-openembedded/meta-oe # recipes-graphics/ttf-fonts/source-code-pro-fonts_2.030_1.050.bb. # # ============================================================================ # FOURTEEN FACES, AND A FIFTEENTH FILE THAT IS THE WHOLE STORY OF THIS PORT. # ============================================================================ # # The recipe requires ttf.inc and then REPLACES its do_install: where the inc # globs `*.tt[cf]`, this one globs `*.otf` and additionally installs a fontconfig # fragment. The zip carries TTF/, WOFF/, WOFF2/ and EOT/ beside OTF/, so the .otf # set is a DECISION of this recipe rather than a property of the tarball -- # ttf-no-extras is anchored on the extension for exactly that reason. # # source-code-pro-fonts /usr/share/fonts/truetype/SourceCodePro-*.otf x14 # /etc/fonts/conf.d/44-source-code-pro-fonts-fontconfig.conf # source-code-pro-fonts-dev, -dbg empty placeholders, not installed # source-code-pro-fonts-doc DOES NOT EXIST -- see below # # NO -doc PACKAGE, AND NO LICENCE FILE ON THE IMAGE. The zip's LICENSE.txt is # never installed -- do_install writes the fourteen faces and the fragment and # nothing else -- and FILES:${PN} is an ASSIGNMENT naming ${sysconfdir}/fonts and # ${datadir}/fonts, so ${PN}-doc is empty and dpkg builds none. That is the # recipe's behaviour, not this port's choice, and requirement 3 is every file the # RECIPE DECLARES, all fifteen of which ship. pkg-no-doc-package asserts the # absence, because "the -doc line was forgotten" and "there is no -doc package to # install" look identical from the file layer alone. The licence is not lost: # name IDs 13/14 inside every face carry the OFL notice and its URL. # # ============================================================================ # THIS PORT TAKES A GENERIC -- monospace -- AND IT IS THE FIRST FONT PORT ON # THIS IMAGE THAT SHIPS THE CONFIGURATION THAT DOES IT. # ============================================================================ # # Every font port before this one either took no generic (ttf-gentium, ttf-droid, # cantarell-fonts, terminus-font) or took one on MERIT out of fontconfig's own # shipped ranking (ttf-inconsolata, which displaced Liberation Mono because # 60-latin.conf ranks Inconsolata third among monospace families and Liberation # Mono is not on that list at all). This port takes one because its RECIPE SHIPS # A FRAGMENT THAT ASKS FOR IT: # # 44-source-code-pro-fonts-fontconfig.conf # monospace # Source Code Pro # Source Code Pro # monospace # # 44 sorts BEFORE 60-latin.conf, and prepends, so Source Code Pro goes # to the head of monospace's family list ahead of Inconsolata's rank-3 claim. # THE PRECONDITION IS ALSO SATISFIED, WHICH IS WHY THIS ACTUALLY BITES: all # fourteen faces carry spacing=100 (FC_MONO) -- fontconfig derives that from the # advance widths and this is a code face -- so there is no proportional-face # mismatch for the sort to reject. fcq-spacing-mono in the verify awk asserts the # precondition and fc-match-monospace here asserts the outcome. # # MEASURED BEFORE IT WAS ASSERTED, AND WITH A NULL CONTROL. A native fontconfig # 2.15.0 -- the same release this image ships, built from this image's own recipe # -- was driven over a fake root holding EXACTLY this image's font set and # /etc/fonts tree. WITHOUT this package it answers sans-serif => Liberation Sans, # serif => Liberation Serif, monospace => Inconsolata, system-ui => Liberation # Mono, which is what the image itself answers, so the rig reproduces the target # baseline and its verdict means something. WITH this package installed the ONLY # generic that moves is monospace, to Source Code Pro; sans-serif, serif, # system-ui, fantasy and cursive are all unchanged. This suite asserts both # halves -- the one that moves and the ones that do not. # # FOUR SIBLING SUITES ASSERTED `fc-match monospace` => Inconsolata AND ARE # AMENDED BY THIS TICKET: 99-liberation-fonts, 99-ttf-inconsolata, 99-ttf-droid # and 99-cantarell-fonts. That is the same repair ttf-inconsolata itself had to # make to 99-liberation-fonts one round earlier, for the same reason and in the # same direction: the generic resolves to the highest-ranked family actually # installed, it is still doing that, and the case now says so from the new side. # The three `-unchanged` cases in those suites keep their names, because what # they assert is that THEIR OWN port did not move the generic, and that is still # true. A disagreement between any two of the five is visible rather than silent. # # ============================================================================ # THE fontcache POSTINST IS THE THING THE TICKET SAYS TO CHECK RATHER THAN # ASSUME, AND IT IS CHECKED IN THE ONE FORM THAT IS BOOT-MODE INDEPENDENT. # ============================================================================ # # fontcache.bbclass appends fontconfig-utils to RDEPENDS -- read back off the # target here, not off the recipe -- and registers an update_font_cache intercept # that runs fc-cache under qemu-user. There is no wasm32 qemu-user, so it is # deferred to run-postinsts at first boot, which /etc/inittab does run # (BRINTOS-53). Whether it HAS run depends on the pid 1 the harness booted -- the # local runner goes straight to a shell and never reaches inittab -- so asserting # the configured state would report the runner's choice as a package red. What is # asserted instead is boot-mode independent and is the actual risk the ticket # names: the scriptlet is on the image, it calls fc-cache, and fc-cache is # present, so the deferred run cannot fail for want of the tool. Nothing had to # be overridden. Image-wide postinst success stays 79-run-postinsts' no-unpacked # case and is not re-litigated here; the fc-* block forces `fc-cache -f` itself # so no other case depends on any of this. # # ============================================================================ # FOUR LAYERS, AND A RED IN AN EARLIER ONE LOCALISES A RED IN A LATER ONE: # # file-*, ttf-*, the payload arrived intact -- size, bytes, mode, type -- # conf-*, cotenant-* the fragment is a regular file and the only one of ours, # pkgfiles-* three co-tenants in the shared directory survived, the # OTHER font directory is untouched, and the package claims # exactly the fifteen paths and no more. No font machinery # involved at all. # pkg-*, postinst-* the packages the image really installs, the fontcache # class's RDEPENDS, and the deferred scriptlet. # ft-* the image's OWN freetype PARSES each face through its CFF # driver and agrees about num_faces, num_glyphs, # units_per_EM, family and style -- the layer the ticket # asks for by name. The STYLE is the load-bearing field: # ten of the fourteen name themselves differently under name # IDs 1/2 than under 16/17, and freetype takes 16/17. # fcq-*, fc-* fontconfig's independent parse (fc-scan, against a native # x86-64 control), then discovery and matching THROUGH THE # CACHE, which is a different path again -- and where the # generic handover this port performs is finally visible. . "$BST_LIB" S=source-code-pro-fonts # THE CANARY, which asserts nothing about source-code-pro-fonts. # # A suite's FIRST BST result line is lost between the guest's printf and the # host's read -- per-suite, deterministic, and NOT a defect in the host tool # (BRINTOS-1149 established that and filed it as linux-in-the-browser#177). # The harness reports the deficit but computes its pass count as total-minus- # failures, so THE DROPPED LINE IS COUNTED AS A PASS. A nothing-case therefore # stands in that position and the eaten line costs nothing; every real case below # is still counted. It sits ahead of the `require` guards deliberately, because a # `require` that skips would emit its skip as the first line and be eaten too. # # Remove this case when linux-in-the-browser#177 is fixed. bst_ok $S/suite-canary D=$BST_DATA REF=$D/source-code-pro-fonts-manifest.txt FACTS=$D/source-code-pro-fonts-fontfacts.txt FACES=$D/source-code-pro-fonts-fcfaces.txt PROBE_SRC=$D/freetype-probe TTFDIR=/usr/share/fonts/truetype CONFDIR=/etc/fonts/conf.d COTDIR=/usr/share/fonts/ttf CONF=$CONFDIR/44-source-code-pro-fonts-fontconfig.conf REG=$TTFDIR/SourceCodePro-Regular.otf PKGLIST=/var/lib/dpkg/info/source-code-pro-fonts.list PI=/var/lib/dpkg/info/source-code-pro-fonts.postinst tmp=${TMPDIR:-/tmp} W=$tmp/bst-scp.$$ require gawk $S/gawk-present require sha256sum $S/sha256sum-present require find $S/find-present # fc-scan runs in the payload block, ahead of the consumer block's own check, so # its absence is guarded here. It is NOT a `require`: fontconfig-utils is a hard # Depends of source-code-pro-fonts, so an absent fc-scan is a defect in the port # rather than a legitimately absent tool, and a skip would report it green. if [ -x /usr/bin/fc-scan ]; then bst_ok $S/fc-scan-present else bst_notok $S/fc-scan-present "fontconfig-utils is a Depends of source-code-pro-fonts but /usr/bin/fc-scan is absent"; fi if [ ! -f "$REF" ] || [ ! -f "$FACTS" ] || [ ! -f "$FACES" ]; then bst_notok $S/ref-present "the reference data did not ship: $REF / $FACTS / $FACES" exit 0 fi bst_ok $S/ref-present # ------------------------------------------------------------- payload shape # One find over this port's own directory, the fragment directory, AND the other # font directory, so every count is a measurement from the same pass. %y catches # a symlink where a regular file is meant and %m the mode -- neither of which # `test -f` can see, and %y is what conf-regular-file rests on. There is no doc # directory to walk: this recipe installs none (see the header). find "$TTFDIR" "$CONFDIR" "$COTDIR" \ -maxdepth 1 -printf '%p %y %s %m %l\n' 2>/dev/null | LC_ALL=C sort > "$W.inv" # One sha256sum over the fifteen payload files. The faces are globbed on OUR OWN # basename shape rather than on `*.otf`, so a co-tenant that arrived as an OTF # would not silently join the digest set; the manifest is the list, and # ttf-no-extras is what says the directory holds nothing our shape does not name. sha256sum "$TTFDIR"/SourceCodePro-*.otf "$CONF" > "$W.sums" 2>&1 # The package's own file list, copied to tmpfs rather than read from the rootfs # in a redirect (brintos/linux#73). An absent list is not fatal here -- the awk's # pkgfiles-loaded case reports it -- so this is not guarded with an exit. cat "$PKGLIST" > "$W.pkgf" 2>/dev/null || : > "$W.pkgf" # One fc-scan over the fourteen installed faces. fontconfig opens them through # FreeType, so this is a second, independent parse -- and it reads fields # freetype's own API does not name (the PostScript name, the derived # slant/weight/spacing, the format and the charset). # # ONE PATTERN PER FILE, unlike 99-cantarell-fonts. None of these is a variable # font -- no fvar, no CFF2 -- so `fc-scan` returns exactly fourteen lines and the # de-dup trap that suite documents does not apply here. LC_ALL=C fc-scan --format '%{file|basename}|%{family}|%{style}|%{slant}|%{weight}|%{spacing}|%{postscriptname}|%{fontformat}|%{scalable}|%{outline}|%{charset}\n' \ "$TTFDIR"/SourceCodePro-*.otf 2>/dev/null | LC_ALL=C sort > "$W.scan" LC_ALL=C gawk -v REF="$REF" -v SUMS="$W.sums" -v INV="$W.inv" -v PKGF="$W.pkgf" \ -v FACES="$FACES" -v SCAN="$W.scan" \ -f "$D/source-code-pro-fonts-verify.awk" "$REF" "$W.sums" "$W.inv" "$W.pkgf" "$FACES" "$W.scan" # ---------------------------------------------------- the packaging on target # THE PACKAGE DATABASE IS THE ONLY PLACE THE SPLIT IS VISIBLE ON TARGET. The # file-* cases would look identical if some other package had installed the same # bytes, so they cannot say that source-code-pro-fonts is a real package the # image installs rather than an IMAGE_INSTALL line that resolved to nothing. One # sed pulls every stanza; the loop is shell builtins. The stanzas are read from a # tmpfs copy, never redirected from the rootfs (brintos/linux#73). # # THE ANCHORS ARE EXACT ON PURPOSE. `source-code-pro-fonts` is a PREFIX of # `source-code-pro-fonts-dev`, `-dbg` and `-doc`, so an unanchored match would # report one stanza as another and make pkg-no-doc-package unfalsifiable. sed -n '/^Package: source-code-pro-fonts$/,/^$/p; /^Package: source-code-pro-fonts-doc$/,/^$/p; /^Package: source-code-pro-fonts-dev$/,/^$/p; /^Package: source-code-pro-fonts-dbg$/,/^$/p' \ /var/lib/dpkg/status > "$W.st" 2>/dev/null _pkg=""; _main=0; _doc=0; _dev=0; _dbg=0; _arch=0; _dep=0 while IFS= read -r l; do case "$l" in "Package: source-code-pro-fonts") _pkg=main; _main=1 ;; "Package: source-code-pro-fonts-doc") _pkg=doc; _doc=1 ;; "Package: source-code-pro-fonts-dev") _pkg=dev; _dev=1 ;; "Package: source-code-pro-fonts-dbg") _pkg=dbg; _dbg=1 ;; "Architecture: all") [ "$_pkg" = main ] && _arch=1 ;; "Depends: "*) case "$l" in *fontconfig-utils*) [ "$_pkg" = main ] && _dep=1 ;; esac ;; esac done < "$W.st" # THE ONE PACKAGE THIS IMAGE INSTALLS. A dropped IMAGE_INSTALL line would take # every file-* and ft-* case with it; this case says the cause is a missing # PACKAGE rather than missing files. if [ "$_main" -eq 1 ]; then bst_ok $S/pkg-known else bst_notok $S/pkg-known "dpkg does not know the package source-code-pro-fonts"; fi # THERE IS NO -doc PACKAGE, AND ITS ABSENCE IS THE RECIPE. Nothing but the faces # and the fragment is installed -- LICENSE.txt stays in ${S} -- so ${PN}-doc is # empty and dpkg builds none. This case names that, because a future recipe # revision that installed LICENSE.txt would change what the image must ask for -- # and because ttf-inconsolata, whose OFL.txt IS the only copy of its licence on # the image, does ship a -doc and this one deliberately does not. if [ "$_doc" -eq 0 ]; then bst_ok $S/pkg-no-doc-package else bst_notok $S/pkg-no-doc-package "dpkg knows a source-code-pro-fonts-doc package -- the recipe now installs documentation"; fi # ...AND -dev / -dbg ARE NOT INSTALLED. Both are built and both are empty. They # are asserted absent rather than ignored: an IMAGE_INSTALL that pulled them in # would add two packages to the manifest for no payload at all, and nothing else # in this suite would notice. if [ "$_dev" -eq 0 ]; then bst_ok $S/pkg-no-dev else bst_notok $S/pkg-no-dev "source-code-pro-fonts-dev is installed -- it is an empty placeholder"; fi if [ "$_dbg" -eq 0 ]; then bst_ok $S/pkg-no-dbg else bst_notok $S/pkg-no-dbg "source-code-pro-fonts-dbg is installed -- it is an empty placeholder"; fi # `allarch` reached the package metadata, which is what makes the byte-identity # reference in the manifest a statement about this build rather than a # coincidence. if [ "$_arch" -eq 1 ]; then bst_ok $S/pkg-arch-all else bst_notok $S/pkg-arch-all "source-code-pro-fonts is not Architecture: all"; fi # THE fontcache CLASS'S RDEPENDS, READ BACK OFF THE TARGET. The recipe declares # no runtime dependency at all -- fontcache.bbclass appends fontconfig-utils to # each FONT_PACKAGES entry -- so this is the case that says the class did its # half and that the dependency resolved against a package this image already # carried (fontconfig-utils has been here since BRINTOS-1032). if [ "$_dep" -eq 1 ]; then bst_ok $S/pkg-depends-fontconfig else bst_notok $S/pkg-depends-fontconfig "source-code-pro-fonts does not Depend on fontconfig-utils"; fi # ------------------------------------------------- the deferred fontcache hook if [ -f "$PI" ]; then bst_ok $S/postinst-present else bst_notok $S/postinst-present "$PI is absent -- the fontcache postinst did not reach the image"; fi # It calls fc-cache on the branch run-postinsts takes ($D unset at first boot). check_out $S/postinst-runs-fc-cache "fc-cache" cat "$PI" # ...and the tool that branch needs is present, so the deferred run cannot fail # for want of it. This is the ticket's stated risk, and it is a shell builtin. if [ -x /usr/bin/fc-cache ]; then bst_ok $S/fc-cache-present else bst_notok $S/fc-cache-present "fontconfig-utils is a Depends of source-code-pro-fonts but /usr/bin/fc-cache is absent"; fi # ------------------------------------------------------ freetype parses them # The rootfs is read-only at browser runtime and data/ arrives 0644, so the probe # is copied to /tmp (mode=1777 tmpfs, no noexec) and the bit is set there. Never # `test -x` the shipped payload: that passes against a hand-placed copy and fails # against every image that ever built the package. if [ ! -f "$PROBE_SRC" ]; then bst_notok $S/probe-present "$PROBE_SRC did not ship" rm -f "$W.inv" "$W.sums" "$W.scan" "$W.st" "$W.pkgf" 2>/dev/null exit 0 fi bst_ok $S/probe-present probe=$tmp/bst-scp-probe.$$ if cp "$PROBE_SRC" "$probe" 2>/dev/null && chmod +x "$probe" 2>/dev/null; then bst_ok $S/probe-stage else bst_notok $S/probe-stage "cannot stage $PROBE_SRC" rm -f "$probe" "$W.inv" "$W.sums" "$W.scan" "$W.st" "$W.pkgf" 2>/dev/null exit 0 fi # The face list comes from the FACTS file rather than from a glob, so a face the # manifest knows about but the image lost is reported as "the probe was never run # over X" instead of silently dropping out of the loop. # # NO TRAILING == ON THE FENCE. `==FONT SourceCodePro-It.otf==` puts # "SourceCodePro-It.otf==" in awk's $2, which matches no key in the facts table, # and every per-face case then reds with "the probe was never run over ..." while # ft-ran stays green -- the defect BRINTOS-1449's host pre-flight caught, and # which this suite's own pre-flight re-ran as a mutation before shipping. : > "$W.ft" _faces=$(LC_ALL=C gawk '!/^#/ && NF >= 5 { print $1 }' "$FACTS") for _f in $_faces; do printf '==FONT %s\n' "$_f" >> "$W.ft" "$probe" "$TTFDIR/$_f" >> "$W.ft" 2>&1 _rc=$? printf '==RC %s %d\n' "$_f" "$_rc" >> "$W.ft" done rm -f "$probe" 2>/dev/null LC_ALL=C gawk -v FACTS="$FACTS" -v FT="$W.ft" \ -f "$D/source-code-pro-fonts-ftverify.awk" "$FACTS" "$W.ft" # --------------------------------------------------------- the consumer block # # EVERYTHING BELOW THIS LINE CAN COST THE GUEST, AND THAT IS WHY IT IS LAST. # fc-cache mmaps each face it walks, and file-backed mmap on this arm is REFUSED # above a mapping-length threshold (linux-in-the-browser#165) -- and the consumer # does not get a failed mmap and fall back, it PARKS, beyond the reach of both # SIGTERM and SIGKILL, taking the guest and every suite behind it in the same # boot. Ordering this block last is the only thing that actually protects the # evidence: every case above has already been emitted by the time the first # mapping happens. # # THESE FOURTEEN FACES SIT WELL INSIDE THE IMAGE'S EXISTING WORKING SET. #165's # bracket on this image is ~66 kB to 577,708 bytes; the largest face here is # 149,272, the 53 font files already walked by every fc-cache run are 23,895 to # 415,816, and TWENTY-THREE of those 53 are larger than our largest. So this # package cannot introduce a new failure mode or a new maximum. Nothing is held # out and there are no held-out-* cases, which is what distinguishes this suite # from 99-ttf-droid's. # # THE BOUND IS BEST-EFFORT AND IS NOT WHAT MAKES THIS SAFE. #165 measured that a # parked fc-cache survives SIGKILL, so `timeout` cannot reclaim it and will # itself hang when the park is the unkillable kind. It is here for the case where # the call merely runs long, and the ordering above is here for the case where it # does not come back at all. Recorded rather than dressed up, because a bound # that looks protective and is not is worse than none. # # BRINTOS-WORKAROUND: linux-in-the-browser#165 remove -- bound the fc-cache call # and order the consumer block last; both go when the mmap population path # tolerates a parking read. # `fc-cache`, NOT `fc-cache -f`, SINCE BRINTOS-1725. The -f rebuilt every # directory whether or not its cache was valid, which means mapping every face on # the image; a file-backed mapping above roughly 578 kB is REFUSED over the cloud # FUSE bridge and the caller PARKS, beyond SIGKILL (linux-in-the-browser#165, # bracketed by BRINTOS-1450). Before ttf-pt-sans the image's largest face was # Ubuntu-L.ttf at 415,552 bytes, under the bracket, and this call was harmless; # that port adds four faces above it, the largest 584,812, and MEASURED on the # resulting image this suite parked here -- reaching 86 of its 96 cases against # a full run on the same base pin without the port. Without -f, fc-cache rebuilds # only what is stale, and nothing is: /var/cache/fontconfig ships populated, and # `fc-cache` returns 0 in 3 s on that image where `timeout -k 5 150 fc-cache -f` # never returned. The case still asserts what it always did -- fc-cache runs and # returns 0. # # BRINTOS-WORKAROUND: linux-in-the-browser#165 revisit -- drop -f so only a stale # cache is rebuilt; it goes back in when the mmap population path tolerates a # parking read. # BST-TIMEOUT-OK: fc-cache walks the font dirs and exits; -k 5 90 is belt-and-braces. timeout -k 5 90 fc-cache > "$W.cache" 2>&1 _rc=$? if [ "$_rc" -eq 0 ]; then bst_ok $S/fc-cache-rc elif [ "$_rc" -eq 124 ] || [ "$_rc" -eq 137 ]; then bst_notok $S/fc-cache-rc "fc-cache did not return within 90s -- linux-in-the-browser#165 (mmap population parked)" else bst_notok $S/fc-cache-rc "fc-cache exited $_rc: $(_bst_1line "$(cat "$W.cache")")"; fi # THE FRAGMENT IS LOADED, ASKED DIRECTLY RATHER THAN INFERRED FROM THE MATCH # BELOW. fc-match monospace answering Source Code Pro is consistent with the # fragment being loaded AND with fontconfig having decided the same thing some # other way; only fc-conflist distinguishes them, and if this case is the one # that reds then the generic handover below is an accident rather than a # configuration this port controls. # A `+` line is a file fontconfig LOADED; a `-` line is one merely available # under conf.avail. The path is matched inside the line rather than anchored # immediately after the "+ ", because fc-conflist appends a description field and # the exact spacing is its business, not this suite's. fc-conflist > "$W.conf" 2>/dev/null _loaded=0 while IFS= read -r l; do case "$l" in "+ "*"$CONF"*) _loaded=1 ;; esac done < "$W.conf" if [ "$_loaded" -eq 1 ]; then bst_ok $S/fc-conf-loaded else bst_notok $S/fc-conf-loaded "fc-conflist does not list $CONF among the loaded (+) configuration files"; fi # One fc-list for the whole consumer read; the parsing below is shell builtins. # # THE OBJECT SET CARRIES `style` FOR THE REASON 99-cantarell-fonts DOCUMENTS -- # fc-list dedupes on the properties it was ASKED for -- even though it is not # strictly needed here. None of these fourteen is a variable font, so each # contributes ONE pattern and each pattern already differs in `file`; asking for # style costs nothing and keeps the five font suites' queries the same shape. fc-list : file family style > "$W.list" 2>&1 # ALL FOURTEEN ARE DISCOVERABLE, not merely present on disk. A cache that # serialised wrongly, or a FreeType that refused the CFF outlines, shows up here # while every file-* case above stays green -- which is the split that says where # to look. # # THE FAMILY FIELD IS MULTI-VALUED ON TEN OF THE FOURTEEN. The line format is # ": :style=", and fontconfig comma-joins ID16 then ID1 -- # so the assertion is on the FIRST value, which is the typographic family and the # one fc-match answers. Comparing the whole field would red on ten working faces. _seen=0; _badfam="" while IFS= read -r l; do case "$l" in "$TTFDIR"/SourceCodePro-*.otf:*) ;; *) continue ;; esac _seen=$((_seen+1)) _rest=${l#*: }; _fam=${_rest%%:style=*}; _first=${_fam%%,*} [ "$_first" = "Source Code Pro" ] || _badfam="$_badfam '$_first'" done < "$W.list" if [ "$_seen" -eq 14 ] && [ -z "$_badfam" ]; then bst_ok $S/fc-list-faces else bst_notok $S/fc-list-faces "fc-list reports $_seen patterns for $TTFDIR/SourceCodePro-*.otf (want 14), families:$_badfam" fi # ...AND THE FAMILY RESOLVES BACK TO OUR FILE. fc-match never fails -- it always # returns some face -- so this is real only because 53 other font files are # installed alongside: a family name that did not reach the cache falls through # to Liberation, which is exactly what 99-terminus-font's first on-target run # reported for its own family. The Regular is what a bare family with no weight # should select out of seven weights, so this pins the weight sort too. _out=$(fc-match --format '%{file} %{family}\n' 'Source Code Pro' 2>&1) case "$_out" in "$REG Source Code Pro") bst_ok $S/fc-match-family ;; *) bst_notok $S/fc-match-family "fc-match 'Source Code Pro' => '$(_bst_1line "$_out")', want '$REG Source Code Pro'" ;; esac # THE ONE GENERIC THIS PORT **DOES** TAKE. This is the only positive # generic-handover case on this image: every other font suite asserts that its # own port left the generics alone, and ttf-inconsolata's fc-match-monospace -- # which asserted Inconsolata until this ticket -- is the one this replaces. # # IT IS NOT A RESTATEMENT OF fc-match-family ABOVE. That case would stay green if # the family had reached the cache and the fragment had NOT been applied; this # one would then be the only red, and fc-conf-loaded above says which of the two # went wrong. The file is asserted as well as the family because `monospace` # resolving to some OTHER Source Code Pro weight would be a different bug from it # resolving to Inconsolata, and only the file distinguishes them. _out=$(fc-match --format '%{file} %{family}\n' monospace 2>&1) case "$_out" in "$REG Source Code Pro") bst_ok $S/fc-match-monospace ;; *) bst_notok $S/fc-match-monospace "fc-match monospace => '$(_bst_1line "$_out")', want '$REG Source Code Pro' -- this port's 44-*.conf prefers Source Code Pro for monospace" ;; esac # THE FIVE GENERICS THIS PORT DOES **NOT** TAKE. These are NOT restatements of # the two cases above: both would stay green if installing this family had ALSO # displaced a generic it has no business touching. The fragment names `monospace` # and nothing else, and Source Code Pro appears nowhere in fontconfig 2.15.0's # own conf.avail -- checked exhaustively, not sampled -- so the only route to any # other generic is through 49-sansserif.conf's seeding or a sort accident, and # these five cases are what would see either. # # MEASURED WITH A NULL CONTROL BEFORE THEY WERE WRITTEN: the same native # fontconfig rig that predicted the monospace handover answers all five # identically with and without this package installed. 99-liberation-fonts, # 99-ttf-droid, 99-ttf-gentium and 99-cantarell-fonts assert the first four from # their side, so a disagreement between the suites stays visible. # # system-ui, fantasy AND cursive READ `Roboto` FROM BRINTOS-1723 AND ARE # RE-MEASURED HERE ON THE MERGED FONT SET. All three are generics no shipped # fragment seeds, so each falls to the highest-ranked family actually installed; # that is precisely why they move again whenever a port adds faces, and # BRINTOS-1729 adds 58. The values below are measured on the MERGED image rather # than carried from either side of the merge. # # sans-serif AND serif MOVED FOR BRINTOS-1729, BY CONFIGURATION AND NOT BY RANK. # ttf-tlwg ships ten fragments at 64; PREPENDS ahead of # the generic while 30-liberation-aliases.conf's only APPENDS behind it, # so Kinnari takes `serif` and Waree takes `sans-serif` regardless of font-set # size. monospace is untouched -- source-code-pro-fonts' own loads at # 44, ahead of these. # # THESE CASES KEEP THEIR -unchanged NAMES, because what they assert is that # SOURCE CODE PRO did not move the generic, which is still true; only the values # they are compared against moved. for _pair in "sans-serif:Waree" "serif:Kinnari" \ "system-ui:Waree" "fantasy:Waree" "cursive:Waree"; do _gen=${_pair%%:*}; _want=${_pair#*:} _out=$(fc-match --format '%{family}\n' "$_gen" 2>&1) case "$_out" in "$_want") bst_ok "$S/fc-match-$_gen-unchanged" ;; *) bst_notok "$S/fc-match-$_gen-unchanged" "fc-match $_gen => '$(_bst_1line "$_out")', want '$_want' -- this port must not take this generic" ;; esac done rm -f "$W.inv" "$W.sums" "$W.scan" "$W.st" "$W.pkgf" "$W.ft" "$W.cache" "$W.list" "$W.conf" 2>/dev/null