. "$BST_LIB" # BST-TIMEOUT: 300 # one probe run plus ~200 shell extractions; the 60s default # is for suites that fork far less than this one does. # libXrender 0.9.11 -- the client half of the RENDER extension (poky # recipes-graphics/xorg-lib). See libxrender_%.bbappend for what the port adds # and why. # # --------------------------------------------------------------------------- # NO ENTRY POINT OF THIS LIBRARY CAN REACH A SERVER HERE, AND MOST OF IT STILL # RUNS # # All forty-four client entry points open with XRenderFindDisplay(dpy) and this # image has no X server, so section DPY is the honest answer to "did you draw # anything": no. What makes Render different from its siblings in this stack is # how much of it is CLIENT-SIDE ARITHMETIC that runs to completion before # anything is sent: # # the standard picture formats a static table inside libXrender.a # the picture-attribute packer a 13-bit mask -> a positional value list # XFixed and the transform 16.16 fixed point, and a 3x3 matrix # XRenderParseColor's rgba: parse, scale, premultiply -- no Display # the trapezoid decomposition fixed point and double precision geometry # # Every one of those is real code out of the archive, every one is exactly the # kind of thing that can be complete, installed and WRONG on a new # architecture, and not one of them would go red if this suite only asserted # that a .a and a header arrived. # # 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 picture formats and the wire constants are fixed # by the Render protocol specification; the attribute order is fixed by it too; # the fixed-point conversions are exact at every value asserted below; and the # polygon under test has integer corners, so its decomposition is exact in both # fixed point and double precision. Each case 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. `long' and a # pointer are 4 bytes here and 8 there, and section ABI exists precisely to # pin the 4 -- a blanket diff would make agreement the defect. # # --------------------------------------------------------------------------- # 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 libXrender.a executes on this arm # 4 the ABI the wire depends on sizeof(long), XFixed, the structs # 5 the extension-info cache Xrender.c's own list, not extutil's # 6 the standard picture formats the static table, field by field # 7 the picture-attribute packer the value list and its ORDER # 8 the transform and XFixed 16.16, and the 3x3 -> 9 scalars map # 9 the colour path rgba: parsing, and the wire colour # 10 the trapezoid decomposition the geometry, in fixed point + double # 11 the protocol constants the wire values # 12 the entry-point census every module linked out of the archive # 13 the extension that is not there each documented refusal, separately # 14 the display that is not there why 5 to 10 are what this suite tests # # A build where 3 passes and 4 does not has a word-size fault in the toolchain # rather than anything wrong with this recipe -- and 7, 8, 9 and 10 will all be # red with it, because each of them memcpys a client struct onto the wire. One # where 12 goes red has lost an entry point out of the archive, and the name in # the red says which. # # NO CASE BELOW IS EXPECTED RED. Render needs no syscall this kernel lacks: it # is arithmetic and a buffer. Section 13 and 14 are the platform's absence of a # server, and both are asserted as PASSES -- the library saying so correctly is # the contract, not a gap. # --------------------------------------------------------------------------- # 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_LIBXRENDER_ROOT:-}" INC=$R/usr/include/X11/extensions LIB=$R/usr/lib PCD=$R/usr/lib/pkgconfig XT=$R/usr/libexec/libxrender-tests work=${TMPDIR:-/tmp}/bst-libxrender.$$ rm -rf "$work"; mkdir -p "$work" hasfile() { if [ -s "$2" ]; then bst_ok "$1"; else bst_notok "$1" "missing or empty: $2"; fi } # xr_line # # The prefix is matched at the start of a line 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. # # NO FORK PER CASE. The probe's output is read once into $xr_out, and each case # is cut out of it with parameter expansion. A grep per case was ~200 execs, and # the guest's memory grows with every exec (brintos/linux#21): on the converted # image that took the host guest process over the 24000 MiB cap partway through # this suite, which then reported nothing. xr_out=$_BST_NL xr_load() { xr_out=$_BST_NL while IFS= read -r _xr_l; do xr_out="$xr_out$_xr_l$_BST_NL"; done < "$work/out" } xr_line() { case "$xr_out" in *"$_BST_NL$2"*) _xr_r=${xr_out#*"$_BST_NL$2"}; _l="$2${_xr_r%%"$_BST_NL"*}" ;; *) _l= ;; esac check_eq "$1" "$2$3" "$_l" } # --------------------------------------------------------------------------- # 0. THE CANARY, which is not an assertion about libXrender 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 libxrender/suite-canary # --------------------------------------------------------------------------- # 1. THE PAYLOAD. # # libXrender installs exactly one header. /usr/include/X11/extensions is shared # with xorgproto and every other extension library, so it is asserted by NAME: # a count taken here would start moving the day the next port lands. check_rc libxrender/dir-extensions 0 test -d "$INC" hasfile libxrender/hdr-Xrender "$INC/Xrender.h" # render.h and renderproto.h are xorgproto's, not this recipe's, and they are # checked because the probe compiles against them and because a consumer of # libXrender needs all three. A red here is a libxrender-dev dependency that did # not arrive, not a defect in this port. hasfile libxrender/hdr-render "$INC/render.h" hasfile libxrender/hdr-renderproto "$INC/renderproto.h" # Asserted on contents rather than size: a truncated install would still be # non-empty. These three names are the whole of what the layers above -- libXft, # cairo, every toolkit -- reach for first. check libxrender/hdr-has-findstandard \ grep -q 'XRenderFindStandardFormat' "$INC/Xrender.h" check libxrender/hdr-has-composite \ grep -q 'XRenderComposite' "$INC/Xrender.h" check libxrender/hdr-has-transform \ grep -q 'XRenderSetPictureTransform' "$INC/Xrender.h" # The archive ships on both arms: converted, the recipe keeps libXrender.a # beside the .so, and the probe links it by path. Branched per arm, as # 57-libxext is: on the converted arm whatever shared object shipped must be # usable; on the static arm there must be none. hasfile libxrender/archive "$LIB/libXrender.a" if bst_ps_converted "$LIB/libXrender.so" "$LIB/libXrender.so.*"; then bst_lib_shape libxrender/shared-usable "$LIB/libXrender.so*" else check_rc libxrender/no-shared 1 test -e "$LIB/libXrender.so.1" fi hasfile libxrender/probe-shipped "$XT/libxrender-probe" # --------------------------------------------------------------------------- # 2. THE .pc -- how a consumer finds any of the above. hasfile libxrender/pc-present "$PCD/xrender.pc" # THE .pc IS ASSERTED ON ITS CONTENTS FIRST, AND THROUGH pkg-config SECOND. # Read directly, these lines are true whatever else is installed; asked through # pkg-config they are true only if the packages xrender.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 libxrender/pc-requires-renderproto \ grep -q '^Requires:.*renderproto' "$PCD/xrender.pc" check libxrender/pc-requires-xproto \ grep -q '^Requires:.*xproto' "$PCD/xrender.pc" # x11 is a PRIVATE require, and correctly so: a consumer of the shared library # would not need it, but libXrender ships only its archive here, so every # consumer does -- libXrender.a calls into Xlib for every request it encodes. check libxrender/pc-requires-private-x11 \ grep -q '^Requires\.private:.*x11' "$PCD/xrender.pc" check libxrender/pc-libs-name grep -q '\-lXrender' "$PCD/xrender.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 libxrender/pkg-config-present if [ -f "$PCD/renderproto.pc" ] && [ -f "$PCD/xproto.pc" ] && \ [ -f "$PCD/x11.pc" ]; then bst_ok libxrender/pc-deps-present check libxrender/pc-exists pkg-config --exists xrender check libxrender/pc-validate pkg-config --validate xrender check_eq libxrender/pc-modversion 0.9.11 \ "$(pkg-config --modversion xrender 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. check_out libxrender/pc-libs -lXrender \ env PKG_CONFIG_ALLOW_SYSTEM_LIBS=1 pkg-config --libs xrender else bst_skip libxrender/pc-deps-present \ "xrender.pc requires renderproto, xproto and x11; one is missing here" fi else bst_skip libxrender/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/libxrender-probe if cp "$XT/libxrender-probe" "$probe" 2>/dev/null && chmod +x "$probe" 2>/dev/null; then "$probe" >"$work/out" 2>"$work/err" rc=$? xr_load # 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 libxrender/probe-runs else bst_notok libxrender/probe-runs "rc=$rc $(_bst_1line "$(cat "$work/err")")"; fi total=$(sed -n 's/^RENDER-TOTAL //p' "$work/out") if [ -n "$total" ]; then bst_ok libxrender/probe-complete else bst_notok libxrender/probe-complete \ "no RENDER-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 180 ]; then bst_ok libxrender/probe-coverage else bst_notok libxrender/probe-coverage \ "reported ${total:-0} measurements, expected not less than 180"; fi # An out-of-memory abort takes its own path and says so rather than merely # producing a short run. if grep -q '^RENDER-FATAL' "$work/out"; then bst_notok libxrender/probe-no-fatal "$(grep '^RENDER-FATAL' "$work/out" | head -1)" else bst_ok libxrender/probe-no-fatal; 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. xr_line libxrender/probe-version "RENDER-VERSION " "0.9.11" # ------------------------------------------------------------------------- # 4. THE ABI THE WIRE DEPENDS ON. # # Render's client structs are memcpy'd onto the wire as their xRender* # counterparts, and nothing makes the two agree except this arm having no # padding and a 32-bit XFixed. Each case pins one side against the sz_ # constant renderproto.h declares for the other, so a red says which struct # moved rather than "something is wrong with rendering". # sizeof(long) IS LOAD-BEARING AND IS NOT MERELY DESCRIPTIVE. Xlib's Data32 # (Xlibint.h) is _XData32 -- which narrows each long to a CARD32 -- only when # LONG64 is defined, and a straight memcpy otherwise. libXrender's attribute # packer builds `unsigned long values[32]' and hands it to Data32, so on this # ILP32 arm the list goes on the wire VERBATIM and is correct only while this # case says 4. Section 7 is what would notice it in practice; this is what # names the cause. xr_line libxrender/abi-long "RENDER-ABI sizeof-long " "4" xr_line libxrender/abi-xid "RENDER-ABI sizeof-XID " "4" xr_line libxrender/abi-xfixed "RENDER-ABI sizeof-XFixed " "4" xr_line libxrender/abi-xdouble "RENDER-ABI sizeof-XDouble " "8" # Each `A vs B' is the client struct against the wire size. They must be equal # AND they must be these numbers: two structs that agreed with each other at # the wrong size would put a well-formed request of the wrong shape on a wire. xr_line libxrender/abi-color "RENDER-ABI XRenderColor " "8 vs 8" xr_line libxrender/abi-pointfix "RENDER-ABI XPointFixed " "8 vs 8" xr_line libxrender/abi-linefix "RENDER-ABI XLineFixed " "16 vs 16" xr_line libxrender/abi-trapezoid "RENDER-ABI XTrapezoid " "40 vs 40" xr_line libxrender/abi-triangle "RENDER-ABI XTriangle " "24 vs 24" xr_line libxrender/abi-transform "RENDER-ABI XTransform " "36 vs 36" # XRenderPictFormat is NOT a wire struct -- it is the client's decoded form, # and renderproto declares no sz_ for it. Pinned anyway because section 6 # indexes an array of them and a change in its size would move every entry. xr_line libxrender/abi-pictformat "RENDER-ABI XRenderPictFormat " "32" xr_line libxrender/abi-directfmt "RENDER-ABI XRenderDirectFormat " "16" # The four request headers this suite reads back field by field. xr_line libxrender/abi-sz-change "RENDER-ABI sz-ChangePicture " "12" xr_line libxrender/abi-sz-create "RENDER-ABI sz-CreatePicture " "20" xr_line libxrender/abi-sz-transform "RENDER-ABI sz-SetPictureTransform " "44" xr_line libxrender/abi-sz-fill "RENDER-ABI sz-FillRectangles " "20" # ------------------------------------------------------------------------- # 5. THE EXTENSION-INFO CACHE (Xrender.c). # # Render does NOT use extutil.h's shared machinery -- Xrender.c carries its # own copy (its comments say "replaces XextFindDisplay"), so libXext's cache # being green says nothing about this one. It is one list plus a one-entry # cache, and a fault in it 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. That is # legitimate for the LOOKUP -- XRenderFindDisplay compares the pointer and # never dereferences it -- and for nothing else; see the probe's header. xr_line libxrender/cache-fresh-head "RENDER-CACHE fresh-head " "NULL" xr_line libxrender/cache-fresh-cur "RENDER-CACHE fresh-cur " "NULL" xr_line libxrender/cache-fresh-n "RENDER-CACHE fresh-ndisplays " "0" # 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. xr_line libxrender/cache-miss-walk "RENDER-CACHE miss-walk " "c" xr_line libxrender/cache-miss-promote "RENDER-CACHE miss-promotes-cur " "c" # The two halves separated. cache-only unlinks 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. xr_line libxrender/cache-only "RENDER-CACHE cache-only " "c" xr_line libxrender/cache-list-only "RENDER-CACHE list-only " "b" xr_line libxrender/cache-list-repro "RENDER-CACHE list-only-repromotes " "b" xr_line libxrender/cache-find-head "RENDER-CACHE find-head " "a" # RenderHasExtension is the guard every entry point opens with, and it is the # conjunction of `there is a node' and `its codes were filled in'. On this # image the second half is what is always false -- which is section 13. xr_line libxrender/cache-has-null "RENDER-CACHE has-null " "0" xr_line libxrender/cache-has-no-codes "RENDER-CACHE has-no-codes " "0" xr_line libxrender/cache-has-codes "RENDER-CACHE has-codes " "1" # ------------------------------------------------------------------------- # 6. THE STANDARD PICTURE FORMATS. # # XRenderFindStandardFormat carries a static table of five templates and a # mask per template, and hands them to XRenderFindFormat. That table is the # client's half of what ARGB32 MEANS -- get a shift or a mask wrong and every # colour composited through this library is wrong, on a build that compiled, # installed and linked without a word. # # HOW THE TABLE IS PINNED WITHOUT BEING READABLE. It is static, so the probe # cannot inspect it; what it does instead is hand XRenderFindStandardFormat a # ONE-ENTRY format table and report whether the library matched. A match means # the library's template agrees with the descriptor on every field its own # mask names. The sensitivity map then perturbs one field at a time and # reports which perturbations LOSE the match -- which is exactly the set of # fields the mask names. The two together determine the archive's template, # value by value, without ever reading it. # # The descriptors are the Render protocol specification's, not a build host's. for s in ARGB32 RGB24 A8 A4 A1; do xr_line "libxrender/fmt-$s-match" "RENDER-FMT $s-match " "yes" done xr_line libxrender/fmt-argb32 "RENDER-FMT ARGB32-descriptor " \ "type=1 depth=32 red=16 redMask=255 green=8 greenMask=255 blue=0 blueMask=255 alpha=24 alphaMask=255 colormap=0" xr_line libxrender/fmt-rgb24 "RENDER-FMT RGB24-descriptor " \ "type=1 depth=24 red=16 redMask=255 green=8 greenMask=255 blue=0 blueMask=255 alpha=0 alphaMask=0 colormap=0" xr_line libxrender/fmt-a8 "RENDER-FMT A8-descriptor " \ "type=1 depth=8 red=0 redMask=0 green=0 greenMask=0 blue=0 blueMask=0 alpha=0 alphaMask=255 colormap=0" xr_line libxrender/fmt-a4 "RENDER-FMT A4-descriptor " \ "type=1 depth=4 red=0 redMask=0 green=0 greenMask=0 blue=0 blueMask=0 alpha=0 alphaMask=15 colormap=0" xr_line libxrender/fmt-a1 "RENDER-FMT A1-descriptor " \ "type=1 depth=1 red=0 redMask=0 green=0 greenMask=0 blue=0 blueMask=0 alpha=0 alphaMask=1 colormap=0" # The masks, read out as which fields the match is sensitive to. # # id and colormap are `no' for all five: no standard names PictFormatID (the # id is the server's, and asking for a standard format is asking the server # which of ITS ids that is) or PictFormatColormap (all five are direct). # # ARGB32 is the only one that names PictFormatAlpha AND has a non-zero alpha # shift. RGB24 names AlphaMask but NOT Alpha -- upstream's table leaves the # alpha SHIFT unconstrained for a format with no alpha channel, which is # correct and is worth pinning because it looks like an omission. # # The three alpha-only formats do not name Red, Green or Blue -- only their # masks, which must be zero. Their alpha SHIFT is named and is zero. xr_line libxrender/fmt-argb32-mask "RENDER-FMT ARGB32-sensitivity " \ "id=no type=yes depth=yes red=yes redMask=yes green=yes greenMask=yes blue=yes blueMask=yes alpha=yes alphaMask=yes colormap=no" xr_line libxrender/fmt-rgb24-mask "RENDER-FMT RGB24-sensitivity " \ "id=no type=yes depth=yes red=yes redMask=yes green=yes greenMask=yes blue=yes blueMask=yes alpha=no alphaMask=yes colormap=no" for s in A8 A4 A1; do xr_line "libxrender/fmt-$s-mask" "RENDER-FMT $s-sensitivity " \ "id=no type=yes depth=yes red=no redMask=yes green=no greenMask=yes blue=no blueMask=yes alpha=yes alphaMask=yes colormap=no" done # The range check, which XRenderFindStandardFormat answers itself rather than # passing an out-of-bounds index down to the matcher. xr_line libxrender/fmt-range-low "RENDER-FMT out-of-range-low " "NULL" xr_line libxrender/fmt-range-high "RENDER-FMT out-of-range-high " "NULL" # XRenderFindFormat's own contract, over a three-entry table of identical # formats: a zero mask matches everything, `count' skips that many matches, # and running off the end is NULL rather than the last entry. xr_line libxrender/fmt-zero-mask "RENDER-FMT zero-mask-first " "0" xr_line libxrender/fmt-count "RENDER-FMT count-selects " "2" xr_line libxrender/fmt-count-end "RENDER-FMT count-past-end " "NULL" xr_line libxrender/fmt-by-id "RENDER-FMT by-id " "1" # ------------------------------------------------------------------------- # 7. THE PICTURE-ATTRIBUTE PACKER (_XRenderProcessPictureAttributes). # # Thirteen attributes, a 13-bit mask, and a variable-length value list. The # server reads that list POSITIONALLY against the mask's bits from least # significant upward, so the packer's order is a wire contract and not an # implementation detail. Nothing about it is checked by a compiler. # # Each case below is one attribute sent alone: the request type, the request # length in 32-bit words (3 for the bare header, 4 with one value), the mask # as it went out, the one packed value, and the total bytes the encoder wrote. # The values are distinct and non-zero by construction, so a value packed at # the wrong offset names the attribute whose slot it landed in. # # 137 is the probe's own major opcode -- there is no server to assign one, so # it installs a recognisable value and this suite checks the encoder copied # it. 5 is X_RenderChangePicture, which is the specification's. xr_line libxrender/attr-repeat "RENDER-ATTR repeat " \ "req=137/5 len=4 mask=0x1 value=0x11 bytes=16" xr_line libxrender/attr-alpha-map "RENDER-ATTR alpha-map " \ "req=137/5 len=4 mask=0x2 value=0x22 bytes=16" xr_line libxrender/attr-alpha-x "RENDER-ATTR alpha-x-origin " \ "req=137/5 len=4 mask=0x4 value=0x33 bytes=16" xr_line libxrender/attr-alpha-y "RENDER-ATTR alpha-y-origin " \ "req=137/5 len=4 mask=0x8 value=0x44 bytes=16" xr_line libxrender/attr-clip-x "RENDER-ATTR clip-x-origin " \ "req=137/5 len=4 mask=0x10 value=0x55 bytes=16" xr_line libxrender/attr-clip-y "RENDER-ATTR clip-y-origin " \ "req=137/5 len=4 mask=0x20 value=0x66 bytes=16" xr_line libxrender/attr-clip-mask "RENDER-ATTR clip-mask " \ "req=137/5 len=4 mask=0x40 value=0x77 bytes=16" xr_line libxrender/attr-graphics-exp "RENDER-ATTR graphics-exposure " \ "req=137/5 len=4 mask=0x80 value=0x88 bytes=16" xr_line libxrender/attr-subwindow "RENDER-ATTR subwindow-mode " \ "req=137/5 len=4 mask=0x100 value=0x99 bytes=16" xr_line libxrender/attr-poly-edge "RENDER-ATTR poly-edge " \ "req=137/5 len=4 mask=0x200 value=0xaa bytes=16" xr_line libxrender/attr-poly-mode "RENDER-ATTR poly-mode " \ "req=137/5 len=4 mask=0x400 value=0xbb bytes=16" xr_line libxrender/attr-dither "RENDER-ATTR dither " \ "req=137/5 len=4 mask=0x800 value=0xcc bytes=16" xr_line libxrender/attr-component-alpha "RENDER-ATTR component-alpha " \ "req=137/5 len=4 mask=0x1000 value=0xdd bytes=16" # All thirteen at once. THIS is the case a per-bit test cannot replace: the # order. Thirteen words after a three-word header is a length of 16 and 64 # bytes written, and the values must come out in mask-bit order. xr_line libxrender/attr-all-mask "RENDER-ATTR all-mask " "0x1fff" xr_line libxrender/attr-all-length "RENDER-ATTR all-length " "16" xr_line libxrender/attr-all-bytes "RENDER-ATTR all-bytes " "64" xr_line libxrender/attr-all-values "RENDER-ATTR all-values " \ "11,22,33,44,55,66,77,88,99,aa,bb,cc,dd" xr_line libxrender/attr-all-order "RENDER-ATTR all-misplaced " "0" # An empty mask sends the bare request and no value list at all -- not a list # of thirteen zeroes, and not a request that was never formed. xr_line libxrender/attr-empty-length "RENDER-ATTR empty-length " "3" xr_line libxrender/attr-empty-bytes "RENDER-ATTR empty-bytes " "12" # XRenderCreatePicture packs the SAME value list behind a five-word header, # and is the only entry point exercised here that allocates an XID. The id is # the probe's own allocator's, installed as dpy->resource_alloc -- which is # where a real Xlib client's ids come from too. xr_line libxrender/attr-create-pid "RENDER-ATTR create-pid " "0x401" xr_line libxrender/attr-create-req "RENDER-ATTR create-req " "137/4" xr_line libxrender/attr-create-echo "RENDER-ATTR create-echoes-pid " "yes" xr_line libxrender/attr-create-draw "RENDER-ATTR create-drawable " "0xbeef" xr_line libxrender/attr-create-format "RENDER-ATTR create-format " "0x6001" xr_line libxrender/attr-create-mask "RENDER-ATTR create-mask " "0x1fff" xr_line libxrender/attr-create-length "RENDER-ATTR create-length " "18" xr_line libxrender/attr-create-first "RENDER-ATTR create-first-value " "0x11" xr_line libxrender/attr-create-last "RENDER-ATTR create-last-value " "0xdd" # ------------------------------------------------------------------------- # 8. XFixed AND THE TRANSFORM. # # XFixed is 16.16 signed fixed point, XDoubleToFixed is a multiply by 65536 # and a truncating cast, XFixedToDouble is a divide. Every value below is # exactly representable, so every one of them must come back bit for bit; a # value that is NOT representable is deliberately absent, because its # truncation is upstream's and is the same everywhere. xr_line libxrender/xfixed-one "RENDER-XFORM one " "65536" xr_line libxrender/xfixed-half "RENDER-XFORM half " "32768" xr_line libxrender/xfixed-sixteenth "RENDER-XFORM sixteenth " "4096" xr_line libxrender/xfixed-eps "RENDER-XFORM eps " "1" xr_line libxrender/xfixed-neg "RENDER-XFORM neg " "-163840" xr_line libxrender/xfixed-back-one "RENDER-XFORM back-one " "1" xr_line libxrender/xfixed-back-half "RENDER-XFORM back-half " "1" xr_line libxrender/xfixed-back-neg "RENDER-XFORM back-neg " "1" # Ten exactly-representable values, none of which may lose a bit. The count is # asserted beside the failure count so that a probe which quietly shortened # the list cannot report zero failures over nothing. xr_line libxrender/xfixed-rt-bad "RENDER-XFORM round-trip-bad " "0" xr_line libxrender/xfixed-rt-n "RENDER-XFORM round-trip-n " "10" # The 3x3 on the wire. XTransform is XFixed[3][3] row-major; xRenderTransform # is nine named scalars, and XRenderSetPictureTransform assigns one to the # other by hand -- nine lines that a transposed pair would survive unnoticed # for an identity matrix. The matrix here is deliberately asymmetric: element # (r,c) is 4096+3r+c, so a transpose shows up in the very first case. # 28 is X_RenderSetPictureTransform; 11 words is the 44-byte request. xr_line libxrender/xform-req "RENDER-XFORM req " "137/28" xr_line libxrender/xform-length "RENDER-XFORM length " "11" xr_line libxrender/xform-bytes "RENDER-XFORM bytes " "44" xr_line libxrender/xform-picture "RENDER-XFORM picture " "0x2345" xr_line libxrender/xform-matrix "RENDER-XFORM matrix " \ "4096,4097,4098,4099,4100,4101,4102,4103,4104" xr_line libxrender/xform-m11 "RENDER-XFORM matrix11 " "4096" xr_line libxrender/xform-m33 "RENDER-XFORM matrix33 " "4104" # ------------------------------------------------------------------------- # 9. THE COLOUR PATH. # # XRenderParseColor's rgba: arm is the one entry point in this library that # runs to completion without a Display at all -- the branch returns before the # else-branch's DefaultColormap(dpy,...). It parses one to four hex digits per # element, SCALES a short element across the full 16 bits, and premultiplies # every channel by alpha, which is the contract XRenderColor states ("Colors # must be premultiplied by alpha by the client"). # Four digits: taken verbatim, then premultiplied. xr_line libxrender/color-full "RENDER-COLOR parse rgba:ffff/8000/0000/ffff " \ "st=1 r=65535 g=32768 b=0 a=65535" # Alpha at half: every channel halves with it. This is the premultiply, and a # build that skipped it would answer 65535 three times. xr_line libxrender/color-premul "RENDER-COLOR parse rgba:ffff/ffff/ffff/8000 " \ "st=1 r=32768 g=32768 b=32768 a=32768" xr_line libxrender/color-zero "RENDER-COLOR parse rgba:0000/0000/0000/0000 " \ "st=1 r=0 g=0 b=0 a=0" # SHORT ELEMENTS ARE SCALED, NOT SHIFTED. `f' is 0xffff and not 0xf000; `80' # is 0x8080 and not 0x8000. The arithmetic is (v * 0xFFFF) / ((1 << 4n) - 1) # through a 32-bit unsigned intermediate -- the widest value this computation # reaches on this arm, and the reason it is worth measuring here at all. xr_line libxrender/color-1digit "RENDER-COLOR parse rgba:f/0/0/f " \ "st=1 r=65535 g=0 b=0 a=65535" xr_line libxrender/color-2digit "RENDER-COLOR parse rgba:80/80/80/ffff " \ "st=1 r=32896 g=32896 b=32896 a=65535" xr_line libxrender/color-3digit "RENDER-COLOR parse rgba:123/456/789/fff " \ "st=1 r=4657 g=17764 b=30871 a=65535" # The documented refusals, each by its own path: a fifth digit, an empty # element, and a digit outside [0-9a-f]. Each returns 0 and leaves the caller's # XRenderColor untouched, which is the half a caller actually depends on. xr_line libxrender/color-too-long "RENDER-COLOR parse rgba:fffff/0/0/f " \ "st=0 r=0 g=0 b=0 a=0" xr_line libxrender/color-empty "RENDER-COLOR parse rgba:/0/0/f " \ "st=0 r=0 g=0 b=0 a=0" # UPPER CASE IS REFUSED, AND THAT IS UPSTREAM'S CHOICE RATHER THAN THIS ARM'S. # Color.c has the A-F arm commented out with "assume string in lowercase", so # "FFFF" is not a colour here. Pinned as what the code does rather than as # what it should do; a red here would mean the parser moved, not that the # oddity was fixed. xr_line libxrender/color-uppercase "RENDER-COLOR parse rgba:FFFF/0/0/f " \ "st=0 r=0 g=0 b=0 a=0" xr_line libxrender/color-bad-digit "RENDER-COLOR parse rgba:zzzz/0/0/f " \ "st=0 r=0 g=0 b=0 a=0" # The colour on the wire. 26 is X_RenderFillRectangles, 3 is PictOpOver, and # the four CARD16s are 0x1111/0x2222/0x3333/0x4444 in decimal. xr_line libxrender/fill-req "RENDER-COLOR fill-req " "137/26" xr_line libxrender/fill-op "RENDER-COLOR fill-op " "3" xr_line libxrender/fill-dst "RENDER-COLOR fill-dst " "0x3456" xr_line libxrender/fill-color "RENDER-COLOR fill-color " "4369/8738/13107/17476" xr_line libxrender/fill-length "RENDER-COLOR fill-length " "7" xr_line libxrender/fill-bytes "RENDER-COLOR fill-bytes " "28" # AND THE BATCHING, which is the only place in this library where a second # call's effect depends on the first. XRenderFillRectangle re-reads # dpy->last_req and, if the op, destination and colour all match, appends an # xRectangle to the previous request and grows its length rather than forming # a new one. A build that got this wrong would send well-formed requests that # drew the wrong number of rectangles. xr_line libxrender/fill-batched "RENDER-COLOR fill-batched-same-req " "yes" xr_line libxrender/fill-batched-len "RENDER-COLOR fill-batched-length " "9" xr_line libxrender/fill-batched-b "RENDER-COLOR fill-batched-bytes " "36" xr_line libxrender/fill-rect0 "RENDER-COLOR fill-rect0 " "1,2,3,4" xr_line libxrender/fill-rect1 "RENDER-COLOR fill-rect1 " "5,6,7,8" # And the two conditions that must BREAK the batch. Without these the case # above would pass on an implementation that batched unconditionally, which is # the failure that corrupts a drawing rather than merely slowing it. xr_line libxrender/fill-break-colour "RENDER-COLOR fill-colour-breaks-batch " "yes" xr_line libxrender/fill-break-dst "RENDER-COLOR fill-dst-breaks-batch " "yes" # ------------------------------------------------------------------------- # 10. THE TRAPEZOID DECOMPOSITION (Poly.c). # # XRenderCompositeDoublePoly converts a polygon of DOUBLES into edges of # XFixed, sorts them, computes an x-coordinate per edge per scanline group # through a double multiply and divide, and emits trapezoids -- all client # side, before one byte is sent. It is the largest piece of arithmetic in this # library and the only place doubles reach the wire. # # The polygon is the rectangle (0,0)-(20,0)-(20,10)-(0,10). Its corners are # integers, so every conversion is exact and the answer cannot differ between # this arm and the build host. Its two horizontal edges are DROPPED (Poly.c's # "drop horizontal edges"), its two vertical ones survive, and they bound # exactly one trapezoid -- so a decomposition that emitted two, or none, is # visible in ntraps alone. # # 10 is X_RenderTrapezoids. 655360 is 10.0 in 16.16; 1310720 is 20.0. xr_line libxrender/poly-req "RENDER-POLY req " "137/10" xr_line libxrender/poly-op "RENDER-POLY op " "3" xr_line libxrender/poly-src "RENDER-POLY src " "0x11" xr_line libxrender/poly-dst "RENDER-POLY dst " "0x22" # A NULL maskFormat is the documented "use the destination's" and goes on the # wire as zero rather than being dereferenced. xr_line libxrender/poly-mask "RENDER-POLY mask-format " "0x0" xr_line libxrender/poly-bytes "RENDER-POLY bytes " "64" xr_line libxrender/poly-ntraps "RENDER-POLY ntraps " "1" xr_line libxrender/poly-top "RENDER-POLY top " "0" xr_line libxrender/poly-bottom "RENDER-POLY bottom " "655360" xr_line libxrender/poly-left "RENDER-POLY left " "0,0,0,655360" xr_line libxrender/poly-right "RENDER-POLY right " "1310720,0,1310720,655360" # The encoder the polygon path ends in, driven directly with two trapezoids so # that the length arithmetic covers more than one element. Two 40-byte # trapezoids behind a 24-byte header is 104 bytes and a length of 26 words. xr_line libxrender/traps-bytes "RENDER-POLY traps-bytes " "104" xr_line libxrender/traps-length "RENDER-POLY traps-length " "26" xr_line libxrender/traps-xsrc "RENDER-POLY traps-xsrc " "7" xr_line libxrender/traps-ysrc "RENDER-POLY traps-ysrc " "9" xr_line libxrender/traps-0 "RENDER-POLY traps-0 " "256,512,768,2560" xr_line libxrender/traps-1 "RENDER-POLY traps-1 " "257,513,769,2561" # ------------------------------------------------------------------------- # 11. THE PROTOCOL CONSTANTS. # # Wire values: a client that disagrees with a server about PictOpOver does not # fail to build, it composites with the wrong operator. Each is stated from # the published Render protocol specification rather than diffed against # anything -- there is nothing about a second machine that could make an # answer here more true. xr_line libxrender/const-name "RENDER-CONST RENDER_NAME " "RENDER" xr_line libxrender/const-major "RENDER-CONST RENDER_MAJOR " "0" xr_line libxrender/const-minor "RENDER-CONST RENDER_MINOR " "11" # The name the library will put into QueryExtension, out of the archive's own # storage rather than out of the header. This case is also the only evidence # that Xrender.o's globals linked at all. xr_line libxrender/const-extname "RENDER-CONST extension-name " "RENDER" # The request opcodes this suite has already read back off the wire, plus the # two that bound the set. xr_line libxrender/const-req-qv "RENDER-CONST X_RenderQueryVersion " "0" xr_line libxrender/const-req-qpf "RENDER-CONST X_RenderQueryPictFormats " "1" xr_line libxrender/const-req-create "RENDER-CONST X_RenderCreatePicture " "4" xr_line libxrender/const-req-change "RENDER-CONST X_RenderChangePicture " "5" xr_line libxrender/const-req-free "RENDER-CONST X_RenderFreePicture " "7" xr_line libxrender/const-req-comp "RENDER-CONST X_RenderComposite " "8" xr_line libxrender/const-req-traps "RENDER-CONST X_RenderTrapezoids " "10" xr_line libxrender/const-req-fill "RENDER-CONST X_RenderFillRectangles " "26" xr_line libxrender/const-req-xform "RENDER-CONST X_RenderSetPictureTransform " "28" xr_line libxrender/const-req-solid "RENDER-CONST X_RenderCreateSolidFill " "33" xr_line libxrender/const-req-conic "RENDER-CONST X_RenderCreateConicalGradient " "36" xr_line libxrender/const-nreq "RENDER-CONST RenderNumberRequests " "37" xr_line libxrender/const-nerr "RENDER-CONST RenderNumberErrors " "5" xr_line libxrender/const-type-idx "RENDER-CONST PictTypeIndexed " "0" xr_line libxrender/const-type-dir "RENDER-CONST PictTypeDirect " "1" # The compositing operators. The first four are Porter-Duff and are what every # consumer above this library names; the three MINIMUMs are the bases of the # extended sets, which are non-contiguous with the basic ones and are the # numbers a hand-written client gets wrong. xr_line libxrender/const-op-clear "RENDER-CONST PictOpClear " "0" xr_line libxrender/const-op-src "RENDER-CONST PictOpSrc " "1" xr_line libxrender/const-op-over "RENDER-CONST PictOpOver " "3" xr_line libxrender/const-op-add "RENDER-CONST PictOpAdd " "12" xr_line libxrender/const-op-max "RENDER-CONST PictOpMaximum " "13" xr_line libxrender/const-op-disj "RENDER-CONST PictOpDisjointMinimum " "0x10" xr_line libxrender/const-op-conj "RENDER-CONST PictOpConjointMinimum " "0x20" xr_line libxrender/const-op-blend "RENDER-CONST PictOpBlendMinimum " "0x30" xr_line libxrender/const-op-hsl "RENDER-CONST PictOpHSLLuminosity " "0x3e" xr_line libxrender/const-std-num "RENDER-CONST PictStandardNUM " "5" xr_line libxrender/const-fmt-id "RENDER-CONST PictFormatID " "0x1" xr_line libxrender/const-fmt-cmap "RENDER-CONST PictFormatColormap " "0x800" xr_line libxrender/const-cp-first "RENDER-CONST CPRepeat " "0x1" xr_line libxrender/const-cp-last "RENDER-CONST CPComponentAlpha " "0x1000" xr_line libxrender/const-cp-bit "RENDER-CONST CPLastBit " "12" xr_line libxrender/const-rep-none "RENDER-CONST RepeatNone " "0" xr_line libxrender/const-rep-refl "RENDER-CONST RepeatReflect " "3" xr_line libxrender/const-edge "RENDER-CONST PolyEdgeSharp " "0" xr_line libxrender/const-mode "RENDER-CONST PolyModeImprecise " "1" xr_line libxrender/const-sp-unk "RENDER-CONST SubPixelUnknown " "0" xr_line libxrender/const-sp-none "RENDER-CONST SubPixelNone " "5" # The filter names are STRINGS on the wire, and a client that spells one # differently simply gets BadValue from a server that has it. xr_line libxrender/const-filt-near "RENDER-CONST FilterNearest " "nearest" xr_line libxrender/const-filt-best "RENDER-CONST FilterBest " "best" xr_line libxrender/const-filt-none "RENDER-CONST FilterAliasNone " "-1" xr_line libxrender/const-err-fmt "RENDER-CONST BadPictFormat " "0" xr_line libxrender/const-err-glyph "RENDER-CONST BadGlyph " "4" # ------------------------------------------------------------------------- # 12. THE ENTRY-POINT CENSUS. # # Section 14 establishes that no display opens here, which makes every # round-trip entry point unreachable -- so the only thing left to say about # the ones sections 5 to 10 do not drive is that they EXIST: that the cross # build compiled each module, that the static linker resolved each name out of # libXrender.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. # # This matters more here than for most ports: libXft and cairo are the next # two members of this stack and they reach for these names directly, so a # missing one fails somebody else's do_compile weeks later rather than # anything on this image. nsym=$(sed -n 's/^RENDER-SYM-COUNT //p' "$work/out") if [ -n "$nsym" ] && [ "$nsym" -ge 45 ]; then bst_ok libxrender/sym-count else bst_notok libxrender/sym-count \ "census names ${nsym:-0} entry points, expected not less than 45"; fi xr_line libxrender/sym-none-null "RENDER-SYM-NULL " "0" # One per source module, so a red says which file left the archive rather than # only that the count moved. XRenderFindDisplay is Xrender.c's own and is not # in Xrender.h -- it is exported because every other module calls it. for s in XRenderFindDisplay XRenderCreatePicture XRenderComposite \ XRenderCompositeTrapezoids XRenderCompositeTriangles \ XRenderCompositeDoublePoly XRenderFillRectangle \ XRenderFillRectangles XRenderAddTraps XRenderCreateGlyphSet \ XRenderCompositeText8 XRenderParseColor XRenderCreateCursor \ XRenderQueryFilters XRenderCreateLinearGradient; do xr_line "libxrender/sym-$s" "RENDER-SYM $s " "linked" done # ------------------------------------------------------------------------- # 13. THE EXTENSION THAT IS NOT THERE. # # THIS SECTION IS ALL PASSES AND DESCRIBES A PLATFORM ABSENCE. It is not a # gap: the contract is that each entry point REFUSES, through its own # documented value, rather than crashing or handing back a half-built object. # # The state under test is the one XRenderExtAddDisplay leaves a display in # when the server does not have RENDER -- a node in the list whose codes are # NULL -- and it is the state EVERY display on this image would be in. Each # entry point below reaches its own RenderCheckExtension or # RenderSimpleCheckExtension and returns before it touches the Display, which # is why forty-odd separate refusals can be measured in one process. # # The `untouched' cases are the half a caller actually depends on: a refusal # that had written through the out-parameters would leave a client believing # it had an event base. xr_line libxrender/gone-query-ext "RENDER-GONE QueryExtension " "0" xr_line libxrender/gone-query-ext-out "RENDER-GONE QueryExtension-untouched " \ "ev=-1 er=-1" xr_line libxrender/gone-query-ver "RENDER-GONE QueryVersion " "0" xr_line libxrender/gone-query-ver-out "RENDER-GONE QueryVersion-untouched " \ "major=-1 minor=-1" xr_line libxrender/gone-query-fmts "RENDER-GONE QueryFormats " "0" # SubPixelUnknown, which is 0 and is the documented answer rather than an # error code borrowed from somewhere else. xr_line libxrender/gone-subpixel-q "RENDER-GONE QuerySubpixelOrder " "0" xr_line libxrender/gone-subpixel-s "RENDER-GONE SetSubpixelOrder " "0" xr_line libxrender/gone-find-format "RENDER-GONE FindFormat " "NULL" for s in ARGB32 RGB24 A8 A4 A1; do xr_line "libxrender/gone-std-$s" "RENDER-GONE FindStandardFormat-$s " "NULL" done xr_line libxrender/gone-index-vals "RENDER-GONE QueryPictIndexValues " "NULL" xr_line libxrender/gone-filters "RENDER-GONE QueryFilters " "NULL" # The resource-returning ones answer 0, which is None. Note that this is NOT # the allocator failing: it is the guard returning before XAllocID is reached, # so no id is consumed -- a client that retried after starting a server would # get the ids it expected. xr_line libxrender/gone-create-pic "RENDER-GONE CreatePicture " "0" xr_line libxrender/gone-create-gs "RENDER-GONE CreateGlyphSet " "0" xr_line libxrender/gone-ref-gs "RENDER-GONE ReferenceGlyphSet " "0" xr_line libxrender/gone-solid "RENDER-GONE CreateSolidFill " "0" xr_line libxrender/gone-cursor "RENDER-GONE CreateCursor " "0" # The fifteen void entry points have no value to inspect, so what is asserted # is that each RETURNED and that not one of them wrote a byte -- the display # they were handed has NULL buffer pointers, so a request formed there would # have faulted rather than gone unnoticed. xr_line libxrender/gone-void-return "RENDER-GONE void-arms-returned " "yes" xr_line libxrender/gone-void-silent "RENDER-GONE void-arms-sent-nothing " "yes" # ------------------------------------------------------------------------- # 14. THE DISPLAY THAT IS NOT THERE. # # The documented no-server path, and the reason sections 5 to 13 are what this # suite tests instead of Render's drawing API: libXrender'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 XRenderQueryExtension 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: each # opens with XRenderFindDisplay(dpy), which on a miss reaches # XRenderExtAddDisplay 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. xr_line libxrender/dpy-no-env "RENDER-DPY no-env " "NULL" xr_line libxrender/dpy-unix-0 "RENDER-DPY unix-0 " "NULL" xr_line libxrender/dpy-unix-99 "RENDER-DPY unix-99 " "NULL" xr_line libxrender/dpy-tcp "RENDER-DPY tcp " "NULL" xr_line libxrender/dpy-end "RENDER-DPY reached-end " "yes" else bst_notok libxrender/probe-stage "cannot stage $XT/libxrender-probe" fi rm -rf "$work"