. "$BST_LIB" # BST-TIMEOUT: 420 # one measuring probe run, three one-shot refusal runs and # ~120 shell extractions. The measuring run is # syscall-free apart from one sysconf and four small file # writes under $TMPDIR; the three refusal runs each end in # exit(1) before any connect completes. The bound is # headroom for a 6.4 MB exec image staging on a fragmented # heap, not a cap on anything this suite is known to # approach. # libXaw 1.0.16 -- the X Athena Widget Set (meta-openembedded # meta-oe/recipes-graphics/xorg-lib). See libxaw_%.bbappend for what the port # adds and why. # # --------------------------------------------------------------------------- # THERE IS NO DISPLAY ON THIS IMAGE AND THERE WILL NOT BE ONE # # libXaw is a widget library: almost every public entry point takes a Widget, # and a Widget needs a Display. So what this suite answers is not "do the # widgets work" but "is this library CORRECT ON THIS ARM for the day an Athena # application binds to it" -- and that question has real content, none of which # needs a display: # # THE ABI XawPannerReport, XawTextBlock, XawListReturnStruct and # XawTextPositionInfo are filled in BY THE CALLER and handed # across a callback boundary. On wasm32 a pointer and a long are # 4 bytes; on the build host, 8. A packing difference here # corrupts every report silently rather than crashing. # THE TABLE XawWidgetArray is the widget-class census every resource # browser walks, and XmuWnInitializeNodes builds the subclass # tree out of it with no display anywhere. It is also the one # cross-package behaviour this port adds: the table is Xaw's and # the algorithm is libXmu's. # THE CLASSES XtInitializeWidgetClass and XtGetResourceList take no Display, # so the COMPILED resource tables -- the ones every # XtGetApplicationResources reads -- can be driven rather than # described, and each resource's size is an ILP32 statement. # THE REFUSAL XtOpenApplication with nothing to open is the documented # failure every Athena program meets on this image, and it is # asserted as a diagnostic, a stream and an exit status. # # --------------------------------------------------------------------------- # WHAT THE TICKET ASKED FOR THAT THIS PACKAGE DOES NOT HAVE # # Two of BRINTOS-2488's acceptance criteria are refuted by libXaw 1.0.16 itself # rather than by this arm, and the sections below assert what is there instead # of inventing what is not: # # NO app-defaults FILES. The ticket asks for "the app-defaults resource files # the package installs, asserted present at the path the packaging declares". # libXaw installs none: Makefile.am's SUBDIRS are include, src, examples, man # and specs, there is no app-defaults rule anywhere in the tree, and this # build's own pkgdata lists 70 headers, Template.c, two .pc files, two # archives and one man page -- and nothing under /usr/share/X11. Section 9 # asserts the ABSENCE, and then asserts the resource-file PATHWAY an Athena # application uses instead, over a fixture the probe writes itself. # # NO VERSION MACRO SAYING 1.0.16. The ticket asks for "the version macros the # installed headers define ... asserted to agree with 1.0.16 as literals". # The only version macro libXaw installs is XawInit.h's XawVersion, and it is # a WIDGET-SET revision, not a package version: 7000002 for the Xaw7 build # and 6700002 for Xaw6. Section 4 asserts that number for what it is, and # section 2 asserts 1.0.16 where it really is stated -- xaw7.pc and xaw6.pc. # # AND THERE IS NO SONAME. The ticket asks for "the shipped soname". This # distro appends --disable-shared to every class-target configure, so no # shared object is built and there is nothing to carry one. Section 1 # asserts the archives and the ABSENCE of the shared objects -- including the # three symlinks to them that the stock recipe wrote and this port removes. # # --------------------------------------------------------------------------- # READ A RED IN SECTION ORDER; THE FIRST SECTION TO GO RED LOCALISES THE DEFECT # # 1 the files arrived packaging only # 2 xaw7.pc / xaw6.pc resolve consumers find the library at all # 3 the probe runs to its end the linked code executes here # 4 the data model and the ABI struct layout on this arm # 5 the widget set initialises Xaw's one universal entry point # 6 the widget-class table what this library declares it has # 7 the subclass tree Xaw's table through libXmu's code # 8 the compiled resource tables what every widget creation reads # 9 the resource-file pathway how an Athena app is configured # 10 the page size the one place Xaw reaches the kernel # 11 the documented refusals RUNS LAST -- each ends its process # # A build where 3 passes and 4 does not has a struct-layout fault and nothing # below it can be trusted. 8 failing while 4 passes is the resource machinery, # not layout. 11 failing on its own is about Xt's error path and the connect, # not about Xaw. # --------------------------------------------------------------------------- # A root prefix, empty on the target and set only when this suite is validated # NATIVELY before it ships. The runner never sets it, so on the image every # path below is exactly the absolute one. R="${BST_LIBXAW_ROOT:-}" INC=$R/usr/include/X11/Xaw XINC=$R/usr/include/X11 PCD=$R/usr/lib/pkgconfig LIB=$R/usr/lib XAWT=$R/usr/libexec/libxaw-tests work=${TMPDIR:-/tmp}/bst-libxaw.$$ rm -rf "$work"; mkdir -p "$work" hasfile() { if [ -s "$2" ]; then bst_ok "$1"; else bst_notok "$1" "missing or empty: $2"; fi } # xaw_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. xaw_line() { _l=$(grep -F -- "$2" "$work/out" 2>/dev/null | head -1) check_eq "$1" "$2$3" "$_l" } # xaw_field # # For a line whose OTHER fields are not hand-derivable -- a widget_size, a # resource offset -- so the case asserts the one field it can state absolutely # and a red still carries the whole line. xaw_field() { _l=$(grep -F -- "$2" "$work/out" 2>/dev/null | head -1) _v=${_l##*$3} _v=${_v%% *} if [ -z "$_l" ]; then bst_notok "$1" "no line matching '$2'" else check_eq "$1" "$4" "$_v" fi } # xaw_head # # Like xaw_line, for a probe line whose TAIL is not hand-derivable -- a # resource offset, libXt's default-representation name -- so the case pins the # fields it can state absolutely and lets the rest vary. A red still carries # the whole line, tail included. xaw_head() { _l=$(grep -F -- "$2" "$work/out" 2>/dev/null | head -1) if [ -z "$_l" ]; then bst_notok "$1" "no line matching '$2'" else case "$_l" in "$2$3"|"$2$3 "*) bst_ok "$1" ;; *) bst_notok "$1" "want head:'$2$3' got:'$_l'" ;; esac fi } # --------------------------------------------------------------------------- # 0. THE CANARY, which is not an assertion about libXaw 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 libxaw/suite-canary # --------------------------------------------------------------------------- # 1. THE PAYLOAD. check_rc libxaw/dir-Xaw 0 test -d "$INC" # Seven headers by name out of the seventy installed: the two every Athena # application includes (XawInit.h, AllWidgets.h), four widget headers that are # the ones a consumer names first, and Reports.h, which defines the callback # structure section 4 asserts the layout of. hasfile libxaw/hdr-XawInit-h "$INC/XawInit.h" hasfile libxaw/hdr-AllWidgets-h "$INC/AllWidgets.h" hasfile libxaw/hdr-Reports-h "$INC/Reports.h" hasfile libxaw/hdr-Command-h "$INC/Command.h" hasfile libxaw/hdr-Label-h "$INC/Label.h" hasfile libxaw/hdr-Form-h "$INC/Form.h" hasfile libxaw/hdr-Text-h "$INC/Text.h" # A PRIVATE header as well, and the omission would be easy to miss: an Athena # widget SUBCLASS -- which is what every application that writes its own widget # is -- includes the P.h of the class it derives from, and those are half the # installed set. hasfile libxaw/hdr-CommandP-h "$INC/CommandP.h" hasfile libxaw/hdr-TextP-h "$INC/TextP.h" # Template.c is installed as a HEADER by include/Makefile.am -- it is the # skeleton upstream ships for writing a new widget -- so it is the one # non-.h file in this directory and a `*.h' install rule would drop it. hasfile libxaw/template-c-shipped "$INC/Template.c" # The census, bounded FROM BELOW and pinned in the recipe as well. 70 is the # complete shipped set of .h files; include/Makefile.am lists 71 entries, of # which one is Template.c above. nh=$(find "$INC" -maxdepth 1 -type f -name '*.h' 2>/dev/null | wc -l) if [ "${nh:-0}" -ge 70 ]; then bst_ok libxaw/hdr-count else bst_notok libxaw/hdr-count "found ${nh:-0} headers under X11/Xaw, expected not less than 70"; fi # THE PAIR OF ARCHIVES. libXaw6 and libXaw7 are genuinely different libraries # built from different source lists -- xaw6.pc's Requires.private names no xpm # because the Xaw6 sources do not use it -- and a build that shipped only one # of them passes every other check here while failing some later consumer's # link with no hint that this recipe is where it went. hasfile libxaw/archive-xaw7 "$LIB/libXaw7.a" hasfile libxaw/archive-xaw6 "$LIB/libXaw6.a" # THE SHARED OBJECTS, AND THE THREE SYMLINKS TO THEM THAT THIS PORT REMOVES. # # meta-oe's libxaw_1.0.16.bb ends in an unconditional # `ln -sf libXaw7.so.7 ${D}${libdir}/libXaw.so' and two siblings. `ln -sf' # writes a link whether or not its target exists, and on this static-only # distro none of the three targets is ever built -- so the stock recipe ships # libXaw.so, libXaw.so.6 and libXaw.so.7 as DANGLING links, one of them in # libxaw-dev where a consumer's `-lXaw' resolves through it. Nothing in the # build catches that: the packaging QA that would is keyed on # oe.package.is_elf() and a wasm module is not ELF (BRINTOS-757). # # The repair is in libxaw_%.bbappend and it is conditional on the target's # absence, so it stays correct if the package-shared arm ever builds this # recipe shared. These cases assert the arm that shipped rather than one arm: # either no .so and no link at all, or a .so with links that resolve. if bst_ps_converted "$LIB/libXaw7.so*" "$LIB/libXaw.so*"; then # The converted arm: whatever shared names shipped must be usable. bst_lib_shape libxaw/shared-usable "$LIB/libXaw*.so*" else ok=yes; bad= for l in "$LIB/libXaw.so" "$LIB/libXaw.so.6" "$LIB/libXaw.so.7" \ "$LIB/libXaw6.so.6" "$LIB/libXaw7.so.7"; do if [ -e "$l" ] || [ -L "$l" ]; then ok=no; bad="$bad $l"; fi done if [ "$ok" = yes ]; then bst_ok libxaw/no-dangling-so else bst_notok libxaw/no-dangling-so "shared-object names present on a static-only arm:$bad"; fi fi hasfile libxaw/probe-shipped "$XAWT/libxaw-probe" hasfile libxaw/open-probe-shipped "$XAWT/libxaw-open-probe" # THE STACK UNDER IT, asserted here because it is a cross-package fact no # libXaw file records: every Xaw header includes X11/Intrinsic.h on its first # page, AllWidgets.h includes X11/Xmu/WidgetNode.h, and the Xaw7 sources # include X11/xpm.h. A consumer that has libXaw's headers without those cannot # compile a line. check_rc libxaw/xt-reachable 0 test -f "$XINC/Intrinsic.h" check_rc libxaw/xmu-reachable 0 test -f "$XINC/Xmu/WidgetNode.h" check_rc libxaw/xpm-reachable 0 test -f "$XINC/xpm.h" check_rc libxaw/xlib-reachable 0 test -f "$XINC/Xlib.h" # THE app-defaults ABSENCE, asserted rather than assumed. See the header # comment: libXaw installs no resource files of its own, and section 9 # measures the pathway an application's own file would take instead. This case # exists so that a future upstream that DID start shipping one is reported # rather than silently ignored. check_rc libxaw/no-app-defaults 1 test -d "$R/usr/share/X11/app-defaults" # --------------------------------------------------------------------------- # 2. xaw7.pc AND xaw6.pc -- how a consumer finds any of the above, and the one # thing on this image that states the package version. hasfile libxaw/pc7-in-libdir "$PCD/xaw7.pc" hasfile libxaw/pc6-in-libdir "$PCD/xaw6.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 libxaw/pkg-config-present check libxaw/pc7-exists pkg-config --exists xaw7 check libxaw/pc7-validate pkg-config --validate xaw7 check libxaw/pc6-exists pkg-config --exists xaw6 check libxaw/pc6-validate pkg-config --validate xaw6 # THE PACKAGE VERSION, and the only statement of it on this image. Both .pc # files take it from AC_INIT's PACKAGE_VERSION, so a disagreement between # them would mean one was generated from a different tree. check_eq libxaw/pc7-modversion 1.0.16 "$(pkg-config --modversion xaw7 2>/dev/null)" check_eq libxaw/pc6-modversion 1.0.16 "$(pkg-config --modversion xaw6 2>/dev/null)" # THE STATIC CLOSURE, AND IT IS THE MOST USEFUL THING IN THIS FILE FOR THE # FIVE TICKETS THIS PORT UNBLOCKS. # # xkbutils, xmessage, xfontsel, xmag and xclock (BRINTOS-2437) all link # through this query, and the bare `pkg-config --libs xaw7' answers # `-lXaw7 -lXt -lX11' -- which on a static-only distro ends on the phantom # env.* imports wasmld refuses an image over, because the edges to Xmu, Xpm, # Xext, SM, ICE, xcb, Xau and Xdmcp exist only in Requires.private. --static # is what expands them, and these cases assert it names every one, so a # consumer author reads the closure from here rather than rediscovering it at # link time. # # PKG_CONFIG_ALLOW_SYSTEM_LIBS is required for the same reason 57-xtrans.test # needs its CFLAGS counterpart: pkg-config SUPPRESSES a -L naming a directory # already on the linker's system path, so the bare query answers correctly # and uselessly. for l in Xaw7 Xmu Xpm Xt SM ICE Xext X11 pthread xcb Xau Xdmcp; do check "libxaw/pc7-static-names-$l" sh -c \ "PKG_CONFIG_ALLOW_SYSTEM_LIBS=1 pkg-config --static --libs xaw7 | grep -q -- -l$l" done # XAW6 IS THE SAME CLOSURE WITHOUT Xpm, and that is the difference worth # asserting: xaw6.pc's Requires.private is `x11 xext xt xmu' where xaw7's is # `x11 xext xt xmu xpm'. A consumer choosing the older widget set reads a # smaller set from it, and the two files becoming identical would be a # packaging fault nothing else here would see. check libxaw/pc6-static-names-Xaw6 sh -c \ "PKG_CONFIG_ALLOW_SYSTEM_LIBS=1 pkg-config --static --libs xaw6 | grep -q -- -lXaw6" check libxaw/pc6-static-names-Xmu sh -c \ "PKG_CONFIG_ALLOW_SYSTEM_LIBS=1 pkg-config --static --libs xaw6 | grep -q -- -lXmu" check_rc libxaw/pc6-static-omits-Xpm 1 sh -c \ "PKG_CONFIG_ALLOW_SYSTEM_LIBS=1 pkg-config --static --libs xaw6 | grep -q -- -lXpm" # The NON-static query, asserted for what it is rather than left implied: it # names Xaw7 and it does NOT name Xmu. That is correct upstream behaviour on # a shared-library distro and is the defect on this one, and a case saying so # is what stops the next reader from "fixing" xaw7.pc. check libxaw/pc7-libs-names-Xaw7 sh -c \ "PKG_CONFIG_ALLOW_SYSTEM_LIBS=1 pkg-config --libs xaw7 | grep -q -- -lXaw7" check_rc libxaw/pc7-libs-omits-Xmu 1 sh -c \ "PKG_CONFIG_ALLOW_SYSTEM_LIBS=1 pkg-config --libs xaw7 | grep -q -- -lXmu" else bst_skip libxaw/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/libxaw-probe if cp "$XAWT/libxaw-probe" "$probe" 2>/dev/null && chmod +x "$probe" 2>/dev/null; then bst_probe libxaw/probe-runs "$work/out" 180 "$probe" total=$(sed -n 's/^XAW-TOTAL //p' "$work/out") if [ -n "$total" ]; then bst_ok libxaw/probe-complete else bst_notok libxaw/probe-complete \ "no XAW-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. 93 is what 1.0.16's 42-entry table # and the fixed sections produce. if [ -n "$total" ] && [ "$total" -ge 90 ]; then bst_ok libxaw/probe-coverage else bst_notok libxaw/probe-coverage \ "reported ${total:-0} measurements, expected not less than 90"; fi # Xt's default error handler EXITS, so an error raised anywhere in the run # would truncate it. The probe installs its own handler and prints instead, # which turns a silent truncation into a named line -- asserted absent here # so that a red says WHICH error rather than only that the total is short. if grep -q '^XAW ERROR ' "$work/out" 2>/dev/null; then bst_notok libxaw/no-xt-error "$(_bst_1line "$(grep '^XAW ERROR ' "$work/out" | head -1)")" else bst_ok libxaw/no-xt-error fi # ------------------------------------------------------------------------- # 4. THE DATA MODEL AND THE ABI. # The one line where agreeing with the build host would be the defect. xaw_line libxaw/data-model "XAW MODEL " "long=4 ptr=4 int=4 short=2" # The Xt scalars Xaw's public structures are built out of. XawTextPosition is # a long, so it is 4 here and 8 on the host -- and it is the type every Text # widget position, every selection bound and every XawTextBlock offset is. xaw_line libxaw/scalar-types "XAW TYPE " \ "Boolean=1 Cardinal=4 Dimension=2 Position=2 XawTextPosition=4" # The caller-filled structures, by total size. xaw_line libxaw/abi-sizes "XAW SIZE " \ "XawPannerReport=16 XawListReturnStruct=8 XawTextBlock=16 XawTextPositionInfo=20 XawTextPropertyInfo=12" # The offsets, separately from the sizes. A structure can be the right total # size with its members in the wrong places, and a reportCallback writing # slider_y into what the caller reads as slider_x is a silently wrong window # rather than a crash. XawPannerReport is the interesting one: an unsigned # int followed by six 2-byte fields, which packs with no padding on this arm. xaw_line libxaw/abi-offsets-panner "XAW OFF XawPannerReport " \ "changed=0 sx=4 sy=6 sw=8 sh=10 cw=12 ch=14" xaw_line libxaw/abi-offsets-textblock "XAW OFF XawTextBlock " \ "firstPos=0 length=4 ptr=8 format=12" xaw_line libxaw/abi-offsets-posinfo "XAW OFF XawTextPositionInfo " \ "line=0 column=4 insert=8 last=12 overwrite=16" # The panner report's change mask -- the protocol between a Panner and its # callback, defined nowhere but Reports.h. XawPRAll is written as the literal # 63 upstream rather than as the union of the six, so a bit added without # updating it would show here as a disagreement. xaw_line libxaw/panner-mask "XAW PRMASK " \ "sliderX=1 sliderY=2 sliderW=4 sliderH=8 canvasW=16 canvasH=32 all=63" # THE VERSION MACRO, ASSERTED FOR WHAT IT IS. XawInit.h's XawVersion is a # widget-set revision and not the package version -- 7000002 for the Xaw7 # build, 6700002 for Xaw6 -- so this case says which of the two the probe was # compiled against, and the package version is section 2's business. xaw_line libxaw/xaw-version "XAW VERSION " "XawVersion=7000002" # ------------------------------------------------------------------------- # 5. THE WIDGET SET INITIALISES, WITH NO DISPLAY. # # XawInitializeWidgetSet is the function every Athena widget's # ClassInitialize calls. It registers Xaw's four pixmap loaders and its # twenty-odd default converters and forces vendorShellWidgetClass to be # initialised. None of that needs a display, and none of it may warn. xaw_line libxaw/init-first "XAW INIT first " "warn=0" # Its own static Boolean guards it, so the second call must be a no-op. A # widget set that re-registered its converters on every ClassInitialize would # warn here -- and every one of the 42 classes below calls it. xaw_line libxaw/init-second "XAW INIT second " "warn=0" # ------------------------------------------------------------------------- # 6. THE WIDGET-CLASS TABLE. # 42 in 1.0.16, and pinned in the recipe as a source-side floor as well, so a # table that shrank fails do_compile rather than going quiet here. xaw_line libxaw/table-count "XAW TABLE " "count=42" # Nine entries by name, each asserting the class_name the class record # carries -- which is NOT the table's own label and is what Xt matches a # resource specification against. A build that linked a stale archive shows # up as a label with the wrong class beside it. xaw_field libxaw/class-command "XAW WIDGET command " "class=" "Command" xaw_field libxaw/class-label "XAW WIDGET label " "class=" "Label" xaw_field libxaw/class-form "XAW WIDGET form " "class=" "Form" xaw_field libxaw/class-paned "XAW WIDGET paned " "class=" "Paned" xaw_field libxaw/class-panner "XAW WIDGET panner " "class=" "Panner" xaw_field libxaw/class-simple "XAW WIDGET simple " "class=" "Simple" xaw_field libxaw/class-tree "XAW WIDGET tree " "class=" "Tree" xaw_field libxaw/class-viewport "XAW WIDGET viewport " "class=" "Viewport" xaw_field libxaw/class-asciisink "XAW WIDGET asciiSink " "class=" "AsciiSink" # EVERY entry printed a line, which is the assertion the nine above cannot # make: a class whose record failed to link would be missing from the output # rather than wrong in it, and the count says so directly. nw=$(grep -c '^XAW WIDGET ' "$work/out" 2>/dev/null) if [ "${nw:-0}" -eq 42 ]; then bst_ok libxaw/class-lines else bst_notok libxaw/class-lines "printed ${nw:-0} widget lines, expected 42"; fi # NO CLASS HAS A ZERO widget_size. That is not a style point: widget_size is # what XtCreateWidget allocates, so a class record that arrived zeroed would # hand every instance a null instance record -- and the table above would # still print its name and its class. nz=$(grep -c '^XAW WIDGET .* size=0 ' "$work/out" 2>/dev/null) if [ "${nz:-0}" -eq 0 ]; then bst_ok libxaw/class-sizes-nonzero else bst_notok libxaw/class-sizes-nonzero "${nz} class record(s) report widget_size 0"; fi # ------------------------------------------------------------------------- # 7. THE SUBCLASS TREE -- Xaw's table through libXmu's code. xaw_line libxaw/nodes-init "XAW NODES initialized " "warn=0" # The Athena chain from a leaf to the Intrinsics' own root, one rung at a # time. Command derives from Label, Label from Simple, Simple from Core, and # Core from RectObj; Object is the root and has no superclass at all. A tree # that linked every node to the same parent, or to none, cannot pass all six. # # lowered_label and lowered_classname are asserted with them because they are # what a resource browser matches a user's typed name against, and they are # derived by libXmu rather than shipped by libXaw -- so a disagreement here # is a cross-package fault and not a typo. xaw_line libxaw/node-command "XAW NODE command " \ "super=label lowlabel=command lowclass=command" xaw_line libxaw/node-label "XAW NODE label " \ "super=simple lowlabel=label lowclass=label" xaw_line libxaw/node-simple "XAW NODE simple " \ "super=core lowlabel=simple lowclass=simple" xaw_line libxaw/node-core "XAW NODE core " \ "super=rect lowlabel=core lowclass=core" xaw_line libxaw/node-object "XAW NODE object " \ "super=(none) lowlabel=object lowclass=object" xaw_line libxaw/node-asciisink "XAW NODE asciiSink " \ "super=textSink lowlabel=asciisink lowclass=asciisink" # THE LOOKUP, and its error path. A name that is not defined must come back # NULL rather than the nearest match -- which is what a resource browser # handed a typo depends on. xaw_line libxaw/lookup-present "XAW LOOKUP command " "command" xaw_line libxaw/lookup-undefined "XAW LOOKUP undefined " "null" # ------------------------------------------------------------------------- # 8. THE COMPILED RESOURCE TABLES. # # XtGetResourceList returns the MERGED table -- the class's own resources # plus every superclass's -- once XtInitializeWidgetClass has run, and both # take no Display. So this section drives the real resource machinery rather # than describing it. # Every class initialised. A class_inited of 0 beside a non-zero count would # mean XtGetResourceList answered from the uncompiled table, and every # assertion below it would be about a different list. ni=$(grep -c '^XAW RES .* inited=1$' "$work/out" 2>/dev/null) if [ "${ni:-0}" -eq 10 ]; then bst_ok libxaw/res-classes-inited else bst_notok libxaw/res-classes-inited "${ni:-0} of 10 classes report class_inited=1"; fi # The counts are bounded FROM BELOW rather than pinned: the merged table # includes Core's and Simple's resources, so the absolute number is a fact # about libXt's release as much as about libXaw's, and pinning it would make # this suite red on an Xt bump that broke nothing. What cannot legitimately # happen is a class whose merged table is EMPTY or nearly so -- that is a # class record that did not link. low=$(awk '/^XAW RES /{n=$0; sub(/.*n=/,"",n); sub(/ .*/,"",n); if (n+0 < 20) c++} END{print c+0}' "$work/out" 2>/dev/null) if [ "${low:-1}" -eq 0 ]; then bst_ok libxaw/res-counts-plausible else bst_notok libxaw/res-counts-plausible "${low} class(es) report fewer than 20 merged resources"; fi # FOUR RESOURCES WHOSE TYPES DIFFER, so a build that got the scalar widths # wrong shows up as four different wrong sizes rather than one. Each size is # read off the widget's own resource table in the source -- sizeof(String), # sizeof(Dimension), sizeof(Boolean) -- and each is an ILP32 statement. xaw_head libxaw/res-label-label "XAW RESENT label.label " \ "type=String size=4" xaw_head libxaw/res-label-internalwidth "XAW RESENT label.internalWidth " \ "type=Dimension size=2" xaw_head libxaw/res-label-resize "XAW RESENT label.resize " \ "type=Boolean size=1" xaw_head libxaw/res-scrollbar-thickness "XAW RESENT scrollbar.thickness " \ "type=Dimension size=2" xaw_head libxaw/res-viewport-allowhoriz "XAW RESENT viewport.allowHoriz " \ "type=Boolean size=1" # THE ORIENTATION RESOURCES ARE THE CROSS-PACKAGE ONE. XtOrientation is not # libXt's and not libXaw's: it is an ENUM declared in X11/Xmu/Converters.h, # so `sizeof(XtOrientation)' is 4 on this toolchain rather than the 1 a # reader expects from a two-valued type. Two Xaw classes size a resource with # it, and both are asserted, because a libXmu that changed the declaration # would move both at once and neither package's own tests would see it. xaw_head libxaw/res-scrollbar-orientation "XAW RESENT scrollbar.orientation " \ "type=Orientation size=4" xaw_head libxaw/res-paned-orientation "XAW RESENT paned.orientation " \ "type=Orientation size=4" # THE ERROR PATH: a resource name that is not defined on the class. Absence # must be reported as absence rather than as the nearest match. xaw_line libxaw/res-undefined "XAW RESENT label.noSuchResourceName " "absent" # EVERY RESOURCE OFFSET LIES INSIDE ITS CLASS'S INSTANCE RECORD. The offsets # themselves are not hand-derivable, but this invariant is exact and it is # the one that matters: an offset past the end of the record is a write into # another widget, and XtSetValues does it silently. bad=$(awk ' /^XAW WIDGET /{ lbl=$3; sz=$0; sub(/.*size=/,"",sz); sub(/ .*/,"",sz); size[lbl]=sz+0 } /^XAW RESENT /{ k=$3; sub(/\..*/,"",k) if ($4 == "absent") next o=$0; sub(/.*offset=/,"",o); sub(/ .*/,"",o) if (o !~ /^[0-9]+$/) { print $3" offset="o; next } if (k in size && size[k] > 0 && o+0 >= size[k]) print $3" offset="o" >= widget_size "size[k] }' "$work/out" 2>/dev/null) if [ -z "$bad" ]; then bst_ok libxaw/res-offsets-in-record else bst_notok libxaw/res-offsets-in-record "$(_bst_1line "$bad")"; fi # CONSTRAINT RESOURCES ARE A SECOND, SEPARATE TABLE, and Form and Paned are # the Athena classes that have one -- a child of a Form carries fromHoriz, # fromVert and the rest in the PARENT's constraint record. A widget set that # merged the two tables would place a child's constraint at an offset into # the parent's instance record. cf=$(sed -n 's/^XAW CONSTRAINT form n=//p' "$work/out") if [ -n "$cf" ] && [ "$cf" -ge 8 ]; then bst_ok libxaw/constraint-form else bst_notok libxaw/constraint-form "form reports ${cf:-0} constraint resources, expected not less than 8"; fi cp_=$(sed -n 's/^XAW CONSTRAINT paned n=//p' "$work/out") if [ -n "$cp_" ] && [ "$cp_" -ge 4 ]; then bst_ok libxaw/constraint-paned else bst_notok libxaw/constraint-paned "paned reports ${cp_:-0} constraint resources, expected not less than 4"; fi # Command is not a constraint class at all, and an EMPTY answer is the # documented result rather than a failure. This is the case that says the # non-zero ones above mean something. xaw_line libxaw/constraint-command "XAW CONSTRAINT command " "n=0" # ------------------------------------------------------------------------- # 9. THE RESOURCE-FILE PATHWAY. # # THE PARSER HERE IS Xrm's, NOT libXaw's, and this comment is the suite # saying so rather than letting the section read as a libXaw measurement. # libXaw ships no app-defaults file of its own (section 1 asserts that), so # what a "Xaw resource file" means on this image is exactly this: a file the # APPLICATION ships, parsed by XrmGetFileDatabase, read back by # XrmGetResource, and handed to the widget tree by Xt. That pathway needs no # display, every Athena program runs it before it opens one, and this is the # first package in the stack that gives it a reason to exist. xaw_line libxaw/rdb-parsed "XAW RDB parsed " "db=nonnull warn=0" # AN INSTANCE-QUALIFIED LINE BEATS A CLASS-QUALIFIED ONE. That precedence is # the whole of what a resource file is for, and it is the first thing a # broken parse gets wrong -- a database that took the last line to arrive # would answer `from-class' here and look perfectly healthy. xaw_line libxaw/rdb-instance-wins "XAW RDB instance-wins " \ "found type=String size=14 value=from-instance" # A LOOSE BINDING (`XawProbe*label') still matches a name the file never # spelled out. Same database, different query, and it is what an application # relies on to set one resource for every widget under it. xaw_line libxaw/rdb-loose-binding "XAW RDB loose-binding " \ "found type=String size=11 value=from-class" xaw_line libxaw/rdb-integer "XAW RDB integer " \ "found type=String size=2 value=7" # A `!' comment is DROPPED rather than stored under some name. xaw_line libxaw/rdb-comment-dropped "XAW RDB comment-dropped " "absent" # THE ERROR PATH the ticket asks for: a resource name that is not in the # database at all. xaw_line libxaw/rdb-undefined "XAW RDB undefined " "absent" # A FILE THAT DOES NOT PARSE. Xrm is documented to SKIP a malformed line # rather than reject the file, so what is asserted is that the good line # survives beside the bad ones. A NULL database would be the defect, and so # would a database that lost the line it could read. xaw_line libxaw/rdb-malformed "XAW RDB malformed " "db=nonnull warn=0" xaw_line libxaw/rdb-malformed-survivor "XAW RDB malformed-survivor " \ "found type=String size=9 value=survived" # A PATH THAT IS NOT THERE. NULL, and no Xt error raised -- which section 3's # no-xt-error case is what confirms. xaw_line libxaw/rdb-missing "XAW RDB missing " "db=null warn=0" # ------------------------------------------------------------------------- # 10. THE ONE PLACE libXaw REACHES THE KERNEL. # # OS.c's _XawGetPageSize prefers sysconf(_SC_PAGESIZE) and falls back to # getpagesize() and then to a compiled-in PAGE_SIZE. AsciiSrc's file-backed # text source sizes its reads off this number, so a libXaw that compiled in a # constant this kernel does not use would read the wrong amount and nothing # else would say why. # # The two are asserted to AGREE rather than pinned to a literal: which page # size this kernel reports is the platform's business, and pinning it would # make this case red on a platform change that broke nothing here. pl=$(grep -F 'XAW PAGESIZE ' "$work/out" 2>/dev/null | head -1) pa=${pl##*xaw=}; pa=${pa%% *} pb=${pl##*sysconf=}; pb=${pb%% *} if [ -z "$pl" ]; then bst_notok libxaw/pagesize "no XAW PAGESIZE line" elif [ "$pa" = "$pb" ] && [ "${pa:-0}" -gt 0 ]; then bst_ok libxaw/pagesize else bst_notok libxaw/pagesize "libXaw says '$pa', sysconf says '$pb'" fi else bst_unrun libxaw/probe-runs "could not stage $XAWT/libxaw-probe under $work" bst_unrun libxaw/probe-complete "probe not staged" fi # --------------------------------------------------------------------------- # 11. THE DOCUMENTED REFUSALS -- RUN LAST, EACH IN ITS OWN PROCESS. # # XtOpenApplication's no-display path does not return: Display.c raises an Xt # ERROR and Xt's default handler writes to stderr and calls exit(1). That is # the documented behaviour and it is what these cases observe, so the probe # leaves the DEFAULT handler installed -- replacing it would have measured the # probe instead of libXt. # # The exact diagnostic is `Error: Can't open display: ' on STDERR: # Error.c's DefaultMsg formats XTERROR_PREFIX (empty by default) then # `Error: ' then the message from the error database, whose default for # invalidDisplay/xtInitialize is `Can't open display: %s'. The trailing name is # whatever DISPLAY resolved to and is not asserted -- it differs between the # two cases on purpose. # # THEY ARE LAST BECAUSE THEY ARE THE ONLY THING HERE THAT COULD BLOCK. A # connect that hung would wedge the guest, and a wedged suite costs every # member of a batch its verify -- so each run is bounded, and every case in # sections 1 to 10 is already on the console before the first one starts. openp=$work/libxaw-open-probe if cp "$XAWT/libxaw-open-probe" "$openp" 2>/dev/null && chmod +x "$openp" 2>/dev/null; then # `oc', not `case': `case' is a shell reserved word and `for case in ...' # is a syntax error in dash, which is the shell this image runs suites under. for oc in nodisplay deadaddr; do out=$work/open-$oc ( "$openp" "$oc" >"$out" 2>"$out.err" ; echo $? >"$out.rc" ) & bpid=$! n=0 while [ ! -e "$out.rc" ] && [ "$n" -lt 60 ]; do sleep 1; n=$((n + 1)); done if [ ! -e "$out.rc" ]; then kill -9 "$bpid" 2>/dev/null bst_notok "libxaw/open-$oc-refuses" "did not return within 60s -- it BLOCKED on the connect" bst_notok "libxaw/open-$oc-diagnostic" "run did not terminate" bst_notok "libxaw/open-$oc-not-on-stdout" "run did not terminate" bst_notok "libxaw/open-$oc-reached-open" "run did not terminate" continue fi orc=0 # BST-REDIRECT-OK: $out.rc is under $work, which is ${TMPDIR:-/tmp} -- tmpfs, # where dup2 does not return 513. read -r orc < "$out.rc" # THE EXIT STATUS. 1 is Xt's, from exit(1) inside the default error # handler; a 0 would mean the toolkit found a display, and anything else # would mean the process died some other way. check_eq "libxaw/open-$oc-refuses" 1 "$orc" # THE DIAGNOSTIC, ON THE DOCUMENTED STREAM. Asserted on stderr, and # asserted ABSENT from stdout in the same breath: a library that wrote its # refusal to stdout would still exit 1 and still look correct to a status # check. if grep -q "Error: Can't open display" "$out.err" 2>/dev/null; then bst_ok "libxaw/open-$oc-diagnostic" else bst_notok "libxaw/open-$oc-diagnostic" \ "stderr: $(_bst_1line "$(cat "$out.err" 2>/dev/null)")" fi check_rc "libxaw/open-$oc-not-on-stdout" 1 grep -q "Can't open display" "$out" # THE PROBE GOT AS FAR AS THE OPEN. `XAWOPEN begin' is printed after # XawInitializeWidgetSet and before XtOpenApplication, so its presence is # what separates "the refusal came from the toolkit" from "the image # refused to start the binary at all" -- which would also produce a # non-zero status and an empty stdout. check_rc "libxaw/open-$oc-reached-open" 0 grep -q "^XAWOPEN begin" "$out" done # XtOpenDisplay ONE FRAME LOWER, where the contract is to RETURN NULL rather # than raise. Reading this beside the two above is what says whether the # refusal came from the connect or from Xt's handling of it: a NULL here with # an exit 1 there is the documented pair, and a hang here would localise the # fault in the transport. out=$work/open-lowlevel ( "$openp" opendisplay >"$out" 2>"$out.err" ; echo $? >"$out.rc" ) & bpid=$! n=0 while [ ! -e "$out.rc" ] && [ "$n" -lt 60 ]; do sleep 1; n=$((n + 1)); done if [ ! -e "$out.rc" ]; then kill -9 "$bpid" 2>/dev/null bst_notok libxaw/opendisplay-rc "did not return within 60s -- it BLOCKED on the connect" bst_notok libxaw/opendisplay-returns "run did not terminate" else orc=0 # BST-REDIRECT-OK: $out.rc is under $work, which is ${TMPDIR:-/tmp}. read -r orc < "$out.rc" check_eq libxaw/opendisplay-rc 0 "$orc" check_eq libxaw/opendisplay-returns "XAWOPEN display ret=null" \ "$(grep -F 'XAWOPEN display ' "$out" 2>/dev/null | head -1)" fi else bst_unrun libxaw/open-nodisplay-refuses "could not stage $XAWT/libxaw-open-probe under $work" bst_unrun libxaw/open-deadaddr-refuses "open probe not staged" bst_unrun libxaw/opendisplay-rc "open probe not staged" bst_unrun libxaw/opendisplay-returns "open probe not staged" fi rm -rf "$work"