. "$BST_LIB" # BST-TIMEOUT: 300 # three probe runs plus ~110 shell extractions. The probes' # own work is bounded and nearly syscall-free: six small # files written to and read back from $TMPDIR, one # gethostname, and no socket of any kind. The bound is # headroom for a loaded host, not a cap on anything this # suite is known to approach. # libXmu 1.1.4 -- Xmu and Xmuu, the X miscellaneous utility libraries # (poky recipes-graphics/xorg-lib). See libxmu_%.bbappend for what the port adds # and why. # # --------------------------------------------------------------------------- # THE PACKAGE IS A PAIR, AND THE PAIR IS WHAT THIS SUITE IS MOST ABOUT # # libXmu.a is the whole grab-bag and needs the X Toolkit. libXmuu.a is the # five-file subset that does not -- ClientWin.c, CursorName.c, DefErrMsg.c, # GetHost.c and Lower.c -- and it exists so a consumer can take the utilities # without linking Xt. xmu.pc says `Requires: xproto x11 xt'; xmuu.pc says # `Requires: xproto x11', and that omission IS the promise. # # A build that shipped one of the two looks complete: do_install succeeds, both # .pc files are generated unconditionally from their .in, and the headers are # one shared set. Nothing here would notice until some later consumer's link # failed with an undefined symbol nobody would attribute to this recipe. So the # pair is asserted three ways -- as files (section 1), as two dependency sets # (section 2), and as a LINK, which happened at build time: libxmuu-probe is # linked against libXmuu.a and libX11 and nothing else, so if the split has # stopped being real the recipe already failed and this suite never ran. # # --------------------------------------------------------------------------- # HALF OF libXmu NEEDS A DISPLAY AND IS NOT TESTED HERE. SAID PLAINLY: # # There is no X server on this image and there will not be one. The atom cache, # the standard-colormap routines, XmuClientWindow's window-tree walk, # XmuCreatePixmapFromBitmap, XmuLocateBitmapFile, XmuDrawLogo, # XmuPrintDefaultErrorMessage and FOUR of the ten string converters # (String-to-Bitmap, -Cursor, -ColorCursor, -Widget) each reach a Display on # their first statement. They are NOT executed and this suite claims nothing # about their behaviour. Case libxmu/linked-display-arm asserts exactly one # thing about them -- that the archive still CONTAINS them, which the probe's # link proved by naming each one's address -- and it is scored as that and # nothing more. # # What IS reachable is substantial, and is what sections 4 to 10 drive: # # THE CASE MAPPING XmuTolower/XmuToupper over all 256 byte values, against # the four ranges re-evaluated inside the # probe. This is the closest thing here to a pure function # of the architecture, and the place a wrongly built # archive shows first -- the mapping is arithmetic on a # char, and a SIGNED char makes every byte above 0x7f # negative and therefore outside all four ranges. # THE CURSOR NAMES All 77 of them, each against 's own # constant rather than a number written down here. # THE BITMAP READER Over fixtures the probe writes itself, so what must come # back is known from the text that produced it. # THE CONVERTERS The six that are display-free, each against the X # protocol constant it returns. # COMPOUND TEXT XctCreate/XctNextItem/XctReset/XctFree, a pure byte-string # parser and the richest display-free thing in the package. # THE ERROR HANDLER XmuSimpleErrorHandler's three ignore arms, which return # before the Display is touched. # # --------------------------------------------------------------------------- # NO BUILD-HOST REFERENCE RUN, AND THAT IS THIS PACKAGE'S PROPERTY # # 57-libxau.test and 57-libice.test pin bytes taken from a native x86-64 run, # because an on-disk file format has no absolute answer that a header states -- # only a second architecture catches a writer that emitted its counts in host # order. Nothing in libXmu is of that kind. Every expectation below has a # reference available in the probe's own translation unit: cursorfont.h's # constants, the keysym ranges, the X protocol constants the converters return, # and a bitmap fixture the probe wrote. The one group deliberately NOT taken # from any other machine is section 3's sizeof/offsetof block -- those are an # ILP32 statement, and agreeing with an LP64 host would be the defect. # # --------------------------------------------------------------------------- # NO NON-PASSES ARE EXPECTED. Every case here is about files this image ships or # about a probe that runs to completion on it. Nothing resolves a name, opens a # socket, or depends on a kernel facility this arm is missing -- which is why, # unlike 57-libsm.test, there is no expected red and no arm scored against the # image rather than against the library. # # --------------------------------------------------------------------------- # READ A RED IN SECTION ORDER; THE FIRST SECTION TO GO RED LOCALISES THE DEFECT # # 1 the files arrived packaging only, both halves # 2 xmu.pc and xmuu.pc resolve consumers find the pair at all # 3 the probes run, and the ABI struct layout on this arm # 4 the case mapping 255 bytes, twice, against the ranges # 5 the cursor names 77, against cursorfont.h # 6 the bitmap reader parse and the four refusals # 7 the converters six of ten, against X constants # 8 Compound Text the parser # 9 colours and the error handler arithmetic, and three ignore arms # 10 the two archives agree libXmu.a vs libXmuu.a, same source # 11 upstream's own check program # # A build where 3 passes and 4 does not has a char-signedness or codegen fault # and nothing below it can be trusted. 10 failing while 4 and 5 pass means the # two archives were built differently from one tree, which is a packaging fault # rather than a porting one. 11 failing on its own is the editres stream codec, # and it is the only case here whose subject is `unsigned long' on the wire. # --------------------------------------------------------------------------- # A root prefix, empty on the target and set only when this suite is validated # NATIVELY under dash before it ships. The runner never sets it, so on the image # every path below is exactly the absolute one. R="${BST_LIBXMU_ROOT:-}" INC=$R/usr/include/X11/Xmu PCD=$R/usr/lib/pkgconfig LIB=$R/usr/lib XMT=$R/usr/libexec/libxmu-tests work=${TMPDIR:-/tmp}/bst-libxmu.$$ rm -rf "$work"; mkdir -p "$work" hasfile() { if [ -s "$2" ]; then bst_ok "$1"; else bst_notok "$1" "missing or empty: $2"; fi } # xmu_line [] # # The prefix is matched with grep -F rather than the whole line, so a red reports # WHAT THE PROBE ACTUALLY SAID for that case instead of merely "absent". Every # prefix is unique by construction: each label is followed by a separator that # ends it. xmu_line() { _f=${4:-$work/out} _l=$(grep -F -- "$2" "$_f" 2>/dev/null | head -1) check_eq "$1" "$2$3" "$_l" } # --------------------------------------------------------------------------- # 0. THE CANARY, which is not an assertion about libXmu at all. # # The guest console drops a suite's FIRST BST result line before the host parser # sees it -- brintos/linux#96. The harness computes its pass count as # total-minus-failures, so THE DROPPED LINE IS COUNTED AS A PASS, and a suite # whose first case is a genuine `not ok' loses the one line that mattered. So # the first line out of this file asserts something already true. # Remove this case when #96 is fixed. bst_ok libxmu/suite-canary # --------------------------------------------------------------------------- # 1. THE PAYLOAD, AND IT IS A PAIR. # # Six headers by name out of the twenty-three: these are the ones a consumer # includes directly, and each is the entry point to a part of the library this # suite goes on to exercise. A missing one fails somebody else's do_compile # rather than anything on this image. check_rc libxmu/dir-Xmu 0 test -d "$INC" hasfile libxmu/hdr-CharSet-h "$INC/CharSet.h" hasfile libxmu/hdr-Converters-h "$INC/Converters.h" hasfile libxmu/hdr-CurUtil-h "$INC/CurUtil.h" hasfile libxmu/hdr-Drawing-h "$INC/Drawing.h" hasfile libxmu/hdr-WinUtil-h "$INC/WinUtil.h" hasfile libxmu/hdr-Xct-h "$INC/Xct.h" # The header count, bounded FROM BELOW. A short install is invisible otherwise: # the build stays green, both .pc files still validate, and the gap surfaces # only when a consumer fails to compile. nh=$(find "$INC" -type f 2>/dev/null | wc -l) if [ "${nh:-0}" -ge 23 ]; then bst_ok libxmu/hdr-count else bst_notok libxmu/hdr-count "found ${nh:-0} files under X11/Xmu, expected not less than 23"; fi # BOTH ARCHIVES. This is the case that catches a build that shipped one half of # the pair, and it is the reason this port needed more than one line of test. hasfile libxmu/archive-Xmu "$LIB/libXmu.a" hasfile libxmu/archive-Xmuu "$LIB/libXmuu.a" # AND THE ABSENCE OF SHARED OBJECTS. This distro appends --disable-shared to # every class-target configure, so libtool produces the two archives and no .so # at all -- which is why FILES:${PN} and FILES:libxmuu are both empty, why the # image names libxmu-staticdev rather than a bare libxmu, and why the probes are # statically linked. A .so appearing here would mean the distro-wide flag # stopped reaching this recipe and every consumer's link line changed silently. # Branched per arm, as 57-libxcb is: on the converted arm the same sentence reads # "whatever shared object shipped must be usable". if bst_ps_converted "$LIB/libXmu.so" "$LIB/libXmu.so.*"; then bst_lib_shape libxmu/shared-usable-Xmu "$LIB/libXmu.so*" if bst_ps_converted "$LIB/libXmuu.so.*"; then bst_lib_shape libxmu/shared-usable-Xmuu "$LIB/libXmuu.so*" else bst_notok libxmu/shared-usable-Xmuu "libXmu.so shipped but libXmuu.so.* did not" fi else check_rc libxmu/no-shared-Xmu 1 test -e "$LIB/libXmu.so" check_rc libxmu/no-shared-Xmuu 1 test -e "$LIB/libXmuu.so" fi hasfile libxmu/probe-shipped "$XMT/libxmu-probe" hasfile libxmu/probeu-shipped "$XMT/libxmuu-probe" hasfile libxmu/editres-shipped "$XMT/libxmu-editresstream" # Cross-package facts no libXmu file records: Converters.h opens by including # , and WinUtil.h by including . A consumer holding # libXmu's headers without those cannot compile a line. check_rc libxmu/intrinsic-reachable 0 test -f "$R/usr/include/X11/Intrinsic.h" check_rc libxmu/cursorfont-reachable 0 test -f "$R/usr/include/X11/cursorfont.h" # --------------------------------------------------------------------------- # 2. THE TWO .pc FILES -- how a consumer finds any of the above, and how it # chooses WHICH HALF it wants. # # Both are architecture-DEPENDENT (each carries a libdir and a -l), so # ${libdir}/pkgconfig is the right home and share would be the defect; xtrans is # pinned the other way for the opposite reason and the two are deliberately # opposed. hasfile libxmu/pc-xmu-in-libdir "$PCD/xmu.pc" hasfile libxmu/pc-xmuu-in-libdir "$PCD/xmuu.pc" # NOT `require pkg-config'. require ENDS THE FILE when the tool is absent, and # everything this suite exists for -- sections 3 to 11 -- comes after this one. if command -v pkg-config >/dev/null 2>&1; then bst_ok libxmu/pkg-config-present check libxmu/pc-xmu-exists pkg-config --exists xmu check libxmu/pc-xmu-validate pkg-config --validate xmu check libxmu/pc-xmuu-exists pkg-config --exists xmuu check libxmu/pc-xmuu-validate pkg-config --validate xmuu check_eq libxmu/pc-xmu-modversion 1.1.4 "$(pkg-config --modversion xmu 2>/dev/null)" check_eq libxmu/pc-xmuu-modversion 1.1.4 "$(pkg-config --modversion xmuu 2>/dev/null)" # THE ASYMMETRY IS THE ASSERTION. xmu.pc names xt on both its Requires and # its Requires.private; xmuu.pc names neither. That difference is the whole # reason the second library exists, and it is machine-readable exactly here. # PKG_CONFIG_ALLOW_SYSTEM_LIBS is required for the same reason # 57-libsm.test's counterpart needs it: pkg-config SUPPRESSES a -L naming a # directory already on the linker's system path, so the bare query answers # correctly and uselessly. check libxmu/pc-xmu-static-names-Xt sh -c \ "PKG_CONFIG_ALLOW_SYSTEM_LIBS=1 pkg-config --static --libs xmu | grep -q -- -lXt" # The load-bearing negative, and the one a regression would break first: a # change that made xmuu.pc pull xt would compile and link everywhere and # silently undo the split. check_rc libxmu/pc-xmuu-static-omits-Xt 1 sh -c \ "PKG_CONFIG_ALLOW_SYSTEM_LIBS=1 pkg-config --static --libs xmuu | grep -q -- -lXt" # ...and it still has to name x11, or it would be omitting a dependency it # really does have rather than one it does not. check libxmu/pc-xmuu-static-names-X11 sh -c \ "PKG_CONFIG_ALLOW_SYSTEM_LIBS=1 pkg-config --static --libs xmuu | grep -q -- -lX11" libs=$(PKG_CONFIG_ALLOW_SYSTEM_LIBS=1 pkg-config --libs xmu 2>/dev/null) case "$libs" in *-lXmu*) bst_ok libxmu/pc-libs-names-Xmu ;; *) bst_notok libxmu/pc-libs-names-Xmu "no -lXmu in '$(_bst_1line "$libs")'" ;; esac libsu=$(PKG_CONFIG_ALLOW_SYSTEM_LIBS=1 pkg-config --libs xmuu 2>/dev/null) case "$libsu" in *-lXmuu*) bst_ok libxmu/pc-libs-names-Xmuu ;; *) bst_notok libxmu/pc-libs-names-Xmuu "no -lXmuu in '$(_bst_1line "$libsu")'" ;; esac else bst_skip libxmu/pkg-config-present "pkg-config not installed on this image" fi # --------------------------------------------------------------------------- # 3. THE PROBES RUN, AND RUN TO THEIR END. THEN THE ABI. # # do_install ships them 0755, but the rootfs is read-only at browser runtime and # the exec bit is not reliably readable there either, so each is copied to /tmp # -- a mode=1777 tmpfs with no noexec -- and given the bit where the copy lands. probe=$work/libxmu-probe probeu=$work/libxmuu-probe if cp "$XMT/libxmu-probe" "$probe" 2>/dev/null && chmod +x "$probe" 2>/dev/null \ && cp "$XMT/libxmuu-probe" "$probeu" 2>/dev/null && chmod +x "$probeu" 2>/dev/null; then TMPDIR="$work" "$probe" >"$work/out" 2>"$work/err" rc=$? TMPDIR="$work" "$probeu" >"$work/outu" 2>"$work/erru" rcu=$? # Both probes exit 0 whatever they measure -- every expectation lives in this # file, not in a binary -- so a non-zero status here means one did not RUN: a # trap, a missing import, an exec refusal. On this arm that is a real and # common failure and is what these two cases are for. if [ "$rc" -eq 0 ]; then bst_ok libxmu/probe-runs else bst_notok libxmu/probe-runs "rc=$rc $(_bst_1line "$(cat "$work/err")")"; fi if [ "$rcu" -eq 0 ]; then bst_ok libxmu/probeu-runs else bst_notok libxmu/probeu-runs "rc=$rcu $(_bst_1line "$(cat "$work/erru")")"; fi total=$(sed -n 's/^XMU-TOTAL //p' "$work/out") totalu=$(sed -n 's/^XMUU-TOTAL //p' "$work/outu") if [ -n "$total" ]; then bst_ok libxmu/probe-complete else bst_notok libxmu/probe-complete \ "no XMU-TOTAL line: $(_bst_1line "$(cat "$work/out")")"; fi if [ -n "$totalu" ]; then bst_ok libxmu/probeu-complete else bst_notok libxmu/probeu-complete \ "no XMUU-TOTAL line: $(_bst_1line "$(cat "$work/outu")")"; fi # The measurement counts, bounded FROM BELOW. Adding a fixture raises them; a # probe that got THINNER while still terminating cleanly is what these catch, # and nothing else here would -- every case below is grepped for by prefix, so # a run that died halfway leaves its remaining cases simply ABSENT. if [ -n "$total" ] && [ "$total" -ge 80 ]; then bst_ok libxmu/probe-coverage else bst_notok libxmu/probe-coverage \ "reported ${total:-0} measurements, expected not less than 80"; fi if [ -n "$totalu" ] && [ "$totalu" -ge 25 ]; then bst_ok libxmu/probeu-coverage else bst_notok libxmu/probeu-coverage \ "reported ${totalu:-0} measurements, expected not less than 25"; fi # ------------------------------------------------------------------------- # THE DATA MODEL, and this is the one place where agreeing with the build host # would be the defect: `long' and a pointer are 4 bytes on wasm32 and 8 on # x86-64. Asserted from BOTH binaries, because they are separate links and a # link that pulled a differently-configured archive is caught by nothing else. xmu_line libxmu/data-model "XMU MODEL " "long=4 ptr=4 int=4 short=2" xmu_line libxmu/data-modelu "XMUU MODEL " "long=4 ptr=4 int=4 short=2" "$work/outu" # XctRec is the only public structure in this package a caller both allocates # through the library and READS THROUGH ITSELF -- XctNextItem's entire result # is the fields it leaves behind -- so every offset is a contract between the # archive and a separately compiled consumer. Twenty-one members, every one a # 4-byte scalar on this arm, no padding anywhere. XctFlags is `unsigned long' # and is the first thing XctCreate takes. # # XErrorEvent is here for the same reason at one remove: section 9 builds one # by hand and hands its address to the library, so its layout is a contract # too. Three unsigned chars at 12..14 and then an XID realigned to 16. xmu_line libxmu/abi-sizes "XMU SIZE " \ "XctFlags=4 XctRec=84 XColor=12 XErrorEvent=20" # The offsets, separately from the size. A structure can be the right total # size with its members in the wrong places, and a consumer reading item_length # out of what the library wrote as char_size gets a plausible small number # rather than a crash. xmu_line libxmu/abi-offsets "XMU OFF XctRec " \ "total_string=0 total_length=4 flags=8 version=12 item=20 item_length=24 encoding=32 priv=80" # ----------------------------------------------------------------------- # 4. THE ISO LATIN-1 CASE MAPPING, BYTE BY BYTE. # # Two 256-entry tables, emitted as eight rows of 32 bytes each. They are # pinned ABSOLUTELY -- computed from the four keysym ranges libXmu's own # src/Lower.c is written in -- rather than only compared against the probe's # re-evaluation of those same ranges, because the two catch different things: # the agreement census below catches a wrongly compiled archive, and these # rows catch a change to the ALGORITHM that both sides would follow. # # Byte 0x00 is reported as the identity it must be rather than measured: a NUL # cannot travel through a NUL-terminated interface. Every other byte is a # measurement. # # THE FOUR EXCEPTIONS ARE WHY THIS IS WORTH 16 ROWS RATHER THAN A CHECKSUM. # ISO Latin-1 puts the multiplication sign at 0xd7, inside what would # otherwise be the upper-case accented run, and the division sign at 0xf7 in # the lower-case one; the ranges are written to step over both. Two more have # no case partner in the encoding at all -- 0xdf, small sharp s, and 0xff, # small y with diaeresis -- and must come back unchanged. All four are visible # in the c0/e0 rows below, and a range written with <= instead of < swallows # exactly them. xmu_line libxmu/lower-00 "XMU LOWER 00 " "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" xmu_line libxmu/lower-20 "XMU LOWER 20 " "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f" xmu_line libxmu/lower-40 "XMU LOWER 40 " "406162636465666768696a6b6c6d6e6f707172737475767778797a5b5c5d5e5f" xmu_line libxmu/lower-60 "XMU LOWER 60 " "606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f" xmu_line libxmu/lower-80 "XMU LOWER 80 " "808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f" xmu_line libxmu/lower-a0 "XMU LOWER a0 " "a0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebf" xmu_line libxmu/lower-c0 "XMU LOWER c0 " "e0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6d7f8f9fafbfcfdfedf" xmu_line libxmu/lower-e0 "XMU LOWER e0 " "e0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff" xmu_line libxmu/upper-00 "XMU UPPER 00 " "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" xmu_line libxmu/upper-20 "XMU UPPER 20 " "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f" xmu_line libxmu/upper-40 "XMU UPPER 40 " "404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f" xmu_line libxmu/upper-60 "XMU UPPER 60 " "604142434445464748494a4b4c4d4e4f505152535455565758595a7b7c7d7e7f" xmu_line libxmu/upper-80 "XMU UPPER 80 " "808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f" xmu_line libxmu/upper-a0 "XMU UPPER a0 " "a0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebf" xmu_line libxmu/upper-c0 "XMU UPPER c0 " "c0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedf" xmu_line libxmu/upper-e0 "XMU UPPER e0 " "c0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6f7d8d9dadbdcdddeff" # The other half of the pair: the archive's compiled code against the same # ranges evaluated by the probe's own compiler. This is the libxext #undef # idiom -- macro here, function linked in -- and it is what catches an archive # built for the wrong word size or with a stale object, which the pinned rows # above could not distinguish from a deliberate change. xmu_line libxmu/case-agree "XMU CASE-AGREE " "disagree=0 of=255" # XmuCompareISOLatin1 is the DIFFERENCE of the two lowered bytes, not a # boolean: a caller that tested it for truth would have the sense of every # comparison inverted. -1 and 1 are 'a' against 'b'; -99 is the prefix case, # where the shorter string ends and 0 - 'c' is returned. xmu_line libxmu/cmp "XMU CMP " \ "equal=0 case=0 latin1=0 lt=-1 gt=1 prefix=-99" # The bounded copy, whose `size' is the BUFFER size, so at most size-1 # characters survive. Six converters below depend on exactly this and one of # them turns it into a documented prefix match. xmu_line libxmu/ncopy7 "XMU NCOPY7 " "lower='center' upper='CENTER'" # A non-positive size is documented to touch nothing, so the sentinel lives. xmu_line libxmu/ncopy0 "XMU NCOPY0 " "lower='sentinel'" # ----------------------------------------------------------------------- # 5. THE CURSOR NAMES. # # All 77, each against the constant of the same name rather # than against a number written here -- so a red means the library and the # header have parted company, which is what a mismatched -dev and -staticdev # install looks like and which compiles and links cleanly right up to the # moment a cursor is created. xmu_line libxmu/cursor-census "XMU CURSOR-CENSUS " "names=77 disagree=0 first='-'" # Four spot values stated absolutely as well, so a census that agreed with a # header that had ITSELF moved is still caught. These are the X cursorfont's # own numbering: even, from 0, in the alphabetical order the font is defined # in, so xterm is the last of the 77 at 152. xmu_line libxmu/cursor-spot "XMU CURSOR " \ "x_cursor=0 arrow=2 xterm=152 watch=150" # The lookup lowercases its argument first, so the fold is part of the # documented interface rather than an accident of the table's spelling. xmu_line libxmu/cursor-fold "XMU CURSOR-FOLD " "upper=152 mixed=108" xmu_line libxmu/cursor-reject "XMU CURSOR-REJECT " "unknown=-1 empty=-1" # The 40-byte guard on the lookup's own buffer. Both arms answer -1, so this # cannot distinguish the early return from a failed search -- what it asserts # is that an over-long name is REFUSED rather than overrunning `char tmp[40]', # which is the one outcome that would not show up as a value at all. xmu_line libxmu/cursor-long "XMU CURSOR-LONG " "n39=-1 n63=-1" # ----------------------------------------------------------------------- # 6. THE BITMAP-FILE READER. # # The fixtures are written by the probe, so what must come back is known from # the text that produced it. The X11 arm carries a hotspot, which is the part # of the format with the strangest parse in it: `#define _x_hot' is # recognised by walking BACKWARDS from the last underscore, twice, guarded # against running off the front of the name. xmu_line libxmu/bitmap-v11 "XMU BITMAP v11 " \ "rc=0 w=16 h=16 xhot=8 yhot=7 bits=000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" # The X10 arm. Each datum is a 16-bit word taken apart with a SHIFT rather # than a cast through a short, so the low byte lands first whatever this # machine's byte order is -- which makes it the one case here that would # survive a big-endian port, and worth having on a little-endian one for # exactly that reason. No hotspot in the fixture, so both come back -1, which # is the reader's own initialiser and not a parse result. xmu_line libxmu/bitmap-v10 "XMU BITMAP v10 " \ "rc=0 w=16 h=2 xhot=-1 yhot=-1 bits=01020304" # THE FOUR REFUSALS, AND THEY MUST BE DISTINGUISHABLE. A reader that answered # one code for every kind of bad input would pass a test that only asked # whether bad input was rejected. 1 is BitmapOpenFailed; 2 is # BitmapFileInvalid, and the three ways of earning it are a different code # path each: no dimensions, no data array, and data that ran out. xmu_line libxmu/bitmap-absent "XMU BITMAP absent " "rc=1" xmu_line libxmu/bitmap-nodims "XMU BITMAP nodims " "rc=2 w=4242 data=null" xmu_line libxmu/bitmap-nobits "XMU BITMAP nobits " "rc=2 w=4242 data=null" xmu_line libxmu/bitmap-truncated "XMU BITMAP truncated " "rc=2 w=4242 data=null" # The 255-byte line buffer. A line that filled it is treated as a malformed # file rather than continuing as if the remainder were a fresh line, which is # what keeps a long comment from being parsed as a declaration. xmu_line libxmu/bitmap-longline "XMU BITMAP longline " "rc=2 w=4242 data=null" # "If it doesn't return BitmapSuccess then its arguments won't have been # touched" -- RdBitF.c's own comment, and the reason a caller may pass # uninitialised locals. 4242 and 999 are the sentinels the probe set. xmu_line libxmu/bitmap-untouched "XMU BITMAP absent-untouched " \ "w=4242 h=4242 xhot=999 data=null" # The same well-formed file through the FILE* entry point, which is what every # in-tree caller actually uses; the filename form is a fopen and a fclose # around it. The two must agree byte for byte. xmu_line libxmu/bitmap-stream "XMU BITMAP stream " \ "rc=0 w=16 h=16 xhot=8 yhot=7 bits=000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" # x_hot and y_hot are documented optional, and NULL for both is the common # case in the X clients. One `if' each, and a reader that dereferenced # unconditionally would fault here rather than answer. xmu_line libxmu/bitmap-nohotspot "XMU BITMAP nohotspot " \ "rc=0 w=16 h=16 data=set" # ----------------------------------------------------------------------- # 7. THE CONVERTERS -- SIX OF THE TEN. # # Each answer is compared against the X protocol constant the probe read out # of the INSTALLED headers in the same translation unit, and then against the # absolute value besides. The first catches a header and an archive that have # parted company; the second catches both of them moving together. # # THE FOUR NOT COVERED are String-to-Bitmap, String-to-Cursor, # String-to-ColorCursor and String-to-Widget: each reaches # XCreateBitmapFromData, XCreateFontCursor or a widget tree on a Display, so # none is reachable on this image. Said here rather than left to a reader to # infer from an absence. xmu_line libxmu/cvt-const-bs "XMU CVT-CONST backingstore " \ "notuseful=0 whenmapped=1 always=2 default=3" xmu_line libxmu/cvt-bs-notuseful "XMU CVT bs notUseful=" "0" xmu_line libxmu/cvt-bs-whenmapped "XMU CVT bs whenMapped=" "1" xmu_line libxmu/cvt-bs-always "XMU CVT bs always=" "2" # `default' is not a fourth value but the SUM of the three, which is how the # X server distinguishes "any" from a specific hint. xmu_line libxmu/cvt-bs-default "XMU CVT bs default=" "3" xmu_line libxmu/cvt-bs-fold "XMU CVT bs fold=" "1" # AND THE REFUSAL, WHICH IS THIS CONVERTER'S ALONE. Its three old-style # siblings set toVal->addr to NULL on a bad string; this one returns having # touched nothing. So `untouched' is the correct answer and `null' would be # the surprise -- and a caller checking only for NULL reads whatever was # already in toVal as a backing-store value. xmu_line libxmu/cvt-bs-refuse "XMU CVT bs refuse=" "untouched" # The reverse converter, which takes a Display and never dereferences it -- # read the body, `dpy' is not named once. rc=1 is True. xmu_line libxmu/cvt-bs-back "XMU CVT bs-back " "rc=1 s='always'" # The documented `ask again' path: too small a buffer returns False AND writes # the size it wants into toVal->size, which is the half a caller cannot guess. # 7 is strlen("always")+1. xmu_line libxmu/cvt-bs-back-short "XMU CVT bs-back-short " "rc=0 wanted=7" # An unconvertible value clears both fields, so a caller cannot mistake the # previous call's answer for this one's. xmu_line libxmu/cvt-bs-back-bad "XMU CVT bs-back-bad " "rc=0 addr=null size=0" xmu_line libxmu/cvt-const-orient "XMU CVT-CONST orientation " \ "horizontal=0 vertical=1" xmu_line libxmu/cvt-orient-h "XMU CVT orient horizontal=" "0" xmu_line libxmu/cvt-orient-v "XMU CVT orient vertical=" "1" xmu_line libxmu/cvt-orient-refuse "XMU CVT orient refuse=" "null" xmu_line libxmu/cvt-const-just "XMU CVT-CONST justify " "left=0 center=1 right=2" xmu_line libxmu/cvt-just-left "XMU CVT just left=" "0" xmu_line libxmu/cvt-just-center "XMU CVT just center=" "1" xmu_line libxmu/cvt-just-right "XMU CVT just right=" "2" xmu_line libxmu/cvt-just-refuse "XMU CVT just refuse=" "null" # THE TRUNCATION IS PART OF THE INTERFACE, not a bug to route around. This # converter lowercases into `char name[7]', so it compares at most six # characters and "centered" is therefore accepted as "center". Pinned because # it is the kind of behaviour a later cleanup silently removes, and a resource # file in the wild may depend on it. xmu_line libxmu/cvt-just-prefix "XMU CVT just prefix6=" "1" # A NULL string is an explicit early return in this converter and in no other. xmu_line libxmu/cvt-just-null "XMU CVT just null=" "untouched" xmu_line libxmu/cvt-const-grav "XMU CVT-CONST gravity " \ "forget=0 northwest=1 north=2 northeast=3 west=4 center=5 east=6 southwest=7 south=8 southeast=9 static=10 unmap=0" # Sixteen names for twelve values: the table carries left/top/right/bottom as # synonyms for west/north/east/south, which is what a resource file written # against a widget set rather than against the protocol uses. UnmapGravity and # ForgetGravity are both 0 in the protocol itself, so the census cannot # separate them and does not claim to. xmu_line libxmu/cvt-grav-census "XMU CVT grav-census " \ "names=16 disagree=0 first='-'" xmu_line libxmu/cvt-grav-refuse "XMU CVT grav refuse=" "untouched" # String to Long, and this is the converter whose ANSWER differs between this # arm and the build host: it stores through a `long *', 4 bytes here and 8 # there, and parses with %ld. The two extremes ARE the ILP32 limits, so a # build that had somehow kept a 64-bit long would not be caught by sizeof # alone but would be caught by what these two values round-trip to. xmu_line libxmu/cvt-const-long "XMU CVT-CONST long " "sizeof=4" # " 17" leads with whitespace, which %ld skips; "42abc" has a trailing tail, # which sscanf stops at while still reporting one conversion. Both are what a # resource file actually contains. xmu_line libxmu/cvt-long "XMU CVT long " "0 -1 2147483647 -2147483648 17 42" xmu_line libxmu/cvt-long-refuse "XMU CVT long refuse=" "untouched" # String to ShapeStyle is a NEW-STYLE converter -- Display, Boolean return, # reporting through done() -- and its four success arms never touch the # Display. Its FAILURE arm does, so it is not run and this suite claims # nothing about it. xmu_line libxmu/cvt-const-shape "XMU CVT-CONST shape " \ "rectangle=1 oval=2 ellipse=3 roundedrectangle=4" xmu_line libxmu/cvt-shape "XMU CVT shape names=4 " "disagree=0" # This converter folds with XmuCompareISOLatin1 rather than a lowercasing # copy, so unlike its siblings it has no length limit and no prefix behaviour # -- the whole string must match, case-insensitively. xmu_line libxmu/cvt-shape-fold "XMU CVT shape fold " "rc=1 v=4" # ----------------------------------------------------------------------- # 8. COMPOUND TEXT. # # A pure byte-string parser with no display anywhere in it. The fixture is # plain ASCII -- GL, ISO8859-1, not one escape sequence -- which is the case # every real caller starts from and the one whose answer the Compound Text # specification states rather than an implementation. # # version=1 and can_ignore_exts=0 are XctReset's initialisers: the string # carries no version escape, so neither is parsed from it. horizontal=0 is # XctUnspecified. xmu_line libxmu/xct-create "XMU XCT create=ok " \ "version=1 can_ignore_exts=0 horizontal=0" # result 0 is XctSegment. The encoding is ISO8859-1 through a path worth # naming: the segment is GL only, but ComputeGLGR has already found that this # GL and this GR name one encoding between them, so the parser reports the # COMBINED name rather than the GL one. A parser that had not run ComputeGLGR # would answer the same string by a different route and this case would not # tell the two apart -- what it does catch is a parser that lost the encoding # altogether, which is the common failure when the private state is # mismanaged. xmu_line libxmu/xct-item1 "XMU XCT item1 " \ "result=0 len=3 char_size=1 text='Xmu' enc='ISO8859-1'" # 8 is XctEndOfText. The parser must reach it rather than looping or erroring. xmu_line libxmu/xct-item2 "XMU XCT item2 " "result=8" # XctReset rewinds over the SAME string, so a second walk reproduces the # first exactly. A parser holding state it failed to reset gives a different # answer here and nowhere else. xmu_line libxmu/xct-reset "XMU XCT after-reset " "result=0 len=3 same=yes" # XctFree without XctFreeString must not free the caller's string. The probe's # is a static, so a build that freed it anyway faults on the way out rather # than in this function -- which is why the check is that the BYTES survived # and not merely that the call returned. xmu_line libxmu/xct-free "XMU XCT free=done " "string-intact=yes" # The degenerate input, reported rather than assumed: a zero-length string is # a valid parse that yields end-of-text immediately. xmu_line libxmu/xct-empty "XMU XCT empty create=ok " "first=8" # ----------------------------------------------------------------------- # 9. THE COLOUR DISTANCE, AND THE ERROR HANDLER. # # XmuDistinguishableColors is the one piece of this package that is floating # point: three differences of `unsigned short' fields promoted to double, # squared and summed against 10000^2 = 1e8. The threshold is `<=', so a # distance of EXACTLY 1e8 is not distinguishable, and the three fixtures sit # either side of it by one unit of the sum rather than by a comfortable margin # -- a rounding error anywhere in the promotion or the multiply moves the # answer, which a generously separated pair would hide. xmu_line libxmu/distinct-at "XMU DISTINCT exactly-at-threshold=" "0" xmu_line libxmu/distinct-above "XMU DISTINCT one-above=" "1" xmu_line libxmu/distinct-below "XMU DISTINCT one-below=" "0" # Three colours where the too-close pair is the SECOND and THIRD, so a routine # that only compared each against the first would call this set # distinguishable. The nested loop is the whole of the function and this is # the only case that reaches its inner half. xmu_line libxmu/distinct-pair "XMU DISTINCT non-adjacent-pair=" "0" # The degenerate counts are the loop's boundary rather than a colour question: # with fewer than two colours there is no pair, and True is the documented # answer. n0 also drives `count - 1' negative, which is where a rewrite using # an unsigned index would wrap and read the whole heap. xmu_line libxmu/distinct-degenerate "XMU DISTINCT n1=" "1 n0=1" # XmuSimpleErrorHandler over an XErrorEvent built by hand. ONLY THE THREE # IGNORE ARMS ARE REACHABLE, and that is a property of the function rather # than a limitation of the probe: each returns 0 before the Display is # touched, and every other input falls through to XmuPrintDefaultErrorMessage, # which reads dpy->ext_procs and NextRequest(dpy) directly. # # So THE NEGATIVE CONTROLS ARE NOT RUN -- the same request code with the wrong # error code, which would prove the switch discriminates on both fields rather # than forgiving the opcode outright. Case libxmu/errh-not-run records that # absence explicitly instead of leaving a reader to assume they passed. xmu_line libxmu/errh-querytree "XMU ERRH querytree-badwindow=" "0" xmu_line libxmu/errh-getattrs "XMU ERRH getwindowattributes-badwindow=" "0" xmu_line libxmu/errh-getgeom "XMU ERRH getgeometry-baddrawable=" "0" # The opcodes and error codes the switch is written in, read out of the # INSTALLED and . Without this the three cases above # would pass just as well against a header whose numbering had moved, since # the probe and the library would both have moved with it. xmu_line libxmu/errh-opcodes "XMU ERRH opcodes " \ "querytree=15 getwindowattributes=3 getgeometry=14 badwindow=3 baddrawable=9" xmu_line libxmu/errh-not-run "XMU ERRH not-run=" "printdefault,mismatched-pairs" # The display half, named by address at build time. This asserts ONE thing -- # that the archive still contains all twelve -- and it is worth having because # the alternative is finding out from a consumer's link months later. It is # NOT a claim that any of them works. xmu_line libxmu/linked-display-arm "XMU LINKED " \ "display-arm=12 absent=0 called=no" # ----------------------------------------------------------------------- # 10. THE TWO ARCHIVES AGREE. # # CursorName.c and Lower.c are compiled into BOTH libXmu.a and libXmuu.a from # one source tree, so the same entry points are reached here through two # different archives in two separately linked binaries. Two archives built # from one tree can still disagree -- a stale object, a different # AM_CPPFLAGS, one of them relinked against a dependency that moved -- and # that disagreement reaches a consumer as an inexplicable behaviour difference # between -lXmu and -lXmuu. # # Compared as WHOLE TABLES rather than spot values: the 16 rows are the # strongest thing either binary emits, and diffing them costs nothing here. a=$(sed -n 's/^XMU LOWER //p;' "$work/out") b=$(sed -n 's/^XMUU LOWER //p;' "$work/outu") check_eq libxmu/pair-lower-agree "$a" "$b" a=$(sed -n 's/^XMU UPPER //p;' "$work/out") b=$(sed -n 's/^XMUU UPPER //p;' "$work/outu") check_eq libxmu/pair-upper-agree "$a" "$b" a=$(sed -n 's/^XMU CMP //p' "$work/out") b=$(sed -n 's/^XMUU CMP //p' "$work/outu") check_eq libxmu/pair-cmp-agree "$a" "$b" # The cursor spot values, restated from the Xmuu side. The full census runs # only in libxmu-probe; what this settles is that the copy of CursorName.o in # the OTHER archive answers the same way. xmu_line libxmu/pair-cursor "XMUU CURSOR " "xterm=152 arrow=2 watch=150" "$work/outu" xmu_line libxmu/pair-cursor-fold "XMUU CURSOR-FOLD " "upper=152 mixed=108" "$work/outu" xmu_line libxmu/pair-cursor-reject "XMUU CURSOR-REJECT " "unknown=-1 empty=-1" "$work/outu" xmu_line libxmu/pair-ncopy "XMUU NCOPY7 " "lower='center' upper='CENTER'" "$work/outu" # size == 1 leaves the empty string; size <= 0 touches nothing. The three # arms are one `if' and one loop condition in XmuNCopyISOLatin1Lowered, and # the converters above rely on all three. xmu_line libxmu/ncopy1-u "XMUU NCOPY1 " "lower=''" "$work/outu" xmu_line libxmu/ncopy0-u "XMUU NCOPY0 " "lower='sentinel'" "$work/outu" xmu_line libxmu/ncopyneg-u "XMUU NCOPYNEG " "lower='sentinel'" "$work/outu" # ----------------------------------------------------------------------- # XmuGetHostname and XmuSnprintf, which are Lower.c's and GetHost.c's # remaining halves and reach the target libc rather than libXmu. # # NOTHING IS RESOLVED here -- no NSS module is loaded and no packet leaves -- # which is what makes this answerable where libSM's SmsGenerateClientID is not. # # WHAT the name is, is not libXmu's business and is not this image's # /etc/hostname either: busybox init's sysinit is `mount -t tmpfs' plus # run-postinsts and nothing applies /etc/hostname, so the UTS nodename stays # the runtime's own default. Score the shim's CONTRACT -- gethostname's answer, # NUL-terminated, with strlen returned -- against the nodename the guest itself # reports, which is the same uname(2) field gethostname reads. # # The rc is in the grep prefix's REMAINDER, never in the prefix: a prefix # carrying the expected value matches nothing when the value differs, so the # red reports an empty `got:' instead of what the probe actually said. hn_sys=$(uname -n 2>/dev/null) xmu_line libxmu/hostname "XMUU HOSTNAME rc=" \ "${#hn_sys} name='$hn_sys' terminated=yes" "$work/outu" # The truncating arm, which is the whole reason the shim exists: SUSv3's # gethostname does not promise termination when the name does not fit, and # XmuGetHostname forces buf[maxlen-1] = '\0' after it. WHAT the three # surviving bytes are is glibc's business rather than libXmu's, so only the # length is scored -- the assertion is that the buffer is bounded and # terminated, not what landed in it. hn4=$(sed -n 's/^XMUU HOSTNAME4 .*len=//p' "$work/outu") if [ "${hn4:-x}" -le 3 ] 2>/dev/null; then bst_ok libxmu/hostname-truncated else bst_notok libxmu/hostname-truncated \ "len=${hn4:-absent}, expected not more than 3 in a 4-byte buffer"; fi # XmuSnprintf goes through the target libc's VARARGS path, which on this arm # is a wasm calling convention the build host does not share. It returns # vsnprintf's value, so on truncation that is the length the output WOULD have # had and not the length written -- a caller advancing a cursor by it walks # off the end of its own buffer if that contract is not honoured. xmu_line libxmu/snprintf-fit "XMUU SNPRINTF fit " "rc=4 s='ab-7'" "$work/outu" xmu_line libxmu/snprintf-trunc "XMUU SNPRINTF trunc " \ "rc=10 s='0123456' len=7" "$work/outu" # %ld with the ILP32 minimum, which is where a varargs slot of the wrong width # would show as a wrong number rather than as a crash. xmu_line libxmu/snprintf-long "XMUU SNPRINTF long " \ "rc=11 s='-214748'" "$work/outu" xmu_line libxmu/snprintf-zero "XMUU SNPRINTF zero " "rc=0 s='keep'" "$work/outu" xmu_line libxmu/pair-display-arm "XMUU DISPLAY-ARM " \ "clientwindow=linked errorhandler=linked called=no" "$work/outu" else bst_notok libxmu/probe-stage "cannot stage the probes from $XMT" fi # --------------------------------------------------------------------------- # 11. UPSTREAM'S OWN CHECK PROGRAM. # # test/EditResStream is the single check_PROGRAM libXmu ships, and it is # entirely display-free: it drives the editres protocol stream codec # (_XEditResPut8/16/32, _XEditResPutString8, _XEditResPutWidgetInfo and their # Get counterparts) over a buffer of its own. # # It is an assert(3) binary -- it exits 0 having proved everything, or it aborts # -- so it is ONE case and the detail is not recoverable from it. That is # upstream's design and not a gap here; the probe carries the granular half. # # It is worth running for something the probe does not cover: _XEditResGet32 # reads a 32-bit wire field into an `unsigned long', and upstream's own comment # says the test exists to check that the FULL long is written. That question has # a different answer on this arm, where long is 4 bytes, than on the LP64 # machine it was written for -- so this is the one case here whose subject is # the width of a long ON THE WIRE rather than in a struct. ers=$work/libxmu-editresstream if cp "$XMT/libxmu-editresstream" "$ers" 2>/dev/null && chmod +x "$ers" 2>/dev/null; then check libxmu/editres-stream "$ers" else bst_notok libxmu/editres-stage "cannot stage $XMT/libxmu-editresstream" fi rm -rf "$work"