. "$BST_LIB" # libfastjson is rsyslog's JSON library: a fork of json-c whose whole API is # renamed fjson_*. It parses, builds, mutates and serializes a reference-counted # fjson_object tree, and its decoder is a RESUMABLE state machine rather than a # recursive-descent parser -- fjson_tokener_parse_ex can be fed one byte at a # time and returns fjson_tokener_continue until the document closes. # # libfastjson has NO CLI: its consumers are rsyslog and liblognorm's # lognormalizer. The payload this suite reads is the seven headers under # /usr/include/libfastjson (-dev), libfastjson.pc, libfastjson.a (-staticdev) # and, on the converted arm, libfastjson.so.4.3.0. Upstream ships no cmake # package files, unlike jansson. # # --------------------------------------------------------------------------- # WHY THIS SUITE RUNS A PROBE INSTEAD OF STOPPING AT PAYLOAD SHAPE # # BRINTOS-217 is why: oniguruma COMPILED and PACKAGED perfectly on this arm and # then returned silently wrong offsets to every caller, so a payload-only suite # would have gone green on the exact defect the port existed to find. # libfastjson is the same shape of risk and rather more of it -- the tokener is # pointer arithmetic over a loop-carried cursor whose STATE STACK SURVIVES ACROSS # CALLS, which is the class hwjs-cc#24 broke for onig, and none of the three JSON # libraries already on this image (cjson, json-c, jansson) has a resumable # decoder to measure. # # So data/fastjson-probe is cross-linked with wasmcc-glibc against THE VERY # ARCHIVE THAT SHIPS (/usr/lib/libfastjson.a), staged to $TMPDIR and run here. # Its source is src/fastjson_probe.c. Six of its groups exist for platform # reasons rather than for libfastjson's, and are the ones to read first on a red # run: # # incr-* the resumable tokener, driven one byte per call: 30 calls for a # 31-byte document, each returning fjson_tokener_continue with # the saved-state stack, the cursor and the printbuf accumulator # carried across the suspend. The hardest loop-carried-cursor # exercise available on this port. # double-* json_object.c prints every double with snprintf("%.17g") and # appends ".0" when modf() says the value is integral, and reads # them back with strtod. These measure libc number conversion and # libm's modf as much as libfastjson. # nan-* inf-* the same printer branches on isnan/isinf and emits the # non-standard NaN/Infinity spellings, which the tokener has a # state to read back. Pure libm/libc territory. # depth-* the tokener carries an explicit depth stack # (FJSON_TOKENER_DEFAULT_DEPTH 32, or a caller's count via # fjson_tokener_new_ex) and grows it as nesting descends, so 200 # levels measure stack growth on a coroutine arm. # pb-sprintbuf* sprintbuf() is the library's ONLY varargs surface and it does # two va_start/va_end pairs in one function -- the second reached # only when the first vsnprintf overflows a 128-byte stack buffer # and the long path falls through to vasprintf. Varargs across # the coroutine rewrite is the hazard class that has bitten # sibling ports. # sort-* bsearch-* fjson_object_array_sort/bsearch hand a function pointer to # libc's qsort/bsearch, so libc calls BACK into coroutinized code # through an indirect call. Nothing else here exercises that # direction. # # EVERY EXPECTED VALUE IS THE VALUE A NATIVE x86_64 BUILD OF THE IDENTICAL # RELEASE PRODUCES. The probe compares each value internally and prints its own # verdict, so the cases below assert the verdict while the console dump carries # the value for diagnosis. The native control scored 154/154, and it corrected # nine assertions of mine before it did -- among them that %g drops trailing # zeros so pi prints as 3.14159265358979 and not to 17 digits, that \uXXXX # escapes come out in LOWERCASE hex (the opposite of jansson), that # fjson_object_get_uint CLAMPS a negative to 0 rather than wrapping, that # fjson_object_size/dump/write default to SPACED and not PLAIN, and that # FJSON_TO_STRING_NOZERO drops a trailing zero from float text rather than # dropping zero-valued members. # # --------------------------------------------------------------------------- # WHY BUILTIN MATCHING INSTEAD OF check_out # # The probe runs ONCE and the payload files are read ONCE into shell variables; # every assertion is a `case` glob against them, so there is no fork per case. # The cjson suite next door was killed by the runner's per-suite bound # (BST_SUITE_TIMEOUT) at 156 cases written as check_out+cat: on the wasm32-hwjs # runtime the forking IS the cost, not the work. This suite is ~185 cases. # --------------------------------------------------------------------------- incd=/usr/include/libfastjson lib=/usr/lib/libfastjson.a pc=/usr/lib/pkgconfig/libfastjson.pc nl=' ' # hasfile -- ok iff is a non-empty regular file. # has -- ok iff contains the literal . # hasline -- ok iff carries as a WHOLE line. # Substring matching would let # fjson_tokener_parse_ex satisfy a lookup for # fjson_tokener_parse. 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; } hasline() { case "$nl$3$nl" in *"$nl$2$nl"*) bst_ok "$1" ;; *) bst_notok "$1" "not in archive: $2" ;; esac; } # An image built without libfastjson is a coverage gap, not a failure: skip once # and stop rather than reporting 185 reds for an absent package. if [ ! -s "$lib" ]; then bst_skip libfastjson/present "libfastjson.a not installed on this image" exit 0 fi bst_ok libfastjson/present # --- the shipped payload ----------------------------------------------------- # All seven of upstream's libfastjsoninclude_HEADERS. json_object_private.h and # atomic.h are internal by name but are installed by upstream's Makefile.am, so # their absence would be a packaging change rather than a tidy-up. for h in atomic json json_object json_object_iterator json_object_private json_tokener json_util; do hasfile "libfastjson/header-$h" "$incd/$h.h" done hasfile libfastjson/archive "$lib" hasfile libfastjson/pkgconfig "$pc" # There is deliberately no libfastjson/no-shared-object case: whether the .so # ships is the arm's property and not this port's, and every sibling library # would assert it too. What IS this port's is that a shipped .so loads, which # the consumer block at the end measures. pctext=$(cat "$pc" 2>/dev/null) has libfastjson/pc-name "Name: libfastjson" "$pctext" has libfastjson/pc-version "Version: 1.2304.0" "$pctext" has libfastjson/pc-libs "-lfastjson" "$pctext" has libfastjson/pc-cflags "-I\${includedir}/libfastjson" "$pctext" has libfastjson/pc-libdir "libdir=/usr/lib" "$pctext" # json.h's own API, which lives in no other header. hdrtext=$(cat "$incd/json.h" 2>/dev/null) has libfastjson/hdr-version-decl "fjson_version(void)" "$hdrtext" has libfastjson/hdr-hash-perllike "FJSON_STR_HASH_PERLLIKE 1" "$hdrtext" tkntext=$(cat "$incd/json_tokener.h" 2>/dev/null) has libfastjson/hdr-default-depth "FJSON_TOKENER_DEFAULT_DEPTH 32" "$tkntext" has libfastjson/hdr-strict-flag "FJSON_TOKENER_STRICT 0x01" "$tkntext" # --- the two configure conclusions that select live code paths --------------- # Both are decided at cross-configure time by a LINK test, land in a config.h # that is not installed, and are read here off the SHIPPED ARCHIVE instead -- # which is the only durable record of which branch compiled. # # 1. HAVE_ATOMIC_BUILTINS. Unset, atomic.h `#include ` and the # fjson_object refcount becomes pthread_mutex_lock/unlock around ++/--. There # are no threads on this arm, so the archive must carry no pthread_mutex # reference at all: the __sync builtins are inlined by the compiler and leave # no symbol, so ZERO here is the positive result. # 2. HAVE_VASPRINTF. Unset, json_print.c compiles an rs_vasprintf fallback that # measures with vsnprintf(&empty, 0, fmt, ap) and then formats with # vsprintf(b, fmt, ap) REUSING ap WITH NO va_copy -- undefined behaviour that # a coroutinized varargs arm has no reason to survive. So glibc's vasprintf # must be the one referenced and rs_vasprintf must be absent. # grep -a over the archive rather than strings(1), which busybox need not carry. grepa() { # grepa if grep -aq "$3" "$lib" 2>/dev/null; then _hit=1; else _hit=0; fi if [ "$2" = present ] && [ "$_hit" -eq 1 ]; then bst_ok "$1" elif [ "$2" = absent ] && [ "$_hit" -eq 0 ]; then bst_ok "$1" elif [ "$2" = present ]; then bst_notok "$1" "not in archive: $3" else bst_notok "$1" "unexpectedly in archive: $3"; fi } grepa libfastjson/no-pthread-refcount absent 'pthread_mutex' grepa libfastjson/vasprintf-from-libc present 'vasprintf' grepa libfastjson/no-rs-vasprintf absent 'rs_vasprintf' # --- symbol completeness, tracked from the INSTALLED headers ------------------ # Every fjson_* function the installed headers declare must be present in the # installed archive, so a partial compile, a visibility mistake or a # header/library skew all fail this. The list is derived from the headers rather # than written here, so it survives a version bump; two grep pipelines are the # only forks. # # fjson_object_iter_is_end is excluded BY CONSTRUCTION and not to make this pass: # it is named only inside json_object_iterator.h's comment explaining why such an # API is deliberately NOT provided ("we do not (and MUST NOT) provide"), so the # derivation below picks it out of prose. Everything else the headers declare is # a real archive symbol -- 71 of them, which is what the count case pins. arcsyms=$(grep -ao 'fjson[a-z0-9_]*' "$lib" 2>/dev/null | sort -u) hdrsyms=$(cat "$incd"/*.h 2>/dev/null | grep -vE 'FJSON_INLINE|^[[:space:]]*#' \ | grep -oE '\bfjson[a-z0-9_]*\(' | sed 's/(//' | sort -u) nsym=0 nmiss=0 missing="" for f in $hdrsyms; do case "$f" in fjson_object_iter_is_end) continue ;; esac nsym=$((nsym + 1)) case "$nl$arcsyms$nl" in *"$nl$f$nl"*) ;; *) nmiss=$((nmiss + 1)); missing="$missing $f" ;; esac done if [ "$nmiss" -eq 0 ]; then bst_ok libfastjson/symbols-complete else bst_notok libfastjson/symbols-complete "$nmiss missing:$missing" fi check_eq libfastjson/symbols-count 71 "$nsym" # A spot-check that the derivation above is really reading the archive and not an # empty string that would make the loop vacuously green. hasline libfastjson/sym-tokener-parse-ex fjson_tokener_parse_ex "$arcsyms" hasline libfastjson/sym-tokener-new-ex fjson_tokener_new_ex "$arcsyms" hasline libfastjson/sym-dump-buffered fjson_object_dump_buffered "$arcsyms" hasline libfastjson/sym-iter-begin fjson_object_iter_begin "$arcsyms" hasline libfastjson/sym-new-double-s fjson_object_new_double_s "$arcsyms" hasline libfastjson/sym-parse-int64 fjson_parse_int64 "$arcsyms" # The three internal-but-exported families the probe links against. Upstream # installs neither printbuf.h nor arraylist.h, yet the archive exports both APIs # and fjson_object_get_array RETURNS a struct array_list* no installed header # defines -- so a consumer that wants them must declare them, which is what # src/fastjson_probe.c does for printbuf. intsyms=$(grep -aoE '(printbuf_[a-z_]*|sprintbuf|array_list_[a-z_]*)' "$lib" 2>/dev/null | sort -u) hasline libfastjson/sym-printbuf-new printbuf_new "$intsyms" hasline libfastjson/sym-sprintbuf sprintbuf "$intsyms" hasline libfastjson/sym-array-list-sort array_list_sort "$intsyms" # --- the library RUNNING, via the cross-linked probe ------------------------- probe=${TMPDIR:-/tmp}/bst-fastjson-probe.$$ if cp "$BST_DATA/fastjson-probe" "$probe" 2>/dev/null && chmod +x "$probe" 2>/dev/null; then # The probe is run ONCE and its exit status kept, rather than re-run for the # rc case: on this runtime a 4 MB wasm module's start-up is the dominant cost # of the whole suite. out=$("$probe" 2>&1); prc=$? # the library's own identity has libfastjson/run-version "FJ-version OK" "$out" # the six fjson_type values, from one parsed document, plus how a JSON null is # represented (a NULL pointer -- get_ex is the only way to tell present-null # from absent) and the type-name table has libfastjson/run-parse-object "FJ-parse-object OK" "$out" has libfastjson/run-member-count "FJ-member-count OK" "$out" has libfastjson/run-object-length "FJ-object-length OK" "$out" has libfastjson/run-type-object "FJ-type-object OK" "$out" has libfastjson/run-type-array "FJ-type-array OK" "$out" has libfastjson/run-type-string "FJ-type-string OK" "$out" has libfastjson/run-type-int "FJ-type-int OK" "$out" has libfastjson/run-type-double "FJ-type-double OK" "$out" has libfastjson/run-type-boolean "FJ-type-boolean OK" "$out" has libfastjson/run-null-is-null-pointer "FJ-null-is-null-pointer OK" "$out" has libfastjson/run-null-present-via-get-ex "FJ-null-present-via-get-ex OK" "$out" has libfastjson/run-is-type-yes "FJ-is-type-yes OK" "$out" has libfastjson/run-is-type-no "FJ-is-type-no OK" "$out" has libfastjson/run-type-name-object "FJ-type-name-object OK" "$out" has libfastjson/run-type-name-array "FJ-type-name-array OK" "$out" has libfastjson/run-type-name-string "FJ-type-name-string OK" "$out" has libfastjson/run-type-name-int "FJ-type-name-int OK" "$out" has libfastjson/run-type-name-double "FJ-type-name-double OK" "$out" has libfastjson/run-type-name-boolean "FJ-type-name-boolean OK" "$out" has libfastjson/run-type-name-null "FJ-type-name-null OK" "$out" # parse edges, and the error contract by CODE rather than by rejection alone has libfastjson/run-parse-empty-array "FJ-parse-empty-array OK" "$out" has libfastjson/run-parse-empty-object "FJ-parse-empty-object OK" "$out" has libfastjson/run-parse-nested "FJ-parse-nested OK" "$out" has libfastjson/run-parse-garbage "FJ-parse-garbage OK" "$out" has libfastjson/run-parse-verbose-ok "FJ-parse-verbose-ok OK" "$out" has libfastjson/run-parse-verbose-err "FJ-parse-verbose-err OK" "$out" has libfastjson/run-err-desc-unexpected "FJ-err-desc-unexpected OK" "$out" has libfastjson/run-err-desc-eof "FJ-err-desc-eof OK" "$out" has libfastjson/run-err-desc-depth "FJ-err-desc-depth OK" "$out" has libfastjson/run-err-desc-success "FJ-err-desc-success OK" "$out" # the resumable tokener, one byte per call (see the header above) has libfastjson/run-tokener-new "FJ-tokener-new OK" "$out" has libfastjson/run-incr-continues "FJ-incr-continues OK" "$out" has libfastjson/run-incr-complete "FJ-incr-complete OK" "$out" has libfastjson/run-incr-value "FJ-incr-value OK" "$out" has libfastjson/run-incr-nested-string "FJ-incr-nested-string OK" "$out" has libfastjson/run-incr-real "FJ-incr-real OK" "$out" has libfastjson/run-incr-error-clear "FJ-incr-error-clear OK" "$out" has libfastjson/run-tokener-reuse "FJ-tokener-reuse OK" "$out" # strict mode vs the default's C-style comments has libfastjson/run-comment-accepted "FJ-comment-accepted OK" "$out" has libfastjson/run-strict-comment-rejected "FJ-strict-comment-rejected OK" "$out" has libfastjson/run-strict-trailing "FJ-strict-trailing OK" "$out" # the depth stack, at its default limit, over it, and grown by new_ex has libfastjson/run-depth-at-limit "FJ-depth-at-limit OK" "$out" has libfastjson/run-depth-over-limit "FJ-depth-over-limit OK" "$out" has libfastjson/run-depth-200-with-new-ex "FJ-depth-200-with-new-ex OK" "$out" # integers: int64 exactness past 2^53, and the coercion rules of the typed # accessors including get_uint's clamp has libfastjson/run-int-basic "FJ-int-basic OK" "$out" has libfastjson/run-int-as-string "FJ-int-as-string OK" "$out" has libfastjson/run-int64-beyond-2p53 "FJ-int64-beyond-2p53 OK" "$out" has libfastjson/run-int64-as-string "FJ-int64-as-string OK" "$out" has libfastjson/run-int64-min-ish "FJ-int64-min-ish OK" "$out" has libfastjson/run-uint-of-negative "FJ-uint-of-negative OK" "$out" has libfastjson/run-uint-i32max "FJ-uint-i32max OK" "$out" has libfastjson/run-int-of-string "FJ-int-of-string OK" "$out" has libfastjson/run-double-of-string "FJ-double-of-string OK" "$out" has libfastjson/run-int-of-bad-string "FJ-int-of-bad-string OK" "$out" has libfastjson/run-int-of-double "FJ-int-of-double OK" "$out" has libfastjson/run-double-of-int "FJ-double-of-int OK" "$out" # doubles: snprintf("%.17g"), modf's ".0" suffix, and strtod on the way back has libfastjson/run-double-integral "FJ-double-integral OK" "$out" has libfastjson/run-double-half "FJ-double-half OK" "$out" has libfastjson/run-double-tenth "FJ-double-tenth OK" "$out" has libfastjson/run-double-negexp "FJ-double-negexp OK" "$out" has libfastjson/run-double-pi "FJ-double-pi OK" "$out" has libfastjson/run-double-big "FJ-double-big OK" "$out" has libfastjson/run-double-big-no-roundtrip "FJ-double-big-no-roundtrip OK" "$out" has libfastjson/run-double-small-exp "FJ-double-small-exp OK" "$out" has libfastjson/run-nozero-integral "FJ-nozero-integral OK" "$out" has libfastjson/run-nozero-exponent "FJ-nozero-exponent OK" "$out" has libfastjson/run-double-custom-string "FJ-double-custom-string OK" "$out" has libfastjson/run-double-custom-value "FJ-double-custom-value OK" "$out" # NaN / Infinity: isnan/isinf out, a tokener state back in has libfastjson/run-nan-print "FJ-nan-print OK" "$out" has libfastjson/run-inf-print "FJ-inf-print OK" "$out" has libfastjson/run-neginf-print "FJ-neginf-print OK" "$out" has libfastjson/run-inf-parse "FJ-inf-parse OK" "$out" has libfastjson/run-nan-parse "FJ-nan-parse OK" "$out" # the standalone strtoll / strtod wrappers has libfastjson/run-parse-int64-ok "FJ-parse-int64-ok OK" "$out" has libfastjson/run-parse-int64-bad "FJ-parse-int64-bad OK" "$out" has libfastjson/run-parse-double-ok "FJ-parse-double-ok OK" "$out" has libfastjson/run-parse-double-bad "FJ-parse-double-bad OK" "$out" # strings: escapes out (LOWERCASE \u hex), UTF-8 and surrogate pairs back in has libfastjson/run-str-value "FJ-str-value OK" "$out" has libfastjson/run-str-length "FJ-str-length OK" "$out" has libfastjson/run-str-len-explicit "FJ-str-len-explicit OK" "$out" has libfastjson/run-str-empty "FJ-str-empty OK" "$out" has libfastjson/run-esc-encode "FJ-esc-encode OK" "$out" has libfastjson/run-esc-control "FJ-esc-control OK" "$out" has libfastjson/run-utf8-passthrough "FJ-utf8-passthrough OK" "$out" has libfastjson/run-unicode-escape-decode "FJ-unicode-escape-decode OK" "$out" has libfastjson/run-surrogate-pair-decode "FJ-surrogate-pair-decode OK" "$out" has libfastjson/run-surrogate-pair-length "FJ-surrogate-pair-length OK" "$out" has libfastjson/run-esc-solidus-decode "FJ-esc-solidus-decode OK" "$out" # objects, their insertion order, and the GLOBAL key-case switch has libfastjson/run-obj-add-get "FJ-obj-add-get OK" "$out" has libfastjson/run-obj-get-ex-hit "FJ-obj-get-ex-hit OK" "$out" has libfastjson/run-obj-get-ex-miss "FJ-obj-get-ex-miss OK" "$out" has libfastjson/run-obj-order "FJ-obj-order OK" "$out" has libfastjson/run-obj-replace "FJ-obj-replace OK" "$out" has libfastjson/run-obj-replace-keeps-length "FJ-obj-replace-keeps-length OK" "$out" has libfastjson/run-obj-del "FJ-obj-del OK" "$out" has libfastjson/run-obj-del-gone "FJ-obj-del-gone OK" "$out" has libfastjson/run-obj-add-ex-new "FJ-obj-add-ex-new OK" "$out" has libfastjson/run-obj-add-ex-const "FJ-obj-add-ex-const OK" "$out" has libfastjson/run-case-sensitive-default "FJ-case-sensitive-default OK" "$out" has libfastjson/run-case-insensitive-toggle "FJ-case-insensitive-toggle OK" "$out" has libfastjson/run-case-sensitive-restore "FJ-case-sensitive-restore OK" "$out" # arrays, including put_idx's sparse growth (the hole reads back as null) has libfastjson/run-arr-length "FJ-arr-length OK" "$out" has libfastjson/run-arr-get-idx "FJ-arr-get-idx OK" "$out" has libfastjson/run-arr-get-idx-oob "FJ-arr-get-idx-oob OK" "$out" has libfastjson/run-arr-put-idx-grows "FJ-arr-put-idx-grows OK" "$out" has libfastjson/run-arr-put-idx-hole "FJ-arr-put-idx-hole OK" "$out" has libfastjson/run-arr-del-idx "FJ-arr-del-idx OK" "$out" # qsort/bsearch calling BACK into coroutinized code through a function pointer has libfastjson/run-sort-callback "FJ-sort-callback OK" "$out" has libfastjson/run-bsearch-hit "FJ-bsearch-hit OK" "$out" has libfastjson/run-bsearch-miss "FJ-bsearch-miss OK" "$out" # the iterator API, whose handle is a STRUCT RETURNED BY VALUE has libfastjson/run-iter-names "FJ-iter-names OK" "$out" has libfastjson/run-iter-values "FJ-iter-values OK" "$out" has libfastjson/run-iter-terminates "FJ-iter-terminates OK" "$out" has libfastjson/run-iter-init-default "FJ-iter-init-default OK" "$out" has libfastjson/run-iter-empty-is-end "FJ-iter-empty-is-end OK" "$out" # the five serialization flag bits, and that size/dump/write default to SPACED has libfastjson/run-ser-plain "FJ-ser-plain OK" "$out" has libfastjson/run-ser-spaced "FJ-ser-spaced OK" "$out" has libfastjson/run-ser-default-is-spaced "FJ-ser-default-is-spaced OK" "$out" has libfastjson/run-ser-pretty-newlines "FJ-ser-pretty-newlines OK" "$out" has libfastjson/run-ser-pretty-indent "FJ-ser-pretty-indent OK" "$out" has libfastjson/run-ser-pretty-tab "FJ-ser-pretty-tab OK" "$out" has libfastjson/run-size-matches-default "FJ-size-matches-default OK" "$out" has libfastjson/run-size-ext-plain "FJ-size-ext-plain OK" "$out" # dump through a caller callback, and again through a 16-byte temp buffer that # forces many small flushes has libfastjson/run-dump-bytes "FJ-dump-bytes OK" "$out" has libfastjson/run-dump-text "FJ-dump-text OK" "$out" has libfastjson/run-dump-buffered-text "FJ-dump-buffered-text OK" "$out" has libfastjson/run-dump-buffered-flushes "FJ-dump-buffered-flushes OK" "$out" # FILE* and path I/O -- stdio is a suspension point on this arm has libfastjson/run-to-file-rc "FJ-to-file-rc OK" "$out" has libfastjson/run-from-file "FJ-from-file OK" "$out" has libfastjson/run-from-fd "FJ-from-fd OK" "$out" has libfastjson/run-to-file-ext-rc "FJ-to-file-ext-rc OK" "$out" has libfastjson/run-from-file-pretty "FJ-from-file-pretty OK" "$out" has libfastjson/run-from-file-missing "FJ-from-file-missing OK" "$out" has libfastjson/run-write-file-bytes "FJ-write-file-bytes OK" "$out" has libfastjson/run-write-file-text "FJ-write-file-text OK" "$out" has libfastjson/run-write-file-ext-text "FJ-write-file-ext-text OK" "$out" # reference counting: get/put, the free on the last put, and add()'s ownership # transfer -- the path that takes the __sync builtins has libfastjson/run-refcount-get-same-pointer "FJ-refcount-get-same-pointer OK" "$out" has libfastjson/run-refcount-put-keeps-alive "FJ-refcount-put-keeps-alive OK" "$out" has libfastjson/run-refcount-alive-after-put "FJ-refcount-alive-after-put OK" "$out" has libfastjson/run-refcount-put-frees "FJ-refcount-put-frees OK" "$out" has libfastjson/run-refcount-add-owns "FJ-refcount-add-owns OK" "$out" # printbuf, and sprintbuf's two varargs paths (short: vsnprintf into a # 128-byte stack buffer; long: a second va_start and vasprintf) has libfastjson/run-pb-new "FJ-pb-new OK" "$out" has libfastjson/run-pb-append "FJ-pb-append OK" "$out" has libfastjson/run-pb-sprintbuf-short "FJ-pb-sprintbuf-short OK" "$out" has libfastjson/run-pb-reset "FJ-pb-reset OK" "$out" has libfastjson/run-pb-sprintbuf-long "FJ-pb-sprintbuf-long OK" "$out" has libfastjson/run-pb-sprintbuf-long-tail "FJ-pb-sprintbuf-long-tail OK" "$out" has libfastjson/run-pb-memset "FJ-pb-memset OK" "$out" has libfastjson/run-global-printbuf-size "FJ-global-printbuf-size OK" "$out" # 1000 keys written and every one read back, and 1000 elements sorted through # the callback: a bad rehash or a bad indirect call loses a value rather than # crashing, so both are asserted by lookup and not by size has libfastjson/run-bigobj-length "FJ-bigobj-length OK" "$out" has libfastjson/run-bigobj-lookup "FJ-bigobj-lookup OK" "$out" has libfastjson/run-bigobj-roundtrip "FJ-bigobj-roundtrip OK" "$out" has libfastjson/run-bigarr-sorted "FJ-bigarr-sorted OK" "$out" # The probe's own tally and its exit status. 154/154 is what the same source # scores natively against a host build of the identical release. has libfastjson/run-summary "FJ-SUMMARY 154/154" "$out" check_eq libfastjson/run-exit0 0 "$prc" rm -f "$probe" else bst_notok libfastjson/run-stage "cannot stage $BST_DATA/fastjson-probe" fi # --- the SHARED library loading, through a shipped consumer ------------------- # The probe above is linked against libfastjson.a, so every case so far is green # on an image whose libfastjson.so is refused at load -- and that has happened: # a main naming a refused needed entry is killed with rc=127 and nothing on # either stream, indistinguishable at the guest from a tool that is absent. The # probe cannot name the .so itself (data/ is prebuilt, and a needed entry names a # content-addressed generation), so the check runs the consumers the image ships, # each only if its needed list really names libfastjson.so -- a consumer that # links the archive in says nothing about the .so and is skipped, not counted. # The signature of a dark library is rc=127 with empty output; a version banner # is proof the loader staged, instantiated and ran its constructors. so=/usr/lib/libfastjson.so.4.3.0 if [ -e "$so" ]; then nso=0 for spec in /usr/bin/lognormalizer:-V /usr/sbin/rsyslogd:-v; do m=${spec%%:*}; flag=${spec#*:}; id=libfastjson/so-consumer-${m##*/} if [ ! -x "$m" ]; then bst_skip "$id" "$m not on this image" elif ! grep -a -q 'libfastjson\.so\.4' "$m" 2>/dev/null; then bst_skip "$id" "$m does not name libfastjson.so (archive linked in)" else nso=$((nso + 1)) bst_run 60 "$m" "$flag" if [ "$rc" = 127 ] || [ "$rc" = 126 ]; then bst_notok "$id" "rc=$rc, output '$(_bst_1line "$out")' -- a refused needed entry (libfastjson.so or a sibling); read the host console" elif [ -z "$out" ]; then bst_notok "$id" "rc=$rc and no output from $m $flag" else bst_ok "$id" fi fi done if [ "$nso" -eq 0 ]; then bst_skip libfastjson/so-consumer-any "libfastjson.so ships but no shipped main names it -- nothing can go dark" else bst_ok libfastjson/so-consumer-any fi else bst_skip libfastjson/so-consumer-any "no libfastjson.so on this image (static arm)" fi