# BST-TIMEOUT: 300 # NOT MEASURED ON TARGET YET. The shape is one probe exec # # (twice -- once full, once --pure) plus a shell fork per # # scored value, ~90 of them, which is the shape 57-libxau # # runs at 300 with deep headroom. The probe itself does no # # I/O beyond reading the X11 locale tree and its own # # reference file; its longest stretch is the KSW sweep, # # ~70000 in-process table lookups. Replace this note with a # # measured elapsed the first time the suite runs on target. . "$BST_LIB" # libX11 1.8.9 (poky recipes-graphics/xorg-lib) -- Xlib. PROVIDES # virtual/libx11, so this is the package every other Xlib consumer in the image # depends on by name. # # --------------------------------------------------------------------------- # THERE IS NO X SERVER ON THIS IMAGE, AND THAT SHAPES THE WHOLE SUITE # # Xlib is a protocol client. Everything that draws, maps a window or reads an # event needs a server, and nothing here can reach one. That is not a gap this # suite papers over: the four XOpenDisplay cases at the bottom assert the # FAILURE, and they assert it in four distinguishable forms so that "no server" # is separable from "the runtime would not give us a socket". # # What IS reachable is the part of Xlib a client runs BEFORE it connects, and # it is most of what a cross-compile can silently get wrong: # # KS / KSW the keysym tables. These do not exist in the tarball -- # src/ks_tables.h is generated at build time by src/util/makekeys # out of the keysymdef.h that --with-keysymdefdir points at. A # wrong keysymdefdir or a short header is invisible in the build. # GEO XParseGeometry -- every X client's -geometry. # COL XParseColor's numeric forms and their channel widening. # XRM the resource manager, end to end. # PARSECMD XrmParseCommand -- the argv front end in every client's main(). # CASE XConvertCase. # RGN the region algebra, which never crosses the wire at all. # TXT the STRING text-property round trip WM_NAME is built from. # # --------------------------------------------------------------------------- # THE ORACLE IS A BUILD-HOST RUN OF THE SAME PROBE, SHIPPED BESIDE IT # # libx11-probe --pure prints exactly the groups above, and the recipe builds the # same source against libx11-native, runs it, and installs the result as # libx11-probe.ref. The target's --pure output must match that file. # # This is the assertion a target-only run cannot make. Round-tripping a keysym # name through the table proves the two directions agree; it does not prove the # table is COMPLETE. A makekeys that read a truncated keysymdef.h would name # every keysym it did have, resolve each one back, and report itself perfect. # Only the reference catches the ones that are not there. # # THE GROUPS OUTSIDE --pure ARE PINNED BY HAND BELOW, and they are outside it # because the two machines must DISAGREE: # # ABI this arm is ILP32; the reference host is LP64. XID, Atom, KeySym and # Mask are all `unsigned long' in Xlib's headers, so every number in # that group differs and agreement would be the defect. The values are # derived by hand from the declarations in Xlib.h and Xutil.h. # LOC the reference host has its own X11 locale tree. # DPY process environment. # OPEN sockets. # # --------------------------------------------------------------------------- # WHAT IS OUT OF REACH, SAID PLAINLY RATHER THAN FAKED # # XParseColor's NAMED forms, XLookupString and XOpenIM all need a real Display: # the first dereferences it in ScreenCount() on the line after the '#' parse # returns, the second reads a keyboard mapping the server sends, the third is an # input method over a connection. None is exercised, and no substitute Display # is fabricated -- that would have produced a confident wrong answer about all # three. XConvertCase stands in for XLookupString's pure half. # # The X11 locale tree the LOC group opens is BRINTOS-1650's libx11-compose-data, # already in this image. That is also why libx11-locale is NOT installed here: # the two packages own the same ${datadir}/X11/locale path and only one of them # can. PROBE=${BST_LIBX11_PROBE:-/usr/libexec/libx11-tests/libx11-probe} REF=${BST_LIBX11_REF:-/usr/libexec/libx11-tests/libx11-probe.ref} ARCHIVE=/usr/lib/libX11.a PCFILE=/usr/lib/pkgconfig/x11.pc HDR=/usr/include/X11/Xlib.h ERRORDB=/usr/share/X11/XErrorDB XCMSTXT=/usr/share/X11/Xcms.txt LOCALEDIR=/usr/share/X11/locale # The version the recipe pins. Asserted rather than read back, so a recipe # bumped without revisiting this suite is a red here instead of a silent change # of subject -- the reference is the oracle for THIS version only. WANT_VERSION=1.8.9 # The first BST result line of a suite is dropped by the guest console # (brintos/linux#96), consistently and every run. This case asserts something # already true so that what is lost is a line that costs nothing; remove it when # #96 lands. if [ -f "$ARCHIVE" ]; then bst_ok libx11/suite-canary else bst_notok libx11/suite-canary "$ARCHIVE is not a file"; fi if [ ! -f "$ARCHIVE" ]; then bst_skip libx11/present "libx11 not installed on this image" exit 0 fi bst_ok libx11/present # --- the package is whole ----------------------------------------------------- check libx11/staticlib test -s "$ARCHIVE" check libx11/pkgconfig test -s "$PCFILE" check libx11/hdr-xlib test -s "$HDR" check libx11/hdr-xutil test -s /usr/include/X11/Xutil.h check libx11/hdr-xrm test -s /usr/include/X11/Xresource.h check libx11/hdr-xatom test -s /usr/include/X11/Xatom.h check libx11/errordb test -s "$ERRORDB" check libx11/xcms-txt test -s "$XCMSTXT" # Shape, not absence: this arm converts to shared libraries per recipe # (BRINTOS-1740), so a .so here is a conversion, not a policy breach. bst_lib_shape libx11/no-shared "/usr/lib/libX11.so" "/usr/lib/libX11.so.6" pcver=$(sed -n 's/^Version: *//p' "$PCFILE" 2>/dev/null | head -1) check_eq libx11/pkgconfig-version "$WANT_VERSION" "$pcver" # x11.pc must still declare the xcb dependency, because a consumer that links # statically gets libxcb only if pkg-config tells it to. if grep -q 'xcb' "$PCFILE" 2>/dev/null; then bst_ok libx11/pkgconfig-xcb else bst_notok libx11/pkgconfig-xcb "x11.pc names no xcb dependency" fi # The locale tree Xlib's i18n layer opens. It is libx11-compose-data's, not # this package's -- asserted here because the LOC group below fails without it # and the two failures look identical from the probe's side. if [ -d "$LOCALEDIR" ]; then bst_ok libx11/locale-dir else bst_notok libx11/locale-dir "$LOCALEDIR is absent, so Xlib's locale layer has nothing to read" fi check libx11/locale-alias test -s "$LOCALEDIR/locale.alias" check libx11/locale-dir-index test -s "$LOCALEDIR/locale.dir" check libx11/compose-dir test -s "$LOCALEDIR/compose.dir" # The archive carries the API. grep rather than nm: the image ships no binutils # nm, and the names are present as plain bytes. -a where the grep supports it -- # on this arm the archive members are LLVM IR bitcode (ThinLTO), so a grep that # suppresses matches in a file containing NULs reports nothing; GNU grep needs # -a, busybox grep as shipped does not. if echo x | grep -aq x 2>/dev/null; then _grepq="grep -aq"; else _grepq="grep -q"; fi for sym in XOpenDisplay XCloseDisplay XParseGeometry XParseColor \ XStringToKeysym XKeysymToString XConvertCase \ XrmGetStringDatabase XrmGetResource XrmParseCommand \ XCreateRegion XPolygonRegion XStringListToTextProperty \ XAllocSizeHints XSupportsLocale XDisplayName; do if $_grepq "$sym" "$ARCHIVE" 2>/dev/null; then bst_ok "libx11/sym-$sym" else bst_notok "libx11/sym-$sym" "$sym absent from $ARCHIVE" fi done # The header must declare what a consumer compiles against. libX11's public # surface is enormous; these are the entry points the rest of the epic and the # first Xlib consumer (fltk) actually need. for decl in XOpenDisplay XCreateWindow XSelectInput XNextEvent \ XParseGeometry XStringToKeysym XLookupString; do if grep -q "$decl" "$HDR" /usr/include/X11/Xutil.h 2>/dev/null; then bst_ok "libx11/hdr-decl-$decl" else bst_notok "libx11/hdr-decl-$decl" "$decl is not declared in the installed headers" fi done # --- the probe ---------------------------------------------------------------- if [ ! -x "$PROBE" ]; then bst_skip libx11/probe-runs "$PROBE absent from the image" exit 0 fi pout=${TMPDIR:-/tmp}/bst-libx11-full.$$ "$PROBE" > "$pout" 2>&1 prc=$? if [ "$prc" -eq 0 ]; then bst_ok libx11/probe-runs elif bst_execfail "$(head -c 200 "$pout" 2>/dev/null)"; then bst_unrun libx11/probe-runs "$(head -c 200 "$pout" 2>/dev/null)" rm -f "$pout" exit 0 else bst_notok libx11/probe-runs "probe exited $prc: $(_bst_1line "$(head -c 300 "$pout")")" fi if grep -q '^PROBE-END$' "$pout" 2>/dev/null; then bst_ok libx11/probe-complete else bst_notok libx11/probe-complete "probe output has no PROBE-END terminator (last line: $(tail -1 "$pout" 2>/dev/null))" fi # val -- the probe's value for one case, empty when the probe stopped # first. Matches on field 1 rather than taking the line by position, because # the capture is 2>&1 and Xlib writes its own diagnostics to stderr. val() { awk -v k="$1" '$1==k { $1=""; sub(/^ /,""); print; exit }' "$pout"; } # want -- score one probe value against a pinned answer. # A missing value is reported as the probe having stopped early rather than as a # mismatch against '', which is a different fault and localises elsewhere. want() { _got=$(val "$1") if [ -z "$_got" ]; then bst_notok "libx11/$2" "no value on target (probe stopped before $1); want='$3'" elif [ "$_got" = "$3" ]; then bst_ok "libx11/$2" else bst_notok "libx11/$2" "want:'$3' got:'$_got'" fi } # =========================================================================== # THE REFERENCE DIFF -- the pure groups # =========================================================================== # # One case per group rather than one per line: the pure output is several # hundred lines and a per-line suite would drown the console in cases that all # say the same thing. Each group's case carries the FIRST differing line and the # number of differences, which is what a reader needs to localise it. if [ ! -s "$REF" ]; then bst_notok libx11/reference-present "$REF is missing or empty, so the target run has nothing to be compared to" else bst_ok libx11/reference-present ppure=${TMPDIR:-/tmp}/bst-libx11-pure.$$ "$PROBE" --pure > "$ppure" 2>/dev/null ppurerc=$? if [ "$ppurerc" -ne 0 ]; then bst_notok libx11/probe-pure-runs "libx11-probe --pure exited $ppurerc" else bst_ok libx11/probe-pure-runs fi # The whole-file verdict first. A green here makes every per-group case below # redundant, which is the point: the groups exist to localise a red. if cmp -s "$ppure" "$REF" 2>/dev/null; then bst_ok libx11/reference-identical else _first=$(awk 'NR==FNR{r[FNR]=$0;n=FNR;next} {if($0!=r[FNR]){printf "line %d ref=[%s] got=[%s]", FNR, r[FNR], $0; exit}} END{}' "$REF" "$ppure" 2>/dev/null) _nref=$(wc -l < "$(bst_local "$REF")" 2>/dev/null) _ngot=$(wc -l < "$ppure" 2>/dev/null) bst_notok libx11/reference-identical "target --pure differs from the build-host reference ($_ngot lines against $_nref): $(_bst_1line "$_first")" fi # grp -- compare just the lines carrying . grp() { _ga=${TMPDIR:-/tmp}/bst-libx11-ga.$$ _gb=${TMPDIR:-/tmp}/bst-libx11-gb.$$ grep "^$2" "$REF" > "$_ga" 2>/dev/null grep "^$2" "$ppure" > "$_gb" 2>/dev/null _na=$(wc -l < "$_ga"); _nb=$(wc -l < "$_gb") if [ "$_na" -eq 0 ]; then bst_notok "libx11/$1" "the reference carries no $2 lines at all, so this group is unmeasured" elif cmp -s "$_ga" "$_gb" 2>/dev/null; then bst_ok "libx11/$1" else _d=$(awk 'NR==FNR{r[FNR]=$0;next}{if($0!=r[FNR]){c++; if(c==1)f=sprintf("ref=[%s] got=[%s]",r[FNR],$0)}}END{printf "%d differing of %d: %s", c, FNR, f}' "$_ga" "$_gb" 2>/dev/null) bst_notok "libx11/$1" "$2 group: ref $_na lines, target $_nb -- $(_bst_1line "$_d")" fi rm -f "$_ga" "$_gb" } grp ref-ver VER- grp ref-keysyms KS- grp ref-ksweep KSW- grp ref-geometry GEO- grp ref-color COL- grp ref-xrm XRM- grp ref-quarks QRK- grp ref-parsecmd PARSECMD- grp ref-case CASE- grp ref-region RGN- grp ref-textprop TXT- grp ref-alloc ALLOC- # The keysym census, stated outright as well as diffed. A table that lost a # block shows up in the group diff as a wall of lines; this is the one number # that says how many keysyms this build's ks_tables.h actually names, and it # is the number to quote when the port is discussed. _kt=$(sed -n 's/^KSW-TOTAL \([0-9][0-9]*\) .*/\1/p' "$REF" | head -1) want KSW-TOTAL ksweep-total "$(grep '^KSW-TOTAL ' "$REF" | head -1 | sed 's/^KSW-TOTAL //')" if [ -n "$_kt" ] && [ "$_kt" -ge 1000 ]; then bst_ok libx11/ksweep-census else bst_notok libx11/ksweep-census "the reference names only ${_kt:-0} keysyms across all blocks, which is too few for a complete keysymdef.h" fi # Nothing in the sweep may fail to round-trip, on either machine. This is # stated separately from the diff because a reference that ALSO had # round-trip failures would make the diff green over them. _rtbad=$(sed -n 's/^KSW-TOTAL [0-9][0-9]* [0-9][0-9]* \([0-9][0-9]*\)$/\1/p' "$REF" | head -1) check_eq libx11/ksweep-ref-roundtrip 0 "${_rtbad:-unknown}" rm -f "$ppure" fi # =========================================================================== # ABI -- ILP32, derived by hand from the declarations # =========================================================================== # # Xlib types every consumer sees. XID, Atom, KeySym and Mask are `unsigned # long' in X.h, so all four are 4 here against the reference host's 8 -- which # is why this group is not in --pure and why these numbers are pinned rather # than diffed. want ABI-LONG abi-long 4 want ABI-PTR abi-ptr 4 want ABI-XID abi-xid 4 want ABI-ATOM abi-atom 4 want ABI-KEYSYM abi-keysym 4 want ABI-MASK abi-mask 4 # Struct sizes and offsets, counted out of Xlib.h/Xutil.h for ILP32: # XEvent is a union whose largest member is `long pad[24]' -- 24 * 4. # XKeyEvent is 15 four-byte members; keycode is the 14th, at 13 * 4 = 52. # XClientMessageEvent is 7 four-byte members then a 20-byte union (char b[20] # / short s[10] / long l[5], all 20 on ILP32), so `data' is at 7 * 4 = 28. # XSizeHints: flags(4) + 4 ints + 4 ints + 2 ints + 2 aspect pairs(16) + # 2 ints + win_gravity(4) = 72. # XTextProperty: value ptr, encoding Atom, format int, nitems ulong = 16. # XRectangle: two shorts and two unsigned shorts = 8. want ABI-XEVENT abi-xevent 96 want ABI-XKEYEVENT abi-xkeyevent 60 want ABI-XCLIENTMSG abi-xclientmsg 48 want ABI-XSIZEHINTS abi-xsizehints 72 want ABI-XTEXTPROP abi-xtextprop 16 want ABI-XRECT abi-xrect 8 want ABI-OFF-KEYCODE abi-off-keycode 52 want ABI-OFF-SERIAL abi-off-serial 4 want ABI-OFF-CM-DATA abi-off-cm-data 28 # =========================================================================== # LOC -- the X11 locale layer, which is what reads the ported compose tree # =========================================================================== # # XSupportsLocale is the deepest Xlib gets into i18n without a Display: it # resolves the current locale through ${datadir}/X11/locale/locale.alias and # locale.dir and loads the XLC_LOCALE description behind it. The C locale is # built into Xlib and must always be supported; en_US.UTF-8 depends on glibc # having that locale generated in this image, which it may not, so its answer # is REPORTED rather than pinned -- see the two cases below. want LOC-SETLOCALE-C loc-setlocale-c C want LOC-SUPPORTS-C loc-supports-c 1 want LOC-SUPPORTS-AFTER loc-supports-after 1 # XSetLocaleModifiers("") returns the modifiers in force, which with no @im= # anywhere is the empty string. A NULL return would mean the i18n layer refused # to initialise at all. _mods=$(val LOC-MODIFIERS) if [ "$_mods" = "(null)" ]; then bst_notok libx11/loc-modifiers "XSetLocaleModifiers returned NULL -- Xlib's locale layer did not initialise" else bst_ok libx11/loc-modifiers fi # Not pinned: whether this image carries a generated en_US.UTF-8. Both answers # are legitimate and neither is libX11's doing. What IS asserted is that the # probe reached the case and that Xlib did not lose the C locale afterwards # (the case above). _u8=$(val LOC-SETLOCALE-UTF8) if [ -z "$_u8" ]; then bst_notok libx11/loc-utf8-reported "the probe stopped before LOC-SETLOCALE-UTF8" else bst_ok libx11/loc-utf8-reported fi # =========================================================================== # DPY -- XDisplayName, three lines of getenv with no connection behind it # =========================================================================== want DPY-UNSET dpy-unset "[]" want DPY-EXPLICIT dpy-explicit "[:3]" want DPY-SET dpy-set "[:7]" want DPY-EMPTY dpy-empty "[:7]" # =========================================================================== # OPEN -- the honest failures # =========================================================================== # # With no X server anywhere, all four must return NULL. That much is trivial. # What matters is that they are DISTINGUISHABLE, because only one of them -- # unixsock -- is evidence about this platform rather than about Xlib: # # nodisplay $DISPLAY unset. Xlib never reaches a syscall. # unixsock ":99" -- socket(AF_UNIX) + connect() to /tmp/.X11-unix/X99. # tcp "127.0.0.1:99" -- socket(AF_INET) + connect() to port 6099. # badhost a name nothing resolves; fails in the resolver. # # errno is printed by the probe and is NOT asserted: Xlib makes no promise # about what it leaves there. It is in the console dump for whoever reads a red. for c in nodisplay unixsock tcp badhost; do _o=$(val "OPEN-$c") case "$_o" in null*) bst_ok "libx11/open-$c" ;; opened*) bst_notok "libx11/open-$c" "XOpenDisplay SUCCEEDED with no X server on this image -- something answered: $_o" ;; "") bst_notok "libx11/open-$c" "the probe stopped before OPEN-$c" ;; *) bst_notok "libx11/open-$c" "unrecognised: $_o" ;; esac done # The four must not be the same failure wearing four names. If every one of # them reports errno=0 the probe never got as far as a syscall on any of them, # which would mean the display-name parse refused all four and the platform's # socket path was never exercised at all. _nz=0 for c in unixsock tcp; do case "$(val "OPEN-$c")" in *errno=0\ *) ;; *errno=*) _nz=$((_nz + 1)) ;; esac done if [ "$_nz" -ge 1 ]; then bst_ok libx11/open-reached-syscall else bst_notok libx11/open-reached-syscall "neither the AF_UNIX nor the AF_INET attempt left an errno, so Xlib refused both display names before opening a socket and the platform's socket path is unmeasured here" fi rm -f "$pout"