# BST-TIMEOUT: 300 # 45 cases, no compiled probe: this suite drives fc-cache # # once and then fc-list/fc-query/fc-match over FOUR faces # # totalling 486,852 bytes. 99-liberation-fonts declares the # # same 300 for a comparable fontconfig-only workload over # # fourteen larger files. # # # # MEASURED, 2026-08-29, first on-target run after # # BRINTOS-1762 cleared: ==BST-SUITE elapsed=39s bound=300s # # cases=45==, on hz1 under brintos_local_verify. The bound # # is kept at 300 rather than tightened to the measurement: # # 39s is one run on an idle host, fc-cache -f is the whole # # of it, and that call scales with every font package the # # image gains, not with this one. # # # # 45 = 26 emitted here + 19 emitted by the verify awk. The # # three `require' calls are NOT among them: require emits a # # case only when the tool is ABSENT, in which case it skips # # and ends the suite. Counting them would put the test-plan # # floor three above what a clean run can produce. # # ttf-liberation-sans-narrow 1.07.4 -- the four Liberation Sans Narrow faces, # packaged apart from the rest of the family because they come from a different # upstream release. meta-openembedded # meta-oe/recipes-graphics/ttf-fonts/ttf-liberation-sans-narrow_1.07.4.bb. # # ============================================================================ # THE PAYLOAD IS UNDER /usr/share/fonts/TTF, NOT truetype/. THAT IS MEASURED, # AND IT IS NOT WHAT THE TICKET PREDICTED. # ============================================================================ # # BRINTOS-1722 describes the files as landing under ${datadir}/fonts/truetype/ # and the recipe as "pruning everything but the narrow faces out of the tarball". # Both halves are wrong about the mechanism, and the first is wrong about the # result. What the recipe actually does, read off ttf.inc plus the .bb: # # ttf.inc do_install install every *.tt[cf] -> ${datadir}/fonts/truetype/ # (all SIXTEEN faces: Mono, Sans, SansNarrow, Serif) # do_install:append install LiberationSansNarrow*.ttf -> ${datadir}/fonts/TTF/ # install the fontconfig fragment, install License.txt # rm -rf ${D}${datadir}/fonts/truetype # # So the last line removes the truetype directory WHOLESALE. There is no # face-by-face prune, and nothing this package installs ends up under truetype/. # Every case below is scoped to TTF/; a suite written to the ticket's wording # would have asserted an empty set and passed. # # The ticket's underlying worry is still the right one and is asserted here in # the form the code actually takes: prune-nonnarrow-absent checks the twelve # non-narrow basenames are not under TTF/, and prune-truetype-unowned checks -- # from the dpkg database, not the filesystem, because truetype/ has four other # tenants -- that this package claims no path there at all. Those two are what # stand between this port and a third Liberation release colliding with # ttf-liberation 0.2 and poky's liberation-fonts 2.1.5, which share all twelve # basenames with this tarball at three different sizes. # # ============================================================================ # THIS PORT IS THE SOLE TENANT OF /usr/share/fonts/TTF AND OF /etc/conf.avail, # SO NO NEIGHBOURING SUITE IS AMENDED. THAT WAS SWEPT, NOT ASSUMED. # ============================================================================ # # Read off the last COMPLETE image (BRINTOS-1714, 2026-08-27), /usr/share/fonts # carried exactly four subdirectories -- cantarell(2), terminus(19), # truetype(27), ttf(23) -- and no TTF. /etc/conf.avail did not exist. So unlike # the sibling ttf-liberation port, which landed twelve files into the shared # truetype/ and had to amend three cases in two suites, this one adds a # directory nothing else reads. # # The neighbours were swept anyway, by what they COUNT rather than by name: no # suite counts /usr/share/fonts whole-tree and none pipes a bare fc-list into # wc. The one whole-directory enumeration in the font suites -- # 99-liberation-fonts:99 -- names /usr/share/fonts/truetype explicitly, which # this port does not write to. 57-fontconfig's conf-avail cases count # /usr/share/fontconfig/conf.avail, fontconfig's own bundled set, and are # bounded from below; /etc/conf.avail is a different directory and does not # reach them. 57-fontconfig's etc-confd is an existence check on # /etc/fonts/conf.d, which this package creates empty and does not populate. # # ============================================================================ # THE RECIPE'S OWN FONTCONFIG FRAGMENT IS NEVER READ -- AND IT WOULD CHANGE # NOTHING IF IT WERE. BOTH HALVES MEASURED. # ============================================================================ # # The recipe creates ${sysconfdir}/fonts/conf.d/ and then installs its fragment # to ${sysconfdir}/conf.avail/30-${PN}-sans.conf -- /etc/conf.avail, with no # fonts/ component. The image's /etc/fonts/fonts.conf carries exactly one # include, `conf.d`, resolved relative # to /etc/fonts. There is no conf.avail include anywhere. So the shipped # fragment is inert: conf-not-in-confd pins that, and it is stated as a fact # about this recipe rather than as a defect this port introduced. # # It costs nothing, and that is the second measurement rather than an inference. # The fragment aliases Arial Narrow <-> Liberation Sans Narrow in both # directions. fontconfig 2.15.0's own 30-metric-aliases.conf -- which IS active, # symlinked into /etc/fonts/conf.d from /usr/share/fontconfig/conf.avail -- # already carries both: # # line 603 Arial Narrow # Liberation Sans Narrow # line 344 Liberation Sans Narrow # Arial Narrow # # The recipe's fragment is a verbatim duplicate of stock fontconfig. Installing # it at the correct path would add nothing; leaving it at the wrong one removes # nothing. NO BBAPPEND, therefore, and no workaround marker is owed: nothing was # worked around. conf-aliases-are-stock asserts the stock file still carries the # alias, so the day fontconfig drops it this suite says so rather than silently # depending on a fragment that is not being read. # # This is also why fc-match-arial-narrow is a POSITIVE case here. "Arial Narrow" # is a family this package does not provide, and it nevertheless resolves into # this package -- correctly, through stock metric aliasing. The ticket asks for # an unprovided family that must NOT resolve here; Arial Narrow is not it, and # neither is Helvetica Narrow, which stock fontconfig aliases to Arial Narrow. # fc-match-liberation-sans-elsewhere is the real negative: "Liberation Sans" is # one word from ours, is provided by poky's liberation-fonts on this image, and # must resolve to ITS file. That is the mis-scoping guard, and it is the same # guard as prune-truetype-unowned seen from the consumer side. # # ============================================================================ # NO NEW MAXIMUM FOR THE mmap REFUSAL BAND. # ============================================================================ # # File-backed mmap is refused on this arm above a mapping-length threshold and # the consumer parks rather than falling back (linux-in-the-browser#165, # bracketed by BRINTOS-1450 between ~66 kB and 577,708 bytes). The four faces # here are 110,560 / 113,304 / 129,448 / 133,540 bytes. The largest is smaller # than the SMALLEST of the twelve poky Liberation faces this image already scans # on every fc-cache (281,536, range to 415,816), so this port adds no new # maximum and nothing to the band #165 is about. No hold-out, no marker. # # ============================================================================ . "$BST_LIB" S=ttf-liberation-sans-narrow bst_ok $S/suite-canary D=$BST_DATA REF=$D/ttf-liberation-sans-narrow-manifest.txt FACES=$D/ttf-liberation-sans-narrow-fcfaces.txt NONNARROW=$D/ttf-liberation-sans-narrow-nonnarrow.txt VERIFY=$D/ttf-liberation-sans-narrow-verify.awk TTFDIR=/usr/share/fonts/TTF TRUETYPE=/usr/share/fonts/truetype CONFAVAIL=/etc/conf.avail CONF=$CONFAVAIL/30-ttf-liberation-sans-narrow-sans.conf CONFD=/etc/fonts/conf.d METRIC=/usr/share/fontconfig/conf.avail/30-metric-aliases.conf LICDIR=/usr/share/licenses/ttf-liberation-sans-narrow PKGLIST=/var/lib/dpkg/info/ttf-liberation-sans-narrow.list PI=/var/lib/dpkg/info/ttf-liberation-sans-narrow.postinst FCCACHE=/var/cache/fontconfig tmp=${TMPDIR:-/tmp} W=$tmp/bst-ttflsn.$$ require gawk $S/gawk-present require sha256sum $S/sha256sum-present require find $S/find-present for t in fc-cache fc-list fc-match fc-query; do if [ -x "/usr/bin/$t" ]; then bst_ok $S/$t-present else bst_notok $S/$t-present "fontconfig-utils is a Depends of ttf-liberation-sans-narrow but /usr/bin/$t is absent"; fi done if [ ! -f "$REF" ] || [ ! -f "$FACES" ] || [ ! -f "$NONNARROW" ] || [ ! -f "$VERIFY" ]; then bst_notok $S/ref-present "the reference data did not ship: $REF / $FACES / $NONNARROW / $VERIFY" exit 0 fi bst_ok $S/ref-present if [ -d "$TTFDIR" ]; then bst_ok $S/ttfdir-is-dir else bst_notok $S/ttfdir-is-dir "$TTFDIR is not a directory -- the payload did not reach the image"; fi # ---- collect the file layer ------------------------------------------------- find "$TTFDIR" "$TRUETYPE" "$CONFAVAIL" "$LICDIR" \ -maxdepth 1 -printf '%p %y %s %m\n' 2>/dev/null | LC_ALL=C sort > "$W.inv" : > "$W.sums" for p in "$TTFDIR"/LiberationSansNarrow-Bold.ttf \ "$TTFDIR"/LiberationSansNarrow-BoldItalic.ttf \ "$TTFDIR"/LiberationSansNarrow-Italic.ttf \ "$TTFDIR"/LiberationSansNarrow-Regular.ttf \ "$CONF" \ "$LICDIR"/LICENSE ; do sha256sum "$p" >> "$W.sums" 2>/dev/null done cat "$PKGLIST" > "$W.pkgf" 2>/dev/null || : > "$W.pkgf" # The dpkg list names every parent directory the package owns, not just its # payload, so only its file rows can be compared against the manifest. Record # which rows are directories rather than naming them one at a time: the package # co-owns the standard parents (/., /etc, /etc/fonts/conf.d, /usr/share/...) # with fontconfig and the other font packages, and that set is not this port's # to pin. PKGPATH itself stays whole -- prune-truetype-unowned has to be able to # see an owned DIRECTORY under truetype/, which is one shape the collision this # port guards against would take. : > "$W.pkgd" while IFS= read -r _p; do [ -d "$_p" ] && printf '%s\n' "$_p" done < "$W.pkgf" >> "$W.pkgd" 2>/dev/null # ---- the fontcache postinst ran, and left a cache --------------------------- 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 check_out $S/postinst-runs-fc-cache "fc-cache" cat "$PI" fc-cache -f >/dev/null 2>&1 _ncache=$(find "$FCCACHE" -type f 2>/dev/null | wc -l) if [ "${_ncache:-0}" -gt 0 ]; then bst_ok $S/fc-cache-usable else bst_notok $S/fc-cache-usable "$FCCACHE holds no cache files after fc-cache -f"; fi # ---- fc-query the four faces, in the committed field order ------------------ : > "$W.qry" for f in "$TTFDIR"/LiberationSansNarrow-*.ttf; do [ -f "$f" ] || continue LC_ALL=C fc-query --format '%{file|basename}|%{family}|%{style}|%{slant}|%{weight}|%{width}\n' \ "$f" >> "$W.qry" 2>/dev/null done LC_ALL=C sort -o "$W.qry" "$W.qry" LC_ALL=C gawk -v REF="$REF" -v SUMS="$W.sums" -v INV="$W.inv" -v PKGF="$W.pkgf" \ -v PKGD="$W.pkgd" \ -v FACES="$FACES" -v QRY="$W.qry" -v NONNARROW="$NONNARROW" \ -f "$VERIFY" "$REF" "$W.sums" "$W.inv" "$W.pkgf" "$W.pkgd" "$FACES" "$W.qry" "$NONNARROW" # ---- the package database --------------------------------------------------- sed -n '/^Package: ttf-liberation-sans-narrow$/,/^$/p' /var/lib/dpkg/status > "$W.st" 2>/dev/null _known=0; _arch=0; _dep=0 while IFS= read -r l; do case "$l" in "Package: ttf-liberation-sans-narrow") _known=1 ;; "Architecture: all") _arch=1 ;; "Depends: "*) case "$l" in *fontconfig-utils*) _dep=1 ;; esac ;; esac done < "$W.st" if [ "$_known" -eq 1 ]; then bst_ok $S/pkg-known else bst_notok $S/pkg-known "dpkg does not know the package ttf-liberation-sans-narrow"; fi if [ "$_arch" -eq 1 ]; then bst_ok $S/pkg-arch-all else bst_notok $S/pkg-arch-all "ttf-liberation-sans-narrow is not Architecture: all -- inherit allarch did not take"; fi if [ "$_dep" -eq 1 ]; then bst_ok $S/pkg-depends-fontconfig else bst_notok $S/pkg-depends-fontconfig "ttf-liberation-sans-narrow does not Depend on fontconfig-utils -- the fontcache class did not wire it"; fi # PACKAGES is an assignment naming only ${PN}, so there is no -doc, -dev or -dbg. for sfx in doc dev dbg staticdev; do if grep -q "^Package: ttf-liberation-sans-narrow-$sfx\$" /var/lib/dpkg/status 2>/dev/null; then bst_notok $S/pkg-no-$sfx "ttf-liberation-sans-narrow-$sfx is installed -- PACKAGES no longer names only \${PN}" else bst_ok $S/pkg-no-$sfx fi done # ---- the fragment, and why it does not matter ------------------------------- if [ -f "$CONF" ]; then bst_ok $S/conf-avail-shipped else bst_notok $S/conf-avail-shipped "$CONF is absent -- the recipe's fragment did not reach the image"; fi if [ -e "$CONFD/30-ttf-liberation-sans-narrow-sans.conf" ]; then bst_notok $S/conf-not-in-confd "the fragment is now under $CONFD -- it is being READ, which this suite's header says it is not; re-measure the aliases before trusting any fc-match case here" else bst_ok $S/conf-not-in-confd fi if grep -q 'Liberation Sans Narrow' "$METRIC" 2>/dev/null; then bst_ok $S/conf-aliases-are-stock else bst_notok $S/conf-aliases-are-stock "$METRIC no longer names Liberation Sans Narrow -- the alias this port relies on came from stock fontconfig, and it is gone"; fi # ---- the consumer reads ----------------------------------------------------- # fc-list enumerates the family, and every file it returns is ours. LC_ALL=C fc-list "Liberation Sans Narrow" file 2>/dev/null | sed 's/: *$//' | LC_ALL=C sort > "$W.list" _nlist=$(wc -l < "$W.list") _foreign=$(grep -cv "^$TTFDIR/" "$W.list" 2>/dev/null) if [ "${_nlist:-0}" -eq 4 ] && [ "${_foreign:-1}" -eq 0 ]; then bst_ok $S/fc-list-family else bst_notok $S/fc-list-family "fc-list 'Liberation Sans Narrow' returned ${_nlist:-0} files (want 4), ${_foreign:-?} of them outside $TTFDIR" fi # fc-match for the family resolves to a file from THIS package. This is the case # that proves the font is usable rather than merely present on disk. _m=$(LC_ALL=C fc-match --format '%{file}\n' "Liberation Sans Narrow" 2>/dev/null) case "$_m" in "$TTFDIR"/LiberationSansNarrow-*.ttf) bst_ok $S/fc-match-family ;; *) bst_notok $S/fc-match-family "fc-match 'Liberation Sans Narrow' => '${_m:-}', want a face under $TTFDIR" ;; esac # Arial Narrow lands here too -- through stock 30-metric-aliases, not through the # recipe's inert fragment. Positive on purpose; see the header. _a=$(LC_ALL=C fc-match --format '%{file}\n' "Arial Narrow" 2>/dev/null) case "$_a" in "$TTFDIR"/LiberationSansNarrow-*.ttf) bst_ok $S/fc-match-arial-narrow ;; *) bst_notok $S/fc-match-arial-narrow "fc-match 'Arial Narrow' => '${_a:-}', want a face under $TTFDIR -- stock 30-metric-aliases accepts Liberation Sans Narrow for it" ;; esac # THE MIS-SCOPING GUARD. Liberation Sans is one word from this package's family, # is provided by poky's liberation-fonts on this image, and must resolve THERE. for fam in "Liberation Sans" "Liberation Serif" "Liberation Mono"; do _id=$(echo "$fam" | tr 'A-Z ' 'a-z-') _o=$(LC_ALL=C fc-match --format '%{file}\n' "$fam" 2>/dev/null) case "$_o" in "$TTFDIR"/*) bst_notok $S/fc-match-$_id-elsewhere "fc-match '$fam' => '$_o' -- a family this package does not provide resolved INTO it; the port is mis-scoped" ;; "") bst_notok $S/fc-match-$_id-elsewhere "fc-match '$fam' returned nothing" ;; *) bst_ok $S/fc-match-$_id-elsewhere ;; esac done rm -f "$W.inv" "$W.sums" "$W.pkgf" "$W.pkgd" "$W.qry" "$W.st" "$W.list" 2>/dev/null