. "$BST_LIB" # BST-TIMEOUT: 300 # Two bounded probe runs plus ~150 shell extractions. The # same figure 57-libxcomposite.test carries for a probe of # the same shape. # libXxf86vm 1.1.5 -- the client half of the XFree86-VidModeExtension (poky # recipes-graphics/xorg-lib). See libxxf86vm_%.bbappend for what the port adds, # and BRINTOS-2489 for the ticket. # # --------------------------------------------------------------------------- # WHAT IS MEASURED HERE, AND -- FIRST -- WHAT IS NOT CLAIMED # # THIS SUITE DOES NOT READ OR SET A VIDEO MODE, AND CANNOT. The extension # exists to read and change a server's mode timings and gamma ramps, and ALL 22 # ENTRY POINTS TAKE A Display. This image has no X server, so no mode is ever # read here and no ramp is ever set -- ever, not merely today. A reader looking # for "the library changed a mode" will not find it, and should not: it is not # a gap in the port, it is what a server-less image permits. # # What is asserted instead is chosen to be worth something anyway: # # the ARTEFACTS the archive, the header and the pkg-config file, # which are the practical value of this package: it # exists to be linked against -- xgamma (BRINTOS-2437) # is the tool this member unblocks -- and that work # reads all three. # # the PACKAGING the .deb having installed on target, and the files # landing where the recipe promises. This is the # ticket's "what ported means here" clause. # # the WIRE LAYOUT sizeof and the member offsets of # XF86VidModeModeInfo and XF86VidModeModeLine, which is # the ticket's substantive clause and the reason this # port has a probe at all. The structures mix # `unsigned short' timings with an `unsigned int' flags # word and an `int' privsize: a packing difference on # wasm32 would misread every mode a server ever reports # and NOTHING WOULD FAIL TO BUILD. The request and # reply sizes are asserted beside them against the # constants the protocol fixes. # # the HONEST-FAILURE each entry point's DOCUMENTED no-extension return, # ARM run twice -- through a registry entry with no codes, # and through a NULL Display -- so the refusal is shown # to be a property of the entry points rather than of # which way the lookup went. This is the ticket's # "refuse cleanly with no DISPLAY", measured. # # the NEGOTIATED ARM the other side of the same branch, for the one entry # point that still returns before the wire once the # extension is present. Without it, a guard that always # returned the failure sentinel would be green above # for the wrong reason. # # the SYMBOL SET all 22 public functions, against the committed list # below. A build that silently dropped part of the API # fails here rather than at the first consumer's link. # # XOpenDisplay's own with no DISPLAY, and with a DISPLAY naming an address # REFUSAL nothing is listening on -- the ticket's second and # third probe clauses, in a SEPARATE probe run because # they are the only part that touches the network # stack. # # --------------------------------------------------------------------------- # HOW THE FAILURE ARM IS REACHED WITHOUT UNDEFINED BEHAVIOUR # # Passing a NULL or invented Display straight into an entry point is undefined # behaviour, not a documented failure: find_display() misses the cache, falls # into XextAddDisplay(), and that calls XInitExtension(dpy, ...), which # dereferences. A probe that crashed there would be reporting on its own # mistake. # # libXcomposite and libXfixes seed their own extension list, which they declare # with external linkage. LIBXXF86VM CANNOT BE DRIVEN THAT WAY -- its registry is # `static XExtensionInfo _xf86vidmode_info_data' in src/XF86VMode.c, private to # the translation unit. So the probe supplies the FIVE extutil.o functions the # library calls (XextCreateExtension, XextFindDisplay, XextAddDisplay, # XextRemoveDisplay, XMissingExtension) and the recipe links it WITHOUT # libXext.a, so the static linker resolves all five in the probe and extutil.o # is never pulled in. That is an ordinary static link against a different # implementation, not a run-time interposition; the library's own code runs its # real prologue for every entry point, and the Display is only ever COMPARED, # never loaded through. See the probe source for why the stock # XMissingExtension would not have been safe (its default handler prints # DisplayString(dpy)). # # --------------------------------------------------------------------------- # NOTHING HERE HAD RUN ON A TARGET WHEN IT WAS WRITTEN, BUT IT IS NOT GUESSWORK # # Every expectation below was MEASURED on 2026-09-11 by a reference run of this # exact probe source, compiled against libXxf86vm 1.1.5 built from the same # tarball on x86-64 and run with no DISPLAY. 176 lines, exit 0. # # FIVE OF THOSE VALUES DO NOT CARRY ACROSS THE WORD SIZE, AND THEY ARE THE ONLY # FIVE: ModeLine-size, ModeLine-private, ModeInfo-size, ModeInfo-private and # Monitor-size all move because each structure ends in a pointer. The LP64 # reference host answered 40, 32, 40, 32 and 48; this ILP32 arm answers 32, 28, # 36, 32 and 28, and those are the numbers asserted below. They are not # predictions: the probe carries a _Static_assert for each, per arm, so the # recipe's do_compile on the build host is what measured them. # # --------------------------------------------------------------------------- # THE SHARED OBJECT IS ASSERTED BY SHAPE, NOT BY ABSENCE # # libxxf86vm was off brintos.conf's allow-list (BRINTOS-2727 retired it), so today # FILES:${PN} (${libdir}/libXxf86vm.so.*) matches nothing and the main package # is never emitted. Asserting the .so absent would go red the day libxxf86vm is # allow-listed by BRINTOS-1740's conversion, which is a property of the build # configuration rather than of this port. bst_lib_shape is the assertion that # survives the conversion: no shared object means unconverted and passes; one # that IS shipped passes iff every file is real and non-empty, which is the # failure conversion actually introduces. # # THE TICKET'S "the shipped soname" CLAUSE IS READ THAT WAY, and its "the # version macros the installed header defines ... asserted to agree with 1.1.5" # clause is NARROWED -- see the version section below for why it cannot be met # as written. PROBE=${BST_LIBXXF86VM_PROBE:-/usr/libexec/libxxf86vm-tests/libxxf86vm-probe} LIB=/usr/lib ARCHIVE=$LIB/libXxf86vm.a PCFILE=$LIB/pkgconfig/xxf86vm.pc INCDIR=/usr/include/X11/extensions t=${TMPDIR:-/tmp} out=$t/bst-libxxf86vm-probe.$$.out oout=$t/bst-libxxf86vm-open.$$.out # The first BST result line of a suite is dropped by the guest console, so the # suite opens with one that costs nothing to lose. bst_ok libxxf86vm/suite-begin # =========================================================================== # 1. THE ARTEFACTS # =========================================================================== check libxxf86vm/archive-present test -f "$ARCHIVE" check libxxf86vm/archive-nonempty test -s "$ARCHIVE" check libxxf86vm/header-present test -f "$INCDIR/xf86vmode.h" # The header must DECLARE the API, not merely exist -- a truncated or wrong # install would satisfy the check above. XF86VidModeQueryExtension is the one # prototype unique to this header and to no dependency's. check libxxf86vm/header-declares-api \ grep -q "XF86VidModeQueryExtension" "$INCDIR/xf86vmode.h" # The two structures the whole probe is about have to be IN the header this # image ships, not only in the one the build host compiled against. check libxxf86vm/header-declares-modeinfo \ grep -q "XF86VidModeModeInfo" "$INCDIR/xf86vmode.h" check libxxf86vm/header-declares-modeline \ grep -q "XF86VidModeModeLine" "$INCDIR/xf86vmode.h" # THE HEADER DOES NOT CARRY THE PROTOCOL VERSION, AND THAT IS WORTH PINNING. # xf86vmode.h includes , which carries the error codes # and permission bits and NO version macro; XF86VIDMODE_MAJOR_VERSION lives in # xorgproto's xf86vmproto.h, the protocol header this client header does not # include. A consumer that expected to find the version here would find # nothing, so the arrangement is asserted rather than assumed. check libxxf86vm/header-includes-xf86vm \ grep -q "X11/extensions/xf86vm.h" "$INCDIR/xf86vmode.h" if grep -q "XF86VIDMODE_MAJOR_VERSION" "$INCDIR/xf86vmode.h" 2>/dev/null; then bst_notok libxxf86vm/header-carries-no-version \ "xf86vmode.h now defines XF86VIDMODE_MAJOR_VERSION; the probe reads it from xf86vmproto.h and the two could disagree" else bst_ok libxxf86vm/header-carries-no-version fi check libxxf86vm/proto-header-present test -f "$INCDIR/xf86vmproto.h" # No shared object means unconverted, and FILES:${PN} matching nothing is the # port working rather than a gap. Once it converts, the red worth having is a # libXxf86vm.so that is dangling or empty, which every consumer of this sysroot # would inherit. bst_lib_shape libxxf86vm/shared-object-shape "$LIB/libXxf86vm.so" "$LIB/libXxf86vm.so.1" # =========================================================================== # 2. THE .pc -- how a consumer finds any of the above # # NOT `require pkg-config'. require ENDS THE FILE when the tool is absent, and # everything this suite exists for comes after this section. # =========================================================================== check libxxf86vm/pkgconfig-present test -f "$PCFILE" check libxxf86vm/pkgconfig-names-xxf86vm grep -q "^Name: *Xxf86vm" "$PCFILE" check libxxf86vm/pkgconfig-version-file grep -q "^Version: *1\.1\.5" "$PCFILE" # The two lines a consumer's build actually consumes -- the ticket's "reported # cflags and libs". A .pc that lost either is a package that cannot be linked # against however complete its files are. check libxxf86vm/pkgconfig-cflags grep -q '^Cflags: *-I\${includedir}' "$PCFILE" check libxxf86vm/pkgconfig-libs grep -q '^Libs: *-L\${libdir} *-lXxf86vm' "$PCFILE" # Requires is the public closure a consumer inherits; Requires.private is what # the bbappend's link closure is spelled out FROM. The recipe deliberately does # NOT link libXext -- the probe supplies the five extutil entry points itself -- # so this case is also the pin on the assumption behind that omission: if # upstream ever changed the line, the recipe's hand-named archives would have to # change with it, and this is where that shows first. check libxxf86vm/pkgconfig-requires \ grep -q "^Requires: *xf86vidmodeproto" "$PCFILE" check libxxf86vm/pkgconfig-requires-private \ grep -q "^Requires.private: *x11 xext" "$PCFILE" if command -v pkg-config >/dev/null 2>&1; then bst_ok libxxf86vm/pkg-config-present # `pkg-config --exists xxf86vm' also resolves xxf86vm.pc's # `Requires: xf86vidmodeproto', so this case is simultaneously an assertion # that xorgproto-dev is in this image. A red here with the file cases green # means the .pc chain broke, not libXxf86vm. check libxxf86vm/pc-exists pkg-config --exists xxf86vm check libxxf86vm/pc-validate pkg-config --validate xxf86vm # The ticket asks for this one by name. 1.1.5 is the PACKAGE version, which # is what a .pc reports; it is not the protocol version, which is 2.2 and # comes from xorgproto -- see the probe's proto-major/proto-minor cases. check_eq libxxf86vm/pc-modversion 1.1.5 "$(pkg-config --modversion xxf86vm 2>/dev/null)" # -lXxf86vm is the whole point of the .pc: a consumer that got an empty Libs # line would link nothing and fail at the first XF86VidMode symbol. check_out libxxf86vm/pc-libs -lXxf86vm pkg-config --libs xxf86vm else bst_skip libxxf86vm/pkg-config-present "pkg-config not installed on this image" fi # =========================================================================== # 3. THE PACKAGING -- the ticket's "the .deb installs on target with dpkg and # the files the recipe promises land where the packaging says". # # The image installs these with dpkg at do_rootfs, so what is checkable on # target is that the package database records them and that each package's # own file list resolves on the filesystem. Re-installing a .deb here would # be testing dpkg, not this port. # =========================================================================== if [ -r /var/lib/dpkg/status ]; then for p in libxxf86vm-dev libxxf86vm-staticdev libxxf86vm-tests; do if grep -qx "Package: $p" /var/lib/dpkg/status 2>/dev/null; then bst_ok "libxxf86vm/pkg-$p" else bst_notok "libxxf86vm/pkg-$p" "$p is not in the package database, so this image did not install it" fi done # Every file each of those packages claims must actually be on the # filesystem. This is the half that catches a FILES: pattern promising a path # the install never wrote. for p in libxxf86vm-dev libxxf86vm-staticdev libxxf86vm-tests; do lst=/var/lib/dpkg/info/$p.list if [ -r "$lst" ]; then # bst_local, not `done < "$lst"'. A stdin redirect the top-level shell # performs on the virtiofs root makes dup2(2) return 513 and ash EXITS, # so the suite would end HERE and every case already emitted would be # reported as a clean, shorter run (brintos/linux#73). miss=$(while read -r f; do [ -e "$f" ] || [ -L "$f" ] || printf '%s ' "$f" done < "$(bst_local "$lst")") check_eq "libxxf86vm/files-$p" "" "$miss" else bst_skip "libxxf86vm/files-$p" "$lst is not readable on this image" fi done else bst_skip libxxf86vm/dpkg-status "/var/lib/dpkg/status is not readable on this image" fi # =========================================================================== # 4. THE PROBE # =========================================================================== check libxxf86vm/probe-installed test -x "$PROBE" bst_probe libxxf86vm/probe-runs "$out" 120 "$PROBE" prc=$? # The END line is the probe's own statement that it did not die part way. Every # case below reads $out, so without it they would all be reading a truncated # file and reporting the absence of a value as a wrong value. It is also the # ticket's no-crash clause: a probe that faulted in an entry point never gets # here. check libxxf86vm/probe-reached-end grep -q '^XXF86VM-PROBE-END$' "$out" # field -- nth whitespace field of the line starting with TAG field() { awk -v t="$1" -v n="$2" '$1==t {print $(n); exit}' "$out"; } # keyed . Most of the probe's output is # tag-plus-key and several tags repeat -- XXF86VM-FAIL alone appears 66 times # across two runs -- so those are read by their key rather than by position. A # case written against a repeated tag by position would silently assert one # line's value under another line's name. keyed() { _got=$(awk -v t="$2" -v k="$3" -v n="$4" '$1==t && $2==k {print $(n); exit}' "$out") if [ "$_got" = "$5" ]; then bst_ok "$1" else bst_notok "$1" "want '$5', got '$_got'"; fi } # arm -- one entry point's answer in one # of the two refusal runs. Field 2 is the run tag, field 3 the entry point. arm() { _got=$(awk -v r="$2" -v e="$3" -v n="$4" \ '$1=="XXF86VM-FAIL" && $2==r && $3==e {print $(n); exit}' "$out") if [ "$_got" = "$5" ]; then bst_ok "$1" else bst_notok "$1" "want '$5', got '$_got'"; fi } # The line count, as a FLOOR. Every case below is grepped for by prefix, so a # run that died halfway leaves its remaining cases simply absent -- and absent # reads the same as "the grep found nothing", which is how a truncated run # passes for a short one. 175 is the reference run's count; a floor rather than # an equality so that adding a case to the probe is not a red here as well as a # red in whichever case it belongs to. _total=$(field XXF86VM-TOTAL 2) if [ -n "$_total" ] && [ "$_total" -ge 175 ] 2>/dev/null; then bst_ok libxxf86vm/probe-total-floor else bst_notok libxxf86vm/probe-total-floor "want >= 175, got '$_total'" fi # --------------------------------------------------------------------------- # 4a. VERSIONS AND NAMES # # THE PROTOCOL VERSION IS NOT THE PACKAGE VERSION. The ticket asks for "the # version macros the installed header defines, all asserted to agree with 1.1.5 # as literals", and THAT CANNOT BE MET AS WRITTEN: the installed header defines # no version macro at all, and the ones that exist -- XF86VIDMODE_MAJOR_VERSION # and _MINOR_VERSION in xorgproto's xf86vmproto.h -- are 2 and 2, the # XFree86-VidModeExtension protocol version, which has never been 1.1.5. So the # clause is read as the two statements it can truthfully be: the PACKAGE version # is 1.1.5, asserted as a literal from the .pc above and from the -D the recipe # compiles the probe with, and the PROTOCOL version is 2.2, asserted as literals # here. A client that confused them would negotiate the wrong protocol. # --------------------------------------------------------------------------- keyed libxxf86vm/version-pv XXF86VM-VERSION pv 3 1.1.5 keyed libxxf86vm/proto-major XXF86VM-VER proto-major 3 2 keyed libxxf86vm/proto-minor XXF86VM-VER proto-minor 3 2 # The wire string the library asks for the extension by, read out of the # archive's read-only data. A client that asked for the wrong name would # silently never get the extension, on every server. Content and length both. keyed libxxf86vm/ext-name XXF86VM-VER ext-name 3 XFree86-VidModeExtension keyed libxxf86vm/ext-name-len XXF86VM-VER ext-name-len 3 24 # The macros the installed header does define in its own right: the error codes # a client compares a received error against, the permission bits # XF86VidModeGetPermissions reports in, the clock flag and the event count. keyed libxxf86vm/err-badclock XXF86VM-VER err-BadClock 3 0 keyed libxxf86vm/err-badhtimings XXF86VM-VER err-BadHTimings 3 1 keyed libxxf86vm/err-badvtimings XXF86VM-VER err-BadVTimings 3 2 keyed libxxf86vm/err-unsuitable XXF86VM-VER err-ModeUnsuitable 3 3 keyed libxxf86vm/err-disabled XXF86VM-VER err-ExtensionDisabled 3 4 keyed libxxf86vm/err-notlocal XXF86VM-VER err-ClientNotLocal 3 5 keyed libxxf86vm/err-zoomlocked XXF86VM-VER err-ZoomLocked 3 6 keyed libxxf86vm/err-count XXF86VM-VER err-count 3 7 keyed libxxf86vm/perm-read XXF86VM-VER perm-read 3 1 keyed libxxf86vm/perm-write XXF86VM-VER perm-write 3 2 keyed libxxf86vm/clkflag XXF86VM-VER clkflag-programable 3 1 # XF86VIDMODE_EVENTS is not defined in this build, so the header's own # arithmetic makes the event count 0. Asserted because the alternative arm # would change the error/event base a QueryExtension hands back. keyed libxxf86vm/event-count XXF86VM-VER event-count 3 0 # --------------------------------------------------------------------------- # 4b. THE LAYOUT -- the ticket's substantive clause # # The offsets are the same on every arm; the two sizes and the two trailing # `private' pointers are what the word size moves, and the ILP32 numbers are # asserted here. Each is also a _Static_assert in the probe source, so a # disagreement fails the recipe's do_compile naming the field -- this section # is the second reading of the same fact, taken on the target rather than on # the build host. # --------------------------------------------------------------------------- keyed libxxf86vm/modeline-size XXF86VM-LAYOUT ModeLine-size 3 32 keyed libxxf86vm/modeline-hdisplay XXF86VM-LAYOUT ModeLine-hdisplay 3 0 keyed libxxf86vm/modeline-hsyncstart XXF86VM-LAYOUT ModeLine-hsyncstart 3 2 keyed libxxf86vm/modeline-hsyncend XXF86VM-LAYOUT ModeLine-hsyncend 3 4 keyed libxxf86vm/modeline-htotal XXF86VM-LAYOUT ModeLine-htotal 3 6 keyed libxxf86vm/modeline-hskew XXF86VM-LAYOUT ModeLine-hskew 3 8 keyed libxxf86vm/modeline-vdisplay XXF86VM-LAYOUT ModeLine-vdisplay 3 10 keyed libxxf86vm/modeline-vsyncstart XXF86VM-LAYOUT ModeLine-vsyncstart 3 12 keyed libxxf86vm/modeline-vsyncend XXF86VM-LAYOUT ModeLine-vsyncend 3 14 keyed libxxf86vm/modeline-vtotal XXF86VM-LAYOUT ModeLine-vtotal 3 16 keyed libxxf86vm/modeline-flags XXF86VM-LAYOUT ModeLine-flags 3 20 keyed libxxf86vm/modeline-privsize XXF86VM-LAYOUT ModeLine-privsize 3 24 keyed libxxf86vm/modeline-private XXF86VM-LAYOUT ModeLine-private 3 28 keyed libxxf86vm/modeinfo-size XXF86VM-LAYOUT ModeInfo-size 3 36 keyed libxxf86vm/modeinfo-dotclock XXF86VM-LAYOUT ModeInfo-dotclock 3 0 keyed libxxf86vm/modeinfo-hdisplay XXF86VM-LAYOUT ModeInfo-hdisplay 3 4 keyed libxxf86vm/modeinfo-hsyncstart XXF86VM-LAYOUT ModeInfo-hsyncstart 3 6 keyed libxxf86vm/modeinfo-hsyncend XXF86VM-LAYOUT ModeInfo-hsyncend 3 8 keyed libxxf86vm/modeinfo-htotal XXF86VM-LAYOUT ModeInfo-htotal 3 10 keyed libxxf86vm/modeinfo-hskew XXF86VM-LAYOUT ModeInfo-hskew 3 12 keyed libxxf86vm/modeinfo-vdisplay XXF86VM-LAYOUT ModeInfo-vdisplay 3 14 keyed libxxf86vm/modeinfo-vsyncstart XXF86VM-LAYOUT ModeInfo-vsyncstart 3 16 keyed libxxf86vm/modeinfo-vsyncend XXF86VM-LAYOUT ModeInfo-vsyncend 3 18 keyed libxxf86vm/modeinfo-vtotal XXF86VM-LAYOUT ModeInfo-vtotal 3 20 keyed libxxf86vm/modeinfo-flags XXF86VM-LAYOUT ModeInfo-flags 3 24 keyed libxxf86vm/modeinfo-privsize XXF86VM-LAYOUT ModeInfo-privsize 3 28 keyed libxxf86vm/modeinfo-private XXF86VM-LAYOUT ModeInfo-private 3 32 # The two structures differ by exactly one leading field -- ModeInfo carries the # dotclock ModeLine does not -- so every timing member sits four bytes further # along. Its own case because it is the RELATIONSHIP a marshalling bug breaks, # and because it holds on every arm rather than only on this one. keyed libxxf86vm/modeinfo-minus-modeline XXF86VM-LAYOUT modeinfo-minus-modeline 3 4 keyed libxxf86vm/gamma-size XXF86VM-LAYOUT Gamma-size 3 12 keyed libxxf86vm/syncrange-size XXF86VM-LAYOUT SyncRange-size 3 8 keyed libxxf86vm/monitor-size XXF86VM-LAYOUT Monitor-size 3 28 # --------------------------------------------------------------------------- # 4c. THE WIRE # # Each case compares the size THIS arm computed for the request or reply struct # (field 3) with the sz_ literal xf86vmproto.h fixes (field 4). They are two # independent statements -- a C declaration the compiler lays out, and a literal # in the protocol header -- so asserting both against the same number is not a # tautology. A client that disagrees with the server here does not fail to # build; it sends the wrong bytes. # --------------------------------------------------------------------------- wire() { # wire _c=$(awk -v k="$2" '$1=="XXF86VM-WIRE" && $2==k {print $3; exit}' "$out") _p=$(awk -v k="$2" '$1=="XXF86VM-WIRE" && $2==k {print $4; exit}' "$out") if [ "$_c" = "$3" ] && [ "$_p" = "$3" ]; then bst_ok "$1" else bst_notok "$1" "want $3/$3, got '$_c'/'$_p'"; fi } wire libxxf86vm/wire-queryversion-req QueryVersionReq 4 wire libxxf86vm/wire-queryversion-reply QueryVersionReply 32 wire libxxf86vm/wire-getmodeline-req GetModeLineReq 8 wire libxxf86vm/wire-getmodeline-reply GetModeLineReply 52 wire libxxf86vm/wire-getallmodelines-req GetAllModeLinesReq 8 wire libxxf86vm/wire-getallmodelines-rep GetAllModeLinesReply 32 wire libxxf86vm/wire-addmodeline-req AddModeLineReq 92 wire libxxf86vm/wire-modmodeline-req ModModeLineReq 48 wire libxxf86vm/wire-deletemodeline-req DeleteModeLineReq 52 wire libxxf86vm/wire-validatemodeline-rq ValidateModeLineReq 52 wire libxxf86vm/wire-validatemodeline-rp ValidateModeLineReply 32 wire libxxf86vm/wire-switchtomode-req SwitchToModeReq 52 wire libxxf86vm/wire-switchmode-req SwitchModeReq 8 wire libxxf86vm/wire-lockmodeswitch-req LockModeSwitchReq 8 wire libxxf86vm/wire-getmonitor-req GetMonitorReq 8 wire libxxf86vm/wire-getmonitor-reply GetMonitorReply 32 wire libxxf86vm/wire-getviewport-req GetViewPortReq 8 wire libxxf86vm/wire-getviewport-reply GetViewPortReply 32 wire libxxf86vm/wire-setviewport-req SetViewPortReq 16 wire libxxf86vm/wire-getdotclocks-req GetDotClocksReq 8 wire libxxf86vm/wire-getdotclocks-reply GetDotClocksReply 32 wire libxxf86vm/wire-setclientversion-rq SetClientVersionReq 8 wire libxxf86vm/wire-getpermissions-req GetPermissionsReq 8 # The request opcodes, which are what the reqType byte carries. An opcode that # moved would address a different request on every server. keyed libxxf86vm/op-queryversion XXF86VM-WIRE op-QueryVersion 3 0 keyed libxxf86vm/op-getmodeline XXF86VM-WIRE op-GetModeLine 3 1 keyed libxxf86vm/op-setclientversion XXF86VM-WIRE op-SetClientVersion 3 14 keyed libxxf86vm/op-getgammaramp XXF86VM-WIRE op-GetGammaRamp 3 17 keyed libxxf86vm/op-setgammaramp XXF86VM-WIRE op-SetGammaRamp 3 18 keyed libxxf86vm/op-getgammarampsize XXF86VM-WIRE op-GetGammaRampSize 3 19 keyed libxxf86vm/op-getpermissions XXF86VM-WIRE op-GetPermissions 3 20 # --------------------------------------------------------------------------- # 4d. THE ENTRY-POINT CENSUS # # All 22 public functions. The probe takes each by address, so the static link # already proved the archive contains it; this asserts the probe still NAMES all # 22, which is the direction the link cannot catch. The header's other two # public names, XF86VidModeSelectNextMode and XF86VidModeSelectPrevMode, are # macros over XF86VidModeSwitchMode and have no symbol to census. # --------------------------------------------------------------------------- for f in XF86VidModeQueryExtension XF86VidModeQueryVersion \ XF86VidModeSetClientVersion XF86VidModeSetGamma XF86VidModeGetGamma \ XF86VidModeGetModeLine XF86VidModeGetAllModeLines \ XF86VidModeAddModeLine XF86VidModeDeleteModeLine \ XF86VidModeModModeLine XF86VidModeValidateModeLine \ XF86VidModeSwitchMode XF86VidModeSwitchToMode \ XF86VidModeLockModeSwitch XF86VidModeGetMonitor \ XF86VidModeGetViewPort XF86VidModeSetViewPort \ XF86VidModeGetDotClocks XF86VidModeSetGammaRamp \ XF86VidModeGetGammaRamp XF86VidModeGetGammaRampSize \ XF86VidModeGetPermissions; do keyed "libxxf86vm/api-$f" XXF86VM-API "$f" 3 resolved done keyed libxxf86vm/api-count XXF86VM-API-COUNT "22" 2 22 # --------------------------------------------------------------------------- # 4e. THE FIXTURE, asserted before anything rests on it # # token-add-calls 0 is the statement that the registry lookup HIT for all 22 # entry points in the first run -- so each of them ran its real prologue against # a cached entry with no codes, which is the state a real server without the # extension produces. null-add-calls 22 is the opposite path, once per entry # point: a cache MISS, XextAddDisplay, a NULL info. Both runs must produce the # same documented answers, and that they do is the statement worth having -- # the refusal is a property of the entry points, not of which way the lookup # went. # --------------------------------------------------------------------------- keyed libxxf86vm/fixture-token-nonnull XXF86VM-FIXTURE token-nonnull 3 1 keyed libxxf86vm/fixture-codes-null XXF86VM-FIXTURE codes-null 3 1 keyed libxxf86vm/fixture-token-add XXF86VM-FIXTURE token-add-calls 3 0 keyed libxxf86vm/fixture-null-add XXF86VM-FIXTURE null-add-calls 3 22 # --------------------------------------------------------------------------- # 4f. THE REFUSAL ARM # # 21 of the 22 entry points route their refusal through # XF86VidModeCheckExtension; XF86VidModeQueryExtension is the one that reads # XextHasExtension itself. The three that spell their sentinel `0' rather than # `False' -- DeleteModeLine, ModModeLine, ValidateModeLine -- are asserted # separately because they are separate statements in the library even though the # value is the same. # # The untouched out-parameters are the half a client actually depends on: one # that trusted a written-through event base on the failure path would add # garbage to every event code it compared. # --------------------------------------------------------------------------- for r in token null; do arm "libxxf86vm/$r-queryextension" "$r" QueryExtension 4 0 arm "libxxf86vm/$r-queryextension-evbase" "$r" QueryExtension-event-base 4 untouched arm "libxxf86vm/$r-queryextension-erbase" "$r" QueryExtension-error-base 4 untouched arm "libxxf86vm/$r-queryversion" "$r" QueryVersion 4 0 arm "libxxf86vm/$r-queryversion-out" "$r" QueryVersion-out 4 untouched arm "libxxf86vm/$r-setclientversion" "$r" SetClientVersion 4 0 arm "libxxf86vm/$r-setgamma" "$r" SetGamma 4 0 arm "libxxf86vm/$r-getgamma" "$r" GetGamma 4 0 arm "libxxf86vm/$r-getmodeline" "$r" GetModeLine 4 0 arm "libxxf86vm/$r-getmodeline-dotclock" "$r" GetModeLine-dotclock 4 untouched arm "libxxf86vm/$r-getallmodelines" "$r" GetAllModeLines 4 0 arm "libxxf86vm/$r-getallmodelines-count" "$r" GetAllModeLines-count 4 untouched arm "libxxf86vm/$r-addmodeline" "$r" AddModeLine 4 0 arm "libxxf86vm/$r-deletemodeline" "$r" DeleteModeLine 4 0 arm "libxxf86vm/$r-modmodeline" "$r" ModModeLine 4 0 arm "libxxf86vm/$r-validatemodeline" "$r" ValidateModeLine 4 0 arm "libxxf86vm/$r-switchmode" "$r" SwitchMode 4 0 arm "libxxf86vm/$r-switchtomode" "$r" SwitchToMode 4 0 arm "libxxf86vm/$r-lockmodeswitch" "$r" LockModeSwitch 4 0 arm "libxxf86vm/$r-getmonitor" "$r" GetMonitor 4 0 arm "libxxf86vm/$r-getviewport" "$r" GetViewPort 4 0 arm "libxxf86vm/$r-getviewport-out" "$r" GetViewPort-out 4 untouched arm "libxxf86vm/$r-setviewport" "$r" SetViewPort 4 0 arm "libxxf86vm/$r-getdotclocks" "$r" GetDotClocks 4 0 arm "libxxf86vm/$r-getdotclocks-out" "$r" GetDotClocks-out 4 untouched arm "libxxf86vm/$r-setgammaramp" "$r" SetGammaRamp 4 0 arm "libxxf86vm/$r-getgammaramp" "$r" GetGammaRamp 4 0 arm "libxxf86vm/$r-getgammarampsize" "$r" GetGammaRampSize 4 0 # GetGammaRampSize and GetPermissions are the exception, and it is the # library's own choice: both write `*out = 0' BEFORE the guard, so their # refusal leaves a DEFINED zero where the other nineteen leave the caller's # value alone. That is the stronger contract -- a caller need not # initialise -- and asserting "untouched" here would be asserting the # opposite of what src/XF86VMode.c says. arm "libxxf86vm/$r-getgammarampsize-out" "$r" GetGammaRampSize-out 4 0 arm "libxxf86vm/$r-getpermissions" "$r" GetPermissions 4 0 arm "libxxf86vm/$r-getpermissions-out" "$r" GetPermissions-out 4 0 # The standing check that every call above really did go down the guarded # path rather than returning for some other reason, and that the library # asked for the extension by the name the server knows it by. arm "libxxf86vm/$r-missing-calls" "$r" missing-calls 4 21 arm "libxxf86vm/$r-missing-name" "$r" missing-name 4 XFree86-VidModeExtension done # --------------------------------------------------------------------------- # 4g. THE NEGOTIATED ARM # # XF86VidModeQueryExtension is the ONLY entry point that returns before # LockDisplay once the extension is present -- every other one reaches the wire, # and driving those would need a server. Without this the failure arm above # would be green for a guard that always returned the failure sentinel, so this # is what makes the whole of 4f discriminate. # --------------------------------------------------------------------------- keyed libxxf86vm/neg-queryextension XXF86VM-NEG QueryExtension 3 1 keyed libxxf86vm/neg-event-base XXF86VM-NEG event-base 3 64 keyed libxxf86vm/neg-error-base XXF86VM-NEG error-base 3 128 # =========================================================================== # 5. XOpenDisplay'S OWN REFUSAL # # The ticket's remaining two probe clauses, in a SEPARATE probe run: this is the # only part that touches the network stack, so a fault or a wedge here costs # these three cases and not the 170-odd above. # # The bound is what makes "refuses rather than blocks on a connect" a # measurement: bst_probe kills the run at 60s and reds the case naming the last # line it printed, and the probe reports its own elapsed seconds beside the # answer so a refusal that took most of the bound is visible rather than merely # passing. # =========================================================================== bst_probe libxxf86vm/open-probe-runs "$oout" 60 "$PROBE" open orc=$? if [ "$orc" -eq 0 ] && grep -q '^XXF86VM-OPEN-END$' "$oout"; then bst_ok libxxf86vm/open-reached-end ofield() { awk -v k="$1" '$1=="XXF86VM-OPEN" && $2==k {print $3; exit}' "$oout"; } check_eq libxxf86vm/open-no-display NULL "$(ofield no-display)" check_eq libxxf86vm/open-dead-address NULL "$(ofield dead-address)" _secs=$(ofield dead-address-seconds) if [ -n "$_secs" ] && [ "$_secs" -le 30 ] 2>/dev/null; then bst_ok libxxf86vm/open-dead-address-bounded else bst_notok libxxf86vm/open-dead-address-bounded \ "XOpenDisplay on an address nothing is listening on took '${_secs}'s; it must refuse, not block" fi else bst_notok libxxf86vm/open-reached-end \ "no END line; rc=$orc. tail: $(tail -n 1 "$oout" 2>/dev/null)" fi rm -f "$out" "$out".err "$oout" "$oout".err