# BST-TIMEOUT: 1800 # 17 documents, 915 KB, parsed three ways: sha256 over all # # 24 installed files, one libxml2 well-formedness pass, and # # a count(//*)+count(//@*) XPath pass per document (17 more # # parses, icccm.xml alone 267 KB). At the 46-68x wall-clock # # factor this platform carries (linux-in-the-browser#117) # # that is minutes, not seconds. The bound is deliberately a # # LOAD bound: it must fire when the guest is starved, not # # when the package regressed. . "$BST_LIB" # xorg-docs is documentation and nothing else -- 17 DocBook 4.3 XML documents and # MAINTAINERS under ${docdir}, six section-7 man pages under ${mandir}. There is # no binary to run, so "the port works" is a statement about the INSTALLED SET, # and the ticket says so: the declared documents are present under ${docdir} and # the installed file list matches a native build of the same version. # # Both halves are asserted against evidence the recipe SHIPPED rather than # against constants typed here: # # CENSUS gen-xorg-docs-census.py, at do_install: the expected set DERIVED from # the generated Makefiles (docbook.am gates four groups of generated # formats on what configure found, so the set is not a constant), per # file sha256 and size, and element/attribute counts from EXPAT. # NATIVE xorg-docs-native-oracle.sh, at do_install: the same tarball # configured, built and installed on x86-64, with its file list carried # verbatim so THIS suite can compare the rootfs against it. # # The counts below are re-derived through LIBXML2, which shares no code with # expat, so agreement is a statement about the bytes rather than about either # parser. DOC=/usr/share/doc/xorg-docs MAN=/usr/share/man/man7 V=/usr/share/xorg-docs CENSUS=$V/CENSUS NATIVE=$V/NATIVE # xorg-sgml-doctools' entity file. Every document but two declares it as an # external parameter entity by RELATIVE system id, so whether it is on the image # decides what can be said about validation -- see section 7. DEFS=/usr/share/sgml/X11/defs.ent # The first BST result line of a suite is dropped by the guest console # (brintos/linux#96). This case exists to be the one that is lost. bst_ok xorg-docs/suite-canary if [ ! -d "$DOC" ]; then bst_skip xorg-docs/present "no $DOC on this image" exit 0 fi bst_ok xorg-docs/present t=${TMPDIR:-/tmp}/bst-xorg-docs.$$ if ! mkdir -p "$t" 2>/dev/null; then bst_notok xorg-docs/tmpdir "cannot create $t" exit 0 fi # --- 1. the recipe's own evidence arrived, intact --------------------------- # # Every later section reads one of these two files. A suite that asserted # agreement WITH A MISSING FILE would agree with nothing and say so as a pass, so # the shape of each read below is "derive from the file, then compare", never # "grep the file for the answer". check xorg-docs/census-installed test -s "$CENSUS" check xorg-docs/native-installed test -s "$NATIVE" check xorg-docs/census-green grep -qx "CENSUS-END fails=0" "$CENSUS" check xorg-docs/native-green grep -qx "NATIVE-END fails=0" "$NATIVE" check_out xorg-docs/census-version "CENSUS-PV 1.7.2" cat "$CENSUS" # --- 2. the declared set, in both directions -------------------------------- # # ${docdir} belongs to this package alone, so the count is an EXACT assertion # rather than a floor: a partially unpacked payload fails here and in # declared-set, and nowhere else. DECL=$t/declared.list sed -n 's/^CENSUS-FILE \([^ ]*\) .*$/\1/p' "$CENSUS" | LC_ALL=C sort > "$DECL" check_eq xorg-docs/declared-count 24 "$(wc -l < "$DECL" | tr -d ' ')" missing=0 while IFS= read -r p; do [ -f "$p" ] || { missing=$((missing+1)); miss1=$p; }; done < "$DECL" check_eq xorg-docs/declared-set 0 "$missing" [ "$missing" -eq 0 ] || bst_notok xorg-docs/declared-set-first "$miss1 declared but not installed" check_eq xorg-docs/docdir-count 18 "$(find "$DOC" -type f 2>/dev/null | wc -l | tr -d ' ')" # Both directions: a file that appears under ${docdir} and is NOT declared is as # much a fault as one that is declared and absent -- it is what a generated # format leaking through would look like. extra=0 for p in $(find "$DOC" -type f 2>/dev/null | LC_ALL=C sort); do grep -qxF "$p" "$DECL" || { extra=$((extra+1)); extra1=$p; } done check_eq xorg-docs/no-extra-files 0 "$extra" [ "$extra" -eq 0 ] || bst_notok xorg-docs/no-extra-files-first "$extra1 installed but not declared" # The eight subdirectories are the shape of the install; losing one takes its # documents with it and is the failure a `cp` that lost its recursion makes. sub_missing=0 for d in ctext fonts graphics icccm input platforms xlfd Xserver; do [ -d "$DOC/$d" ] || sub_missing=$((sub_missing+1)) done check_eq xorg-docs/subdirs 0 "$sub_missing" manmiss=0 for m in Consortium Standards X XOrgFoundation XProjectTeam Xsecurity; do [ -f "$MAN/$m.7" ] || manmiss=$((manmiss+1)) done check_eq xorg-docs/man-pages-present 0 "$manmiss" # --- 3. the bytes ----------------------------------------------------------- bad=0 while read -r _ p sz sum; do [ -f "$p" ] || { bad=$((bad+1)); continue; } [ "$(wc -c < "$p" | tr -d ' ')" = "$sz" ] || { bad=$((bad+1)); bad1="$p size"; continue; } [ "$(sha256sum "$p" 2>/dev/null | cut -d' ' -f1)" = "$sum" ] || { bad=$((bad+1)); bad1="$p sha256"; } done </dev/null | wc -c | tr -d ' ')" # The sha256 check above passes on a file whose digest was never computed, so # prove the comparison can go red: the same content plus one byte must not match # the census entry it came from. ref=$DOC/platforms/Darwin.xml cp "$ref" "$t/mutated.xml" && printf 'x' >> "$t/mutated.xml" refsum=$(sed -n "s|^CENSUS-FILE $ref [0-9]* ||p" "$CENSUS") mutsum=$(sha256sum "$t/mutated.xml" 2>/dev/null | cut -d' ' -f1) if [ -n "$refsum" ] && [ -n "$mutsum" ] && [ "$refsum" != "$mutsum" ]; then bst_ok xorg-docs/control-sha256-detects-change else bst_notok xorg-docs/control-sha256-detects-change "census='$refsum' mutated='$mutsum'" fi # --- 4. the native comparison, asserted against THIS rootfs ----------------- # # NATIVE-FILELIST records what do_install produced; this compares what do_rootfs # DELIVERED. They are different claims: a package split, an image-level doc strip # or a lost -doc entry changes the second without touching the first. NAT=$t/native.list sed -n 's/^NATIVE-LIST //p' "$NATIVE" | LC_ALL=C sort > "$NAT" check_eq xorg-docs/native-list-count 24 "$(wc -l < "$NAT" | tr -d ' ')" HAVE=$t/rootfs.list { find "$DOC" -type f 2>/dev/null grep "^$MAN/" "$NAT" | while IFS= read -r p; do [ -f "$p" ] && echo "$p"; done } | LC_ALL=C sort > "$HAVE" if diff "$NAT" "$HAVE" > "$t/list.diff" 2>&1; then bst_ok xorg-docs/rootfs-matches-native else bst_notok xorg-docs/rootfs-matches-native "$(_bst_1line "$(head -6 "$t/list.diff")")" fi check_out xorg-docs/native-configure "NATIVE-CONFIGURE rc=0" cat "$NATIVE" check_out xorg-docs/native-filelist "NATIVE-FILELIST identical=1" cat "$NATIVE" check_out xorg-docs/native-bytes "NATIVE-BYTES same=24 differing=0" cat "$NATIVE" check_out xorg-docs/native-count "NATIVE-COUNT native=24 cross=24" cat "$NATIVE" # Both builds took the same branch of docbook.am, which is what makes the file # lists comparable at all. Asserted rather than assumed: a native host that HAD # xmlto would install up to five more files per document, and the comparison # would then be measuring the two hosts' tooling rather than this arm. gates=0 for g in XMLTO XSLTPROC FOP STYLESHEET_SRCDIR XORG_SGML_PATH; do grep -qx "NATIVE-TOOL $g=empty" "$NATIVE" || gates=$((gates+1)) grep -qx "CENSUS-TOOL $g=empty" "$CENSUS" || gates=$((gates+1)) done check_eq xorg-docs/doc-toolchain-gates-off 0 "$gates" check_out xorg-docs/native-generated-none "NATIVE-GENERATED declared=0" cat "$NATIVE" check_out xorg-docs/census-generated-none "CENSUS-GENERATED declared=0" cat "$CENSUS" # --- 5. no generated format reached the rootfs ------------------------------ # # The direct statement of the same thing, made against the tree rather than # against a report: with xmlto, xsltproc and fop all absent at configure time # there is no .html, .txt, .pdf, .ps or .db anywhere under ${docdir}. check_eq xorg-docs/no-generated-formats 0 \ "$(find "$DOC" -type f \( -name '*.html' -o -name '*.txt' -o -name '*.pdf' \ -o -name '*.ps' -o -name '*.db' \) 2>/dev/null | wc -l | tr -d ' ')" # --- 6. the documents, through libxml2 -------------------------------------- require xmllint xorg-docs/xmllint-present XMLS=$t/xml.list find "$DOC" -type f -name '*.xml' 2>/dev/null | LC_ALL=C sort > "$XMLS" check_eq xorg-docs/xml-count 17 "$(wc -l < "$XMLS" | tr -d ' ')" # Non-validating: the external DTD and defs.ent are declared but not loaded, so # this is a well-formedness statement about the shipped bytes and nothing else. # libxml2 reports the unresolved entities on stderr and still exits 0, which is # why every case here is written on an exit status or an extracted number rather # than on "no output". nwf=0 while IFS= read -r f; do xmllint --nonet --noout "$f" >/dev/null 2>&1 || { nwf=$((nwf+1)); wf1=$f; } done < "$XMLS" check_eq xorg-docs/xml-wellformed 0 "$nwf" [ "$nwf" -eq 0 ] || bst_notok xorg-docs/xml-wellformed-first "$wf1 is not well-formed" # Element and attribute totals, re-derived here through libxml2's XPath and # compared against the census's expat numbers. Agreement across two # implementations is what makes these a measurement of the documents. # _num defaults a non-number to 0. It is load-bearing, not defensive style: a # document that fails to parse yields an EMPTY xpath result, `$((tel + ))` is a # syntax error in dash, and the shell exits -- so one malformed file would end # the run silently, taking sections 7-9 with it and reporting fewer cases rather # than a red. Found by the mutation pass, which is the only thing that looks. _num() { case "$1" in ''|*[!0-9]*) echo 0 ;; *) echo "$1" ;; esac; } tel=0; tat=0 while IFS= read -r f; do pair=$(xmllint --nonet --xpath 'concat(count(//*)," ",count(//@*))' "$f" 2>/dev/null) e=${pair%% *}; a=${pair##* } tel=$((tel + $(_num "${e%%.*}"))); tat=$((tat + $(_num "${a%%.*}"))) done < "$XMLS" check_eq xorg-docs/xml-elements "$(sed -n 's/^CENSUS-XML-TOTAL files=[0-9]* elements=\([0-9]*\).*$/\1/p' "$CENSUS")" "$tel" check_eq xorg-docs/xml-attrs "$(sed -n 's/^CENSUS-XML-TOTAL .*attrs=\([0-9]*\)$/\1/p' "$CENSUS")" "$tat" check_eq xorg-docs/census-xml-files 17 "$(sed -n 's/^CENSUS-XML-TOTAL files=\([0-9]*\).*$/\1/p' "$CENSUS")" # One DocBook version across the whole set. A document at another version is not # a fault by itself, but it changes which DTD section 7 must resolve, so it is # pinned rather than discovered later. n43=0 while IFS= read -r f; do head -4 "$f" | grep -q 'DocBook XML V4.3//EN' || n43=$((n43+1)) done < "$XMLS" check_eq xorg-docs/xml-doctype-43 0 "$n43" # The control for the whole section: xmllint must be able to say no. printf '\n' > "$t/broken.xml" # Non-zero, not a pinned code: libxml2 spells "unclassified", "DTD" and # "validation" errors 1/2/3/4 and has moved which it uses. The control's claim is # that it CAN say no, and a red here for a renumbered exit code would say nothing # about this package. if xmllint --nonet --noout "$t/broken.xml" >/dev/null 2>&1; then bst_notok xorg-docs/control-xmllint-detects-malformed "accepted a malformed document" else bst_ok xorg-docs/control-xmllint-detects-malformed fi # --- 7. what the documents depend on, and what that costs ------------------- # # 15 of the 17 declare `` -- a RELATIVE system # id, resolved by X.Org's build through --searchpath into xorg-sgml-doctools' # tree. Installed as sources they carry that reference unresolved, so DTD # validation of the real documents needs that package on the image. This is a # property of what upstream ships, not a defect of the port, and it is pinned # here so it cannot change unnoticed. ndefs=0 while IFS= read -r f; do grep -q 'ENTITY % defs SYSTEM "defs.ent"' "$f" && ndefs=$((ndefs+1)) done < "$XMLS" check_eq xorg-docs/docs-declare-defs-ent 15 "$ndefs" # The DTD path itself IS exercised on this image, against a self-contained # fixture, so the skip below is narrow: it is about defs.ent, not about whether # validation works here at all. check_out xorg-docs/dtd43-catalog-resolves "docbook" \ xmlcatalog /etc/xml/catalog "-//OASIS//DTD DocBook XML V4.3//EN" cat > "$t/fixture.xml" <<'XEOF'
brintOS xorg-docs fixture SENTINELFIXTURESENTINEL
XEOF check xorg-docs/fixture-valid-43 xmllint --nonet --noout --valid "$t/fixture.xml" # and it can go red: is not permitted directly inside . sed 's||<articleinfo><sect1 id="bad"/><title>|' "$t/fixture.xml" > "$t/badfixture.xml" if xmllint --nonet --noout --valid "$t/badfixture.xml" >/dev/null 2>&1; then bst_notok xorg-docs/control-fixture-invalid-43 "sect1 inside articleinfo validated" else bst_ok xorg-docs/control-fixture-invalid-43 fi if [ -f "$DEFS" ]; then # xorg-sgml-doctools is here, so the documents can be validated the way their # own build validates them: --path is xmllint's equivalent of --searchpath. nval=0 while IFS= read -r f; do xmllint --nonet --noout --valid --path "$(dirname "$DEFS")" "$f" >/dev/null 2>&1 \ || { nval=$((nval+1)); val1=$f; } done < "$XMLS" check_eq xorg-docs/docs-valid-43 0 "$nval" [ "$nval" -eq 0 ] || bst_notok xorg-docs/docs-valid-43-first "$val1 did not validate" else bst_skip xorg-docs/docs-valid-43 \ "xorg-sgml-doctools is not on this image, so defs.ent cannot be resolved and the documents cannot be DTD-validated as installed" fi # --- 8. the documents drive an XSLT engine on this target ------------------- # # The strongest thing that can be said about a document is that something reads # it. The stylesheet is written here rather than taken from docbook-xsl on # purpose: it needs no catalog, so a green result is attributable to the SHIPPED # XML and to libxslt on wasm32, and not to the image's DocBook stack. if command -v xsltproc >/dev/null 2>&1; then cat > "$t/probe.xsl" <<'XEOF' <?xml version="1.0"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="text"/> <xsl:template match="/"> <xsl:text>TITLE=</xsl:text><xsl:value-of select="normalize-space((//title)[1])"/> <xsl:text>|ELEMENTS=</xsl:text><xsl:value-of select="count(//*)"/> <xsl:text>|ULINKS=</xsl:text><xsl:value-of select="count(//ulink)"/> <xsl:text> </xsl:text> </xsl:template> </xsl:stylesheet> XEOF tout=$(xsltproc --nonet "$t/probe.xsl" "$DOC/platforms/Darwin.xml" 2>/dev/null); trc=$? if [ "$trc" -eq 0 ]; then bst_ok xorg-docs/transform-rc else bst_notok xorg-docs/transform-rc "rc=$trc"; fi check_eq xorg-docs/transform-fields \ "TITLE=X on Darwin and Mac OS X|ELEMENTS=17|ULINKS=7" "$tout" # The same transform over the largest document, scored on the count the census # recorded for it -- so libxslt's parse of a 267 KB DocBook book is compared # against expat's, not against a number typed here. bout=$(xsltproc --nonet "$t/probe.xsl" "$DOC/icccm/icccm.xml" 2>/dev/null) bel=${bout#*|ELEMENTS=}; bel=${bel%%|*}; bel=$(_num "$bel") check_eq xorg-docs/transform-large-elements \ "$(sed -n "s|^CENSUS-XML $DOC/icccm/icccm.xml [a-z]* \([0-9]*\) .*$|\1|p" "$CENSUS")" "$bel" # The control: the same engine over something that is not XML must fail. printf 'this is not xml\n' > "$t/notxml" if xsltproc --nonet "$t/probe.xsl" "$t/notxml" >/dev/null 2>&1; then bst_notok xorg-docs/control-transform-rejects-nonxml "transformed a non-XML input" else bst_ok xorg-docs/control-transform-rejects-nonxml fi else bst_skip xorg-docs/transform-rc "xsltproc not installed on this image" fi # --- 9. the man pages ------------------------------------------------------- # # These six are the only GENERATED files in the package: sed output over .man # sources, substituting xorg-macros' MAN_SUBSTS plus __datadir__, __libdir__ and # __sysconfdir__. A substitution that resolved to the BUILD sysroot would leave # the file list, every size and every count untouched, so it is checked directly. nroff=0; ntok=0 for m in Consortium Standards X XOrgFoundation XProjectTeam Xsecurity; do grep -q '^\.TH ' "$MAN/$m.7" 2>/dev/null || nroff=$((nroff+1)) grep -qE '__[a-zA-Z][a-zA-Z0-9_]*__' "$MAN/$m.7" 2>/dev/null && ntok=$((ntok+1)) done check_eq xorg-docs/man-roff 0 "$nroff" check_eq xorg-docs/man-no-unsubstituted-tokens 0 "$ntok" # and the substitutions resolved to the TARGET prefix, which is the half that a # token scan alone cannot show. check_out xorg-docs/man-datadir-substituted "/usr/share/X11/rgb.txt" cat "$MAN/X.7" check_out xorg-docs/man-libdir-substituted "/usr/lib/X11/" cat "$MAN/X.7" # The control for the scan: a planted token must be found. printf '.TH T 7\n.\\" __projectroot__\n' > "$t/planted.7" check xorg-docs/control-token-scan-works grep -qE '__[a-zA-Z][a-zA-Z0-9_]*__' "$t/planted.7" # man-db 2.12.0 and groff 1.23.0 are on this image, and they READ these pages: # the lookup, the NAME-section parse and both groff preprocessors all succeed # against X.7. Only the final formatting stage does not -- see below. E="env MANPATH=/usr/share/man MANPAGER=cat MANWIDTH=80" if command -v man >/dev/null 2>&1; then check_out xorg-docs/man-locate-x "$MAN/X.7" $E man -w 7 X locmiss=0 for m in Consortium Standards X XOrgFoundation XProjectTeam Xsecurity; do [ "$($E man -w 7 "$m" 2>/dev/null)" = "$MAN/$m.7" ] || locmiss=$((locmiss+1)) done check_eq xorg-docs/man-locate-all 0 "$locmiss" else bst_skip xorg-docs/man-locate-x "man not installed on this image" fi # lexgrog parses the NAME section the way whatis/apropos do, so a green here says # the page is well-formed man source and not merely well-formed roff. if command -v lexgrog >/dev/null 2>&1; then check_out xorg-docs/man-lexgrog "network-transparent window system" lexgrog "$MAN/X.7" else bst_skip xorg-docs/man-lexgrog "lexgrog not installed on this image" fi # soelim and preconv are the two groff preprocessors man pipes a page through # before troff. Both run here, which is what makes the failure below specifically # troff's and not the toolchain's. if command -v soelim >/dev/null 2>&1 && command -v preconv >/dev/null 2>&1; then n=$(soelim "$MAN/X.7" 2>/dev/null | wc -c | tr -d ' '); n=$(_num "$n") sz=$(wc -c < "$MAN/X.7" | tr -d ' ') if [ "$n" -ge "$sz" ]; then bst_ok xorg-docs/man-soelim else bst_notok xorg-docs/man-soelim "soelim emitted $n bytes for a $sz-byte page"; fi check_out xorg-docs/man-preconv "network-transparent window system" \ sh -c "preconv '$MAN/X.7' 2>/dev/null | head -200" else bst_skip xorg-docs/man-soelim "soelim/preconv not installed on this image" fi # --- 10. the one platform defect this port meets ---------------------------- # # THE CAUSE, ASSERTED FIRST AND ON ITS OWN: troff traps SIGILL (rc 132) in a # static constructor of libgroff's uniuni.cpp, BEFORE main(), so even # `troff --version` dies without printing. That is # linux-in-the-browser#171, already tracked and already carried as a red by # 89-man-db.test -- it is a property of groff on wasm32 and has nothing to do # with this package. Measured here rather than inferred: `man 7 X` with LC_ALL=C # fails identically, so the "can't set the locale" line man prints alongside it # (this image ships no locales) is noise, not the cause. # # Both cases are written in the direction that is TRUE ONCE #171 LANDS, so they # self-flip rather than needing an edit. Two reds, one cause: the second is the # effect, and it is kept because it is the assertion a reader of this port cares # about -- whether the six pages can be read as pages. if command -v troff >/dev/null 2>&1; then check_out xorg-docs/man-troff-runs "GNU troff (groff) version 1.23.0" troff --version else bst_skip xorg-docs/man-troff-runs "troff not installed on this image" fi if command -v man >/dev/null 2>&1; then check_out xorg-docs/man-renders-x "portable, network-transparent window system" \ $E man 7 X else bst_skip xorg-docs/man-renders-x "man not installed on this image" fi rm -rf "$t"