. "$BST_LIB" # BST-TIMEOUT: 300 # one probe run plus ~130 shell extractions; the 60s default # is for suites that fork far less than this one does. # libXext 1.3.6 -- the X standard extension library (poky recipes-graphics/ # xorg-lib). See libxext_%.bbappend for what the port adds and why. # # --------------------------------------------------------------------------- # ALMOST NONE OF THIS LIBRARY CAN RUN ON THIS IMAGE, AND THAT IS THE POINT # # libXext is the client half of sixteen X extensions -- SHAPE, SYNC, DPMS, # MIT-SHM, DOUBLE-BUFFER and the rest of what ships with the core server -- and # essentially every entry point is a round trip: find_display(dpy), then a # request on a wire. THIS IMAGE HAS NO X SERVER. No display opens (section 6), # so XShapeQueryVersion and its ninety siblings are unreachable here -- not # untested today, unreachable by construction. # # A shell suite is therefore left saying that an archive and some headers # arrived, which is a statement about tar rather than about a cross compiler. # So the port builds the consumer libXext does not ship, and this suite drives # the parts that genuinely stand alone: # # the extension-info cache extutil.c, shared by all sixteen extensions # the SYNC 64-bit values XSync.c, the one arch-sensitive arithmetic here # # Both are real library code out of libXext.a, and both are exactly the kind of # thing that can be complete, installed and WRONG on a new architecture with # nothing else going red. # # WHY THE EXPECTATIONS ARE WRITTEN OUT HERE RATHER THAN DIFFED AGAINST x86-64. # 57-libxcb.test compares its probe against a build-host reference because its # question -- what a code generator emitted under cross -- has no absolute # answer. This one does. The cache is pointer bookkeeping with a documented # result for every case; the protocol constants are wire values fixed by the X # specification; the arithmetic is defined to the bit by syncconst.h. Each case # below states its answer outright, which is the sharper assertion and does not # rot when the build host moves. # # It would also be wrong for the lines that ARE arch-dependent -- hi is a # signed int and the seam it carries across is at 32 bits on both machines, but # `long' and a pointer are 4 bytes here and 8 there, so a blanket diff would # make agreement the defect somewhere. # # --------------------------------------------------------------------------- # READ A RED IN SECTION ORDER; THE FIRST SECTION TO GO RED LOCALISES THE DEFECT # # 1 the payload arrived packaging only # 2 the .pc resolves consumers find the headers at all # 3 the probe runs to its end libXext.a executes on this arm # 4 the extension-info cache extutil.c, all sixteen extensions # 5 the extension error handler what a client actually sees here # 6 the SYNC 64-bit arithmetic the arch-sensitive core # 7 the protocol constants the wire values # 8 the entry-point census every module linked out of the archive # 9 the display that is not there the documented no-server path # 10 System V shared memory the MIT-SHM platform gap # # A build where 3 passes and 6 does not has a word-size fault in the toolchain # rather than anything wrong with this recipe. One where 8 goes red has lost a # whole extension module -- the name in the red says which. 10 is EXPECTED red # in one direction only; see its own comment. # --------------------------------------------------------------------------- # 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_LIBXEXT_ROOT:-}" INC=$R/usr/include/X11/extensions LIB=$R/usr/lib PCD=$R/usr/lib/pkgconfig XT=$R/usr/libexec/libxext-tests work=${TMPDIR:-/tmp}/bst-libxext.$$ rm -rf "$work"; mkdir -p "$work" hasfile() { if [ -s "$2" ]; then bst_ok "$1"; else bst_notok "$1" "missing or empty: $2"; fi } # xe_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 is a section tag plus a case name, and # the case name is followed by a space that ends it. xe_line() { _l=$(grep -F -- "$2" "$work/out" 2>/dev/null | head -1) check_eq "$1" "$2$3" "$_l" } # --------------------------------------------------------------------------- # 0. THE CANARY, which is not an assertion about libXext 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 libxext/suite-canary # --------------------------------------------------------------------------- # 1. THE PAYLOAD. # # By name and not by count: /usr/include/X11/extensions is shared with xorgproto # and every other extension library, so a count taken here would start moving # the day the next port lands. These sixteen headers are libXext's OWN -- each # is the client API for one extension, and each is #included by name from some # consumer's translation unit, so a missing one fails somebody else's # do_compile rather than anything on this image. check_rc libxext/dir-extensions 0 test -d "$INC" hasfile libxext/hdr-Xext "$INC/Xext.h" hasfile libxext/hdr-extutil "$INC/extutil.h" hasfile libxext/hdr-shape "$INC/shape.h" hasfile libxext/hdr-sync "$INC/sync.h" hasfile libxext/hdr-dpms "$INC/dpms.h" hasfile libxext/hdr-XShm "$INC/XShm.h" hasfile libxext/hdr-Xdbe "$INC/Xdbe.h" hasfile libxext/hdr-XEVI "$INC/XEVI.h" hasfile libxext/hdr-Xcup "$INC/Xcup.h" hasfile libxext/hdr-MITMisc "$INC/MITMisc.h" hasfile libxext/hdr-multibuf "$INC/multibuf.h" hasfile libxext/hdr-security "$INC/security.h" hasfile libxext/hdr-Xge "$INC/Xge.h" hasfile libxext/hdr-XLbx "$INC/XLbx.h" hasfile libxext/hdr-Xag "$INC/Xag.h" hasfile libxext/hdr-xtestext1 "$INC/xtestext1.h" # The archive. This distro is static-only, so libXext.a is the whole delivery # and there must be no .so beside it -- one would mean the recipe had started # producing something nothing on this image can load. hasfile libxext/archive "$LIB/libXext.a" check_rc libxext/no-shared 1 test -e "$LIB/libXext.so.6" hasfile libxext/probe-shipped "$XT/libxext-probe" # extutil.h is the one header here that is not an extension's API but the # machinery all of them share, and XEXT_GENERATE_FIND_DISPLAY is the macro each # module instantiates to get its find_display(). Asserted on contents rather # than size: a truncated install would still be non-empty. check libxext/extutil-has-generator \ grep -q 'XEXT_GENERATE_FIND_DISPLAY' "$INC/extutil.h" check libxext/extutil-has-checkext \ grep -q 'XextCheckExtension' "$INC/extutil.h" # --------------------------------------------------------------------------- # 2. THE .pc -- how a consumer finds any of the above. # # NOT `require pkg-config'. require ENDS THE FILE when the tool is absent, and # everything this suite exists for comes after this section. Gating the probe on # a query tool would mean an image without pkg-config reported a clean skip for # the library it never exercised. So these cases skip individually and the file # runs on. hasfile libxext/pc-present "$PCD/xext.pc" # THE .pc IS ASSERTED ON ITS CONTENTS FIRST, AND THROUGH pkg-config SECOND. # Read directly, these three lines are true whatever else is installed; asked # through pkg-config they are true only if the packages xext.pc NAMES are also # on the image, which is a fact about the image rather than about this port. # Both are worth having, and separating them is what makes a red say which. check libxext/pc-requires-xextproto \ grep -q '^Requires: *xextproto' "$PCD/xext.pc" # x11 is a PRIVATE require, and correctly so: a consumer of the shared library # would not need it, but this distro is static-only, so every consumer here does # -- libXext.a calls into Xlib for every request it encodes (XInitExtension, # _XReply, LockDisplay) and would not link without it. check libxext/pc-requires-private-x11 \ grep -q '^Requires\.private: *x11' "$PCD/xext.pc" check libxext/pc-libs-name grep -q '\-lXext' "$PCD/xext.pc" # NOT `require pkg-config'. require ENDS THE FILE when the tool is absent, and # everything this suite exists for comes after this section. Gating the probe on # a query tool would mean an image without pkg-config reported a clean skip for # the library it never exercised. So these cases skip individually and the file # runs on. if command -v pkg-config >/dev/null 2>&1; then bst_ok libxext/pkg-config-present # The graph queries below resolve xext.pc's requires, so they answer about # xorgproto-dev and libx11-dev as much as about this port. Gated on both being # present, and gated by NAME, so that an image missing one reports which -- # rather than reporting `xext.pc is broken', which it would not be. if [ -f "$PCD/xextproto.pc" ] && [ -f "$PCD/x11.pc" ]; then bst_ok libxext/pc-deps-present check libxext/pc-exists pkg-config --exists xext check libxext/pc-validate pkg-config --validate xext check_eq libxext/pc-modversion 1.3.6 "$(pkg-config --modversion xext 2>/dev/null)" # PKG_CONFIG_ALLOW_SYSTEM_LIBS is required for the same reason # 57-xtrans.test records for its --cflags case: pkg-config SUPPRESSES a -L # naming a directory already on the linker's default path, so the bare query # answers usefully only for the -l part. Asked for the flags it COMPUTED, # the library name has to be there. check_out libxext/pc-libs -lXext \ env PKG_CONFIG_ALLOW_SYSTEM_LIBS=1 pkg-config --libs xext else bst_skip libxext/pc-deps-present \ "xext.pc requires xextproto and x11; missing on this image" fi else bst_skip libxext/pkg-config-present "pkg-config not installed on this image" fi # --------------------------------------------------------------------------- # 3. THE PROBE RUNS, AND RUNS TO ITS END. # # do_install ships it 0755, but the rootfs is read-only at browser runtime and # the exec bit is not reliably readable there either, so it is copied to /tmp -- # a mode=1777 tmpfs with no noexec -- and given the bit where the copy lands. probe=$work/libxext-probe if cp "$XT/libxext-probe" "$probe" 2>/dev/null && chmod +x "$probe" 2>/dev/null; then "$probe" >"$work/out" 2>"$work/err" rc=$? # The probe exits 0 whatever it measures -- every expectation lives in this # file, not in the binary -- so a non-zero status here means it did not RUN: a # trap, a missing import, an exec refusal. On this arm that is a real and # common failure and is what this case is for. if [ "$rc" -eq 0 ]; then bst_ok libxext/probe-runs else bst_notok libxext/probe-runs "rc=$rc $(_bst_1line "$(cat "$work/err")")"; fi total=$(sed -n 's/^XEXT-TOTAL //p' "$work/out") if [ -n "$total" ]; then bst_ok libxext/probe-complete else bst_notok libxext/probe-complete \ "no XEXT-TOTAL line: $(_bst_1line "$(cat "$work/out")")"; fi # The measurement count, bounded from below. Adding a fixture raises it; a # probe that got THINNER while still terminating cleanly is what this catches, # and nothing else here would -- every case below greps for what it expects, # so a line that stopped being printed is indistinguishable from one whose # grep simply found nothing. if [ -n "$total" ] && [ "$total" -ge 150 ]; then bst_ok libxext/probe-coverage else bst_notok libxext/probe-coverage \ "reported ${total:-0} measurements, expected not less than 150"; fi # The version the archive was built from, reported by the binary rather than # read off a path, so a stale probe left behind by an earlier build cannot # pass for this one. xe_line libxext/probe-version "XEXT-VERSION " "1.3.6" # ------------------------------------------------------------------------- # 4. THE EXTENSION-INFO CACHE (extutil.c). # # One list and one one-entry cache, shared by all sixteen extensions through # XEXT_GENERATE_FIND_DISPLAY. A fault here is a fault in every extension at # once and would surface only with two displays open, which on this image is # never -- so it would ship silently and break the first real X client. # # The Display* values are opaque tokens the probe never loads through; see the # probe's header for why that is legitimate for these five functions and for # nothing else in libXext. # A fresh descriptor. XextCreateExtension mallocs and zeroes three fields, and # the two lookups below are the empty-list arms of the walk. xe_line libxext/cache-fresh-n "XEXT-CACHE fresh-ndisplays " "0" xe_line libxext/cache-fresh-head "XEXT-CACHE fresh-head " "NULL" xe_line libxext/cache-fresh-cur "XEXT-CACHE fresh-cur " "NULL" xe_line libxext/cache-find-empty "XEXT-CACHE find-on-empty " "NULL" # XextRemoveDisplay's own comment calls this `hmm, actually an error'; 0 is # nonetheless what it returns and what every caller sees. xe_line libxext/cache-remove-empty "XEXT-CACHE remove-on-empty " "0" xe_line libxext/cache-ndisplays "XEXT-CACHE ndisplays " "3" # The miss path walks the list, and the walk is what PROMOTES the entry into # the cache. The display looked up is the DEEPEST node, so this is the full # traversal rather than a head hit. xe_line libxext/cache-miss-walk "XEXT-CACHE miss-walk " "a" xe_line libxext/cache-miss-promote "XEXT-CACHE miss-promotes-cur " "a" # The two halves separated. cache-only empties the list, so only extinfo->cur # can answer; list-only clears the cache, so only the walk can -- and it must # re-promote what it found. A build that ignored the cache would pass a plain # repeated lookup and fail cache-only. xe_line libxext/cache-only "XEXT-CACHE cache-only " "a" xe_line libxext/cache-list-only "XEXT-CACHE list-only " "a" xe_line libxext/cache-list-repro "XEXT-CACHE list-only-repromotes " "a" # A display that was never added, asked for while the cache is live. NULL is # what turns into XextAddDisplay in the generated find_display, so a false # positive here would hand an extension somebody else's codes. xe_line libxext/cache-find-absent "XEXT-CACHE find-absent " "NULL" xe_line libxext/cache-absent-cur "XEXT-CACHE absent-leaves-cur " "a" # Removing the CACHED entry must flush the cache (extutil.c:201). If it did # not, the next lookup for that display would hand back a freed node -- a # use-after-free reachable from any client that closes one of two displays. xe_line libxext/cache-remove-cached "XEXT-CACHE remove-cached " "1" xe_line libxext/cache-remove-flush "XEXT-CACHE remove-flushes-cur " "NULL" xe_line libxext/cache-remove-n "XEXT-CACHE after-remove-ndisplays " "2" xe_line libxext/cache-find-removed "XEXT-CACHE find-removed " "NULL" xe_line libxext/cache-remove-twice "XEXT-CACHE remove-twice " "0" # Unlinking from the middle of the list rather than the head -- the other # branch of the same loop, and the one a `prev' handled wrongly would corrupt. xe_line libxext/cache-remove-middle "XEXT-CACHE remove-middle " "1" xe_line libxext/cache-head-after "XEXT-CACHE head-after-middle " "c" xe_line libxext/cache-find-c "XEXT-CACHE find-c " "c" xe_line libxext/cache-final-n "XEXT-CACHE final-ndisplays " "1" # XextHasExtension is the guard every entry point opens with, and it is what # turns `the server does not have this' into the documented return value. It # is false for a NULL info and for an entry whose codes were never filled in # -- which is the state this image would leave every extension in, if a # display could be opened at all. xe_line libxext/cache-has-null "XEXT-CACHE has-null " "0" xe_line libxext/cache-has-no-codes "XEXT-CACHE has-no-codes " "0" xe_line libxext/cache-destroy-n "XEXT-CACHE destroy-ndisplays " "1" xe_line libxext/cache-destroyed "XEXT-CACHE destroyed " "ok" # ------------------------------------------------------------------------- # 5. THE EXTENSION ERROR HANDLER (extutil.c). # # XMissingExtension is what a client SEES when an extension is absent, which # on this image is every extension on every display -- so it is the one # libXext path a brintOS user is guaranteed to reach, and the only one whose # on-target behaviour is a user-visible contract rather than an internal one. # ZEROINIT'd NULL in globals.c:70. This case is also the only evidence that # globals.c linked at all -- nothing else in the archive references it. xe_line libxext/err-initial "XEXT-ERR previous " "NULL" # The handler's return value is passed through, unexamined. xe_line libxext/err-rc "XEXT-ERR rc " "42" xe_line libxext/err-calls "XEXT-ERR calls " "1" xe_line libxext/err-name "XEXT-ERR name " "SHAPE" # X_EXTENSION_MISSING. Asserted as the literal a client's handler receives, # rather than by re-reading the header, because that string IS the contract. xe_line libxext/err-reason "XEXT-ERR reason " "missing" # A NULL extension name is substituted for (X_EXTENSION_UNKNOWN) rather than # passed through -- so a handler may print it without checking. xe_line libxext/err-null-name "XEXT-ERR null-name " "unknown" xe_line libxext/err-null-calls "XEXT-ERR null-name-calls " "2" # Installing NULL restores the DEFAULT handler rather than disabling dispatch # (`handler ? handler : _default_exterror'), so the previous-handler chain has # to come back non-NULL and be something other than the probe's own. xe_line libxext/err-round-trip "XEXT-ERR round-trip " "same" xe_line libxext/err-null-def "XEXT-ERR null-installs-default " "set" xe_line libxext/err-def-other "XEXT-ERR default-is-not-probe " "other" # ------------------------------------------------------------------------- # 6. THE SYNC 64-BIT VALUES (XSync.c). # # The only arithmetic in libXext, and the only thing in it whose answer could # differ between the LP64 build host and this ILP32 target. XSyncValue is # { int hi; unsigned int lo; } and every operation carries or borrows across # the 32-bit seam by hand (syncconst.h:102-119). # # EACH OPERATION IS RUN TWICE -- as the header macro, compiled here by # whichever compiler built the probe, and as the LIBRARY FUNCTION out of # libXext.a. syncconst.h:124-127 says the function is uncovered by #undef'ing # the macro, and the distinction is what makes this a statement about the # PORT: a probe that omitted the #undef would test the header and pass # cleanly over an archive built for the wrong word size. xe_line libxext/sync-macro-int "XEXT-SYNC macro-int-to-value " "hi=-1 lo=4294967295" xe_line libxext/sync-macro-ints "XEXT-SYNC macro-ints-to-value " "hi=0 lo=4294967295" xe_line libxext/sync-macro-max "XEXT-SYNC macro-max " "hi=2147483647 lo=4294967295" xe_line libxext/sync-macro-min "XEXT-SYNC macro-min " "hi=-2147483648 lo=0" xe_line libxext/sync-fn-int "XEXT-SYNC fn-int-to-value " "hi=-1 lo=4294967295" xe_line libxext/sync-fn-ints "XEXT-SYNC fn-ints-to-value " "hi=0 lo=4294967295" xe_line libxext/sync-fn-max "XEXT-SYNC fn-max " "hi=2147483647 lo=4294967295" xe_line libxext/sync-fn-min "XEXT-SYNC fn-min " "hi=-2147483648 lo=0" # And the two arms must AGREE. The four cases above pin each side to the # documented value, which already implies this; it is asserted separately so # that a divergence reports as a divergence -- `the archive and the header do # not compute the same thing' is a different defect, with a different cause, # from `both are wrong in the same way'. for f in int-to-value ints-to-value max min; do _m=$(sed -n "s/^XEXT-SYNC macro-$f //p" "$work/out") _f=$(sed -n "s/^XEXT-SYNC fn-$f //p" "$work/out") if [ -n "$_m" ] && [ "$_m" = "$_f" ]; then bst_ok "libxext/sync-agree-$f" else bst_notok "libxext/sync-agree-$f" "macro:'$_m' fn:'$_f'"; fi done # The carry. 0xffffffff + 1 must move a bit across the seam into hi, and must # NOT report overflow: both operands are non-negative and so is the result. A # build that dropped the carry would answer hi=0 lo=0 -- which is zero, and # which not one comparison below would notice. xe_line libxext/sync-add-carry "XEXT-SYNC add-carry " "hi=1 lo=0 ovf=0" # The carry into a NEGATIVE high half: -1 + 1 is exactly zero. hi is signed # here, so the increment crosses from -1 to 0 while lo wraps. xe_line libxext/sync-add-neg "XEXT-SYNC add-negative " "hi=0 lo=0 ovf=0" # The borrow. 1 - 0xffffffff = -4294967294, which is hi=-1 lo=2. # # ovf comes out 1 and that is UPSTREAM'S SIGN TEST, not this arm's # arithmetic: _XSyncValueSubtract reuses the ADDITION's overflow condition # (signa == signb && sign(result) != signa), which is wrong for a subtraction # -- two non-negative operands can legitimately give a negative difference. # The result is correct, the flag is upstream's, and it is the same on every # architecture. Pinned as what the code does rather than as what it should do; # this suite is not the place to correct upstream, and a red here would mean # the arithmetic moved rather than that the bug was fixed. xe_line libxext/sync-sub-borrow "XEXT-SYNC sub-borrow " "hi=-1 lo=2 ovf=1" # The borrow the other way: 2^32 - 1. hi goes 1 -> 0 as lo wraps down. xe_line libxext/sync-sub-seam "XEXT-SYNC sub-seam " "hi=0 lo=4294967295 ovf=0" # The comparisons, on a value whose hi is negative. hi is a SIGNED int, so -1 # must order below 1; a build that compared it as unsigned would get all six # of these backwards and every SYNC alarm trigger with it. xe_line libxext/sync-lt "XEXT-SYNC lt " "1" xe_line libxext/sync-gt "XEXT-SYNC gt " "0" xe_line libxext/sync-le "XEXT-SYNC le " "1" xe_line libxext/sync-ge "XEXT-SYNC ge " "1" xe_line libxext/sync-eq "XEXT-SYNC eq " "1" xe_line libxext/sync-ne "XEXT-SYNC ne " "0" xe_line libxext/sync-min-neg "XEXT-SYNC min-negative " "1" xe_line libxext/sync-min-pos "XEXT-SYNC min-positive " "0" xe_line libxext/sync-max-neg "XEXT-SYNC max-negative " "0" xe_line libxext/sync-max-pos "XEXT-SYNC max-positive " "1" xe_line libxext/sync-min-lt-max "XEXT-SYNC min-lt-max " "1" xe_line libxext/sync-zero-is-zero "XEXT-SYNC zero-is-zero " "1" # Zero is POSITIVE by this predicate -- _XSyncValueIsPositive is the negation # of the sign bit, not a test against zero. Pinned because it is surprising # and because a "corrected" implementation would break every caller that # relies on IsPositive and IsNegative partitioning the whole range. xe_line libxext/sync-zero-is-pos "XEXT-SYNC zero-is-positive " "1" # The wire split: every SYNC request sends a value as _lo and _hi, and this is # the pair of accessors that produce them. xe_line libxext/sync-split "XEXT-SYNC split " "lo=3735928559 hi=-2" # Eight bytes on both machines, and this is the one number in this section # where agreement with the build host is REQUIRED rather than incidental: the # struct is two fixed-width halves, so a wasm32 build that made it anything # else would be putting a different shape on the wire. xe_line libxext/sync-sizeof "XEXT-SYNC sizeof-value " "8" # ------------------------------------------------------------------------- # 7. THE PROTOCOL CONSTANTS. # # Wire values: a client that disagrees with a server about ShapeBounding does # not fail to build, it corrupts a window. Each is stated from the published # X11 protocol specification rather than diffed against anything -- there is # nothing about a second machine that could make an answer here more true. xe_line libxext/const-shape-name "XEXT-CONST SHAPENAME " "SHAPE" xe_line libxext/const-shape-major "XEXT-CONST SHAPE_MAJOR " "1" xe_line libxext/const-shape-minor "XEXT-CONST SHAPE_MINOR " "1" # The region operations, in the order the SHAPE specification numbers them. # These are the argument to XShapeCombineRegion and friends. xe_line libxext/const-shape-set "XEXT-CONST ShapeSet " "0" xe_line libxext/const-shape-union "XEXT-CONST ShapeUnion " "1" xe_line libxext/const-shape-intersect "XEXT-CONST ShapeIntersect " "2" xe_line libxext/const-shape-subtract "XEXT-CONST ShapeSubtract " "3" xe_line libxext/const-shape-invert "XEXT-CONST ShapeInvert " "4" # The three shape KINDS -- which of a window's shapes is being set. xe_line libxext/const-shape-bounding "XEXT-CONST ShapeBounding " "0" xe_line libxext/const-shape-clip "XEXT-CONST ShapeClip " "1" xe_line libxext/const-shape-input "XEXT-CONST ShapeInput " "2" xe_line libxext/const-shape-notify "XEXT-CONST ShapeNotify " "0" xe_line libxext/const-shape-notify-mask "XEXT-CONST ShapeNotifyMask " "1" xe_line libxext/const-shape-nevents "XEXT-CONST ShapeNumberEvents " "1" xe_line libxext/const-sync-name "XEXT-CONST SYNC_NAME " "SYNC" xe_line libxext/const-sync-major "XEXT-CONST SYNC_MAJOR " "3" xe_line libxext/const-sync-minor "XEXT-CONST SYNC_MINOR " "1" xe_line libxext/const-dpms-name "XEXT-CONST DPMSName " "DPMS" xe_line libxext/const-dpms-major "XEXT-CONST DPMS_MAJOR " "1" xe_line libxext/const-dpms-minor "XEXT-CONST DPMS_MINOR " "2" xe_line libxext/const-dpms-on "XEXT-CONST DPMSModeOn " "0" xe_line libxext/const-dpms-standby "XEXT-CONST DPMSModeStandby " "1" xe_line libxext/const-dpms-suspend "XEXT-CONST DPMSModeSuspend " "2" xe_line libxext/const-dpms-off "XEXT-CONST DPMSModeOff " "3" # The extension NAMES, which are what goes into QueryExtension on the wire. # Several are historical and none of them is guessable -- "MIT-SUNDRY- # NONSTANDARD" and "Extended-Visual-Information" are exactly as spelled here, # and a client that spells one differently simply never finds the extension. xe_line libxext/const-shm-name "XEXT-CONST SHMNAME " "MIT-SHM" xe_line libxext/const-dbe-name "XEXT-CONST DBE_NAME " "DOUBLE-BUFFER" xe_line libxext/const-dbe-major "XEXT-CONST DBE_MAJOR " "1" xe_line libxext/const-dbe-minor "XEXT-CONST DBE_MINOR " "0" xe_line libxext/const-evi-name "XEXT-CONST EVINAME " "Extended-Visual-Information" xe_line libxext/const-cup-name "XEXT-CONST XCUPNAME " "TOG-CUP" xe_line libxext/const-mitmisc-name "XEXT-CONST MITMISCNAME " "MIT-SUNDRY-NONSTANDARD" xe_line libxext/const-multibuf-name "XEXT-CONST MULTIBUF_NAME " "Multi-Buffering" xe_line libxext/const-security-name "XEXT-CONST SECURITY_NAME " "SECURITY" xe_line libxext/const-ge-name "XEXT-CONST GE_NAME " "Generic Event Extension" # The two strings section 5 measured coming back out of XMissingExtension. xe_line libxext/const-missing "XEXT-CONST X_EXTENSION_MISSING " "missing" xe_line libxext/const-unknown "XEXT-CONST X_EXTENSION_UNKNOWN " "unknown" # ------------------------------------------------------------------------- # 8. THE ENTRY-POINT CENSUS. # # Section 9 establishes that no display opens here, which makes every # round-trip entry point unreachable -- so the only thing left to say about # them is that they EXIST: that the cross build compiled each module, that the # static linker resolved each name out of libXext.a, and that the address is # in the shipped image. Taking the address is what forces the archive member # in, so a module the build had silently dropped fails the LINK in do_compile, # naming the symbol that went missing. # # Checked here by COUNT and by a sample of names, not by re-listing ninety-six # of them: the count is what notices a module leaving, and the recipe's own # LIBXEXT_MIN_ENTRY_POINTS floor is what notices the probe's table shrinking # to match. The named ones below are one per extension module -- the census is # only as good as its coverage of MODULES, and a count alone cannot say that # SHAPE and SYNC are both still in it. nsym=$(sed -n 's/^XEXT-SYM-COUNT //p' "$work/out") if [ -n "$nsym" ] && [ "$nsym" -ge 96 ]; then bst_ok libxext/sym-count else bst_notok libxext/sym-count \ "census names ${nsym:-0} entry points, expected not less than 96"; fi xe_line libxext/sym-none-null "XEXT-SYM-NULL " "0" # One per module. A red here says which extension left, which a count cannot. for s in XextFindDisplay XShapeQueryVersion XSyncInitialize DPMSGetVersion \ XShmAttach XdbeSwapBuffers XeviQueryVersion XcupQueryVersion \ XMITMiscGetBugMode XmbufGetVersion XSecurityQueryExtension \ XGEQueryVersion; do xe_line "libxext/sym-$s" "XEXT-SYM $s " "linked" done # ------------------------------------------------------------------------- # 9. THE DISPLAY THAT IS NOT THERE. # # The documented no-server path, and the reason sections 4 to 8 are what this # suite tests instead of the extension APIs: libXext's API begins at a # Display, Xlib is the only thing that makes one, and on this image it cannot. # # What must hold is that it SAYS so -- NULL, for each spelling of a display -- # rather than crashing, blocking, or handing back a half-built Display that # the first XShapeQueryVersion would then walk into. The last case is the one # that distinguishes a clean refusal from a hang: the probe reached its end. # # Note what is NOT here. No entry point is called with a NULL Display: every # one of them opens with find_display(dpy), which reaches XInitExtension and # dereferences, so that would be undefined behaviour rather than a documented # failure, and a probe that crashed there would be reporting its own mistake. xe_line libxext/dpy-no-env "XEXT-DPY no-env " "NULL" xe_line libxext/dpy-unix-0 "XEXT-DPY unix-0 " "NULL" xe_line libxext/dpy-unix-99 "XEXT-DPY unix-99 " "NULL" xe_line libxext/dpy-tcp "XEXT-DPY tcp " "NULL" xe_line libxext/dpy-end "XEXT-DPY reached-end " "yes" # ------------------------------------------------------------------------- # 10. SYSTEM V SHARED MEMORY -- THE MIT-SHM PLATFORM GAP. # # THIS CASE IS EXPECTED RED IN ONE DIRECTION AND IS NOT A PORT DEFECT. # # XShmAttach is the client half of a bargain whose other half is a SysV shared # memory segment that both the client and the server map. libXext ships that # code and it links (section 8), but the segment cannot be created on this # image: brintOS's kernel does not implement the System V IPC calls, so # shmget fails ENOSYS -- brintos/linux#31. # # It is measured rather than worked around so that the day #31 lands, the red # appears HERE, on a case whose entire content is the gap, instead of # somewhere downstream a year later. When that happens the two lines below are # what change, and MIT-SHM becomes usable for the first time. xe_line libxext/shm-shmget "XEXT-SHM shmget " "rc=-1 errno=ENOSYS" xe_line libxext/shm-shmat "XEXT-SHM shmat " "rc=-1 errno=skipped" else bst_notok libxext/probe-stage "cannot stage $XT/libxext-probe" fi rm -rf "$work"