# BST-TIMEOUT: 300 # measured elapsed=11s for all 187 cases (==BST-SUITE, # # 2026-08-20, local guest, host also running a Yocto # # build -- so already a loaded-host figure). 27x headroom. # # The cost is one instantiation of an ~8.5 MB probe (which # # itself waits 50 ms on a condition and 300 ms on a # # socket), one pass over a 440 kB archive and one over the # # probe, and ~20 whole-file reads. . "$BST_LIB" # p8-platform 2.1.0.1+git at SRCREV a7cd0d57 (meta-oe recipes-extended) -- # Pulse-Eight's platform-abstraction library: threads, sockets, mutexes and # conditions, timers, a synced buffer, two atomics headers and a large string # utility class. It is what libcec and the Kodi binary add-ons sit on. Eleventh # port of the C++ round (BRINTOS-1094). See # recipes-extended/p8platform/p8platform_%.bbappend for what the port adds. # # --------------------------------------------------------------------------- # WHY THIS SUITE IS SHAPED THE WAY IT IS # # This package compiles exactly ONE translation unit -- src/util/StringUtils.cpp # -- and ships sixteen headers that are the whole of the rest of the library. # So a suite that listed files would report a green package while saying nothing # about the sockets, the threads, the mutexes, the timers, the buffer or either # atomics header, none of which this recipe ever compiles. # # That gap is not hypothetical: BOTH ATOMICS HEADERS WERE UNCOMPILABLE as # shipped. util/atomic.h and threads/atomics.h open with a __sync_* builtin # branch gated on HAS_BUILTIN_SYNC_* macros that upstream's CMake computes and # then discards, so every target falls through to inline assembly for a register # machine -- and the final #else is 32-bit x86, complete with a `register` # storage class that C++17 removed. The package still built, packaged, passed QA # and populated the sysroot, because nothing in it includes those headers. # # data/p8platform-probe is the consumer that closes both gaps: a program # compiled against these headers and linked against THIS build's # libp8-platform.a, built by the recipe so it cannot drift from what shipped. It # includes both atomics headers and calls every function in them, drives # CTcpConnection against a loopback listener it stands up itself, and exercises # StringUtils end to end. # # WHAT IS COMPARED BYTE-FOR-BYTE, AND WHAT IS NOT. The probe prints two # sections. Everything from ==P8-RESULTS== onward is deterministic and is # compared line for line against data/p8platform-native.txt -- the identical # source built and run on x86-64 by the p8platform-native recipe, with no # tolerance band and no normalisation. Everything BEFORE it is # environment-dependent (clock, scheduler, network stack, thread substrate) and # is asserted as invariants here, because the two arms genuinely differ there # and that difference is this port's finding rather than a defect. # # NOTHING IN THE COMPARED BLOCK IS A POINTER, A NATIVE-WIDTH size_t, A CLOCK # READING OR AN ADDRESS -- the target is ILP32 and the oracle's host is LP64, so # any of those would differ for a reason that is not the port. # # THE ANCHORED CASES EXIST BECAUSE AN ORACLE CAN BE WRONG. A control captured # from an already-broken build would make every compared line agree with it. So # the values that upstream's own source fixes independently -- the size-prefix # arithmetic, the natural-order comparison, the bracket scanner's entry # contract, the atomics' return values -- are ALSO asserted against literals # here, each derived by reading the implementation. Three of those literals were # WRONG in the first draft and were corrected against the source, which is the # whole argument for keeping them. # # EXEC BUDGET. Every exec on this guest is a fresh wasm module instantiation, so # this file reads each file ONCE and matches every needle against it with a # shell `case`. If you add a needle, add it to an existing list; if you add a # `cat` or a `grep` you have added seconds, not milliseconds. # --------------------------------------------------------------------------- # A root prefix, empty on the target and set only when this suite is validated # natively before it ships. The runner never sets it. R="${BST_P8_ROOT:-}" INC=$R/usr/include/p8-platform LIB=$R/usr/lib ARCHIVE=$LIB/libp8-platform.a PC=$LIB/pkgconfig/p8-platform.pc CMK=$LIB/p8-platform/p8-platform-config.cmake PROBE=$BST_DATA/p8platform-probe NATIVE=$BST_DATA/p8platform-native.txt if [ ! -f "$ARCHIVE" ]; then bst_skip p8platform/present "p8platform not installed on this image" exit 0 fi bst_ok p8platform/present nl=' ' tmp=${TMPDIR:-/tmp} # slurp -> $SLURP, with a leading and trailing newline so `has` can # anchor whole lines. One exec per FILE, never one per case. slurp() { SLURP=$nl$(cat "$1" 2>/dev/null)$nl } # has has() { case "$2" in *"$nl$3$nl"*) bst_ok "$1" ;; *) bst_notok "$1" "missing line: $3" ;; esac } # sub sub() { case "$2" in *"$3"*) bst_ok "$1" ;; *) bst_notok "$1" "missing: $3" ;; esac } # hasnt hasnt() { case "$2" in *"$3"*) bst_notok "$1" "present but must not be: $3" ;; *) bst_ok "$1" ;; esac } # --- the package is whole ---------------------------------------------------- check p8/hdr-os test -f "$INC/os.h" check p8/hdr-posix-types test -f "$INC/posix/os-types.h" check p8/hdr-posix-sock test -f "$INC/posix/os-socket.h" check p8/hdr-posix-thr test -f "$INC/posix/os-threads.h" check p8/hdr-sock-socket test -f "$INC/sockets/socket.h" check p8/hdr-sock-tcp test -f "$INC/sockets/tcp.h" check p8/hdr-sock-cdev test -f "$INC/sockets/cdevsocket.h" check p8/hdr-thr-atomics test -f "$INC/threads/atomics.h" check p8/hdr-thr-mutex test -f "$INC/threads/mutex.h" check p8/hdr-thr-threads test -f "$INC/threads/threads.h" check p8/hdr-util-atomic test -f "$INC/util/atomic.h" check p8/hdr-util-buffer test -f "$INC/util/buffer.h" check p8/hdr-util-strutl test -f "$INC/util/StringUtils.h" check p8/hdr-util-stdstr test -f "$INC/util/StdString.h" check p8/hdr-util-time test -f "$INC/util/timeutils.h" check p8/hdr-util-util test -f "$INC/util/util.h" check p8/archive test -f "$ARCHIVE" check p8/pkgconfig test -f "$PC" check p8/cmake-config test -f "$CMK" # THE WINDOWS HEADERS MUST NOT BE HERE. CMakeLists installs windows/ or posix/, # never both, so their presence would mean the build took the WIN32 branch. check p8/no-windows-hdrs test ! -d "$INC/windows" # 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 p8/no-shared "$LIB/libp8-platform.so" bst_lib_shape p8/no-shared-vers "$LIB/libp8-platform.so.2" # --- the pkg-config file, and this port's repair of it ----------------------- # # THE ONE LINE THIS PORT FIXED IN THE RECIPE. meta-oe passes # CMAKE_INSTALL_LIBDIR as an absolute path and p8-platform.pc.in composes its # libdir field as ${prefix}/${CMAKE_INSTALL_LIBDIR}, so the shipped file read # `libdir=/usr//usr/lib` and `pkg-config --libs` answered `-L/usr//usr/lib`. # Asserted BOTH ways: the correct line must be present AND the doubled prefix # must be absent anywhere in the file, because a fix that produced some third # wrong value would satisfy only one of the two. slurp "$PC" PCTXT=$SLURP has p8/pc-libdir "$PCTXT" "libdir=/usr/lib" has p8/pc-prefix "$PCTXT" "prefix=/usr" has p8/pc-includedir "$PCTXT" "includedir=/usr/include" hasnt p8/pc-no-doubled "$PCTXT" "/usr//usr" sub p8/pc-name "$PCTXT" "Name: p8-platform" sub p8/pc-libs "$PCTXT" "-lp8-platform" # THE LIBRARY'S OWN VERSION IS 2.1.1, WHICH IS NOT THE RECIPE'S PV. CMakeLists # sets VERSION_MAJOR/MINOR/PATCH 2/1/1 and that is what reaches the .pc; # meta-oe's recipe calls the same SRCREV 2.1.0.1+git. Both are asserted rather # than one being picked, so a future version bump cannot silently satisfy the # check by moving only one of them. has p8/pc-version "$PCTXT" "Version: 2.1.1" slurp "$CMK" CMKTXT=$SLURP sub p8/cmake-target "$CMKTXT" "add_library (p8-platform UNKNOWN IMPORTED)" sub p8/cmake-version "$CMKTXT" 'set (p8-platform_VERSION "2.1")' hasnt p8/cmake-no-doubled "$CMKTXT" "/usr//usr" # --- the headers carry the surface a consumer compiles against --------------- slurp "$INC/util/StringUtils.h" SU=$SLURP sub p8/su-class "$SU" "class StringUtils" sub p8/su-format "$SU" "static std::string Format(const char *fmt, ...);" sub p8/su-formatv "$SU" "static std::string FormatV(const char *fmt, va_list args);" sub p8/su-split "$SU" "static std::vector Split(" sub p8/su-tokenize "$SU" "static std::vector Tokenize(" sub p8/su-alnum "$SU" "static int64_t AlphaNumericCompare(" sub p8/su-uuid "$SU" "static std::string CreateUUID();" sub p8/su-utf8len "$SU" "static size_t utf8_strlen(const char *s);" sub p8/su-timefmt-enum "$SU" "TIME_FORMAT_HH_MM_SS = 7" slurp "$INC/sockets/tcp.h" TCP=$SLURP sub p8/tcp-socket-class "$TCP" "class CTcpSocket : public CCommonSocket" sub p8/tcp-conn-class "$TCP" "class CTcpConnection : public CProtectedSocket" sub p8/tcp-resolve "$TCP" "TcpResolveAddress" slurp "$INC/threads/threads.h" THR=$SLURP sub p8/thr-class "$THR" "class CThread" sub p8/thr-createthread "$THR" "virtual bool CreateThread(bool bWait = true)" sub p8/thr-process-pure "$THR" "virtual void *Process(void) = 0;" slurp "$INC/posix/os-threads.h" OT=$SLURP # The thread substrate this arm cannot use, named in the header so the probe's # REFUSED verdict below is attributable to a specific call rather than to "the # threads did not work". sub p8/ot-threadscreate "$OT" "pthread_create(&thread, GetDetachedThreadAttribute()" sub p8/ot-detached "$OT" "PTHREAD_CREATE_DETACHED" sub p8/ot-recursive "$OT" "PTHREAD_MUTEX_RECURSIVE" # THIS PORT'S PATCH, VISIBLE ON TARGET IN THE SHIPPED HEADERS. If it ever stops # applying, the recipe still builds -- these two headers are compiled by nothing # in the package -- and only these four cases go red. slurp "$INC/threads/atomics.h" AT=$SLURP sub p8/patch-atomics-cas "$AT" "#if defined(HAS_BUILTIN_SYNC_VAL_COMPARE_AND_SWAP) || defined(__wasm__)" sub p8/patch-atomics-add "$AT" "#if defined(HAS_BUILTIN_SYNC_ADD_AND_FETCH) || defined(__wasm__)" sub p8/patch-atomics-sub "$AT" "#if defined(HAS_BUILTIN_SYNC_SUB_AND_FETCH) || defined(__wasm__)" sub p8/patch-atomics-cas2 "$AT" " #if defined(__wasm__)" # The x86 fallback is still there and is still what a non-wasm, non-enumerated # target would get -- the patch ADDS an arm, it does not remove one. Asserted so # "the patch applied" cannot be confused with "the header was rewritten". sub p8/atomics-x86-kept "$AT" 'register long reg __asm__ ("eax")' slurp "$INC/util/atomic.h" UA=$SLURP sub p8/patch-atomic-inc "$UA" "#if defined(HAS_BUILTIN_SYNC_ADD_AND_FETCH) || defined(__wasm__)" # --- the archive's shape ----------------------------------------------------- # # One flatten and one grep over the whole archive, for the exec reason above. # The members are bitcode, so these names live in the bitcode string tables. # # NO _ZTV/_ZTI NEEDLE HERE, AND THAT IS CORRECT RATHER THAN AN OMISSION. # StringUtils.cpp is the only compiled translation unit and StringUtils is a # class of static methods with no virtual member, so this archive HAS no # polymorphic type and a vtable needle against it would be a guard that can # never pass. The C++-evidence needles are on the PROBE below, which links the # genuinely polymorphic ISocket/CTcpSocket hierarchy out of the headers. nf=$tmp/bst-p8-needles.$$ hf=$tmp/bst-p8-hits.$$ cat > "$nf" <<'NEEDLES' _ZN11StringUtils6FormatEPKcz _ZN11StringUtils6FormatEPKwz _ZN11StringUtils7FormatVEPKcPv _ZN11StringUtils5SplitERKNSt _ZN11StringUtils8TokenizeERKNSt _ZN11StringUtils19AlphaNumericCompareEPKwS1_ _ZN11StringUtils10CreateUUIDEv _ZN11StringUtils11utf8_strlenEPKc _ZN11StringUtils12SizeToStringEx _ZN11StringUtils19TimeStringToSecondsERKNSt _ZN11StringUtils14FindEndBracketERKNSt _ZN11StringUtils19SecondsToTimeStringEl11TIME_FORMAT _ZN11StringUtils5EmptyE NEEDLES cat "$ARCHIVE" 2>/dev/null | tr -c 'A-Za-z0-9_.' '\n' | grep -F -f "$nf" > "$hf" 2>/dev/null AHITS=$nl$(cat "$hf" 2>/dev/null)$nl # ITANIUM-MANGLED C++ NAMES ARE THE EVIDENCE THE C ARM CANNOT FORGE. The # distro's default CXX is the C driver wasmcc-glibc; if the bbappend's opt-in # had not taken, these sources would not have compiled at all, and any archive # that did appear would carry unmangled names. # EVERY NEEDLE HERE WAS MEASURED OFF THE BUILT ARCHIVE, not derived. The first # draft spelled the class length 12 (`_ZN12StringUtils`) and every one of the # eleven cases went red on target -- "StringUtils" is 11 characters. Two others # were wrong in the same way and for the same reason: FormatV's va_list argument # mangles as `Pv` on this arm, not `St9__va_list`, and AlphaNumericCompare's # second parameter is a back-reference `S1_`, not `S0_`. sub p8/sym-format "$AHITS" "_ZN11StringUtils6FormatEPKcz" sub p8/sym-wformat "$AHITS" "_ZN11StringUtils6FormatEPKwz" sub p8/sym-formatv "$AHITS" "_ZN11StringUtils7FormatVEPKcPv" sub p8/sym-split "$AHITS" "_ZN11StringUtils5SplitERKNSt" sub p8/sym-tokenize "$AHITS" "_ZN11StringUtils8TokenizeERKNSt" # The one site in the library: use_facet>. Its symbol # is here and the runtime cases below drive it. sub p8/sym-alnum "$AHITS" "_ZN11StringUtils19AlphaNumericCompareEPKwS1_" sub p8/sym-uuid "$AHITS" "_ZN11StringUtils10CreateUUIDEv" sub p8/sym-utf8len "$AHITS" "_ZN11StringUtils11utf8_strlenEPKc" sub p8/sym-sizetostr "$AHITS" "_ZN11StringUtils12SizeToStringEx" sub p8/sym-timestr "$AHITS" "_ZN11StringUtils19TimeStringToSecondsERKNSt" sub p8/sym-endbracket "$AHITS" "_ZN11StringUtils14FindEndBracketERKNSt" # The enum reaches the mangling by NAME, which is a statement about the header # and the archive agreeing rather than only about the archive. sub p8/sym-secstostr "$AHITS" "_ZN11StringUtils19SecondsToTimeStringEl11TIME_FORMAT" sub p8/sym-empty-data "$AHITS" "_ZN11StringUtils5EmptyE" # --- the probe --------------------------------------------------------------- if [ ! -f "$PROBE" ]; then bst_notok p8/probe-present "$PROBE missing -- the library cannot be proven to run" rm -f "$nf" "$hf" 2>/dev/null exit 0 fi if [ ! -f "$NATIVE" ]; then bst_notok p8/native-present "$NATIVE missing -- no x86-64 control for the probe run" rm -f "$nf" "$hf" 2>/dev/null exit 0 fi bst_ok p8/probe-present bst_ok p8/native-present # The PROBE is where the polymorphic evidence lives -- ISocket declares nine # pure virtuals and CTcpSocket/CProtectedSocket implement them, so the linked # image carries vtables and typeinfo records for the socket hierarchy that no C # compile could emit. cat > "$nf" <<'PNEEDLES' _ZTVN10P8PLATFORM10CTcpSocketE _ZTVN10P8PLATFORM14CTcpConnectionE _ZTVN10P8PLATFORM16CProtectedSocketINS_10CTcpSocketEEE _ZTVN10P8PLATFORM13CCommonSocketIiEE _ZTVN10P8PLATFORM7CThreadE _ZTVN10P8PLATFORM6CEventE _ZTVN10P8PLATFORM12SyncedBufferIiEE _ZTVN10P8PLATFORM14CConditionImplE _ZN10P8PLATFORM6CMutex4LockEv _ZN10P8PLATFORM6CMutex7TryLockEv _ZN10P8PLATFORM10CTcpSocket4OpenEy _ZN10P8PLATFORM10CTcpSocket4ReadEPvmy _ZN10P8PLATFORM10CConditionIbE4WaitERNS_6CMutexERbj _ZTIN10P8PLATFORM _ZTSN10P8PLATFORM PNEEDLES cat "$PROBE" 2>/dev/null | tr -c 'A-Za-z0-9_.' '\n' | grep -F -f "$nf" > "$hf" 2>/dev/null PHITS=$nl$(cat "$hf" 2>/dev/null)$nl rm -f "$nf" "$hf" 2>/dev/null # THE VTABLE IS THE C++ EVIDENCE ON THIS ARM; THE TYPEINFO RECORD IS NOT, AND # THAT DISTINCTION WAS MEASURED RATHER THAN ASSUMED. ISocket declares nine pure # virtuals and five classes below it implement them, so the linked image carries # their vtables -- records no C compile could emit, and therefore direct # evidence that the bbappend's wasmc++-glibc opt-in took effect rather than the # distro's C driver having silently compiled the sources. # # There is NO _ZTI or _ZTS record anywhere in this image, for any type, # including libc++abi's own. Nothing in this program uses typeid or # dynamic_cast, so unused typeinfo is legitimately dead-stripped -- this is a # property of the link, not a defect, and it is asserted as an ABSENCE so that a # toolchain change which starts retaining RTTI shows up as a red here rather # than silently. The first draft of this suite asserted the typeinfo records as # PRESENT and went red on target for exactly this reason. sub p8/probe-vtable-tcpsocket "$PHITS" "_ZTVN10P8PLATFORM10CTcpSocketE" sub p8/probe-vtable-tcpconn "$PHITS" "_ZTVN10P8PLATFORM14CTcpConnectionE" sub p8/probe-vtable-protsocket "$PHITS" "_ZTVN10P8PLATFORM16CProtectedSocketINS_10CTcpSocketEEE" sub p8/probe-vtable-commsocket "$PHITS" "_ZTVN10P8PLATFORM13CCommonSocketIiEE" sub p8/probe-vtable-cthread "$PHITS" "_ZTVN10P8PLATFORM7CThreadE" sub p8/probe-vtable-cevent "$PHITS" "_ZTVN10P8PLATFORM6CEventE" sub p8/probe-vtable-buffer "$PHITS" "_ZTVN10P8PLATFORM12SyncedBufferIiEE" sub p8/probe-vtable-condimpl "$PHITS" "_ZTVN10P8PLATFORM14CConditionImplE" hasnt p8/probe-no-typeinfo "$PHITS" "_ZTIN10P8PLATFORM" hasnt p8/probe-no-typename "$PHITS" "_ZTSN10P8PLATFORM" # The header-only surfaces this port ships, as SYMBOLS in the one program that # links them. The atomics are deliberately absent from this list: they are # `static inline` and the optimiser inlines every one of them away, so a needle # for cas or atomic_inc would be a guard that can never pass. They are asserted # by VALUE below instead, which is the stronger statement anyway. sub p8/probe-sym-mutex-lock "$PHITS" "_ZN10P8PLATFORM6CMutex4LockEv" sub p8/probe-sym-mutex-trylock "$PHITS" "_ZN10P8PLATFORM6CMutex7TryLockEv" sub p8/probe-sym-tcp-open "$PHITS" "_ZN10P8PLATFORM10CTcpSocket4OpenEy" sub p8/probe-sym-tcp-read "$PHITS" "_ZN10P8PLATFORM10CTcpSocket4ReadEPvmy" sub p8/probe-sym-cond-wait "$PHITS" "_ZN10P8PLATFORM10CConditionIbE4WaitERNS_6CMutexERbj" # do_install stages data/* at 0644 and the deployed rootfs is read-only at # browser runtime, so the payload cannot be executed where it lies. pd=$tmp/bst-p8.$$ p=$pd/p8platform-probe mkdir -p "$pd" 2>/dev/null if ! cp "$PROBE" "$p" 2>/dev/null || ! chmod 0755 "$p" 2>/dev/null || [ ! -x "$p" ]; then bst_notok p8/probe-stage "cannot stage $PROBE" rm -rf "$pd" 2>/dev/null exit 0 fi bst_ok p8/probe-stage out=$("$p" 2>&1); rc=$? OUT=$nl$out$nl # The run produced SOMETHING. A probe that printed nothing at all would # otherwise make every `has` below report the same missing-line detail and read # as a hundred separate defects rather than one. if [ -z "$out" ]; then bst_notok p8/probe-output "probe printed nothing (rc=$rc)" rm -rf "$pd" 2>/dev/null exit 0 fi bst_ok p8/probe-output sub p8/probe-version "$OUT" "P8 probe/version 2.1.0.1+git" # THE TARGET IS ILP32 AND THE ORACLE'S HOST IS LP64. Asserted directly, because # it is the premise of every "byte-identical" claim below: the compared block is # only meaningful if nothing in it is printed at native width. has p8/probe-ilp32-long "$OUT" "P8 probe/sizeof-long 4" has p8/probe-ilp32-ptr "$OUT" "P8 probe/sizeof-void-p 4" # --- section A: the environment, as invariants rather than values ------------ has p8/time-monotonic "$OUT" "P8 time/monotonic-nondecreasing OK" has p8/time-nonzero "$OUT" "P8 time/nonzero OK" has p8/time-tick-mono "$OUT" "P8 time/tickcount-nondecreasing OK" has p8/time-tick-nonzero "$OUT" "P8 time/tickcount-nonzero OK" has p8/time-sec-agrees "$OUT" "P8 time/sec-agrees-ms OK" has p8/time-timeout-unset "$OUT" "P8 time/timeout-unset-not-set OK" has p8/time-timeout-zero "$OUT" "P8 time/timeout-unset-left-zero OK" has p8/time-timeout-set "$OUT" "P8 time/timeout-set OK" has p8/time-timeout-band "$OUT" "P8 time/timeout-left-in-band OK" has p8/time-timeout-exp "$OUT" "P8 time/timeout-expired-left-small OK" # CEvent::Sleep is pthread_cond_timedwait on a condition nothing signals -- the # one genuinely blocking primitive in this library. On an arm that could not # time it out, the suite would not reach here at all. sub p8/event-sleep-returns "$OUT" "P8 event/sleep-50ms-returns OK" sub p8/event-sleep-waited "$OUT" "P8 event/sleep-50ms-waited OK" sub p8/event-signal-true "$OUT" "P8 event/signalled-wait-returns-true OK" sub p8/event-signal-fast "$OUT" "P8 event/signalled-wait-immediate OK" # THE THREAD SUBSTRATE IS A FINDING, NOT A PASS/FAIL. This arm has no working # pthread_create -- the guest kernel refuses a thread-mode clone with EAGAIN -- # so p8-platform's CThread cannot start one, and the port ships with its # threading wrappers present, linkable and unusable. Asserted as REFUSED so the # boundary of this port is PINNED: the day the substrate arrives, this case goes # red and somebody re-reads the exclusion instead of inheriting it. has p8/threads-refused "$OUT" "P8 threads/create REFUSED" has p8/threads-not-created "$OUT" "P8 threads/ran NOT-CREATED" has p8/threads-no-hang "$OUT" "P8 threads/no-hang OK" # cas2 IS IMPLEMENTED ON THIS ARM AND IS NOT ON x86-64. Upstream's x86-64 arm is # `throw "cas2 is not implemented on x86_64!"`; the wasm arm this port added # gives it a real 64-bit compare-and-swap. So this is one of the very few places # where the target is strictly ahead of the control -- which is exactly why the # line lives in the environment section and not in the byte-compared block, # where it would red the comparison on the port WORKING. sub p8/atom-cas2 "$OUT" "P8 atom/cas2 IMPLEMENTED prev=4294967298 value=12884901892" # The socket stack, driven through p8-platform's own CTcpConnection against a # loopback listener the probe stands up itself. has p8/socket-listen "$OUT" "P8 socket/listen OK" has p8/socket-connect "$OUT" "P8 socket/client OK" has p8/socket-isopen "$OUT" "P8 socket/isopen OK" sub p8/socket-name "$OUT" "P8 socket/name OK 127.0.0.1" has p8/socket-accept "$OUT" "P8 socket/accept OK" has p8/socket-write "$OUT" "P8 socket/write-len OK" has p8/socket-srv-read-len "$OUT" "P8 socket/server-read-len OK" sub p8/socket-srv-read "$OUT" "P8 socket/server-read-body OK p8-platform-probe" has p8/socket-srv-write "$OUT" "P8 socket/server-write-len OK" has p8/socket-cli-read-len "$OUT" "P8 socket/client-read-len OK" sub p8/socket-cli-read "$OUT" "P8 socket/client-read-body OK ACK-42" sub p8/socket-timeout-rc "$OUT" "P8 socket/read-timeout-returns OK" sub p8/socket-timeout-wait "$OUT" "P8 socket/read-timeout-waited OK" has p8/socket-closed "$OUT" "P8 socket/closed OK" # --- section B: anchored values, asserted against the source not the oracle --- # # Each of these is derivable from src/util/StringUtils.cpp without reference to # any build, so they hold whatever the control says. has p8/anchor-format "$OUT" "P8 str/format-int [42--7]" has p8/anchor-format-w "$OUT" "P8 str/format-width [0003.142| 42|42 |]" has p8/anchor-tolower "$OUT" "P8 str/tolower [mixed case 123]" has p8/anchor-trim "$OUT" "P8 str/trim [padded]" has p8/anchor-dedup "$OUT" "P8 str/dedup-spaces [a b c d]" has p8/anchor-replace "$OUT" "P8 str/replace-char [bonono]" # Replace() must not re-scan what it just wrote: "aaa" with a -> bb is three # replacements and six characters, not an unbounded loop. has p8/anchor-replace-grow-n "$OUT" "P8 str/replace-grow-n 3" has p8/anchor-replace-grow "$OUT" "P8 str/replace-grow [bbbbbb]" # Split KEEPS empty fields; Tokenize DROPS them. That is the documented # difference between the two and the reason both exist. has p8/anchor-split "$OUT" "P8 str/split [<>]" has p8/anchor-split-max "$OUT" "P8 str/split-max []" has p8/anchor-split-empty "$OUT" "P8 str/split-empty-n 0" has p8/anchor-tokenize "$OUT" "P8 str/tokenize []" has p8/anchor-join "$OUT" "P8 str/join [a+b+c]" # Natural order: file2 sorts BEFORE file10. This is the case that reaches # use_facet>(locale()) -- the library's only site, and # the one place libc++'s locale machinery and facet RTTI have to work. has p8/anchor-alnum-lt "$OUT" "P8 str/alnum-lt -1" has p8/anchor-alnum-gt "$OUT" "P8 str/alnum-gt 1" has p8/anchor-alnum-eq "$OUT" "P8 str/alnum-eq 0" has p8/anchor-alnum-abc "$OUT" "P8 str/alnum-abc -1" has p8/anchor-timestr "$OUT" "P8 str/timestr-hms 3723" has p8/anchor-utf8len "$OUT" "P8 str/utf8len-multi 3" # SecondsToTimeString(3661, MM_SS) DROPS the hours rather than folding them into # minutes -- 61 minutes renders as "01". Upstream's arithmetic, pinned as # measured so a "fix" is visible rather than silent. has p8/anchor-secs-mmss "$OUT" "P8 str/secs-mmss [01:01]" has p8/anchor-secs-guess "$OUT" "P8 str/secs-guess-3661 [01:01:01]" # The threshold is 1000 and the divisor is 1024, so 1000 B reads "0.98 kB" and # 1023 B reads "1.00 kB". Both sides of the boundary are pinned. has p8/anchor-size-999 "$OUT" "P8 str/size-999 [999 B ]" has p8/anchor-size-1000 "$OUT" "P8 str/size-1000 [0.98 kB]" has p8/anchor-size-1023 "$OUT" "P8 str/size-1023 [1.00 kB]" has p8/anchor-size-1mib "$OUT" "P8 str/size-1mib [1.00 MB]" # FindEndBracket enters with blocks=1, so startPos is the first character INSIDE # the bracket. Passing the opener's own index counts it twice and returns npos # on a balanced string -- which is what the fourth case pins. has p8/anchor-bracket "$OUT" "P8 str/endbracket-simple 4" has p8/anchor-bracket-nest "$OUT" "P8 str/endbracket-nested 7" has p8/anchor-bracket-none "$OUT" "P8 str/endbracket-none -1" has p8/anchor-bracket-open "$OUT" "P8 str/endbracket-at-open -1" has p8/anchor-date "$OUT" "P8 str/date-ymd 20260820" has p8/anchor-paramify "$OUT" 'P8 str/paramify ["a\"b\\c"]' has p8/anchor-wordtodigit "$OUT" "P8 str/wordtodigits [663]" has p8/anchor-uuid-len "$OUT" "P8 str/uuid-len 36" has p8/anchor-uuid-shape "$OUT" "P8 str/uuid-shape 1" has p8/anchor-uuid-nonhex "$OUT" "P8 str/uuid-nonhex 0" has p8/anchor-uuid-distin "$OUT" "P8 str/uuid-distinct 1" # The wide-string arm of Format goes through vswprintf rather than vsnprintf -- # a different libc entry point, and the only one in this library that touches # wide output. has p8/anchor-wformat "$OUT" "P8 str/wformat [6/7]" has p8/anchor-wtoupper "$OUT" "P8 str/wtoupper [MIXED]" # THE ATOMICS THE PATCH EXISTS FOR, ASSERTED BY VALUE. atomic_inc/_dec/_add/_sub # return the NEW value; cas returns the PREVIOUS one and swaps only on a match. has p8/atom-inc-1 "$OUT" "P8 atom/inc-1 1" has p8/atom-inc-2 "$OUT" "P8 atom/inc-2 2" has p8/atom-dec "$OUT" "P8 atom/dec-1 9" has p8/atom-add "$OUT" "P8 atom/add 123" has p8/atom-sub "$OUT" "P8 atom/sub 120" has p8/atom-cas-hit "$OUT" "P8 atom/cas-hit-prev 7" has p8/atom-cas-hit-v "$OUT" "P8 atom/cas-hit-value 9" has p8/atom-cas-miss "$OUT" "P8 atom/cas-miss-prev 9" has p8/atom-cas-miss-v "$OUT" "P8 atom/cas-miss-value 9" has p8/mutex-lock "$OUT" "P8 mutex/lock 1" has p8/mutex-recursive "$OUT" "P8 mutex/trylock-recursive 1" has p8/mutex-lockobj "$OUT" "P8 mutex/lockobject-trylock 1" has p8/mutex-trylock "$OUT" "P8 mutex/trylockobject-locked 1" has p8/mutex-clear "$OUT" "P8 mutex/clear-after-release 1" has p8/buf-push-3 "$OUT" "P8 buf/push-3 1" has p8/buf-push-over "$OUT" "P8 buf/push-over-max 0" has p8/buf-fifo-1 "$OUT" "P8 buf/pop-1-val 11" has p8/buf-fifo-3 "$OUT" "P8 buf/pop-3-val 33" # Pop with iTimeoutMs=0 must NOT wait on the condition -- an empty buffer # returns false immediately. On a target with no second thread to push, a Pop # that waited would hang the suite. has p8/buf-drained "$OUT" "P8 buf/pop-drained-rc 0" has p8/buf-cleared "$OUT" "P8 buf/empty-after-clear 1" # --- the byte-for-byte comparison against the x86-64 control ------------------ # # Everything from ==P8-RESULTS== to just before `P8 probe/failures`, compared # line for line with NO tolerance and NO normalisation. The oracle was cut at # the same two boundaries by the p8platform-native recipe. printf '%s\n' "$out" > "$pd/out.txt" sed -n '/^==P8-RESULTS==$/,/^P8 probe\/failures /p' "$pd/out.txt" | sed '$d' > "$pd/det.txt" if [ ! -s "$pd/det.txt" ]; then bst_notok p8/deterministic-block "no ==P8-RESULTS== block in the probe output" else bst_ok p8/deterministic-block d=$(diff "$NATIVE" "$pd/det.txt" 2>&1) if [ -z "$d" ]; then bst_ok p8/native-identical else bst_notok p8/native-identical "$(_bst_1line "$d")" fi fi # The probe's own verdict over the WHOLE run, environment included. Kept last so # a failure here is read after the specific case that caused it. has p8/probe-failures-zero "$OUT" "P8 probe/failures 0" has p8/probe-all-ok "$OUT" "ALL-P8-OK" check_eq p8/probe-rc 0 "$rc" rm -rf "$pd" 2>/dev/null