. "$BST_LIB" # BST-TIMEOUT: 300 # NOT MEASURED ON TARGET YET. One probe run plus ~120 shell # extractions -- the shape of 57-libxtst.test, which # carries the same 300 for ~130 of them. Replace this note # with a measured elapsed the first time the suite runs on # target. # libXScrnSaver 1.2.4 -- the client half of MIT-SCREEN-SAVER (poky/meta # recipes-graphics/xorg-lib). See libxscrnsaver_%.bbappend for what the port # adds and why. # # --------------------------------------------------------------------------- # NOTHING HERE HAS RUN ON THIS TARGET YET -- BUT MOST OF IT HAS RUN SOMEWHERE # # Every expectation below is DERIVED FROM SOURCE: libXScrnSaver 1.2.4's # src/XScrnSaver.c, libX11 1.8.9's src/InitExt.c, libXext 1.3.6's # src/extutil.c and include/X11/extensions/extutil.h, and the staged xorgproto # saver.h / saverproto.h. This file was written in a phase that builds at recipe # scope only and never boots an image, so NO VALUE IN IT IS A FINDING ABOUT THIS # IMAGE. The first on-target run is what turns these into results, and a red # should be read as this file having been wrong until the case is checked # against the source again. # # Two reference builds were run to keep the derivation honest, and it is worth # being precise about what each one does and does not settle. Neither is a # wasm32-hwjs run; both are x86-64 host builds of the same sources. # # AN ILP32 REFERENCE (gcc -m32) over libXScrnSaver's own scrnsaver.h and the # STAGED xorgproto headers confirmed every V and A value below, value for # value -- 23 constants and 27 layout numbers. That matters because this arm # is ILP32 too, so the arithmetic group A encodes is the arithmetic that # reference performed. It is still not a measurement of THIS toolchain's # struct layout, which is the gap the on-target run closes. # # A STATIC x86-64 REFERENCE linked the probe exactly as the recipe does -- # the probe's object first, then libXss.a and libX11.a by path -- and ran it. # It linked with no duplicate symbol, took no TRAP, resolved all eleven census # entries and reached PROBE-END, and confirmed all 48 behavioural # expectations: every N, X, I, R, U and L case below. The static link is the # point: it is the same shape as the target's, so unlike a shared-library # reference it exercises the same XQueryExtension interposition the method # depends on. # # What it does NOT settle is group A, because that host is LP64 -- it answers # 40 and 72 for the two structures where this arm should say 24 and 40. That # is the ILP32 reference's half. # # The reference run also EARNED ITS KEEP by finding two cases that were wrong: # R02 and X06 compared a memset byte pattern against a 32-bit literal, which # made them accidental assertions about word width rather than about a structure # being writable and a refusal leaving a caller's buffer alone. Both are now # compared against a value of the same type filled with the same byte. # # --------------------------------------------------------------------------- # THE EXTENSION CANNOT REACH A SERVER HERE, AND THE SHAPE OF THE REFUSAL IS # WHAT IS MEASURED # # MIT-SCREEN-SAVER is a server-side extension: it reports how long the server # has been idle and lets a client register its own screen-saver window. This # image has no X server -- 57-libx11 (test plan section 631) measures # XOpenDisplay returning NULL in four forms, and this suite does not repeat it. # # So no call completes. What is NOT uniform, and is executable, is HOW each of # the eleven entry points declines: # # R ONE NEVER TOUCHES A DISPLAY. XScreenSaverAllocInfo has no dpy parameter # at all -- it is Xmalloc(sizeof(XScreenSaverInfo)). Executed in full. # # N ONE REFUSES WITHOUT RAISING. XScreenSaverQueryExtension has no # XextCheckExtension guard; it tests XextHasExtension itself and returns # False from its own `else'. Nothing is raised, and that is the whole # difference between it and the six below. # # X SIX REFUSE THROUGH A GUARD THAT RAISES. QueryVersion and QueryInfo take # ScreenSaverCheckExtension; SelectInput, SetAttributes, UnsetAttributes # and Suspend take ScreenSaverSimpleCheckExtension. Both expand to # XextCheckExtension, which calls XMissingExtension and returns before # LockDisplay. # # U AND THREE HAVE NO EXTENSION GUARD AT ALL. XScreenSaverRegister, # XScreenSaverUnregister and XScreenSaverGetRegistered do not speak the # extension protocol -- they read and write the root-window property # _MIT_SCREEN_SAVER_ID via XInternAtom / XChangeProperty / # XGetWindowProperty, never consulting find_display. Nothing refuses them: # their first act is an Xlib round trip, and RootWindow(dpy,screen) loads # through the Display before even that. They are named in the probe's # census and never called, and recorded below as skips carrying that # reason. Calling one would not measure a refusal; it would fault. # # The probe installs an extension-error handler, so "returned 0" and "returned 0 # having raised the missing-extension error" are DIFFERENT measurements -- and # so that Xlib's default handler, which prints and exits, does not end the run # at the first guarded call. # # --------------------------------------------------------------------------- # HOW THE GUARDS ARE REACHED, AND THE CASE EVERYTHING RESTS ON # # Every path runs find_display, whose cache-miss arm is XextAddDisplay -> # XInitExtension -> XQueryExtension. XInitExtension calls XQueryExtension as its # FIRST act and returns NULL when it answers False, before any LockDisplay -- so # a stub XQueryExtension stops the library short of the socket. The probe # DEFINES XQueryExtension; in a static link that definition is taken from the # probe's object while libX11's QuExt.o, which holds that function and nothing # else, is never pulled. # # If that link-order argument were wrong, the real XQueryExtension would run # over a Display with no socket and the fault would take the guest's console # down with it -- on an image several tickets share. It cannot. Every path into # Xlib's request machinery begins with LockDisplay; the probe supplies the # Display's lock_fns; and before each call the trap is armed with the number of # stub answers that must have arrived before any lock is legitimate. A lock that # comes too early prints `TRAP ...', prints PROBE-ABORT instead of PROBE-END, # and exits 0. So a red on libxscrnsaver/no-trap with the X and N cases absent # is the METHOD failing safely, not the library failing -- and probe-complete # says so in the same run. # # Exactly one lock is legitimate, and only on the first call: once # XInitExtension has returned NULL, XextAddDisplay's else-branch runs # XAddExtension (which locks) and XESetCloseDisplay, because libXScrnSaver's # hook table sets close_display. Every later call hits the cache and returns at # the guard. # # AND THE TRAP MEASURES ITSELF -- libxscrnsaver/trap-live below. LockDisplay is # `if ((d)->lock_fns) ...' only in the threaded Xlibint.h; where threads are # compiled out the macro is empty and the trap is inert all run. A suite that # reported the safety property without checking whether it existed would be # claiming something it had not measured, so the lock count is scored. PROBE=${BST_LIBXSCRNSAVER_PROBE:-/usr/libexec/libxscrnsaver-tests/libxscrnsaver-probe} ARCHIVE=/usr/lib/libXss.a PCFILE=/usr/lib/pkgconfig/xscrnsaver.pc HDR=/usr/include/X11/extensions/scrnsaver.h HDR_PROTO=/usr/include/X11/extensions/saver.h # 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 -- every expectation below is derived from THIS version's source. WANT_VERSION=1.2.4 # 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. bst_ok libxscrnsaver/suite-canary if [ ! -f "$ARCHIVE" ]; then bst_skip libxscrnsaver/present "libxscrnsaver not installed on this image" exit 0 fi bst_ok libxscrnsaver/present # --- the package is whole ----------------------------------------------------- check libxscrnsaver/staticlib test -s "$ARCHIVE" check libxscrnsaver/pkgconfig test -s "$PCFILE" check libxscrnsaver/hdr test -s "$HDR" # The archive is named libXss.a while the recipe is libxscrnsaver and PROVIDES # libxss -- three names for one deliverable. A consumer links -lXss, so the # archive's name is the one that has to be right. bst_lib_shape libxscrnsaver/lib-shape '/usr/lib/libXss.so*' pcver=$(sed -n 's/^Version: *//p' "$PCFILE" 2>/dev/null | head -1) check_eq libxscrnsaver/pkgconfig-version "$WANT_VERSION" "$pcver" # xscrnsaver.pc must name what a consumer resolves through it. On a static-only # distro a missing entry is not a warning -- it is a link that fails in the # consumer, because there is no shared object to carry the dependency. Upstream # splits them: scrnsaverproto is public (a consumer compiles against its headers # through this file -- saver.h is where every constant group V asserts comes # from) and x11 / xext are private. Both halves matter here, since every link is # static and libXss.a calls into both. pcpub=$(sed -n 's/^Requires: *//p' "$PCFILE" 2>/dev/null | head -1) case "$pcpub" in *scrnsaverproto*) bst_ok libxscrnsaver/pkgconfig-requires-scrnsaverproto ;; *) bst_notok libxscrnsaver/pkgconfig-requires-scrnsaverproto "xscrnsaver.pc Requires does not name scrnsaverproto: '$pcpub'" ;; esac pcpriv=$(sed -n 's/^Requires\.private: *//p' "$PCFILE" 2>/dev/null | head -1) for want in x11 xext; do case " $pcpriv " in *" $want "*) bst_ok "libxscrnsaver/pkgconfig-requires-$want" ;; *) bst_notok "libxscrnsaver/pkgconfig-requires-$want" "xscrnsaver.pc Requires.private does not name $want: '$pcpriv'" ;; esac done # THE TICKET ASKS FOR TWO THINGS THIS ARM DOES NOT HAVE, AND THEY ARE RECORDED # AS SKIPS RATHER THAN FAKED. # # A SONAME. This distro is static-only: the recipe ships libXss.a and # FILES:${PN}'s ${libdir}/libXss.so.* matches nothing, so ${PN} is never emitted # and there is no shared object to carry a soname. The assertion has no subject # here. libxscrnsaver/lib-shape above is what survives of it -- whatever IS # shipped must be usable. bst_skip libxscrnsaver/soname "static-only distro: the recipe ships libXss.a and emits no shared object, so there is no soname to assert; lib-shape covers what is shipped" # # VERSION MACROS IN THE INSTALLED HEADER. scrnsaver.h defines NONE -- it is 134 # lines of two structs and eleven prototypes, with no package-version macro of # any kind. The macros that do exist, ScreenSaverMajorVersion and # ScreenSaverMinorVersion, are xorgproto's in saver.h and are the PROTOCOL # version (1.1); they have nothing to do with libXScrnSaver being 1.2.4 and # would not move if it were bumped. Asserting 1.2.4 against them would be # asserting a coincidence that does not hold. The package version is asserted # against xscrnsaver.pc above, which is where it actually lives, and the # protocol version is asserted separately as V03/V04 below. bst_skip libxscrnsaver/hdr-version-macros "scrnsaver.h defines no package-version macro; 1.2.4 is asserted against xscrnsaver.pc, and saver.h's ScreenSaverMajor/MinorVersion is the protocol version, asserted as V03/V04" # --- the premise: there is no X server on this image -------------------------- # Stated here rather than executed, because 57-libx11 owns the executed form # (section 631) and runs it last for a reason. These two are free and they fix # what the rest of this file means: with a display, groups N and X would be # measuring something else entirely. if [ -z "${DISPLAY:-}" ]; then bst_ok libxscrnsaver/no-display else bst_notok libxscrnsaver/no-display "DISPLAY is set to '$DISPLAY' on an image with no X server"; fi if [ ! -d /tmp/.X11-unix ]; then bst_ok libxscrnsaver/no-x-socket-dir else bst_notok libxscrnsaver/no-x-socket-dir "/tmp/.X11-unix exists"; fi # The ticket's second connection case -- DISPLAY pointing at an address nothing # is listening on, asserted to refuse rather than block -- is 57-libx11's # `libx11/open-tcp' (DISPLAY="127.0.0.1:99"), beside open-unixsock, open-badhost # and open-nodisplay. It is not repeated here: XOpenDisplay is Xlib's, it is # already measured in four distinguishable forms in section 631, and a second # copy on a shared image would be a second set of connect attempts measuring # what libx11 already measured. bst_skip libxscrnsaver/display-refused "XOpenDisplay against an unlistening address is 57-libx11's libx11/open-tcp (section 631), measured there in four distinguishable forms; not repeated on a shared image" # 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. Probing keeps this measuring # libXScrnSaver rather than measuring the image's grep. if echo x | grep -aq x 2>/dev/null; then _grepq="grep -aq"; else _grepq="grep -q"; fi # All ELEVEN, because eleven is the whole library -- scrnsaver.h declares eleven # and src/XScrnSaver.c defines eleven, so unlike libxvmc's split there is no # second archive and no dlopen trampoline to account for. The probe's link is # the exhaustive check; this is the part that survives the probe being absent. for sym in XScreenSaverQueryExtension XScreenSaverQueryVersion \ XScreenSaverAllocInfo XScreenSaverQueryInfo \ XScreenSaverSelectInput XScreenSaverSetAttributes \ XScreenSaverUnsetAttributes XScreenSaverRegister \ XScreenSaverUnregister XScreenSaverGetRegistered \ XScreenSaverSuspend; do if $_grepq "$sym" "$ARCHIVE" 2>/dev/null; then bst_ok "libxscrnsaver/sym-$sym" else bst_notok "libxscrnsaver/sym-$sym" "$sym absent from $ARCHIVE" fi done # The installed header must declare what a consumer compiles against -- the two # structures a caller BUILDS or receives as well as the calls. for decl in XScreenSaverQueryExtension XScreenSaverQueryVersion \ XScreenSaverAllocInfo XScreenSaverQueryInfo \ XScreenSaverSelectInput XScreenSaverSuspend \ XScreenSaverInfo XScreenSaverNotifyEvent; do if grep -q "$decl" "$HDR" 2>/dev/null; then bst_ok "libxscrnsaver/hdr-decl-$decl" else bst_notok "libxscrnsaver/hdr-decl-$decl" "$decl is not declared in $HDR" fi done # saver.h is xorgproto's and is what scrnsaver.h includes for every constant. # A consumer that compiles against scrnsaver.h alone gets these through it, so # its absence would be a compile failure in the consumer rather than here. check libxscrnsaver/hdr-proto test -s "$HDR_PROTO" # --- the probe ---------------------------------------------------------------- if [ ! -x "$PROBE" ]; then bst_skip libxscrnsaver/probe-runs "$PROBE absent from the image" exit 0 fi # BOUNDED, and through bst_bound rather than timeout(1), which never expired on # a kernel without the brintos/linux#77 fix (alarm(2) was unwired). The ticket # asks for the # refusals to be measured "inside a bounded run", and on a shared image a probe # that wedged would cost every member of the batch its verify, not just this # ticket. 60 s is far above anything this probe can legitimately take: it opens # no connection, and its slowest act is eleven guarded calls and a memset. pout=${TMPDIR:-/tmp}/bst-libxscrnsaver-out.$$ bst_bound 60 "$PROBE" > "$pout" 2>&1 prc=$? if [ "$prc" -eq 0 ]; then bst_ok libxscrnsaver/probe-runs elif [ "$prc" -eq 124 ]; then bst_notok libxscrnsaver/probe-runs "the probe did not return within 60s -- it blocked, which on this image means it reached a connect or a lock it should never have reached" rm -f "$pout" exit 0 elif bst_execfail "$(head -c 200 "$pout" 2>/dev/null)"; then bst_unrun libxscrnsaver/probe-runs "$(head -c 200 "$pout" 2>/dev/null)" rm -f "$pout" exit 0 else bst_notok libxscrnsaver/probe-runs "probe exited $prc: $(_bst_1line "$(head -c 300 "$pout")")" fi if grep -q '^PROBE-END$' "$pout" 2>/dev/null; then bst_ok libxscrnsaver/probe-complete else bst_notok libxscrnsaver/probe-complete "probe output has no PROBE-END terminator (last line: $(tail -1 "$pout" 2>/dev/null))" fi # The trap described at the top of this file. A TRAP line means the probe # stopped ITSELF rather than faulting, so this case and probe-complete going red # together, with N/X/I absent, is the method failing safely. if grep -q '^TRAP ' "$pout" 2>/dev/null; then bst_notok libxscrnsaver/no-trap "the probe trapped: $(grep -m1 '^TRAP ' "$pout")" else bst_ok libxscrnsaver/no-trap fi # val -- the probe's value for one case, empty when the probe stopped # first. Matches on the ID in field 1 rather than taking the line by position, # because the probe's output is captured with 2>&1 and a platform diagnostic # could land in the middle of it. val() { awk -v k="$1" '$1==k { $1=""; sub(/^ /,""); print; exit }' "$pout"; } # want -- score one probe value against a derived 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 to a different # line. want() { _got=$(val "$1") if [ -z "$_got" ]; then bst_notok "libxscrnsaver/$2" "no value on target (probe stopped before $1); want='$3'" elif [ "$_got" = "$3" ]; then bst_ok "libxscrnsaver/$2" else bst_notok "libxscrnsaver/$2" "want:'$3' got:'$_got'" fi } # --- V: the constants the archive and the staged protocol headers agree on ---- # All out of xorgproto's saver.h and saverproto.h. V03/V04 are the PROTOCOL # version -- MIT-SCREEN-SAVER 1.1 -- and are deliberately not 1.2.4; see the # hdr-version-macros skip above. V05..V11 are the ticket's "documented state and # kind constants": the four states an info structure can report and the three # kinds of blanking, which are what a consumer switches on after a QueryInfo. want V01 name MIT-SCREEN-SAVER want V02 property-name _MIT_SCREEN_SAVER_ID want V03 proto-major 1 want V04 proto-minor 1 want V05 state-off 0 want V06 state-on 1 want V07 state-cycle 2 want V08 state-disabled 3 want V09 kind-blanked 0 want V10 kind-internal 1 want V11 kind-external 2 want V12 notify-event 0 want V13 number-events 1 want V14 notify-mask 1 want V15 cycle-mask 2 want V16 req-query-version 0 want V17 req-query-info 1 want V18 req-select-input 2 want V19 req-set-attributes 3 want V20 req-unset-attributes 4 want V21 req-suspend 5 want V22 wire-sz-info-reply 32 want V23 wire-sz-notify-event 32 # --- A: the in-memory layout this arm hands the packages above it ------------- # ILP32, derived by hand from the two declarations in scrnsaver.h with # unsigned long, XID, Time and every pointer at 4 bytes. Not confirmed by any # reference run: an LP64 host would answer 48/8/... for the info structure and # 72/... for the event, which is why these are derived rather than borrowed. # # XScreenSaverInfo Window, int, int, ulong, ulong, ulong = 24 # XScreenSaverNotifyEvent int, ulong, Bool(int), Display*, Window, # Window, int, int, Bool(int), Time = 40 want A01 sizeof-pointer 4 want A02 sizeof-xid 4 want A03 sizeof-time 4 want A04 sizeof-ulong 4 want A05 sizeof-card32 4 want A06 sizeof-info 24 want A07 off-info-window 0 want A08 off-info-state 4 want A09 off-info-kind 8 want A10 off-info-til-or-since 12 want A11 off-info-idle 16 want A15 off-info-eventmask 20 # THE TICKET'S OWN QUESTION. XScreenSaverInfo declares til_or_since and idle as # `unsigned long'; xScreenSaverQueryInfoReply declares tilOrSince and idle as # CARD32; and XScreenSaverQueryInfo assigns one to the other with a plain `=' # and no cast or mask. On this ILP32 arm the two widths coincide, so a 32-bit # millisecond counter that wraps wraps identically on both sides and the # assignment is exact. # # It is a COINCIDENCE, not a guarantee -- on an LP64 host the same `=' zero- # extends into a 64-bit field and the wrap point moves -- which is exactly why # the ticket asks for it to be asserted rather than assumed. A12/A13/A14 are # each asserted at 4 so that a red names WHICH of the three moved: the library's # field, its sibling, or the wire. want A12 sizeof-info-idle 4 want A13 sizeof-info-til-or-since 4 want A14 sizeof-wire-idle 4 want A16 sizeof-notify-event 40 want A17 off-ev-type 0 want A18 off-ev-serial 4 want A19 off-ev-send-event 8 want A20 off-ev-display 12 want A21 off-ev-window 16 want A22 off-ev-root 20 want A23 off-ev-state 24 want A24 off-ev-kind 28 want A25 off-ev-forced 32 want A26 off-ev-time 36 # A28 is a SAFETY property, not a layout fact, and is the one A case compared # rather than asserted against a literal: wire_to_event casts the XEvent* a # caller hands it to XScreenSaverNotifyEvent* and writes ten fields through it, # so if the notify event were the larger of the two that write would run off the # end of a correctly-sized caller buffer. A27 is printed for the reader; only # A28 is scored, because sizeof(XEvent) is Xlib's business and could legitimately # change. want A28 event-fits-xevent 1 # --- R: the one entry point that never touches a Display ---------------------- # XScreenSaverAllocInfo takes no dpy argument, so this is a COMPLETE execution # of a public entry point on an image with no server -- not a refusal. R02 reads # back a write across the structure's whole declared extent, so an allocation # that came up short is caught here rather than in whichever consumer first # filled one in. want R01 allocinfo-nonnull nonnull want R02 allocinfo-writable 1 want R03 allocinfo-usable 0 want R04 allocinfo-freed freed # --- N: the refusal that raises NOTHING --------------------------------------- # XScreenSaverQueryExtension has no XextCheckExtension guard. N02 is the case # that distinguishes it from all six of group X, and N03 is the half a consumer # actually depends on: the True branch is what writes event_base and error_base, # so a False return must leave the caller's variables alone. A library that # scribbled on them while returning False would hand a consumer a plausible # event base for an extension that is not there. want N01 queryextension-false 0 want N02 queryextension-raises-nothing 0 want N03 queryextension-outputs-untouched 1 # --- I: what find_display asked Xlib, and what it left behind ----------------- # Exactly one XQueryExtension, for MIT-SCREEN-SAVER, and never again -- # XextFindDisplay caches the XExtDisplayInfo on the first miss, so every later # call is a hit. I03 is that cache holding across a second call; if it did not, # every entry point would re-ask and the count would climb. want I01 init-one-queryextension 1 want I02 init-asked-for MIT-SCREEN-SAVER want I03 init-cache-holds 1 # --- X: the six that refuse THROUGH a guard that raises ----------------------- # Each case scores the return value AND the raise, because the pair is what # separates these from group N. The four void ones have no return value to # score, so the raise is the whole measurement -- plus the fact that control # came back at all, which is what the case existing at all asserts. want X01 queryversion-zero 0 want X02 queryversion-raises 1 want X03 queryversion-outputs-untouched 1 # The ticket's "query against a drawable that does not exist". The drawable # never matters: the guard fires before the request is encoded, so what is # measured is that an invalid id is refused by the extension check rather than # reaching a wire and coming back as a BadDrawable. X06 is the load-bearing # half -- a refusal that scribbled on the caller's info structure would be one a # consumer could not tell from a fill. want X04 queryinfo-zero 0 want X05 queryinfo-raises 1 want X06 queryinfo-info-untouched 1 want X07 selectinput-raises 1 want X08 setattributes-raises 1 want X09 unsetattributes-raises 1 want X10 suspend-raises 1 # Every raise named this extension and no other. A guard that fired for the # wrong extension would mean find_display had been handed the wrong # XExtensionInfo -- which no return value would show, because every one of them # is 0 either way. want X11 raises-name-ok 1 want X12 raises-last-name MIT-SCREEN-SAVER want X13 raises-total 6 # --- U: the three with no extension guard at all ------------------------------ # Named in the probe's census and deliberately never called. This is the # library's own structural oddity and the thing about it most worth carrying # away: unlike every other entry point, these three have nothing that can refuse # them, because they do not speak the extension protocol -- they are property # operations on the root window. Their first act is an Xlib round trip, and # RootWindow(dpy,screen) loads through the Display before even that. want U02 unguarded-count 3 for f in XScreenSaverRegister XScreenSaverUnregister XScreenSaverGetRegistered; do bst_skip "libxscrnsaver/unguarded-$f" "no extension guard: goes straight to XInternAtom/XChangeProperty/XGetWindowProperty on the root window, so it cannot refuse without a server -- named in the probe census, never called" done # A NULL Display is the ticket's remaining error path, and it is a skip for the # same reason libxvmc's was. Xlib documents no behaviour for one, and on this # path it is not a documentation question: find_display's miss arm reaches # XAddExtension, whose first statement is LockDisplay(dpy) -- `if # ((dpy)->lock_fns)' -- which loads through the pointer. A NULL there faults; it # does not refuse. Asserting a "documented result" would be asserting something # upstream does not document and this code does not implement. bst_skip libxscrnsaver/null-display "XAddExtension's LockDisplay(dpy) loads through the pointer on find_display's miss arm, so a NULL Display faults rather than refusing; Xlib documents no behaviour for one" # --- L: the lock accounting, which is also the trap's self-measurement -------- # trap-live is the case that keeps no-trap honest. LockDisplay is # `if ((d)->lock_fns) ...' only in the threaded Xlibint.h; compiled out, the # macro is empty, no lock is ever counted, and the trap is inert for the whole # run. One legitimate lock is expected -- XAddExtension on the first call -- so a # count of zero means the trap was never armed and the safety property no-trap # reports was not actually in force. _lc=$(val L02) if [ -z "$_lc" ]; then bst_notok libxscrnsaver/trap-live "no value on target (probe stopped before L02)" elif [ "$_lc" -gt 0 ] 2>/dev/null; then bst_ok libxscrnsaver/trap-live else bst_notok libxscrnsaver/trap-live "LockDisplay counted 0 calls, so Xlibint.h's threaded LockDisplay is compiled out on this arm and the trap was inert all run -- libxscrnsaver/no-trap above is then a statement about nothing" fi # Xlib's own invariant: XAddExtension unlocks on every path out, including its # allocation-failure path. A run that locked and did not unlock would have left # the Display locked for whatever ran next. want L04 lock-balanced 1 # --- the census --------------------------------------------------------------- # Every public entry point resolved to an address at link time. The recipe's # LIBXSCRNSAVER_MIN_ENTRY_POINTS floor is the build-side half of this; a .test # cannot read a bitbake variable, so the floor is restated here as a literal. # Eleven is the whole library. _n=$(grep -c '^CENSUS ' "$pout" 2>/dev/null) check_eq libxscrnsaver/census-count 11 "$_n" _null=$(grep -c '^CENSUS .* null$' "$pout" 2>/dev/null) check_eq libxscrnsaver/census-all-resolved 0 "$_null" rm -f "$pout"