# BST-TIMEOUT: 300 # MEASURED, not guessed: `==BST-SUITE ttf-ubuntu-font-family # # elapsed=44s bound=300s cases=88==` on the first on-target # # run (hz1, 2026-08-29, brintos_local_verify, idle host). # # 300 is ~6.8x that and matches the four sibling font # # suites. It is deliberately NOT tightened to the ~3x the # # packager guide suggests: a marker OVERRIDES the 300 the # # ticket gate and the nightly already pass in the # # environment, so a smaller number here would REDUCE this # # suite's headroom on a loaded host rather than protect it. # # Re-measure from the elapsed line if the case count moves. # # ttf-ubuntu-font-family 0.83 -- the Ubuntu Font Family under the UFL, taken # from the upstream 0cef8205-ubuntu-font-family-0.83.zip. meta-openembedded # meta-oe/recipes-graphics/ttf-fonts/ttf-ubuntu-font-family_0.83.bb. # # WHAT THIS IMAGE ACTUALLY INSTALLS, MEASURED, NOT ASSUMED: FOURTEEN files in # TWO packages, 4,378,368 bytes, all at /usr/share/fonts/truetype/. Four # UbuntuMono-* faces in ttf-ubuntu-mono (823,572 bytes) and ten Ubuntu-* ones in # ttf-ubuntu-sans (3,554,796). There is no ttf-ubuntu-font-family package, no # -dbg, no -dev and no -doc: `PACKAGES` is an ASSIGNMENT naming exactly the two, # which is why the image asks for the two by name and why pkg-no-bare-package # below is a real case rather than a formality. # # THE TWO-WAY SPLIT IS THE POINT OF THIS SUITE, AND dpkg IS THE ONLY PLACE ON # TARGET IT IS VISIBLE. All fourteen files are byte-correct whichever package # holds them, so every file-* case would stay green if the split had collapsed # into one package -- which is precisely the failure the ticket asks about. The # suite therefore joins the manifest's fourth column to # /var/lib/dpkg/info/ttf-ubuntu-{mono,sans}.list and asserts ownership PER FILE # (split-owner), then asserts the same split a second time from the outlines # rather than the database (fcq-spacing-split), so a red in one and not the # other says which layer moved. # # FIVE FAMILIES RIDE ON FOURTEEN FILES, AND THE PACKAGE NAMES ARE WRONG ABOUT # THIS. The ticket says "fc-list enumerates the family by name", singular per # package. It is five: Ubuntu, Ubuntu Light, Ubuntu Thin, Ubuntu Condensed and # Ubuntu Mono. The ten Ubuntu-* faces alone declare four of them, because the # non-RIBBI styles (Light, Medium, Thin) carry the name ID 16/17 typographic # split and fontconfig reads both the typographic pair and the legacy one: # # Ubuntu-R.ttf family "Ubuntu" style "Regular" # Ubuntu-L.ttf family "Ubuntu,Ubuntu Light" style "Light,Regular" # Ubuntu-C.ttf family "Ubuntu Condensed" style "Regular" # # fcq-family-* asserts each family's membership from the CONTROL's own family # column rather than from a package name. # # AND ONE OF THOSE FAMILY NAMES IS AN UPSTREAM METADATA DEFECT WE SHIP # VERBATIM. Ubuntu-M.ttf and Ubuntu-MI.ttf -- the MEDIUM faces -- carry, on the # Windows platform name records fontconfig reads (pid=3 eid=1 lid=0x0409), # name ID 1 = "Ubuntu Light" and name ID 2 = "Bold" / "Bold Italic". The # Macintosh records (pid=1) say "Ubuntu"/"Medium" and are right; ID 16/17 say # "Ubuntu"/"Medium" on both platforms and are right. So each Medium face # declares the LIGHT family's name as its second family, and the consequence is # observable rather than cosmetic: with the four candidates for "Ubuntu Light" # being Ubuntu-L (weight 50), Ubuntu-LI (50), Ubuntu-M (100) and Ubuntu-MI # (100), a default request at weight 80 lands on the MEDIUM face. # fc-match-family-Ubuntu-Light pins that, because it is what this image does and # a silent change to it would mean the metadata or the ranking moved. # # The recipe is `allarch` with no do_configure and no do_compile, pinned to # SRC_URI[sha256sum] 61a2b342...ecf, so the defect is upstream's bytes and not # something the port introduced or could remove without diverging from the # release. Not reported upstream: we file nothing against third-party public # repositories (docs/conventions/no-public-upstream-reports.md). # # THE ZIP SHIPS FOURTEEN APPLEDOUBLE FILES NAMED *.ttf, AND ONE LINE OF THE # RECIPE IS WHY NONE OF THEM IS INSTALLED. __MACOSX/ubuntu-font-family-0.83/ # holds a 212-byte ._.ttf beside every real face, and ttf.inc's do_install # is `find ./ -name '*.tt[cf]' -exec install ...`, which matches them. They stay # out only because this recipe sets S = "${WORKDIR}/ubuntu-font-family-${PV}" -- # the scan root is the font directory and __MACOSX/ is its sibling. Had S been # "${WORKDIR}" (which is what ttf-roboto's recipe does, and what BRINTOS-1723 # had to work around for a different reason), four of the fourteen would have # been packaged into ttf-ubuntu-mono by the *Mono* glob and the other ten would # have failed do_package_qa as installed-but-not-shipped. no-appledouble is the # case that would go red. # # FOUR LAYERS, AND A RED IN AN EARLIER ONE LOCALISES A RED IN A LATER ONE: # # file-*, ttf-* the payload arrived intact -- size, mode, type, digest, # cotenant-* count, total bytes -- and the other font directory is # no-appledouble untouched. No font machinery involved at all. # pkg-*, split-* the two packages the image really installs, dpkg's record # postinst-* of which owns which file, the fontcache class's RDEPENDS, # and the deferred first-boot scriptlet. # fcq-* fontconfig's own parse of each FILE, against a native # x86-64 fontconfig 2.15.0 control -- the same release this # image ships, built by the same bitbake tree. # fc-list-*, discovery THROUGH THE CACHE, which is a different path # fc-match-* again: a face on disk and absent from the cache is green # no-false-family everywhere above and red here. # # THERE IS NO freetype-probe LAYER HERE, DELIBERATELY -- the same reasoning # 99-ttf-roboto records. file-* pins every face by sha256, so a probe cannot # disagree about the FILE, and the driver it would exercise (freetype's TrueType # path) is already covered by 57-freetype and by three sibling font suites. # Fourteen invocations would roughly double this suite's elapsed to re-answer a # settled question. # # WHAT THIS SUITE DELIBERATELY DOES NOT ASSERT, AND WHY. # # THE GENERIC ALIASES. sans-serif, serif, monospace, system-ui, fantasy and # cursive are decided by the whole image's font set and its conf.d, not by # this package, and this port ships no fontconfig fragment. An isolated # x86-64 control carrying only these fourteen answers `Ubuntu Condensed` to # all six, which is what an unseeded generic does when it has nothing else to # fall to -- it is not evidence about this image and no case here rests on it. # The sibling suites already own the generics from the taking side # (99-source-code-pro-fonts holds monospace by explicit ; # 99-cantarell-fonts and 99-ttf-roboto carry -unchanged / -taken cases), so a # generic this port moved is a red THERE, which is where it belongs. # # `fc-match` FOR A FAMILY WE DO NOT SHIP. The ticket asks that fc-match for # such a family "not resolve here". fc-match cannot express that -- it ALWAYS # returns a best match, so asking it for "Ubuntu Sans" on any image answers # something, and a case built on it would assert nothing while looking strict. # The property the requirement is reaching for is about what the installed # faces DECLARE, and fc-list reports that directly: no-false-family asserts # that NOTHING on this image is listed under "Ubuntu Sans" or "Ubuntu Medium". # Both are sharp probes rather than invented names -- "Ubuntu Sans" is what # upstream renamed this family to in the 2023 1.0 release, and is the name # this package's own ttf-ubuntu-sans invites a reader to expect; "Ubuntu # Medium" is the fullname of Ubuntu-M.ttf and the family of nothing at all. # # THE LICENCE IS NOT ON THE TARGET, and that is upstream's shape plus this # recipe's PACKAGES line, not a defect introduced here. ttf.inc's do_install # copies only *.tt[cf], so LICENCE.txt (UFL 1.0), LICENCE-FAQ.txt, FONTLOG.txt, # copyright.txt, CONTRIBUTING.txt, TRADEMARKS.txt and README.txt are never # installed, and PACKAGES names no -doc package that could hold them. This image # sets neither COPY_LIC_MANIFEST nor COPY_LIC_DIRS, so licence text ships in the # build's licence manifest rather than in the rootfs -- the same treatment every # other package on this image gets. Asserted nowhere here because there is # nothing on target to assert; recorded so the next reader does not go looking # for a doc-* case. Note also that poky carries no common-licenses file named # UFL, so the build emits one `No generic license file exists for: UFL` warning; # it is a warning, not an error, and nothing downstream of it changes. # # WRITTEN TO EXEC AS LITTLE AS POSSIBLE. One find, one sha256sum, two seds, one # fc-cache, one fc-list and one gawk, plus the per-face fc-query loop which IS # the measurement. . "$BST_LIB" S=ttf-ubuntu-font-family # THE CANARY, which asserts nothing about ttf-ubuntu-font-family. # # 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/ttf-ubuntu-font-family-manifest.txt FACES=$D/ttf-ubuntu-font-family-fcfaces.txt TTFDIR=/usr/share/fonts/truetype COTDIR=/usr/share/fonts/ttf PI_MONO=/var/lib/dpkg/info/ttf-ubuntu-mono.postinst PI_SANS=/var/lib/dpkg/info/ttf-ubuntu-sans.postinst LI_MONO=/var/lib/dpkg/info/ttf-ubuntu-mono.list LI_SANS=/var/lib/dpkg/info/ttf-ubuntu-sans.list tmp=${TMPDIR:-/tmp} W=$tmp/bst-ttf-ubuntu.$$ require gawk $S/gawk-present require sha256sum $S/sha256sum-present require find $S/find-present # fc-query 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 both packages, so an absent fc-query is a defect in the port rather # than a legitimately absent tool, and a skip would report it green. if [ -x /usr/bin/fc-query ]; then bst_ok $S/fc-query-present else bst_notok $S/fc-query-present "fontconfig-utils is a Depends of ttf-ubuntu-sans but /usr/bin/fc-query is absent"; fi if [ ! -f "$REF" ] || [ ! -f "$FACES" ]; then bst_notok $S/ref-present "the reference data did not ship: $REF / $FACES" exit 0 fi bst_ok $S/ref-present # The fourteen basenames, named once and reused. Ordered as the manifest is. FACELIST="UbuntuMono-B.ttf UbuntuMono-BI.ttf UbuntuMono-R.ttf UbuntuMono-RI.ttf Ubuntu-B.ttf Ubuntu-BI.ttf Ubuntu-C.ttf Ubuntu-L.ttf Ubuntu-LI.ttf Ubuntu-M.ttf Ubuntu-MI.ttf Ubuntu-R.ttf Ubuntu-RI.ttf Ubuntu-Th.ttf" # ------------------------------------------------------------- payload shape # One find over THIS package's directory and over the other font directory, so # every count below 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. Unfiltered by name, because no-appledouble has to be able to SEE a # ._.ttf in order to red on it. find "$TTFDIR" "$COTDIR" \ -maxdepth 1 -printf '%p %y %s %m %l\n' 2>/dev/null | LC_ALL=C sort > "$W.inv" # One sha256sum over the fourteen payload files. Named explicitly rather than # globbed: a glob of "$TTFDIR"/Ubuntu* would be right today but would also # silently absorb a fifteenth Ubuntu file, which is precisely what ttf-count # exists to catch. _paths="" for _b in $FACELIST; do _paths="$_paths $TTFDIR/$_b"; done # shellcheck disable=SC2086 sha256sum $_paths > "$W.sums" 2>&1 # One fc-query sweep over the fourteen installed faces -- the ticket's named # check. It reads the FILES, not the cache, so it is independent of the fc-cache # in the consumer block below. Field order matches the committed control. # shellcheck disable=SC2086 LC_ALL=C fc-query --format '%{file|basename}|%{family}|%{style}|%{slant}|%{weight}|%{spacing}|%{fontformat}\n' \ $_paths 2>/dev/null | LC_ALL=C sort > "$W.scan" # dpkg's OWN record of which package owns which path, reduced to the payload # directory. This is the input the split cases join against, and it comes from # the package database rather than from the basenames -- inferring the package # from "does it say Mono" would assert the very thing under test. sed -n "s|^\(${TTFDIR}/.*\)\$|ttf-ubuntu-mono \1|p" "$LI_MONO" > "$W.owned" 2>/dev/null sed -n "s|^\(${TTFDIR}/.*\)\$|ttf-ubuntu-sans \1|p" "$LI_SANS" >> "$W.owned" 2>/dev/null LC_ALL=C gawk -v REF="$REF" -v SUMS="$W.sums" -v INV="$W.inv" \ -v FACES="$FACES" -v SCAN="$W.scan" -v OWNED="$W.owned" \ -f "$D/ttf-ubuntu-font-family-verify.awk" \ "$REF" "$W.sums" "$W.inv" "$FACES" "$W.scan" "$W.owned" # ---------------------------------------------------- the packaging on target # THE PACKAGE DATABASE IS THE ONLY PLACE THE TWO-WAY SPLIT IS VISIBLE ON TARGET. # 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. `ttf-ubuntu` is a PREFIX of both real # package names, so an unanchored match would report a font package's stanza as # the bare package's and make pkg-no-bare-package unfalsifiable. sed -n '/^Package: ttf-ubuntu-font-family$/,/^$/p; /^Package: ttf-ubuntu-font-family-doc$/,/^$/p; /^Package: ttf-ubuntu-mono$/,/^$/p; /^Package: ttf-ubuntu-sans$/,/^$/p' \ /var/lib/dpkg/status > "$W.st" 2>/dev/null _pkg=""; _mono=0; _sans=0; _bare=0; _doc=0 _amono=0; _asans=0; _dmono=0; _dsans=0 while IFS= read -r l; do case "$l" in "Package: ttf-ubuntu-font-family") _pkg=bare; _bare=1 ;; "Package: ttf-ubuntu-font-family-doc") _pkg=doc; _doc=1 ;; "Package: ttf-ubuntu-mono") _pkg=mono; _mono=1 ;; "Package: ttf-ubuntu-sans") _pkg=sans; _sans=1 ;; "Architecture: all") [ "$_pkg" = mono ] && _amono=1 [ "$_pkg" = sans ] && _asans=1 ;; "Depends: "*) case "$l" in *fontconfig-utils*) [ "$_pkg" = mono ] && _dmono=1 [ "$_pkg" = sans ] && _dsans=1 ;; esac ;; esac done < "$W.st" # THE TWO PACKAGES THIS IMAGE INSTALLS. Each is a half of the port: a dropped # IMAGE_INSTALL line would take that half's file-* and fcq-* cases with it, and # these cases say the cause is a missing PACKAGE rather than missing files. if [ "$_mono" -eq 1 ]; then bst_ok $S/pkg-mono-known else bst_notok $S/pkg-mono-known "dpkg does not know the package ttf-ubuntu-mono"; fi if [ "$_sans" -eq 1 ]; then bst_ok $S/pkg-sans-known else bst_notok $S/pkg-sans-known "dpkg does not know the package ttf-ubuntu-sans"; fi # THERE IS NO ttf-ubuntu-font-family PACKAGE, AND ITS ABSENCE IS THE RECIPE. # `PACKAGES` is an assignment that omits ${PN} entirely, so # `IMAGE_INSTALL += "ttf-ubuntu-font-family"` would not resolve -- the image must # ask for the two font packages by name. This case names that, because a future # recipe revision restoring the default PACKAGES would change what the image # must ask for and nothing else would say so. if [ "$_bare" -eq 0 ]; then bst_ok $S/pkg-no-bare-package else bst_notok $S/pkg-no-bare-package "dpkg knows a ttf-ubuntu-font-family package -- PACKAGES no longer omits \${PN}"; fi if [ "$_doc" -eq 0 ]; then bst_ok $S/pkg-no-doc-package else bst_notok $S/pkg-no-doc-package "dpkg knows a ttf-ubuntu-font-family-doc package -- PACKAGES no longer omits \${PN}-doc"; fi # `allarch` reached the package metadata, which is what makes the byte-identity # claim in the manifest a statement about this build rather than a coincidence. # Asserted for both: they are built by one recipe but packaged separately, and a # class that reached one need not have reached the other. if [ "$_amono" -eq 1 ]; then bst_ok $S/pkg-mono-arch-all else bst_notok $S/pkg-mono-arch-all "ttf-ubuntu-mono is not Architecture: all -- allarch did not take"; fi if [ "$_asans" -eq 1 ]; then bst_ok $S/pkg-sans-arch-all else bst_notok $S/pkg-sans-arch-all "ttf-ubuntu-sans is not Architecture: all -- allarch did not take"; fi # THE fontcache CLASS'S RDEPENDS, READ BACK OFF THE TARGET. The recipe declares # no runtime dependency at all and ttf.inc sets INHIBIT_DEFAULT_DEPS -- # fontcache.bbclass appends fontconfig-utils to each FONT_PACKAGES entry -- so # these are the cases that say the class did its half for both packages and that # the dependency resolved against a package this image already carried # (fontconfig-utils has been here since BRINTOS-1032). if [ "$_dmono" -eq 1 ]; then bst_ok $S/pkg-mono-depends-fontconfig else bst_notok $S/pkg-mono-depends-fontconfig "ttf-ubuntu-mono does not Depend on fontconfig-utils"; fi if [ "$_dsans" -eq 1 ]; then bst_ok $S/pkg-sans-depends-fontconfig else bst_notok $S/pkg-sans-depends-fontconfig "ttf-ubuntu-sans does not Depend on fontconfig-utils"; fi # ------------------------------------------------- the deferred fontcache hook # BOTH packages are in FONT_PACKAGES, so both get a scriptlet. There is no # wasm32 qemu-user, so fontcache.bbclass's update_font_cache intercept cannot # run at do_rootfs and 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 -- so # asserting the configured state here would report the runner's choice as a # package red. What is asserted instead is the actual risk: the scriptlets are # on the image, they call fc-cache, and fc-cache is present, so the deferred run # cannot fail for want of the tool. The consumer block below forces `fc-cache # -f` itself, so it is independent of all of this. if [ -f "$PI_MONO" ]; then bst_ok $S/postinst-mono-present else bst_notok $S/postinst-mono-present "$PI_MONO is absent -- the fontcache postinst did not reach the image"; fi if [ -f "$PI_SANS" ]; then bst_ok $S/postinst-sans-present else bst_notok $S/postinst-sans-present "$PI_SANS is absent -- the fontcache postinst did not reach the image"; fi check_out $S/postinst-mono-runs-fc-cache "fc-cache" cat "$PI_MONO" check_out $S/postinst-sans-runs-fc-cache "fc-cache" cat "$PI_SANS" 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 ttf-ubuntu-sans but /usr/bin/fc-cache is absent"; fi # --------------------------------------------------------- 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. # # THIS PORT ADDS VOLUME, NOT A NEW MAXIMUM. #165's bracket on this image is # ~66 kB to 577,708 bytes; the largest face here is Ubuntu-L.ttf at 415,552, and # liberation-fonts 2.1.5 already puts a 415,816-byte face in front of every # fc-cache this image runs. Bounded anyway, matching the sibling font suites, # until #165 is fixed. # # 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. # # THIS SUITE WAS NOT ITSELF MEASURED PARKING, and that is worth stating rather # than implying. It landed on main after the base BRINTOS-1725 was built against, # so it was not on the image its census swept and became visible only at the # merge. Four of its peers WERE measured, on the ported image, each dying at the # 600 s bound in its consumer block -- 99-cantarell-fonts at 43 of 50, # 99-ttf-gentium at 47 of 55, 99-source-code-pro-fonts at 86 of 96 and # 99-liberation-fonts at 24 of 25 -- against 50/50 and 55/55 for the first two on # the same base pin without the port. This suite makes the same call over the # same font set. 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. # # 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. 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 # One fc-list for the whole consumer read; the parsing below is shell builtins. fc-list : file family > "$W.list" 2>&1 # THE FACES ARE DISCOVERABLE THROUGH THE CACHE, not merely present on disk and # parseable by fc-query. A cache that serialised wrongly, or a FreeType that # refused the outlines, shows up here while every file-* and fcq-* case above # stays green -- which is the split that says where to look. Matched on the FULL # PATH; the family compared is the whole comma-joined LIST fc-list prints, which # for the six faces carrying a name ID 16/17 split is two names. for _b in $FACELIST; do case "$_b" in UbuntuMono-*) _wantfam="Ubuntu Mono" ;; Ubuntu-C.ttf) _wantfam="Ubuntu Condensed" ;; Ubuntu-L.ttf|Ubuntu-LI.ttf|Ubuntu-M.ttf|Ubuntu-MI.ttf) _wantfam="Ubuntu,Ubuntu Light" ;; Ubuntu-Th.ttf) _wantfam="Ubuntu,Ubuntu Thin" ;; *) _wantfam="Ubuntu" ;; esac _seen=0; _fam="" while IFS= read -r l; do case "$l" in "$TTFDIR/$_b":*) ;; *) continue ;; esac _seen=$((_seen+1)) _fam=${l#*: } done < "$W.list" if [ "$_seen" -eq 1 ] && [ "$_fam" = "$_wantfam" ]; then bst_ok "$S/fc-list-$_b" else bst_notok "$S/fc-list-$_b" "fc-list reports $_seen entries for $TTFDIR/$_b family '$_fam', want 1 of '$_wantfam'" fi done # EACH FAMILY RESOLVES TO A FACE THIS PACKAGE OWNS. This is the ticket's # "actually usable and not merely present on disk" check. fc-match never fails, # it always returns some face, so this is real only because forty-odd # non-Ubuntu faces are installed alongside: a family that did not reach the # cache falls through to one of them, which is exactly what 99-terminus-font's # first on-target run reported for its own family. # # "Ubuntu Light" RESOLVES TO THE MEDIUM FACE, and that is the upstream metadata # defect in the header made observable rather than an error in this table. It is # pinned so that a change to it -- a corrected upstream release, a fontconfig # that ranks weight differently -- is visible instead of silent. for _pair in "Ubuntu:Ubuntu-R.ttf" "Ubuntu Mono:UbuntuMono-R.ttf" \ "Ubuntu Condensed:Ubuntu-C.ttf" "Ubuntu Thin:Ubuntu-Th.ttf" \ "Ubuntu Light:Ubuntu-M.ttf"; do _fam=${_pair%:*}; _wantf=${_pair##*:} _out=$(fc-match --format '%{file}' "$_fam" 2>&1) _id=$(printf '%s' "$_fam" | tr ' ' '-') if [ "$_out" = "$TTFDIR/$_wantf" ]; then bst_ok "$S/fc-match-family-$_id" else bst_notok "$S/fc-match-family-$_id" "fc-match '$_fam' => '$(_bst_1line "$_out")', want '$TTFDIR/$_wantf'"; fi done # A FAMILY THIS RELEASE DOES NOT PROVIDE IS LISTED UNDER NOTHING. Asserted with # fc-list rather than fc-match, for the reason in the header: fc-match always # answers, so it cannot express "does not resolve", while fc-list can say that # no font on this image declares the name at all. Both probes are real names, # not invented ones -- see the header. for _fam in "Ubuntu Sans" "Ubuntu Medium"; do _out=$(fc-list --format '%{file}\n' ":family=$_fam" 2>&1) _id=$(printf '%s' "$_fam" | tr ' ' '-') if [ -z "$_out" ]; then bst_ok "$S/no-false-family-$_id" else bst_notok "$S/no-false-family-$_id" "a face on this image declares the family '$_fam': $(_bst_1line "$_out")"; fi done # ...AND THE ONE THIS PACKAGE DOES PROVIDE IS LISTED UNDER EXACTLY ITS OWN FOUR # FILES. The counterpart of the two cases above, and the family-level statement # the ticket asks for, made per package: "Ubuntu Mono" is ttf-ubuntu-mono's # whole contribution, so a fifth file answering here means either a face landed # in the wrong package or something else on the image claims the name. _n=0; _bad="" _out=$(fc-list --format '%{file}\n' ':family=Ubuntu Mono' 2>&1) for _f in $_out; do _n=$((_n+1)) case "$_f" in "$TTFDIR"/UbuntuMono-*.ttf) ;; *) _bad="$_bad $_f" ;; esac done if [ "$_n" -eq 4 ] && [ -z "$_bad" ]; then bst_ok $S/fc-list-family-Ubuntu-Mono else bst_notok $S/fc-list-family-Ubuntu-Mono "fc-list :family='Ubuntu Mono' returned $_n files, want 4 from this package;$_bad"; fi rm -f "$W.inv" "$W.sums" "$W.scan" "$W.owned" "$W.st" "$W.cache" "$W.list" 2>/dev/null