# BST-TIMEOUT: 300 . "$BST_LIB" # sblim-sfcc 2.2.8 -- the SBLIM Small Footprint CIM Client, ported as -dev + # -staticdev + -tests: eight headers in two directories, three archives, and the # probe this suite is mostly about. # # Numbered 81 beside the other build-a-document-and-encode-it libraries. sfcc # overlaps none of them: they read JSON, CBOR, msgpack, XML or MIME, and this one # builds CIM object paths and instances and encodes them to the DMTF CIM-XML # KEYBINDING form. Nothing else on this image speaks CIM. # # WHAT THE PORT DECIDED. # # 1. Upstream's TEST/ dropped from SUBDIRS. `SUBDIRS = . TEST` builds thirty-odd # noinst_PROGRAMS for `all`, and two of them do not compile -- v2test_ec.c # and v2test_ein.c pass CIMC* pointers to the show.h helpers, which are # declared against the legacy CMPI* types, without the cast the rest of the # tree uses: # # TEST/v2test_ec.c:86: passing 'CIMCClass *' to parameter of type # 'CMPIConstClass *' [-Wincompatible-pointer-types] # # That is upstream's bug and NOT this arm's: sfcc 2.2.8 predates clang 16 # and gcc 14, where the diagnostic became an error by default, and it # reproduces identically on x86-64 with any such compiler. The whole # directory goes rather than the two casts because nothing in it installs # (noinst_PROGRAMS) and every programme in it is a CIMOM client that cannot # run without a CIMOM. Section 3 pins that none of them reached the image. # # 2. NOTHING ELSE. There is no patch of ours against the library, no configure # override and no compiler opt-in: the three archives build clean on # wasm32-hwjs as upstream wrote them. # # TWO FINDINGS THIS SUITE EXISTS TO PIN. # # A. THE DOCUMENTED ENTRY POINT CANNOT WORK HERE. sfcc's is NewCIMCEnv(), and # NewCIMCEnv is a dlopen(3) of libcimcClientXML.so.0. This distro refuses # shared objects -- wasmld has no stable -shared ABI on the HWJS-3 coro arm # -- so there is no such file and never will be. Section 4's loader-* cases # measure that rather than asserting it, and the port ships the library # unchanged rather than papering over it: the failure is diagnosable (rc=1 # and a message naming the library) rather than a crash, which is the part # that matters to a consumer. What is left is to link the archives and call # the factories directly -- and those are declared in NO installed header, # which section 1 pins as an absence. # # B. A CIMC_chars KEY OR PROPERTY IS SILENTLY CORRUPTED. Upstream's # property.c:__addProperty hands native_new_CMPIString the CMPIValue* union # instead of its .chars member, so the library stores a strdup of the # POINTER'S OWN BYTES. It is architecture-independent, it is not this # port's, and the port deliberately does not fix it -- see the chars-* group # in section 4 for the reasoning and for the one-line consumer workaround. # # WHAT THE PROBE IS FOR, AND WHY B WAS FOUND AT ALL. sfcc installs no programme # -- and after decision 1 above there is not even an uninstalled one left -- so # without /usr/libexec/sblim-sfcc-tests/sblim-sfcc-probe this suite could only # list files. BRINTOS-217 is the standing reason that is not coverage for a # library like this one: oniguruma packaged perfectly on wasm32-hwjs and then # handed every caller silently wrong match offsets. sfcc does the same thing, and # nothing short of running it would have said so. # # EVERY EXPECTED BYTE IN THE PROBE IS A MEASUREMENT. sfcc's object-model # translation units compile unchanged on x86-64 (only client.c and enumeration.c # need curl), so the whole probe was run first against a native build of this # identical tarball; the constants are that run's output, and it reported # pass=135 fail=2 with the two failures being the ILP32-only cases this suite # documents. That oracle is what found finding B, and it contradicted a careful # reading of the source in three further places -- the absent-key status, the # array bounds status, and what setPropertyFilter actually filters -- each of # which is called out where it is asserted. # # Style follows 81-json-c, 81-jsoncpp and 81-libmimetic: files are read once into # shell variables and matched with `case` globs, each archive is one batched pass, # and the probe is run ONCE -- on this runtime the wasm module's start-up # dominates the cost of the whole suite, so ~140 check_out spawns would cost more # than the assertions. cimcd=/usr/include/cimc cmcid=/usr/include/CimClientLib libd=/usr/lib hasfile() { if [ -s "$2" ]; then bst_ok "$1"; else bst_notok "$1" "absent or empty: $2"; fi; } has() { case "$3" in *"$2"*) bst_ok "$1" ;; *) bst_notok "$1" "not found: $2" ;; esac; } lacks() { case "$3" in *"$2"*) bst_notok "$1" "present but should not be: $2" ;; *) bst_ok "$1" ;; esac; } noglob_ok() { # ok iff nothing matched the glob already expanded into "$@" _id=$1; shift if [ ! -e "$1" ]; then bst_ok "$_id"; else bst_notok "$_id" "present: $1"; fi } # --------------------------------------------------------------------------- # 1. The shipped payload -- all eight headers, in the two directories upstream # installs them to. # # Enumerated rather than counted, and enumerated per directory, because sfcc's # Makefile.am overrides includedir twice (cimcincludedir = $includedir/cimc, # legacyincludedir = $includedir/CimClientLib). That is an unusual layout and a # `make install` that lost one of those overrides would put a whole subtree in # the wrong place -- which a count would not see and a consumer's #include would. # # The two trees are two DIFFERENT APIs, not one API split in half: cimc/ is the # v2 CIMC interface the probe drives, and CimClientLib/ is the legacy CMPI-shaped # client. Both ship, so both are asserted. for h in cimc cimcdt cimcft; do hasfile "sblim-sfcc/header-cimc-$h" "$cimcd/$h.h" done for h in native cmcidt cmcift cmci cmcimacs; do hasfile "sblim-sfcc/header-cmci-$h" "$cmcid/$h.h" done # The umbrella headers are what upstream documents as the include. Asserting the # lines is asserting that each still reaches the rest of its own tree -- a header # that ships while its umbrella has stopped naming it is present and unreachable. umb=$(cat "$cimcd/cimc.h" 2>/dev/null) has sblim-sfcc/umbrella-cimcdt "#include \"cimcdt.h\"" "$umb" has sblim-sfcc/umbrella-cimcft "#include \"cimcft.h\"" "$umb" # NewCIMCEnv is the documented entry point and it is declared HERE and nowhere # else that installs. Section 4 measures what it does on this image; this case is # only that a consumer can still see it. has sblim-sfcc/umbrella-newcimcenv "CIMCEnv* NewCIMCEnv" "$umb" # CIMC_NO_CURL_INIT is the option that makes an offline object-model consumer # possible at all -- without it every env creation calls curl_global_init. It is # installed, so a consumer can name it; the probe depends on that. has sblim-sfcc/umbrella-no-curl-init "CIMC_NO_CURL_INIT" "$umb" cmb=$(cat "$cmcid/cmci.h" 2>/dev/null) has sblim-sfcc/cmci-includes-cmcidt "cmcidt.h" "$cmb" has sblim-sfcc/cmci-includes-cmcift "cmcift.h" "$cmb" # cmciConnect is the legacy tree's entry point, and unlike NewCIMCEnv it does NOT # dlopen -- it is compiled into libcmpisfcc.a. So the legacy API is the one that # is reachable by linking alone, which is worth knowing and is asserted here # rather than left to be discovered. has sblim-sfcc/cmci-connect-declared "cmciConnect" "$cmb" # _Create_XML_Env is the only other route to a CIMCEnv once NewCIMCEnv's dlopen # has failed, and it is declared in NO installed header -- backend/cimxml is # noinst_HEADERS. So is every native factory the probe calls instead. That # absence is half of finding A, and it is pinned as an absence in both installed # trees: if a later version starts installing these declarations, these cases go # red and the workaround the port documents is no longer needed. lacks sblim-sfcc/no-create-xml-env-cimc "_Create_XML_Env" "$umb" lacks sblim-sfcc/no-create-xml-env-cmci "_Create_XML_Env" "$cmb" noglob_ok sblim-sfcc/no-nativecimxml-h "$cimcd/nativeCimXml.h" # --------------------------------------------------------------------------- # 2. The archives. # # Three of them, and they are not interchangeable: libcimcclient.a is the dlopen # loader ONLY, libcimcClientXML.a is the whole object model plus the HTTP # transport, and libcmpisfcc.a is the legacy CMPI-shaped front end. Their sizes # differ by a factor of forty, which is the shape of that split. for a in libcimcclient libcimcClientXML libcmpisfcc; do hasfile "sblim-sfcc/archive-$a" "$libd/$a.a" check_eq "sblim-sfcc/archive-format-$a" '!' "$(head -c 7 "$libd/$a.a" 2>/dev/null)" done # Flatten each archive's printable runs to one token per line first: a raw # `grep -o` over binary data reports "Binary file matches" instead of the # matches, which would silently under-count and read as a partial compile. tmp=${TMPDIR:-/tmp} flat=$tmp/sfcc-flat.$$ ( tr -c '[:print:]' '\n' < "$libd/libcimcClientXML.a" > "$flat" 2>/dev/null ) axml=$(cat "$flat" 2>/dev/null) aclient=$( ( tr -c '[:print:]' '\n' < "$libd/libcimcclient.a" ) 2>/dev/null ) asfcc=$( ( tr -c '[:print:]' '\n' < "$libd/libcmpisfcc.a" ) 2>/dev/null ) # --- the compiled unit census ---------------------------------------------- # # THE EXHAUSTIVE CHECK, and it is the archive MEMBER list rather than "every # declared entry point is present". A member name is one per translation unit, so # a partial compile drops the member -- whereas a symbol search would go on # reporting `objectpath` found because some other unit mentions it. # # libtool prefixes every member with the library's own name (per-target CPPFLAGS # force it), so the names are `libcimcClientXML_la-.o`. Twenty-three # sources in the Makefile.am and twenty-three members; the prefix is matched # explicitly so that a member arriving from somewhere else would not satisfy the # case. nobj=0 for o in args array cimXmlParser client constClass datetime enumeration \ genericlist grammar hashtable indicationlistener instance method \ objectpath parameter parserUtil property qualifier string \ utilFactory utilHashtable utilStringBuffer value; do case "$axml" in *"libcimcClientXML_la-$o.o"*) nobj=$((nobj+1)) ;; *) bst_notok "sblim-sfcc/object-$o" "libcimcClientXML_la-$o.o not in libcimcClientXML.a -- that translation unit is not in the archive" ;; esac done if [ "$nobj" -eq 23 ]; then bst_ok sblim-sfcc/objects-complete else bst_notok sblim-sfcc/objects-complete "found=$nobj want=23"; fi # The other two are one translation unit each, which is the whole point of them: # the loader is a single function and the legacy front end is a single file. has sblim-sfcc/object-cimcclient "libcimcclient_la-cimcclient.o" "$aclient" has sblim-sfcc/object-sfcclient "libcmpisfcc_la-sfcclient.o" "$asfcc" # --- named symbols, one per layer ------------------------------------------- # # These are C, so a symbol name is the identifier verbatim and a substring match # would over-report. Each is therefore a function this port's consumers actually # reach, chosen one per layer so that a failure names the layer that broke rather # than only reporting a count. for s in _Create_XML_Env newCMPIObjectPath native_new_CMPIInstance \ native_new_CMPIString native_new_CMPIArray native_new_CMPIDateTime \ native_new_CMPIArgs pathToXml pathToChars value2Chars keytype2Chars \ guessType str2CMPIValue getNameSpaceComponents newStringBuffer \ newList; do has "sblim-sfcc/sym-$s" "$s" "$axml" done # The loader's two exports, in the archive that is supposed to hold them and NOT # in the one that is not. The second half is the assertion: _Create_XML_Env # living in libcimcClientXML.a and NewCIMCEnv living in libcimcclient.a is # exactly why the link order in the recipe is not alphabetical, and a build that # merged them would make that comment silently wrong. has sblim-sfcc/sym-newcimcenv "NewCIMCEnv" "$aclient" has sblim-sfcc/sym-releasecimcenv "ReleaseCIMCEnv" "$aclient" lacks sblim-sfcc/loader-has-no-factory "_Create_XML_Env" "$aclient" # dlopen/dlsym are in the LOADER and nowhere else. That is what makes section 4's # finding a property of one translation unit rather than of the library: a # consumer that never links libcimcclient.a never pulls a dynamic loader in. has sblim-sfcc/loader-uses-dlopen "dlopen" "$aclient" lacks sblim-sfcc/xml-has-no-dlopen "dlopen" "$axml" # cmciConnect is the legacy front end's entry point and it is compiled, not # dlopen'd -- the asymmetry section 1 asserted from the header, now from the # archive. has sblim-sfcc/sym-cmciconnect "cmciConnect" "$asfcc" # The floor guards the check itself: an extraction that silently matched nothing # would otherwise pass every case above vacuously. Both numbers here are measured # off the shipped archive, not estimated from a conventional ELF one: LLVM bitcode # packs identifiers into shared blobs, so a printable-run extraction sees runs like # native_new_CMPIDateTimetvtztimezonetz_minuteswesttz_dsttime rather than one # symbol per string. That is also why the leading \b is gone -- it demanded a word # boundary a mid-blob match almost never has, and cost 243 distinct identifiers # down to 42. 120 sits at half the measured 243, an order of magnitude above the # ~20 identifiers the named cases above reach, so half the library going missing # still trips it. nsym=$(grep -oE '(CMPI|CIMC|native_|__oft_|__ift_|util)[A-Za-z0-9_]+' "$flat" 2>/dev/null | sort -u | grep -c .) if [ "$nsym" -ge 120 ]; then bst_ok sblim-sfcc/sym-floor else bst_notok sblim-sfcc/sym-floor "distinct sfcc symbols=$nsym want>=120"; fi rm -f "$flat" # --- static-only guards ------------------------------------------------------- # # Shared objects are refused distro-wide, and sfcc is a libtool package building # THREE libraries, so a .so or a .la here would mean the static selection was # lost rather than merely that a file appeared. This matters more than usual: a # libcimcClientXML.so.0 appearing is precisely what would make section 4's # loader-* cases start passing for the wrong reason. set -- $libd/libcimcClientXML.so*; noglob_ok sblim-sfcc/no-shared-xml "$@" set -- $libd/libcimcclient.so*; noglob_ok sblim-sfcc/no-shared-client "$@" set -- $libd/libcmpisfcc.so*; noglob_ok sblim-sfcc/no-shared-sfcc "$@" set -- $libd/libcimcClientXML.la $libd/libcimcclient.la $libd/libcmpisfcc.la noglob_ok sblim-sfcc/no-libtool "$@" # Upstream ships no pkg-config file; this pins that nothing in the port invented # one, which a consumer would then depend on and a version bump would drop. set -- $libd/pkgconfig/sfcc.pc $libd/pkgconfig/sblim-sfcc.pc noglob_ok sblim-sfcc/no-pc "$@" # --------------------------------------------------------------------------- # 3. Upstream's TEST/ programmes reached nothing. # # The port drops the whole directory (decision 1 above). These are noinst # programmes, so they would not have installed even if they had compiled -- but # the names are distinctive enough to assert, and asserting them is what turns # "we removed it from SUBDIRS" into "nothing from it is on the image". The names # are all `v2test_*` and `test_[a-z][a-z]`, which nothing else on this image # uses. set -- /usr/bin/v2test_* /usr/sbin/v2test_* /usr/libexec/v2test_* noglob_ok sblim-sfcc/no-v2test-binaries "$@" set -- /usr/bin/test_native /usr/bin/test_ec /usr/bin/test_gi /usr/bin/test_leak noglob_ok sblim-sfcc/no-test-binaries "$@" # --------------------------------------------------------------------------- # 4. The probe -- the library actually running. # # Built by the sblim-sfcc recipe against the archives that same build produced # and shipped in sblim-sfcc-tests, so it cannot drift from the library it tests. # It is installed 0755 in libexecdir and needs no staging: it allocates, encodes # and frees, and writes nothing, so the read-only rootfs at browser runtime is # not in its way. `require' rather than a hard failure -- an image that takes # sblim-sfcc-dev without sblim-sfcc-tests legitimately has nothing to run here, # and that is a coverage prompt (add the package), not a broken port. SF=/usr/libexec/sblim-sfcc-tests require "$SF/sblim-sfcc-probe" sblim-sfcc/probe-present # Run ONCE and keep both the output and the status. out=$("$SF/sblim-sfcc-probe" 2>&1); prc=$? bst_ok sblim-sfcc/probe-ran # --- the loader that cannot work here ---------------------------------------- # THE PORT'S CENTRAL FINDING, measured. NewCIMCEnv dlopen(3)s # libcimcClientXML.so.0 and this distro has no shared objects, so the documented # entry point fails -- and these cases pin that it fails the SPECIFIC way # cimcclient.c writes it (NULL, rc=1, a message naming the library) rather than # by crashing or by handing back a half-built environment. loader-badid-* is the # control: the id is validated before any dlopen, so that arm is reachable on any # image and its passing is what says the failure above is the dlopen and not the # argument checking. # # If this image ever grows shared objects, loader-xml-* go red. That is the # intended behaviour and the point at which someone should re-read this port's # packaging decision -- not a regression in sfcc. for c in loader-xml-null loader-xml-rc loader-xml-msg \ loader-badid-null loader-badid-rc loader-badid-msg; do has "sblim-sfcc/run-$c" "SF-$c OK" "$out" done # --- the object path ---------------------------------------------------------- # op-sethostname-unsupported and op-gethostname-null are load-bearing rather than # incidental: they are WHY a reference key's XML always carries # localhost in the xml-reference case below, and the two are meant # to be read together. # # op-getkey-missing-* is one of the three places the x86-64 oracle contradicted a # reading of the header. An absent key answers CIMC_RC_ERR_NO_SUCH_PROPERTY with # CIMC_nullValue in the data state -- NOT CIMC_notFound, which is defined, # suggestively named, and never set on this path. A consumer testing for it # treats every missing key as present, so the third case pins the absence. for c in op-create op-create-rc op-namespace op-classname op-keycount-empty \ op-sethostname-unsupported op-gethostname-null op-gethostname-rc \ op-setns op-setcn op-keycount \ op-getkey-name-rc op-getkey-name-type op-getkey-name-value \ op-getkey-name-state op-getkey-id-type op-getkey-id-value \ op-getkey-active-type op-getkey-active-value \ op-getkey-missing-rc op-getkey-missing-state \ op-getkey-missing-not-notfound \ op-getkeyat-name op-getkeyat-type op-tostring op-tochars-uri \ op-clone op-clone-independent op-clone-carried-keys; do has "sblim-sfcc/run-$c" "SF-$c OK" "$out" done # --- the XML encoding, byte for byte ------------------------------------------ # xml-reference is the one that matters most: it is the recursive case, and an # encoder that stopped at the first boundary level would still pass every other # case in this suite. The whole nested document -- NAMESPACEPATH, the namespace # split into one element per component, the inner INSTANCENAME and # its own KEYBINDING -- is compared as a single string inside the probe. # xml-reference-repeatable then encodes the SAME path a second time and requires # identical bytes, which is the cheap guard against an encoder that consumes what # it walks. for c in xml-buffer xml-keys xml-nokeys xml-reference xml-reference-repeatable; do has "sblim-sfcc/run-$c" "SF-$c OK" "$out" done # --- every CIMC data type through the one encoder ----------------------------- # value2Chars is the single choke point: KEYVALUE bodies, object-path text and # the URI form all pass through it, so a type it renders wrongly is wrong # everywhere at once. The boundary values are the assertion -- the # signed/unsigned confusions this catches only show at the extremes. for c in v2c-boolean-true v2c-boolean-false v2c-uint8-max v2c-sint8-min \ v2c-uint16-max v2c-sint16-min v2c-uint64-max v2c-sint64-min \ v2c-real32 v2c-real64 \ v2c-chars v2c-chars-null v2c-string-null v2c-ref-null v2c-string; do has "sblim-sfcc/run-$c" "SF-$c OK" "$out" done # THE TWO ILP32-ONLY CASES, and the only place in this suite where this arm and # the x86-64 reference build must DISAGREE. value2CharsUri prints uint32 with # "%lu" and sint32 with "%ld" against an unsigned int/int argument, which is # well-defined only where long is 32 bits. On wasm32 they are exact; the oracle # prints ~1e19 and ~-9.2e18 of stack garbage for the same two calls. They are # asserted rather than skipped because this is a genuine ILP32-vs-LP64 property # of the port and a change in either compiler's varargs handling is worth # hearing about immediately. for c in v2c-uint32-max-ilp32 v2c-sint32-min-ilp32; do has "sblim-sfcc/run-$c" "SF-$c OK" "$out" done # THREE MEASURED GAPS IN UPSTREAM'S ENCODER, pinned as behaviour rather than # editorialised. The port ships the library as upstream wrote it; these cases are # how a consumer finds out about them from the suite instead of from a CIMOM # rejecting a request. # # v2c-real64-6sigfig %g defaults to six significant digits, so a real64 does # not survive a round trip through the text or XML form: # 1.2345678 is emitted as 1.23457. # v2c-no-xml-escaping value2Chars does not escape XML metacharacters, so a key # value carrying '<' or '&' yields a KEYVALUE body that is # not well-formed XML. # v2c-*-empty four types have no arm in value2CharsUri at all -- arrays # (the whole CIMC_ARRAY branch is an empty block), char16, # and the embedded instance/args types -- and fall through # to the empty string rather than to "NULL" or a diagnostic. # # A later version growing a real encoder for any of these turns the matching case # red, which is the correct signal: the behaviour changed, go and read it. for c in v2c-real64-6sigfig v2c-no-xml-escaping \ v2c-char16-empty v2c-instance-empty v2c-args-empty v2c-array-empty; do has "sblim-sfcc/run-$c" "SF-$c OK" "$out" done # keytype2Chars collapses every CIM type to one of three VALUETYPE strings, and # its default arm is "string" -- so an unmapped type is silently a string. That # is why the numeric and boolean arms are asserted one by one rather than by a # single round trip. for c in keytype-boolean keytype-uint32 keytype-real64 keytype-sint64 \ keytype-chars keytype-string keytype-datetime; do has "sblim-sfcc/run-$c" "SF-$c OK" "$out" done # --- THE UPSTREAM DEFECT: a CIMC_chars key is corrupted ----------------------- # # THIS IS THE FINDING THE PROBE EXISTS FOR, and it is exactly the BRINTOS-217 # shape: the package builds clean, installs clean, and hands the caller wrong # data. property.c:__addProperty converts a chars value to a CIMCString and # passes the WRONG POINTER doing it -- # # tmp->value.string = native_new_CMPIString ( (char *) value, &rc ); # # where `value` is the CMPIValue* union, not `value->chars`. The library # therefore strdup(3)s the raw bytes of the pointer itself and stores those. So # every key, property and method argument added as CIMC_chars comes back as a # short run of address bytes. # # Upstream's, and architecture-independent -- found on the x86-64 oracle, # asserted here. The corrupted run is a different LENGTH on this arm (a four-byte # pointer rather than eight), which is why the length is not asserted: the # portable statement, and the one that matters, is that what comes out is not # what went in. # # chars-retyped-to-string is the deliberate half (upstream means chars to become # string) and is asserted separately, so a future fix to the value shows up as # exactly ONE red -- chars-value-corrupt -- rather than as two, and names itself. # # WHY THE PORT DOES NOT FIX IT: the fix changes what a CIMOM on the other end # receives, and nothing on this image can test that end to end. A one-line change # that is right in isolation and unverifiable in situ is not a port decision to # take unilaterally. A consumer's workaround is one line -- wrap the value with # the string factory and add it as CIMC_string, which is what every working case # in this suite does. for c in chars-rc chars-retyped-to-string chars-value-corrupt; do has "sblim-sfcc/run-$c" "SF-$c OK" "$out" done # --- the instance ------------------------------------------------------------- # inst-seeded-count is a finding rather than a formality: newInstance seeds the # instance from the path's KEYS, so it is not empty to begin with, and a consumer # that assumes it is and indexes from 0 gets the key back rather than its own # first property. inst-getobjectpath-text is the other half -- getObjectPath # rebuilds a path from the key properties ONLY, so the four ordinary properties # must be absent from it. # # THE FILTER GROUP IS THE THIRD ORACLE CONTRADICTION and the name invites the # wrong reading. setPropertyFilter GATES WRITES, NOT READS: after filtering to # {Label, Count} the property count is unchanged and Flag is still readable, but # a LATER setProperty of a name outside the list is silently dropped while one # inside it takes. A consumer that filters and then reads, expecting a narrowed # instance, gets the whole thing. for c in inst-create inst-create-rc inst-seeded-count inst-propcount \ inst-get-label-rc inst-get-label-type inst-get-label-value \ inst-get-count-type inst-get-count-value \ inst-get-flag-type inst-get-flag-value \ inst-get-ratio-type inst-get-ratio-value \ inst-get-missing-rc inst-get-missing-state \ inst-replace-count inst-replace-value \ inst-getat-name inst-getat-type \ inst-getobjectpath inst-getobjectpath-text \ inst-setfilter-rc inst-filter-count-unchanged \ inst-filter-read-not-narrowed inst-filter-count-still-5 \ inst-filter-drops-excluded inst-filter-keeps-included \ inst-clone inst-clone-independent; do has "sblim-sfcc/run-$c" "SF-$c OK" "$out" done # --- string, array, datetime, args -------------------------------------------- # arr-get-oob-* is the second oracle contradiction: an out-of-range index answers # through the DATA STATE and not through rc. Measured, rc stays CIMC_RC_OK and # the state carries CIMC_badValue -- so a consumer checking only the status reads # an unset union and believes it. # # dt-now asserts only that the clock produces a well-formed 25-character CIM # datetime -- there is no clock oracle here -- while dt-fromchars and # dt-interval-format pin the two RENDERED forms against fixed strings, which is # the half a consumer serialising a datetime depends on. The interval form is not # interchangeable with the timestamp form: it carries a leading ':' where a # timestamp carries a timezone. for c in str-create str-create-rc str-getcharptr str-clone str-clone-value \ str-after-clone-release str-null-create str-null-charptr \ arr-create arr-create-rc arr-size arr-simpletype \ arr-get-0 arr-get-2 arr-get-elem-type \ arr-get-oob-rc-is-ok arr-get-oob-badvalue \ dt-fromchars dt-fromchars-rc dt-stringformat dt-not-interval \ dt-frombinary dt-is-interval dt-binaryformat dt-interval-format \ dt-now dt-now-length \ args-create args-create-rc args-count-empty args-count \ args-get-first args-get-second args-getat-name args-getat-type; do has "sblim-sfcc/run-$c" "SF-$c OK" "$out" done # --- the transport, and why it is not run here -------------------------------- # # THE SKIP IS DECIDED FROM A MEASUREMENT, NOT FROM AN ASSUMPTION, and the # measurement was taken at BUILD time rather than here. sfcc's CIMCEnv factory # _Create_XML_Env sits in client.c beside the whole HTTP/TLS transport, so a # binary reaching it drags libcurl, libssl, libcrypto, libidn2 and libunistring # in: built and measured, that binary came to 48979172 bytes against a # libcimcClientXML.a of 975666. Fifty times the library, to reach a CIM server # this image does not have and cannot have. # # So the recipe LINKS that binary at build time -- which is the real assertion, # that sfcc's DEPENDS is complete and a consumer who wants the transport can # have it -- and does not install it. What ships is the object-model probe, # which calls the native factories client.c's env wrappers are one-line casts # over. Nothing is skipped at run time because nothing about the transport is # runnable here; the part that could be checked was, in the place where it # could be. # # This case is the guard on that decision: the probe must NOT be carrying the # transport. If a future change links it back in, the shipped binary jumps by # ~48 MB and this case is where that is noticed rather than in a rootfs size # report nobody reads. SFPROBE=$SF/sblim-sfcc-probe sz=$(wc -c < "$SFPROBE" 2>/dev/null) case "$sz" in ''|*[!0-9]*) bst_notok sblim-sfcc/probe-size "could not size $SFPROBE" ;; *) if [ "$sz" -lt 10000000 ]; then bst_ok sblim-sfcc/probe-size else bst_notok sblim-sfcc/probe-size "probe is $sz bytes (>=10M) -- the HTTP/TLS transport has been linked back into a shipped binary"; fi ;; esac # The summary is the guard on the whole of section 4: the probe reports its own # tally, so a run that died a third of the way through -- taking six dozen `has` # cases red with it but leaving the rest of the suite green -- is named here as # one unambiguous failure rather than left to be inferred from the pattern. # # 137 is a MEASURED figure, not a count of the lines above: the same probe was # run against an x86-64 build of this tarball and reported pass=135 fail=2, the # two failures being the ILP32-only cases documented above. On this arm both are # expected to pass, which is the whole of the difference between the two runs. has sblim-sfcc/probe-summary "SF-summary pass=137 fail=0" "$out" check_eq sblim-sfcc/probe-rc 0 "$prc"