. "$BST_LIB" # jansson is a C library for encoding, decoding and manipulating JSON: a # reference-counted json_t tree, a recursive-descent decoder, an encoder driven # by flag bits, and json_pack/json_unpack -- a printf-shaped varargs API for # building and destructuring that tree in one call. # # The distro is static-only and jansson has NO CLI of its own. The stock recipe # builds upstream's 17 API test programs and its simple_parse example, but Yocto # installs none of them (ptest is not in DISTRO_FEATURES), and the bbappend turns # both off rather than pay a wasm32 link for programs nobody ships. So the whole # installed payload is two headers, one pkg-config file, the find_package(jansson) # cmake files (-dev) and the archive libjansson.a (-staticdev). # # --------------------------------------------------------------------------- # WHY THIS SUITE RUNS A PROBE INSTEAD OF STOPPING AT PAYLOAD SHAPE # # The header-and-archive libraries before this one (cjson, json-c, nlohmann-json) # verify the shipped artifact and stop, because with no consumer on the image and # no on-target C compiler there is nothing to run. BRINTOS-217 is why that is not # enough here: 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. jansson is the # same shape of risk -- its decoder is pointer arithmetic over a loop-carried # cursor (lex_scan, parse_value), which is the class hwjs-cc#24 broke for onig. # # So data/jansson-probe is cross-linked with wasmcc-glibc against THE VERY # ARCHIVE THAT SHIPS (/usr/lib/libjansson.a), staged to $TMPDIR and run here. # Its source is src/jansson_probe.c. Four of its groups exist for platform # reasons rather than for jansson's, and are the ones to read first on a red run: # # pack-* / unpack-* jansson's only va_list API. Every one of json_pack, # json_unpack, json_vpack_ex and json_vunpack_ex IS # coroutinized on this arm (they can suspend through malloc), # so these cases are the on-target guard for varargs across # the coroutine rewrite. # real-* / num-* strconv.c routes every real through strtod and # snprintf("%.*g") and corrects for the locale decimal point # (jansson_config.h has JSON_HAVE_LOCALECONV=1 on this arm), # so these measure libc number conversion, not just jansson. # deep-* the decoder recurses once per nesting level, so 1000-deep # nesting measures stack depth on a coroutine arm rather # than assuming the native stack. # bigobj-* the hashtable seeds itself once -- from /dev/urandom when # readable, else gettimeofday+getpid -- and grows by # rehashing. A wrong seed path or a bad rehash loses a key # rather than crashing, so 1000 keys are written and then # every one is read back. # # 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 and the console dump carries the # value for diagnosis. The native control scored 110/110, and it corrected four # assertions of mine before it did: the default real precision is 17 significant # digits so -2.5e-3 dumps as -0.0025000000000000001 and not -0.0025, \uXXXX # escapes come out with UPPERCASE hex, and a duplicate key has its own error code # (json_error_duplicate_key, 14) rather than json_error_invalid_format. # # --------------------------------------------------------------------------- # 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 ~130 cases. # --------------------------------------------------------------------------- incd=/usr/include lib=/usr/lib/libjansson.a pc=/usr/lib/pkgconfig/jansson.pc cm=/usr/lib/cmake/jansson 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 json_object_seed # satisfy a lookup for json_object, and # json_dumps satisfy one for json_dump. 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; } # --- the shipped payload ----------------------------------------------------- hasfile jansson/header-jansson "$incd/jansson.h" hasfile jansson/header-jansson-config "$incd/jansson_config.h" hasfile jansson/archive "$lib" hasfile jansson/pkgconfig "$pc" hasfile jansson/cmake-config "$cm/janssonConfig.cmake" hasfile jansson/cmake-version "$cm/janssonConfigVersion.cmake" hasfile jansson/cmake-targets "$cm/janssonTargets.cmake" hasfile jansson/cmake-targets-noconfig "$cm/janssonTargets-noconfig.cmake" # There is deliberately no jansson/no-shared-object case: shared objects are # refused distro-wide on this arm, so an absent libjansson.so is the distro's # property and not this port's, and every sibling library would assert it too. pctext=$(cat "$pc" 2>/dev/null) has jansson/pc-name "Name: Jansson" "$pctext" has jansson/pc-version "Version: 2.14" "$pctext" has jansson/pc-libs "-ljansson" "$pctext" has jansson/pc-libdir "libdir=\${exec_prefix}/lib" "$pctext" # jansson_config.h is GENERATED at configure time, so these three lines are what # the cross-configure actually concluded about this arm rather than upstream # defaults: with LOCALECONV set, strconv.c consults localeconv() for the decimal # point, and with the two builtin macros set the hash seed takes its atomic path # rather than the thread-unsafe fallback. cfgtext=$(cat "$incd/jansson_config.h" 2>/dev/null) has jansson/cfg-localeconv "#define JSON_HAVE_LOCALECONV 1" "$cfgtext" has jansson/cfg-atomic "#define JSON_HAVE_ATOMIC_BUILTINS 1" "$cfgtext" has jansson/cfg-sync "#define JSON_HAVE_SYNC_BUILTINS 1" "$cfgtext" has jansson/cfg-inline "#define JSON_INLINE inline" "$cfgtext" # --- symbol completeness, tracked from the INSTALLED header ------------------- # Every function the installed header declares 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 header rather than written here, so # it survives a version bump; two grep+sort pipelines are the only forks. # # json_incref and json_decref are excluded BY CONSTRUCTION, not to make this # pass: both are `static JSON_INLINE` wrappers over json_delete that exist only # in the header, and upstream's own export list (src/jansson.def, 79 entries) # omits them for the same reason. Everything else the header declares is a real # archive symbol -- 79 of them, which is what the count case pins. arcsyms=$(grep -ao 'json[a-z0-9_]*' "$lib" 2>/dev/null | sort -u) hdrsyms=$(grep -vE 'JSON_INLINE|^[[:space:]]*#' "$incd/jansson.h" 2>/dev/null \ | grep -oE '\bjson[a-z0-9_]*\(' | sed 's/(//' | sort -u) nsym=0 nmiss=0 missing="" for f in $hdrsyms; do case "$f" in json_incref|json_decref) 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 jansson/symbols-complete else bst_notok jansson/symbols-complete "$nmiss missing:$missing" fi check_eq jansson/symbols-count 79 "$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 jansson/sym-json_loads json_loads "$arcsyms" hasline jansson/sym-json_dumps json_dumps "$arcsyms" hasline jansson/sym-json_pack_ex json_pack_ex "$arcsyms" hasline jansson/sym-json_vunpack_ex json_vunpack_ex "$arcsyms" hasline jansson/sym-json_object_seed json_object_seed "$arcsyms" # --- the library RUNNING, via the cross-linked probe ------------------------- probe=${TMPDIR:-/tmp}/bst-jansson-probe.$$ if cp "$BST_DATA/jansson-probe" "$probe" 2>/dev/null && chmod +x "$probe" 2>/dev/null; then out=$("$probe" 2>&1) # the library's own identity has jansson/run-version "JAN-version OK" "$out" has jansson/run-version-cmp "JAN-version-cmp OK" "$out" # decode, and the eight json_t types the tree can hold has jansson/run-decode "JAN-decode OK" "$out" has jansson/run-type-object "JAN-type-object OK" "$out" has jansson/run-object-size "JAN-object-size OK" "$out" has jansson/run-type-integer "JAN-type-integer OK" "$out" has jansson/run-type-real "JAN-type-real OK" "$out" has jansson/run-type-string "JAN-type-string OK" "$out" has jansson/run-type-true "JAN-type-true OK" "$out" has jansson/run-type-false "JAN-type-false OK" "$out" has jansson/run-type-null "JAN-type-null OK" "$out" has jansson/run-type-array "JAN-type-array OK" "$out" has jansson/run-type-boolean "JAN-type-boolean OK" "$out" has jansson/run-type-number "JAN-type-number OK" "$out" # typed accessors, including the two coercion rules has jansson/run-int-value "JAN-int-value OK" "$out" has jansson/run-real-value "JAN-real-value OK" "$out" has jansson/run-string-value "JAN-string-value OK" "$out" has jansson/run-string-length "JAN-string-length OK" "$out" has jansson/run-num-of-int "JAN-num-of-int OK" "$out" has jansson/run-num-of-real "JAN-num-of-real OK" "$out" has jansson/run-int-of-real "JAN-int-of-real OK" "$out" # integers: json_int_t is 64-bit, so exactness holds past 2^53 has jansson/run-int-i32max "JAN-int-i32max OK" "$out" has jansson/run-int-i32min "JAN-int-i32min OK" "$out" has jansson/run-int-beyond-2p53 "JAN-int-beyond-2p53 OK" "$out" # reals: strtod in, snprintf("%.*g") out, locale decimal point has jansson/run-real-plain "JAN-real-plain OK" "$out" has jansson/run-real-exp "JAN-real-exp OK" "$out" has jansson/run-real-negexp "JAN-real-negexp OK" "$out" has jansson/run-real-zero "JAN-real-zero OK" "$out" has jansson/run-real-pi "JAN-real-pi OK" "$out" has jansson/run-real-prec3 "JAN-real-prec3 OK" "$out" has jansson/run-real-prec10 "JAN-real-prec10 OK" "$out" # string escapes and UTF-8, decode and encode directions has jansson/run-esc-newline "JAN-esc-newline OK" "$out" has jansson/run-esc-tab "JAN-esc-tab OK" "$out" has jansson/run-esc-quote "JAN-esc-quote OK" "$out" has jansson/run-esc-backslash "JAN-esc-backslash OK" "$out" has jansson/run-esc-solidus "JAN-esc-solidus OK" "$out" has jansson/run-esc-control "JAN-esc-control OK" "$out" has jansson/run-esc-u-bmp "JAN-esc-u-bmp OK" "$out" has jansson/run-esc-surrogate-pair "JAN-esc-surrogate-pair OK" "$out" has jansson/run-utf8-raw "JAN-utf8-raw OK" "$out" has jansson/run-ensure-ascii "JAN-ensure-ascii OK" "$out" has jansson/run-ensure-ascii-astral "JAN-ensure-ascii-astral OK" "$out" has jansson/run-utf8-length "JAN-utf8-length OK" "$out" # encoder flag bits has jansson/run-dump-compact "JAN-dump-compact OK" "$out" has jansson/run-dump-sortkeys "JAN-dump-sortkeys OK" "$out" has jansson/run-dump-indent2 "JAN-dump-indent2 OK" "$out" has jansson/run-dump-default "JAN-dump-default OK" "$out" has jansson/run-dump-any-refused "JAN-dump-any-refused OK" "$out" has jansson/run-dump-any "JAN-dump-any OK" "$out" # arrays has jansson/run-array-build "JAN-array-build OK" "$out" has jansson/run-array-size "JAN-array-size OK" "$out" has jansson/run-array-remove "JAN-array-remove OK" "$out" has jansson/run-array-extend "JAN-array-extend OK" "$out" has jansson/run-array-set "JAN-array-set OK" "$out" has jansson/run-array-clear "JAN-array-clear OK" "$out" # objects, including the insertion order the intrusive list keeps has jansson/run-object-build "JAN-object-build OK" "$out" has jansson/run-object-get "JAN-object-get OK" "$out" has jansson/run-object-get-missing "JAN-object-get-missing OK" "$out" has jansson/run-object-del "JAN-object-del OK" "$out" has jansson/run-object-order "JAN-object-order OK" "$out" has jansson/run-object-foreach "JAN-object-foreach OK" "$out" has jansson/run-object-iter "JAN-object-iter OK" "$out" has jansson/run-object-iter-key "JAN-object-iter-key OK" "$out" has jansson/run-object-clear "JAN-object-clear OK" "$out" # equality, shallow copy and deep copy has jansson/run-equal-true "JAN-equal-true OK" "$out" has jansson/run-equal-false "JAN-equal-false OK" "$out" has jansson/run-copy-equal "JAN-copy-equal OK" "$out" has jansson/run-copy-shallow "JAN-copy-shallow OK" "$out" has jansson/run-deepcopy-equal "JAN-deepcopy-equal OK" "$out" has jansson/run-deepcopy-distinct "JAN-deepcopy-distinct OK" "$out" # reference counting, and set vs set_new ownership has jansson/run-refcount "JAN-refcount OK" "$out" has jansson/run-refcount-set "JAN-refcount-set OK" "$out" # json_pack / json_unpack -- the va_list API (see the header above) has jansson/run-pack-object "JAN-pack-object OK" "$out" has jansson/run-pack-array "JAN-pack-array OK" "$out" has jansson/run-pack-nested "JAN-pack-nested OK" "$out" has jansson/run-unpack-nested "JAN-unpack-nested OK" "$out" has jansson/run-unpack-object "JAN-unpack-object OK" "$out" has jansson/run-unpack-strict "JAN-unpack-strict OK" "$out" has jansson/run-sprintf "JAN-sprintf OK" "$out" # decoder errors, by error CODE and not just by rejection has jansson/run-err-unterminated "JAN-err-unterminated OK" "$out" has jansson/run-err-syntax "JAN-err-syntax OK" "$out" has jansson/run-err-trailing "JAN-err-trailing OK" "$out" has jansson/run-err-bare-scalar "JAN-err-bare-scalar OK" "$out" has jansson/run-err-bad-utf8 "JAN-err-bad-utf8 OK" "$out" has jansson/run-err-lone-surrogate "JAN-err-lone-surrogate OK" "$out" has jansson/run-err-dup-key "JAN-err-dup-key OK" "$out" has jansson/run-err-line "JAN-err-line OK" "$out" has jansson/run-err-column "JAN-err-column OK" "$out" has jansson/run-err-position "JAN-err-position OK" "$out" has jansson/run-err-source "JAN-err-source OK" "$out" has jansson/run-err-text "JAN-err-text OK" "$out" # decoder flag bits has jansson/run-flag-decode-any "JAN-flag-decode-any OK" "$out" has jansson/run-flag-eof-check "JAN-flag-eof-check OK" "$out" has jansson/run-flag-int-as-real "JAN-flag-int-as-real OK" "$out" has jansson/run-flag-allow-nul "JAN-flag-allow-nul OK" "$out" has jansson/run-loadb-length "JAN-loadb-length OK" "$out" # the callback APIs, with a 1-byte-at-a-time reader has jansson/run-dump-callback "JAN-dump-callback OK" "$out" has jansson/run-load-callback "JAN-load-callback OK" "$out" # FILE* and path I/O has jansson/run-dump-file "JAN-dump-file OK" "$out" has jansson/run-load-file "JAN-load-file OK" "$out" has jansson/run-loadf "JAN-loadf OK" "$out" has jansson/run-dumpf "JAN-dumpf OK" "$out" has jansson/run-load-file-missing "JAN-load-file-missing OK" "$out" # deep nesting -- the decoder recurses per level has jansson/run-deep-100 "JAN-deep-100 OK" "$out" has jansson/run-deep-1000 "JAN-deep-1000 OK" "$out" # a 1000-key object: hash seeding and rehash on growth has jansson/run-bigobj-size "JAN-bigobj-size OK" "$out" has jansson/run-bigobj-lookup "JAN-bigobj-lookup OK" "$out" has jansson/run-bigobj-roundtrip "JAN-bigobj-roundtrip OK" "$out" # the custom allocator hook, and that it balances has jansson/run-alloc-hook "JAN-alloc-hook OK" "$out" has jansson/run-alloc-balanced "JAN-alloc-balanced OK" "$out" # The probe's own tally and its exit status. 110/110 is what the same # source scores natively against a host build of the identical release. has jansson/run-summary "JAN-SUMMARY 110/110" "$out" check_rc jansson/run-exit0 0 "$probe" rm -f "$probe" else bst_notok jansson/run-stage "cannot stage $BST_DATA/jansson-probe" fi