# BST-TIMEOUT: 900 # ~170 cases, but ~20 of them are separate wasm process # # spawns (the shipped tools, each on its own topology) and a # # spawn is the expensive operation on this target. . "$BST_LIB" # hwloc 2.9.3 -- "the Portable Hardware Locality software package provides a # portable abstraction of the hierarchical topology of modern architectures" # (meta-oe recipes-extended/hwloc). What ships is /usr/lib/libhwloc.a, the # hwloc/ headers, hwloc.pc, and the tool set: lstopo-no-graphics (with lstopo # and hwloc-ls as links to it), hwloc-info, hwloc-calc, hwloc-bind, hwloc-ps, # hwloc-distrib, hwloc-annotate, hwloc-diff, hwloc-patch, and the two shell # scripts hwloc-compress-dir and hwloc-gather-topology. # # --------------------------------------------------------------------------- # THE ORACLE IS A SYNTHETIC TOPOLOGY, AND THAT IS THE WHOLE DESIGN # # hwloc's job is to describe the machine it runs on, so the obvious test -- # "does lstopo report this box correctly" -- has no oracle on a target whose # sysfs is nearly empty, and would measure the browser rather than the port. # Upstream's own tests/ tree has exactly that problem: almost every case loads # the real topology and asserts against what it finds. # # hwloc's synthetic backend is the way out. It builds a topology from a text # description -- "pack:2 numa:1 core:2 pu:2" -- with no kernel involvement at # all, so every structural answer is a pure function of the library. That makes # a native x86_64 run of the SAME probe on the SAME description a legitimate # byte-for-byte control (data/hwloc-native.txt, from src/hwloc_mknative.sh), and # it makes the tool comparisons below fixed literals rather than "whatever this # machine has". # # So the suite has two halves, and they answer different questions: # # HW-* the library and the tools on an INVENTED machine -- does hwloc # compute correctly here? A red is the port. # HWX-L* the library on the REAL guest -- what does the browser's sysfs and # procfs actually expose? These are REPORTED, not scored against a # control, because a build host and a browser guest are not the same # machine and it would be dishonest to pretend a difference is a bug. # A thin or empty topology here is a finding about the platform. # # --------------------------------------------------------------------------- # WHY THE LIVE GROUP IS A SEPARATE PROBE INVOCATION # # The live group is the only code here that touches the platform, so it is the # only code that can take the process down. Run in the same invocation, a fault # there would erase the deterministic groups' output and read as a broken port. # `hwloc-probe --live` therefore runs on its own, and its failure costs exactly # the live cases. lib=/usr/lib/libhwloc.a incd=/usr/include/hwloc pc=/usr/lib/pkgconfig/hwloc.pc DATA=$BST_DATA NATIVE=$DATA/hwloc-native.txt PROBE=$DATA/hwloc-probe TMP=${TMPDIR:-/tmp} nl=' ' # The one description the deterministic half is built on. It must match SYNTH in # src/hwloc_probe.c and the one src/hwloc_mknative.sh recorded, or the literals # below describe a different machine than the control does. SYN='pack:2 numa:1 core:2 pu:2' if [ ! -f "$lib" ]; then bst_skip hwloc/present "hwloc not installed on this image" exit 0 fi bst_ok hwloc/present hasfile() { if [ -s "$2" ]; then bst_ok "$1"; else bst_notok "$1" "absent or empty: $2"; fi; } hasline() { case "$nl$3$nl" in *"$nl$2$nl"*) bst_ok "$1" ;; *) bst_notok "$1" "not in archive: $2" ;; esac; } hastool() { if [ -x "$2" ]; then bst_ok "$1"; else bst_notok "$1" "$2 absent or not executable"; fi; } # --- payload shape ----------------------------------------------------------- hasfile hwloc/archive "$lib" hasfile hwloc/header-hwloc /usr/include/hwloc.h hasfile hwloc/header-bitmap "$incd/bitmap.h" hasfile hwloc/header-helper "$incd/helper.h" hasfile hwloc/header-distances "$incd/distances.h" hasfile hwloc/header-memattrs "$incd/memattrs.h" hasfile hwloc/header-cpukinds "$incd/cpukinds.h" hasfile hwloc/header-diff "$incd/diff.h" hasfile hwloc/header-export "$incd/export.h" hasfile hwloc/header-autogen "$incd/autogen/config.h" hasfile hwloc/pkgconfig "$pc" # Shape, not absence: this arm converts to shared libraries per recipe # (BRINTOS-1740), so a .so here is a conversion, not a policy breach. bst_lib_shape hwloc/no-shared-object "/usr/lib/libhwloc.so" "/usr/lib/libhwloc.so.15" pctext=$(cat "$pc" 2>/dev/null) case "$pctext" in *"Version: 2.9.3"*) bst_ok hwloc/pc-version ;; *) bst_notok hwloc/pc-version "unexpected Version in hwloc.pc: $(_bst_1line "$(grep -i '^Version' "$pc" 2>/dev/null)")" ;; esac case "$pctext" in *"-lhwloc"*) bst_ok hwloc/pc-libs ;; *) bst_notok hwloc/pc-libs "hwloc.pc does not name -lhwloc" ;; esac # --- the programs the port installs ------------------------------------------ # lstopo-no-graphics is the real binary; lstopo and hwloc-ls are links to it, # made by upstream's install-exec-hook. Without cairo there is no separate # graphical lstopo, so a missing link would silently cost the name every # document and every habit uses. hastool hwloc/bin-lstopo-no-graphics /usr/bin/lstopo-no-graphics hastool hwloc/bin-lstopo /usr/bin/lstopo hastool hwloc/bin-hwloc-ls /usr/bin/hwloc-ls hastool hwloc/bin-hwloc-info /usr/bin/hwloc-info hastool hwloc/bin-hwloc-calc /usr/bin/hwloc-calc hastool hwloc/bin-hwloc-bind /usr/bin/hwloc-bind hastool hwloc/bin-hwloc-distrib /usr/bin/hwloc-distrib hastool hwloc/bin-hwloc-annotate /usr/bin/hwloc-annotate hastool hwloc/bin-hwloc-diff /usr/bin/hwloc-diff hastool hwloc/bin-hwloc-patch /usr/bin/hwloc-patch hastool hwloc/bin-hwloc-ps /usr/bin/hwloc-ps hastool hwloc/bin-hwloc-compress-dir /usr/bin/hwloc-compress-dir hastool hwloc/bin-hwloc-gather-topology /usr/bin/hwloc-gather-topology # hwloc-gather-cpuid is x86-only and hwloc-dump-hwdata is Linux-on-x86 only, so # neither is built for wasm32. Their ABSENCE is the correct result, and it is # asserted rather than left unsaid -- a wasm32 image that grew an x86 CPUID # dumper would mean the arch conditionals in the build stopped working. if [ -e /usr/bin/hwloc-gather-cpuid ]; then bst_notok hwloc/no-x86-cpuid-tool "hwloc-gather-cpuid shipped on a non-x86 target" else bst_ok hwloc/no-x86-cpuid-tool fi if [ -e /usr/sbin/hwloc-dump-hwdata ]; then bst_notok hwloc/no-x86-hwdata-tool "hwloc-dump-hwdata shipped on a non-x86 target" else bst_ok hwloc/no-x86-hwdata-tool fi # --- symbol census ----------------------------------------------------------- # One name per subsystem, so a partially-linked archive is legible rather than # merely "incomplete". arcsyms=$(grep -ao 'hwloc_[a-z0-9_]*' "$lib" 2>/dev/null | sort -u) hasline hwloc/sym-topology-init hwloc_topology_init "$arcsyms" hasline hwloc/sym-topology-load hwloc_topology_load "$arcsyms" hasline hwloc/sym-topology-set-synthetic hwloc_topology_set_synthetic "$arcsyms" hasline hwloc/sym-topology-restrict hwloc_topology_restrict "$arcsyms" hasline hwloc/sym-topology-dup hwloc_topology_dup "$arcsyms" hasline hwloc/sym-export-xmlbuffer hwloc_topology_export_xmlbuffer "$arcsyms" hasline hwloc/sym-set-xmlbuffer hwloc_topology_set_xmlbuffer "$arcsyms" hasline hwloc/sym-diff-build hwloc_topology_diff_build "$arcsyms" hasline hwloc/sym-diff-apply hwloc_topology_diff_apply "$arcsyms" hasline hwloc/sym-bitmap-alloc hwloc_bitmap_alloc "$arcsyms" hasline hwloc/sym-bitmap-list-sscanf hwloc_bitmap_list_sscanf "$arcsyms" hasline hwloc/sym-distances-get hwloc_distances_get "$arcsyms" hasline hwloc/sym-memattr-get-by-name hwloc_memattr_get_by_name "$arcsyms" hasline hwloc/sym-cpukinds-get-nr hwloc_cpukinds_get_nr "$arcsyms" # hwloc_distrib is static __hwloc_inline in hwloc/helper.h — never in the archive if grep -q 'hwloc_distrib' "$incd/helper.h" 2>/dev/null then bst_ok hwloc/sym-distrib else bst_notok hwloc/sym-distrib "hwloc_distrib not found in $incd/helper.h"; fi hasline hwloc/sym-get-cpubind hwloc_get_cpubind "$arcsyms" hasline hwloc/sym-linux-backend hwloc_linux_component "$arcsyms" hasline hwloc/sym-xml-component hwloc_xml_component "$arcsyms" nsym=$(printf '%s\n' "$arcsyms" | grep -c '^hwloc_' 2>/dev/null || echo 0) if [ "$nsym" -ge 250 ]; then bst_ok hwloc/symbols-counted else bst_notok hwloc/symbols-counted "only $nsym hwloc_* names in the archive"; fi # ============================================================================= # THE SHIPPED TOOLS, ON THE SYNTHETIC TOPOLOGY # ============================================================================= # These are the values a user sees. They are written as LITERALS rather than # compared to a second control file, because each one is fixed by hwloc's own # contract for this description -- eight PUs numbered 0-7 under two packages -- # and a literal is what notices when a control regenerated against a broken # build quietly moves. `--input ` makes hwloc build the topology # from text, so not one of these reads the guest. lstopo=/usr/bin/lstopo-no-graphics if [ ! -x "$lstopo" ]; then bst_skip hwloc/cli "lstopo-no-graphics not on this image" else # BST-TIMEOUT-OK: every bound below wraps a one-shot hwloc/lstopo query against a # synthetic --input topology, which cannot block. Converting all 24 would add # ~24 s to a suite whose bound is sized for the work, not for the wrapper. out=$(timeout 60 "$lstopo" --input "$SYN" --of console 2>/dev/null) if bst_execfail "$out"; then bst_unrun hwloc/cli-lstopo-console "$out" else # The console rendering is the tool's headline output: the tree, the # per-object logical (L#) and physical (P#) numbering, and the memory roll-up. check_out hwloc/cli-lstopo-machine "Machine (2048MB total)" printf '%s' "$out" check_out hwloc/cli-lstopo-package0 "Package L#0" printf '%s' "$out" check_out hwloc/cli-lstopo-package1 "Package L#1" printf '%s' "$out" check_out hwloc/cli-lstopo-numa0 "NUMANode L#0 (P#0 1024MB)" printf '%s' "$out" check_out hwloc/cli-lstopo-core3 "Core L#3" printf '%s' "$out" check_out hwloc/cli-lstopo-pu7 "PU L#7 (P#7)" printf '%s' "$out" n=$(printf '%s\n' "$out" | grep -c 'PU L#') check_eq hwloc/cli-lstopo-pu-count 8 "$n" fi # lstopo and hwloc-ls are links to the same binary, so they must render the # same tree. A broken link would show up as a shell error here, not as a # difference -- which is why the comparison is on the OUTPUT and not on # `test -L`. for alias in lstopo hwloc-ls; do a=$(timeout 60 "/usr/bin/$alias" --input "$SYN" --of console 2>/dev/null) if [ "$a" = "$out" ]; then bst_ok "hwloc/cli-alias-$alias" else bst_notok "hwloc/cli-alias-$alias" "$alias renders differently from lstopo-no-graphics"; fi done fi if [ ! -x /usr/bin/hwloc-info ]; then bst_skip hwloc/cli-hwloc-info "hwloc-info not on this image" else out=$(timeout 60 hwloc-info --input "$SYN" 2>/dev/null) if bst_execfail "$out"; then bst_unrun hwloc/cli-info-levels "$out" else # The level census, including the SPECIAL negative depth NUMA lives at in # hwloc 2.x. A consumer that still expects NUMA to be an ordinary level is # the single most common way 2.x is misread, so it is pinned here too. check_out hwloc/cli-info-machine "1 Machine (type #0)" printf '%s' "$out" check_out hwloc/cli-info-package "2 Package (type #1)" printf '%s' "$out" check_out hwloc/cli-info-core "4 Core (type #2)" printf '%s' "$out" check_out hwloc/cli-info-pu "8 PU (type #3)" printf '%s' "$out" check_out hwloc/cli-info-numa "Special depth -3: 2 NUMANode (type #13)" printf '%s' "$out" fi o=$(timeout 60 hwloc-info --input "$SYN" --objects pu:0 2>/dev/null) if bst_execfail "$o"; then bst_unrun hwloc/cli-info-object "$o" else check_out hwloc/cli-info-obj-header "PU L#0" printf '%s' "$o" check_out hwloc/cli-info-obj-depth "depth = 3" printf '%s' "$o" check_out hwloc/cli-info-obj-cpuset "cpuset = 0x00000001" printf '%s' "$o" check_out hwloc/cli-info-obj-nodeset "nodeset = 0x00000001" printf '%s' "$o" fi fi if [ ! -x /usr/bin/hwloc-calc ]; then bst_skip hwloc/cli-hwloc-calc "hwloc-calc not on this image" else # hwloc-calc is the cpuset algebra every launcher shells out to. Each of these # is a different operator, and each answer is fixed by the description. check_out hwloc/cli-calc-pu-range "0x0000000f" timeout 60 hwloc-calc --input "$SYN" pu:0-3 check_out hwloc/cli-calc-package1 "0x000000f0" timeout 60 hwloc-calc --input "$SYN" pack:1 check_out hwloc/cli-calc-nbcores "4" timeout 60 hwloc-calc --input "$SYN" --number-of core machine:0 check_out hwloc/cli-calc-nbpus "8" timeout 60 hwloc-calc --input "$SYN" --number-of pu machine:0 check_out hwloc/cli-calc-intersect "4,5,6,7" timeout 60 hwloc-calc --input "$SYN" --intersect PU pack:1 check_out hwloc/cli-calc-hier "0x00000030" timeout 60 hwloc-calc --input "$SYN" pack:1.core:0 fi if [ ! -x /usr/bin/hwloc-distrib ]; then bst_skip hwloc/cli-hwloc-distrib "hwloc-distrib not on this image" else # The scheduling primitive: split the machine into n balanced cpusets. Four # over two packages must land one per core, in order. d=$(timeout 60 hwloc-distrib --input "$SYN" 4 2>/dev/null | tr '\n' ' ') check_eq hwloc/cli-distrib-4 "0x00000003 0x0000000c 0x00000030 0x000000c0 " "$d" d=$(timeout 60 hwloc-distrib --input "$SYN" 2 2>/dev/null | tr '\n' ' ') check_eq hwloc/cli-distrib-2 "0x0000000f 0x000000f0 " "$d" fi # --- XML: export, re-import, annotate, diff, patch --------------------------- # This is the interchange path, and the reason the port keeps libxml2 rather # than hwloc's cut-down built-in parser. It is also the only group here that # writes files, so it needs a writable directory: the deployed rootfs is # read-only at browser runtime. X=$TMP/bst-hwloc.$$ mkdir -p "$X" 2>/dev/null if [ ! -d "$X" ] || [ ! -w "$X" ]; then bst_skip hwloc/xml "no writable temp dir at $TMP" elif [ ! -x "$lstopo" ]; then bst_skip hwloc/xml "lstopo-no-graphics not on this image" else timeout 60 "$lstopo" --input "$SYN" --of xml "$X/a.xml" >/dev/null 2>&1 if [ -s "$X/a.xml" ]; then bst_ok hwloc/xml-export check_out hwloc/xml-doctype "" cat "$X/a.xml" check_out hwloc/xml-machine "/dev/null 2>&1 if cmp -s "$X/a.xml" "$X/a2.xml"; then bst_ok hwloc/xml-export-stable else bst_notok hwloc/xml-export-stable "two exports of the same topology differ"; fi # Re-import: the file must describe the same machine the description did. if [ -x /usr/bin/hwloc-info ]; then r=$(timeout 60 hwloc-info --input "$X/a.xml" 2>/dev/null) check_out hwloc/xml-reimport-pu "8 PU (type #3)" printf '%s' "$r" check_out hwloc/xml-reimport-numa "2 NUMANode" printf '%s' "$r" else bst_skip hwloc/xml-reimport-pu "hwloc-info not on this image" bst_skip hwloc/xml-reimport-numa "hwloc-info not on this image" fi # annotate: add an info key and read it back. if [ -x /usr/bin/hwloc-annotate ]; then timeout 60 hwloc-annotate "$X/a.xml" "$X/ann.xml" root info BstMarker BstValue >/dev/null 2>&1 if [ -s "$X/ann.xml" ]; then bst_ok hwloc/xml-annotate check_out hwloc/xml-annotate-readback "value=\"BstValue\"" cat "$X/ann.xml" else bst_notok hwloc/xml-annotate "hwloc-annotate produced no output" bst_skip hwloc/xml-annotate-readback "no annotated topology" fi else bst_skip hwloc/xml-annotate "hwloc-annotate not on this image" bst_skip hwloc/xml-annotate-readback "hwloc-annotate not on this image" fi # diff + patch, on the one difference class hwloc can actually represent: # a changed object attribute (NUMA memory size). An added info key is # reported "too complex" by design, so a round trip built on one would # measure upstream's refusal rather than our port. timeout 60 "$lstopo" --input "pack:2 numa:1(memory=2GB) core:2 pu:2" \ --of xml "$X/b.xml" >/dev/null 2>&1 if [ ! -s "$X/b.xml" ]; then bst_notok hwloc/xml-second-topology "lstopo produced no XML for the 2GB variant" elif [ ! -x /usr/bin/hwloc-diff ]; then bst_skip hwloc/xml-diff "hwloc-diff not on this image" else dout=$(timeout 60 hwloc-diff "$X/a.xml" "$X/b.xml" "$X/d.xml" 2>&1) check_out hwloc/xml-diff-count "Found 3 differences" printf '%s' "$dout" if [ -s "$X/d.xml" ]; then bst_ok hwloc/xml-diff-exported check_out hwloc/xml-diff-doctype "" cat "$X/d.xml" check_out hwloc/xml-diff-oldvalue "obj_attr_oldvalue=\"1073741824\"" cat "$X/d.xml" check_out hwloc/xml-diff-newvalue "obj_attr_newvalue=\"2000000000\"" cat "$X/d.xml" if [ -x /usr/bin/hwloc-patch ]; then timeout 60 hwloc-patch "$X/a.xml" "$X/d.xml" "$X/p.xml" >/dev/null 2>&1 if [ -s "$X/p.xml" ] && [ -x /usr/bin/hwloc-info ]; then bst_ok hwloc/xml-patch # The patched topology must carry the NEW memory size. (It is not # byte-identical to b.xml: page_type counts are not part of the # diff format, which is upstream's limitation and not ours.) pm=$(timeout 60 hwloc-info --input "$X/p.xml" --objects numa:0 2>/dev/null) check_out hwloc/xml-patch-memory "2000000000" printf '%s' "$pm" else bst_notok hwloc/xml-patch "hwloc-patch produced no output" bst_skip hwloc/xml-patch-memory "no patched topology" fi else bst_skip hwloc/xml-patch "hwloc-patch not on this image" bst_skip hwloc/xml-patch-memory "hwloc-patch not on this image" fi else bst_notok hwloc/xml-diff-exported "hwloc-diff wrote no diff: $(_bst_1line "$dout")" fi fi else bst_notok hwloc/xml-export "lstopo --of xml produced no file" fi fi # ============================================================================= # THE LIBRARY ITSELF, VIA THE CROSS-LINKED PROBE # ============================================================================= if [ ! -s "$NATIVE" ]; then bst_notok hwloc/native-present "$NATIVE missing -- no oracle to compare against" rm -rf "$X" exit 0 fi bst_ok hwloc/native-present # do_install stages data/* at 0644 and the deployed rootfs is read-only at # browser runtime, so the probe cannot be executed where it lies. _p=$TMP/bst-hwloc-probe.$$ cp "$PROBE" "$_p" 2>/dev/null && chmod 0755 "$_p" 2>/dev/null if [ ! -x "$_p" ]; then bst_notok hwloc/probe-exec "could not stage an executable copy of $PROBE" rm -f "$_p" rm -rf "$X" exit 0 fi bst_ok hwloc/probe-exec out=$TMP/bst-hwloc-out.$$ bst_bound 300 "$_p" > "$out.out" 2>"$out.err"; prc=$? check_eq hwloc/probe-rc 0 "$prc" # A truncated run must be distinguishable from a run that legitimately produced # these lines: with no terminator, a wedge half way through would silently # reduce the number of compared cases rather than fail one. if [ "$(grep -c '^HW-ZZ-complete yes' "$out.out" 2>/dev/null)" = "1" ]; then bst_ok hwloc/probe-complete else bst_notok hwloc/probe-complete "no terminator; last saw: $(_bst_1line "$(tail -n 2 "$out.out" 2>/dev/null)")" fi # --- tag-by-tag against the native control ----------------------------------- # One awk over both files rather than a shell loop of ~134 awk calls: process # spawn is expensive on this target and the whole comparison is in-memory. # # Nothing is skipped here. Every HW- line is computed from a topology that # exists only in memory, so there is no platform gap that could legitimately # move one -- which is exactly why this half of the suite is the one that says # whether hwloc WORKS on wasm32. awk ' NR == FNR { if ($0 !~ /^HW-/) next k = $1; $1 = ""; sub(/^ /, ""); W[k] = $0; order[++n] = k; next } /^HW-/ { k = $1; $1 = ""; sub(/^ /, ""); G[k] = $0; seen[k] = 1 } END { for (i = 1; i <= n; i++) { k = order[i]; t = substr(k, 4) if (!(k in seen)) { printf "BST not ok hwloc/cmp-%s : absent from target output\n", t; continue } if (G[k] == W[k]) printf "BST ok hwloc/cmp-%s\n", t else printf "BST not ok hwloc/cmp-%s : want:%s got:%s\n", t, W[k], G[k] } } ' "$NATIVE" "$out.out" # --- the values that legitimately differ, asserted rather than ignored ------- hw_get() { awk -v k="$1" '$1==k { $1=""; sub(/^ /,""); print; exit }' "$out.out"; } check_eq hwloc/probe-sizeof-ptr 4 "$(hw_get HWX-A90-sizeof-ptr)" check_eq hwloc/probe-sizeof-long 4 "$(hw_get HWX-A91-sizeof-long)" check_eq hwloc/probe-sizeof-size-t 4 "$(hw_get HWX-A92-sizeof-size-t)" # struct hwloc_obj is pointer-dense, so its size is a consequence of ILP32 and # not a value with a contract. It is recorded, not pinned to a number: what # matters is that it is non-zero and smaller than the LP64 control's. szobj=$(hw_get HWX-A93-sizeof-hwloc-obj) if [ -n "$szobj" ] && [ "$szobj" -gt 0 ] 2>/dev/null; then bst_ok hwloc/probe-sizeof-obj-sane else bst_notok hwloc/probe-sizeof-obj-sane "sizeof(struct hwloc_obj) reported '${szobj:-}'" fi # --- anchored: values hwloc's own contract fixes, not the control ------------ # These duplicate comparisons above ON PURPOSE. They are the invariants a # consumer actually depends on, written as literals, so a control regenerated # against a broken build could not quietly move them. check_eq hwloc/anchor-nb-pu 8 "$(hw_get HW-B06-nb-pu)" check_eq hwloc/anchor-nb-core 4 "$(hw_get HW-B05-nb-core)" check_eq hwloc/anchor-nb-package 2 "$(hw_get HW-B04-nb-package)" check_eq hwloc/anchor-nb-numa 2 "$(hw_get HW-B07-nb-numa)" # NUMA at a special negative depth is the defining structural change of hwloc # 2.x; a port that quietly returned an ordinary depth would break every 2.x # consumer while looking healthy. check_eq hwloc/anchor-depth-numa -3 "$(hw_get HW-B08-depth-numa)" check_eq hwloc/anchor-pack1-cpuset "4-7" "$(hw_get HW-D02-pack1-cpuset)" check_eq hwloc/anchor-bitmap-and "2-3,9" "$(hw_get HW-C11-and)" check_eq hwloc/anchor-bitmap-mask "0x0000020f" "$(hw_get HW-C03-mask)" # The XML round trip is the reason libxml2 is kept in PACKAGECONFIG. check_eq hwloc/anchor-xml-reimport "ok" "$(hw_get HW-E07-reimport)" check_eq hwloc/anchor-xml-cpuset "yes" "$(hw_get HW-E11-reimport-cpuset-same)" # restrict is what a container runtime performs; it must renumber and drop. check_eq hwloc/anchor-restrict-pu 4 "$(hw_get HW-F05-restrict-nb-pu)" check_eq hwloc/anchor-diff-apply 0 "$(hw_get HW-F13-diff-apply)" check_eq hwloc/anchor-diff-memory 2000000000 "$(hw_get HW-F14-patched-numa0-memory)" rm -f "$_p" "$out.out" "$out.err" # ============================================================================= # THE LIVE TOPOLOGY -- WHAT THE GUEST ACTUALLY EXPOSES # ============================================================================= # Separate invocation, separate contract. These are NOT scored against the # control: the build host is a 12-PU x86_64 box and the guest is a browser, so a # difference is expected and is the finding. What IS asserted is that hwloc # reaches a coherent answer rather than crashing, and the answer is printed so a # reader can see what sysfs and procfs gave it. A thin or empty topology here is # a platform observation, not a failed port. _l=$TMP/bst-hwloc-live.$$ cp "$PROBE" "$_l" 2>/dev/null && chmod 0755 "$_l" 2>/dev/null if [ ! -x "$_l" ]; then bst_skip hwloc/live "could not stage the probe for the live run" else lout=$TMP/bst-hwloc-live-out.$$ bst_bound 120 "$_l" --live > "$lout.out" 2>"$lout.err"; lrc=$? check_eq hwloc/live-rc 0 "$lrc" if [ "$(grep -c '^HWX-ZZ-live-complete yes' "$lout.out" 2>/dev/null)" = "1" ]; then bst_ok hwloc/live-complete else bst_notok hwloc/live-complete "live run did not terminate; last saw: $(_bst_1line "$(tail -n 2 "$lout.out" 2>/dev/null)")" fi lv() { awk -v k="$1" '$1==k { $1=""; sub(/^ /,""); print; exit }' "$lout.out"; } # The two that must hold whatever the guest exposes: hwloc must load, and it # must report at least one PU. hwloc synthesises a single-PU machine when it # can find nothing at all, so zero PUs would mean the load itself is broken. check_eq hwloc/live-load "ok" "$(lv HWX-L02-load)" npu=$(lv HWX-L07-nb-pu) if [ -n "$npu" ] && [ "$npu" -ge 1 ] 2>/dev/null; then bst_ok hwloc/live-has-pu else bst_notok hwloc/live-has-pu "hwloc found $npu PUs on the live topology" fi # The topology cpuset must be consistent with the PU count -- an hwloc that # reported PUs it then left out of the cpuset would mislead every consumer. lcs=$(lv HWX-L09-cpuset) if [ -n "$lcs" ]; then bst_ok hwloc/live-cpuset-nonempty else bst_notok hwloc/live-cpuset-nonempty "live topology cpuset is empty"; fi # XML export of the REAL topology: the path hwloc-gather-topology uses to ship # a machine's description off-box, and the one an absent /sys would break. check_out hwloc/live-xml-export "ok" printf '%s' "$(lv HWX-L18-xml-export)" # Reported, never scored: this is the guest's own answer, and printing it is # the point. Each is one skip carrying the value, so the report shows what the # browser exposed without pretending a build host is the oracle for it. for k in HWX-L03-depth HWX-L04-nb-machine HWX-L05-nb-package HWX-L06-nb-core \ HWX-L07-nb-pu HWX-L08-nb-numa HWX-L09-cpuset HWX-L10-backend \ HWX-L11-osname HWX-L12-arch HWX-L13-root-total-memory \ HWX-L14-support-pu HWX-L15-support-set-thisproc-cpubind \ HWX-L16-support-get-thisproc-cpubind HWX-L17-get-cpubind; do bst_skip "hwloc/live-$(printf '%s' "$k" | sed 's/^HWX-L[0-9]*-//')" \ "guest topology, not comparable to a build host: $(lv "$k")" done rm -f "$_l" "$lout.out" "$lout.err" fi # --- hwloc-bind and hwloc-ps on the live machine ----------------------------- # Both are about BINDING, which is a platform capability rather than a library # one, so they are reported the way the live group is. hwloc-bind --get asks the # OS where the current process may run; on a guest with no affinity syscalls it # is expected to say so rather than lie. if [ -x /usr/bin/hwloc-bind ]; then b=$(timeout 60 hwloc-bind --get 2>&1); brc=$? if bst_execfail "$b"; then bst_unrun hwloc/live-bind-get "$b" else bst_skip hwloc/live-bind-get "platform capability, reported: rc=$brc out=$(_bst_1line "$b")" fi else bst_skip hwloc/live-bind-get "hwloc-bind not on this image" fi if [ -x /usr/bin/hwloc-ps ]; then ps_out=$(timeout 60 hwloc-ps 2>&1); psrc=$? if bst_execfail "$ps_out"; then bst_unrun hwloc/live-ps "$ps_out" else # hwloc-ps walks /proc for bound processes. An empty list is the correct # answer on a machine where nothing is bound, so the assertion is on the # exit status, not on the output. check_eq hwloc/live-ps-rc 0 "$psrc" fi else bst_skip hwloc/live-ps "hwloc-ps not on this image" fi rm -rf "$X"