. "$BST_LIB"
# oniguruma 6.9.9 -- the regex library jq and Ruby use. The distro is static-only,
# so the payload is two headers, a .pc and the onig-config stub (-dev) plus
# libonig.a (-staticdev), and nothing on this image links it yet.
#
# THIS SUITE IS NOT PAYLOAD-ONLY, and that is the point of the port. onig is the
# package that produced the coroutinize pass's dynamic-alloca refusal: without the
# bbappend's patch the archive builds and packages perfectly and then every
# consumer's final link dies, so "the files are present and well-formed" is
# EXACTLY the evidence that would have passed on a library nobody could use. The
# only way to tell the two apart on target is to run something linked against the
# archive, so data/onig-probe -- cross-linked with wasmcc-glibc against this very
# libonig.a, the data/vfs-probe shape -- is driven below and its output compared
# against a native build of the identical source.
#
# That decision is what found the SECOND defect. The static half of this suite is
# 159/159 green; the runtime half is 21/26 RED on hwjs-cc#24, a silent
# wrong-answer bug that no payload-shaped suite could ever have seen. See the
# banner above the runtime section.
#
# Four things here would be got wrong by copying a neighbouring suite, all of
# them measured rather than assumed:
#
# 1. THE mixed-* CASES ARE THE PATCH'S REGRESSION GUARD, not decoration.
# disable_noname_group_capture() is the one function the pass refused; it
# runs only when a pattern MIXES named and unnamed groups under a syntax
# setting ONIG_SYN_CAPTURE_ONLY_NAMED_GROUP. Instrumenting the library showed
# the probe reaches it exactly 4 times -- the four mixed cases -- and zero
# times for the three controls, so the pairing is what makes the guard real.
# 2. AN UNNAMED GROUP IS DEMOTED TO NON-CAPTURING, which is the observable
# behaviour the patched function implements: `(?x)(y)` yields ONE capture,
# not two. A suite asserting two would fail against a correct port. The
# contrast case is ONIG_OPTION_CAPTURE_GROUP, which keeps both -- and it is
# the only available contrast, because EVERY built-in syntax that can express
# (?...) at all (Oniguruma, Ruby, Perl_NG) also sets that syntax bit.
# Plain ONIG_SYNTAX_PERL rejects (?...) outright.
# 3. oniguruma.pc's Cflags AND Libs ARE BOTH NON-EMPTY AT THE SOURCE
# (`-I${includedir}` / `-L${libdir} -lonig`), so pkgconf FILTERS them and
# --keep-system-* RESTORES them. This is the cmark case and the exact
# opposite of 76-libmxml.test, where identical output proves the fields were
# never populated. Asserting only the filtered half would pass for the wrong
# reason, so both directions are asserted.
# 4. onig-config IS A STUB THAT MUST FAIL. The recipe inherits
# binconfig-disabled, so the script's job is to refuse and exit 1. Asserting
# that it ANSWERS anything would be asserting the policy had broken.
root=${BST_ROOT:-}
inc=$root/usr/include/oniguruma.h
gnu=$root/usr/include/oniggnu.h
pc=$root/usr/lib/pkgconfig/oniguruma.pc
lib=$root/usr/lib/libonig.a
cfg=$root/usr/bin/onig-config
# ---------------------------------------------------------------- headers ----
check onig/header-present test -f "$inc"
check onig/header-nonempty test -s "$inc"
check_out onig/header-guard "#define ONIGURUMA_H" cat "$inc"
check_out onig/header-extern-c 'extern "C" {' cat "$inc"
check onig/gnu-header test -f "$gnu"
check_out onig/gnu-header-guard "#define ONIGGNU_H" cat "$gnu"
# Version, three macros plus the packed integer a consumer compares against.
check_eq onig/ver-major 6 "$(awk '/define[ \t]+ONIGURUMA_VERSION_MAJOR/{print $3}' "$inc")"
check_eq onig/ver-minor 9 "$(awk '/define[ \t]+ONIGURUMA_VERSION_MINOR/{print $3}' "$inc")"
check_eq onig/ver-teeny 9 "$(awk '/define[ \t]+ONIGURUMA_VERSION_TEENY/{print $3}' "$inc")"
check_eq onig/ver-int 60909 "$(awk '/define[ \t]+ONIGURUMA_VERSION_INT/{print $3}' "$inc")"
# onigposix.h is ABSENT and that is correct: the POSIX API is off by upstream's
# default in 6.9.x and the recipe does not enable it. Asserted so that turning it
# on later is a visible test change rather than a silent one.
check onig/no-posix-header sh -c '[ ! -e "$1/usr/include/onigposix.h" ]' _ "$root"
# The syntax and encoding externs a caller names. These are the whole reason to
# use oniguruma over glibc's POSIX regex, and each is a real object in the
# archive further down, so header and archive have to agree.
for s in ONIG_SYNTAX_ONIGURUMA ONIG_SYNTAX_RUBY ONIG_SYNTAX_PERL \
ONIG_SYNTAX_PERL_NG ONIG_SYNTAX_JAVA ONIG_SYNTAX_GNU_REGEX \
ONIG_SYNTAX_GREP ONIG_SYNTAX_EMACS ONIG_SYNTAX_POSIX_BASIC \
ONIG_SYNTAX_POSIX_EXTENDED ONIG_SYNTAX_DEFAULT; do
check_out "onig/hdr-$s" "#define $s" cat "$inc"
done
for e in ONIG_ENCODING_UTF8 ONIG_ENCODING_ASCII ONIG_ENCODING_ISO_8859_1 \
ONIG_ENCODING_EUC_JP ONIG_ENCODING_SJIS ONIG_ENCODING_UTF16_BE \
ONIG_ENCODING_KOI8_R ONIG_ENCODING_BIG5 ONIG_ENCODING_GB18030; do
check_out "onig/hdr-$e" "#define $e" cat "$inc"
done
# The option bits and the one error code the probe asserts by value.
for o in ONIG_OPTION_NONE ONIG_OPTION_IGNORECASE ONIG_OPTION_EXTEND \
ONIG_OPTION_MULTILINE ONIG_OPTION_SINGLELINE ONIG_OPTION_FIND_LONGEST \
ONIG_OPTION_CAPTURE_GROUP ONIG_OPTION_DONT_CAPTURE_GROUP; do
check_out "onig/hdr-$o" "#define $o" cat "$inc"
done
check_out onig/hdr-syn-capture-only "#define ONIG_SYN_CAPTURE_ONLY_NAMED_GROUP" cat "$inc"
check_out onig/hdr-err-unmatched-paren \
"define ONIGERR_END_PATTERN_WITH_UNMATCHED_PARENTHESIS" cat "$inc"
check_out onig/hdr-max-errmsg "#define ONIG_MAX_ERROR_MESSAGE_LEN" cat "$inc"
# ------------------------------------------------------------ pkg-config ----
check onig/pc-present test -f "$pc"
check_out onig/pc-name "Name: oniguruma" cat "$pc"
check_out onig/pc-desc "Description: Regular expression library" cat "$pc"
check_out onig/pc-version "Version: 6.9.9" cat "$pc"
check_out onig/pc-prefix "prefix=/usr" cat "$pc"
check_out onig/pc-libdir "libdir=/usr/lib" cat "$pc"
check_out onig/pc-incdir "includedir=/usr/include" cat "$pc"
# Non-empty at the source -- see note 3. These two exact strings are what
# --keep-system-* restores below.
check_eq onig/pc-libs-raw '-L${libdir} -lonig' \
"$(sed -n 's/^Libs:[ ]*//p' "$pc")"
check_eq onig/pc-cflags-raw '-I${includedir}' \
"$(sed -n 's/^Cflags:[ ]*//p' "$pc")"
# No Requires: oniguruma needs nothing beyond libc, so a consumer's link line is
# self-contained.
check_eq onig/pc-requires-empty "" "$(sed -n 's/^Requires:[ ]*//p' "$pc")"
# ------------------------------------------------------- onig-config stub ----
# See note 4: the stub's contract is to refuse.
check onig/cfg-present test -f "$cfg"
check_rc onig/cfg-exits-1 1 "$cfg" --version
# The message is captured first because check_out also requires exit 0, and this
# script's whole contract is to exit 1 -- asserting it through check_out directly
# would fail on a stub that is behaving correctly.
cfgout=$("$cfg" --cflags 2>&1 || true)
check_out onig/cfg-says-pkgconfig "use an alternative such as pkg-config" \
printf '%s\n' "$cfgout"
# ------------------------------------------------------------- the archive ----
check onig/lib-present test -f "$lib"
check onig/lib-nonempty test -s "$lib"
check_out onig/lib-archive "!" head -c 8 "$lib"
flat=${TMPDIR:-/tmp}/bst-onig.$$
tr -c '\40-\176\n' ' ' < "$lib" > "$flat" 2>/dev/null
# 48 members, one per translation unit: the engine, then one per encoding. The
# encoding members are most of the archive and are the reason it is ~1.9 MB.
for m in regparse regcomp regexec regenc regerror regext regsyntax regtrav \
regversion st reggnu unicode onig_init ascii utf8 utf16_be utf16_le \
utf32_be utf32_le euc_jp sjis big5 gb18030 koi8_r cp1251 euc_tw euc_kr \
iso8859_1 iso8859_5 iso8859_15 iso8859_16 \
unicode_unfold_key unicode_fold1_key unicode_fold2_key unicode_fold3_key; do
check "onig/member-$m" grep -q "$m\.o" "$flat"
done
# The public API a consumer links against.
for s in onig_new onig_new_without_alloc onig_free onig_free_body \
onig_search onig_search_with_param onig_match onig_match_with_param \
onig_scan onig_region_new onig_region_free onig_region_copy \
onig_region_clear onig_region_resize onig_region_set \
onig_name_to_group_numbers onig_name_to_backref_number \
onig_foreach_name onig_number_of_names onig_number_of_captures \
onig_number_of_capture_histories onig_get_capture_tree \
onig_error_code_to_str onig_initialize onig_end onig_version \
onig_copyright onig_get_encoding onig_get_syntax onig_set_syntax_op \
onig_get_options onig_set_default_syntax onig_new_deluxe \
onig_regset_new onig_regset_add onig_regset_search onig_regset_free \
onig_set_callout_of_name onig_get_callout_num_by_tag \
onig_initialize_encoding onig_get_default_case_fold_flag; do
check "onig/sym-$s" grep -q "$s" "$flat"
done
# The syntax and encoding OBJECTS the header's macros dereference. A header
# declaring ONIG_SYNTAX_RUBY whose OnigSyntaxRuby is missing from the archive is a
# link error in the consumer, not a compile error, so these are asserted apart
# from the macros above.
for s in OnigSyntaxOniguruma OnigSyntaxRuby OnigSyntaxPerl OnigSyntaxPerl_NG \
OnigSyntaxJava OnigSyntaxGnuRegex OnigSyntaxGrep OnigSyntaxEmacs \
OnigSyntaxPosixBasic OnigSyntaxPosixExtended OnigDefaultSyntax; do
check "onig/obj-$s" grep -q "$s" "$flat"
done
for e in OnigEncodingUTF8 OnigEncodingASCII OnigEncodingISO_8859_1 \
OnigEncodingEUC_JP OnigEncodingSJIS OnigEncodingUTF16_BE \
OnigEncodingKOI8_R OnigEncodingBIG5 OnigEncodingGB18030; do
check "onig/obj-$e" grep -q "$e" "$flat"
done
# The wasm32 arm witness, and a size window. ~1.96 MB here; a build that dropped
# the encoding members would fall far below, one that kept debug info far above.
check onig/arm-not-elf sh -c '! head -c 512 "$1" | grep -q "ELF"' _ "$lib"
sz=$(wc -c < "$lib")
check onig/lib-size-window sh -c '[ "$1" -gt 1500000 ] && [ "$1" -lt 2500000 ]' _ "$sz"
# Static-only packaging policy: onig's configure builds libonig.so.5 by default
# and the distro's blanket --disable-shared is what turns it off, so a stray .so
# would mean that flag stopped reaching this recipe.
check onig/no-shared sh -c 'set -- "$1"/usr/lib/libonig.so*; [ ! -e "$1" ]' _ "$root"
check onig/no-libtool sh -c '[ ! -e "$1/usr/lib/libonig.la" ]' _ "$root"
# ptest is not in DISTRO_FEATURES, so the recipe's do_install_ptest never ran and
# none of onig's test binaries reached the image.
check onig/no-ptest sh -c '[ ! -d "$1/usr/lib/onig/ptest" ]' _ "$root"
rm -f "$flat"
# --------------------------------------------------- the library, RUNNING ----
# Everything above is true of an UNLINKABLE library too (see the header comment).
# This is the part that is not — and this is the part that is currently RED.
#
# 21 OF THE 26 ASSERTIONS BELOW FAIL ON TARGET, ALL ON ONE ROOT CAUSE:
# brintos.io/brintos/hwjs-cc/issues/24. oniguruma links (refused=0, after the
# bbappend's patch) and then returns silently wrong match offsets: the match
# START is correct, the match END comes back equal to the start, and every
# capture group comes back unset. No trap, no diagnostic. onig's OWN upstream
# `testc` scores 118/785 on this arm against 785/785 natively, so this is the
# library on this platform, not this suite and not this probe.
#
# THE EXPECTED VALUES BELOW ARE DELIBERATELY LEFT AT THE CORRECT ONES -- the
# values a native build of the identical release produces. They are not relaxed
# to match the broken behaviour and the cases are not skipped, because that would
# convert a live regression tripwire into a suite that passes on a broken
# library. When #24 is fixed these 21 flip green on their own, which is the whole
# point of leaving them failing. The five that DO pass (version, copyright, the
# name table, regset and the error path) are the ones that read state out of the
# compiled regex rather than out of an OnigRegion.
probe=${TMPDIR:-/tmp}/bst-onig-probe.$$
if cp "$BST_DATA/onig-probe" "$probe" 2>/dev/null && chmod +x "$probe" 2>/dev/null; then
out=$("$probe" 2>&1)
check_out onig/run-version "ONIG-version OK [6.9.9]" printf '%s\n' "$out"
check_out onig/run-copyright "ONIG-copyright OK" printf '%s\n' "$out"
# Note 1/2: the four cases that reach the patched function, asserted by their
# full group layout rather than by a bare OK, because the layout IS what
# disable_noname_group_capture() rewrites.
check_out onig/run-mixed-2 \
"ONIG-mixed-2 OK [names=1 caps=1 rc=0 regs=2 g1=x]" printf '%s\n' "$out"
check_out onig/run-mixed-3 \
"ONIG-mixed-3 OK [names=2 caps=2 rc=0 regs=3 g1=a g2=c]" printf '%s\n' "$out"
check_out onig/run-mixed-digit \
"ONIG-mixed-digit OK [names=1 caps=1 rc=0 regs=2 g1=42]" printf '%s\n' "$out"
check_out onig/run-perlng-mixed \
"ONIG-perlng-mixed OK [names=1 caps=1 rc=0 regs=2 g1=x]" printf '%s\n' "$out"
# ...and the three that do not. mixed-capture-opt is the same pattern and
# syntax as mixed-2 with ONIG_OPTION_CAPTURE_GROUP added: caps goes 1 -> 2.
check_out onig/run-mixed-capture-opt \
"ONIG-mixed-capture-opt OK [names=1 caps=2 rc=0 regs=3 g1=x g2=y]" printf '%s\n' "$out"
check_out onig/run-allnamed \
"ONIG-allnamed OK [names=2 caps=2 rc=0 regs=3 g1=x g2=y]" printf '%s\n' "$out"
check_out onig/run-allunnamed \
"ONIG-allunnamed OK [names=0 caps=2 rc=0 regs=3 g1=x g2=y]" printf '%s\n' "$out"
# The name table, sorted (the callback's own order is a hash artifact).
check_out onig/run-names \
"ONIG-names OK [count=2 list=mon,year mon->n=1 g=2]" printf '%s\n' "$out"
check_out onig/run-backref-icase \
"ONIG-backref-icase OK [pos=2 len=4]" printf '%s\n' "$out"
check_out onig/run-scan \
"ONIG-scan OK [n=3 cb=3 text=1,22,333]" printf '%s\n' "$out"
check_out onig/run-regset \
"ONIG-regset OK [idx=0 pos=3 n=2]" printf '%s\n' "$out"
# The error path returns a code AND renders a message; both are asserted, since
# a stubbed onig_error_code_to_str would still return the right code.
check_out onig/run-error \
"ONIG-error-badpat OK [rc=-117 msg=end pattern with unmatched parenthesis]" \
printf '%s\n' "$out"
# Five grammars over the same engine -- the dialect support that is the reason
# to ship oniguruma rather than rely on glibc's POSIX regex.
check_out onig/run-syn-ruby "ONIG-syn-ruby OK [pos=2 len=4]" printf '%s\n' "$out"
check_out onig/run-syn-perl "ONIG-syn-perl OK [pos=2 len=3]" printf '%s\n' "$out"
check_out onig/run-syn-java "ONIG-syn-java OK [pos=2 len=3]" printf '%s\n' "$out"
check_out onig/run-syn-posix "ONIG-syn-posix OK [pos=2 len=2]" printf '%s\n' "$out"
check_out onig/run-syn-grep "ONIG-syn-grep OK [pos=2 len=3]" printf '%s\n' "$out"
# Four encodings, including two multibyte ones -- these are the only cases that
# actually consult an encoding table rather than carry it.
check_out onig/run-enc-utf8 "ONIG-enc-utf8 OK [pos=2 len=4]" printf '%s\n' "$out"
check_out onig/run-enc-ascii "ONIG-enc-ascii OK [pos=1 len=3]" printf '%s\n' "$out"
check_out onig/run-enc-latin1 "ONIG-enc-latin1 OK [pos=2 len=2]" printf '%s\n' "$out"
check_out onig/run-enc-eucjp "ONIG-enc-eucjp OK [pos=1 len=4]" printf '%s\n' "$out"
check_out onig/run-utf8-prop "ONIG-utf8-prop OK [pos=3 len=3]" printf '%s\n' "$out"
# The probe's own tally, and its exit status. 24/24 is what the same source
# scores natively against a host build of the identical release.
check_out onig/run-summary "ONIG-SUMMARY 24/24" printf '%s\n' "$out"
check_rc onig/run-exit0 0 "$probe"
rm -f "$probe"
else
bst_notok onig/run-stage "cannot stage $BST_DATA/onig-probe"
fi