# BST-TIMEOUT: 600 # one instantiation of a ~6.4 MB probe + one pass over a 600 kB archive . "$BST_LIB" # double-conversion (meta-oe recipes-support/dc, 3.3.0 at SRCREV 4f7a25d8) -- # Google's binary<->decimal library: the shortest-round-trip double printing V8 # and most JSON writers use, plus the decimal parser that reads it back. Sixth # port of the C++ round (BRINTOS-1094), after abseil-cpp, re2, gflags, glog and # fmt. # # --------------------------------------------------------------------------- # TWO CONSUMERS, BECAUSE THEY PROVE DIFFERENT THINGS # # The PAYLOAD blocks assert what a downstream recipe reaches -- the eleven # headers, the archive, the four CMake package files -- plus mangled C++ # symbols and a pair of __cxa_guard_* calls, which a C compile of the same # sources cannot emit and which are therefore direct evidence that the C++ # arm of the toolchain worked. There is no _ZTV/_ZTI to point at: this # library has no virtual function anywhere, by design. # # data/dc-probe is a CONSUMER of that payload: a program compiled against # these headers and LINKED AGAINST THIS BUILD'S libdouble-conversion.a, built # by the recipe so it cannot drift from what shipped. # # THE PROBE IS WHY THIS PORT CAN CLAIM ANYTHING AT ALL. double-conversion is # static-only here, so without a consumer the recipe ships headers and an # archive and no program -- and an undefined symbol in a static archive is not # an error until something links it. That is how glog (BRINTOS-1101) shipped # green and unlinkable, and what fmt's __udivmodti4 turned out to be # (BRINTOS-1102). The one place this library carries that risk is # string-to-double.cc's ToLower(), which resolves # std::use_facet > against std::locale::classic() behind a # function-local static -- the only use of in the sources and the # only site needing libc++'s locale machinery, a static guard and RTTI. The # parse/*-ci-* cases below DRIVE it rather than merely link it. # # WHAT IS COMPARED BYTE-FOR-BYTE. The probe's run is compared line for line # against data/dc-native.txt -- the identical source built and run on x86-64 # from the double-conversion-native recipe the bbappend adds -- with NO # tolerance band and NO NORMALISATION AT ALL. Every value the probe converts # enters as a 64-bit PATTERN rather than a decimal literal, so the compilers' # own literal parsers are not part of the comparison; nothing reads the clock, # the environment, the filesystem, an address or a locale-sensitive default; # and nothing printed is a `long`, a `size_t` or a pointer, so the ILP32/LP64 # split between the arms cannot show. One differing line is a defect. # # 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 renderings IEEE-754 and this library's documented contract fix # independently -- the shortest round-trips, the exact decimal expansions, the # ToFixed wall, the parser's sentinels -- are ALSO asserted against literals # here. Those hold whatever the control says. # --------------------------------------------------------------------------- # 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_DC_ROOT:-}" ARCHIVE=$R/usr/lib/libdouble-conversion.a INCDIR=$R/usr/include/double-conversion CMDIR=$R/usr/lib/cmake/double-conversion PROBE=$BST_DATA/dc-probe NATIVE=$BST_DATA/dc-native.txt # THE CANARY, which is not an assertion about double-conversion at all. # # brintos_local_verify.py loses a suite's FIRST BST result line before the host # parser ever sees it -- BRINTOS-1149, a defect in our own host-side tooling and # not in the runner, the guest or any package. The harness reports the deficit # (`declared N case(s), N-1 reached the console`) but computes its pass count as # total-minus-failures, so THE DROPPED LINE IS COUNTED AS A PASS. A suite whose # first case is a genuine `not ok` therefore loses the one line that mattered, # silently. # # This file's first case WAS double-conversion/present, a real assertion, and the # first local verify of this port duly lost it. So the first line out of the file # now asserts something already true. It hides nothing -- the harness still # reports the deficit and every real case below is still counted. Same idiom, and # the same reason, as 83-flatbuffers (BRINTOS-1114). # # Remove this case when 1149 is fixed. bst_ok double-conversion/suite-canary if [ ! -f "$ARCHIVE" ]; then bst_skip double-conversion/present "double-conversion not installed on this image" exit 0 fi bst_ok double-conversion/present nl=' ' tmp=${TMPDIR:-/tmp} # has # A shell `case` rather than a grep: this suite has ~90 content assertions and # an exec apiece is what killed the first draft of the abseil suite on target, # where every process is a fresh instantiation of a multi-megabyte module. has() { case "$2" in *"$nl$3$nl"*) bst_ok "$1" ;; *) bst_notok "$1" "missing: $3" ;; esac } # sub sub() { case "$2" in *"$3"*) bst_ok "$1" ;; *) bst_notok "$1" "missing: $3" ;; esac } # hasnt -- substring, for "must NOT be there" hasnt() { case "$2" in *"$3"*) bst_notok "$1" "present but must not be: $3" ;; *) bst_ok "$1" ;; esac } # --- the package is whole ---------------------------------------------------- check dc/hdr-double-conversion test -f "$INCDIR/double-conversion.h" check dc/hdr-double-to-string test -f "$INCDIR/double-to-string.h" check dc/hdr-string-to-double test -f "$INCDIR/string-to-double.h" check dc/hdr-bignum test -f "$INCDIR/bignum.h" # bignum-dtoa.h is deliberately NOT asserted: upstream ships it in the source # tree but leaves it out of CMakeLists' install list, so it is absent from every # build of this version rather than missing from ours. Caught by the native dry # run of this file, which is what that dry run is for. check dc/hdr-cached-powers test -f "$INCDIR/cached-powers.h" check dc/hdr-diy-fp test -f "$INCDIR/diy-fp.h" check dc/hdr-fast-dtoa test -f "$INCDIR/fast-dtoa.h" check dc/hdr-fixed-dtoa test -f "$INCDIR/fixed-dtoa.h" check dc/hdr-ieee test -f "$INCDIR/ieee.h" check dc/hdr-strtod test -f "$INCDIR/strtod.h" check dc/hdr-utils test -f "$INCDIR/utils.h" check dc/archive test -f "$ARCHIVE" check dc/cmake-config test -f "$CMDIR/double-conversionConfig.cmake" check dc/cmake-version test -f "$CMDIR/double-conversionConfigVersion.cmake" check dc/cmake-targets test -f "$CMDIR/double-conversionTargets.cmake" check dc/cmake-noconfig test -f "$CMDIR/double-conversionTargets-noconfig.cmake" # 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 dc/no-shared "$R/usr/lib/libdouble-conversion.so" # The stock recipe's most visible feature is its ptest arm, which needs cmake # AND ctest on the target to run a cctest tree. Neither is ported. This distro # carries no "ptest" in DISTRO_FEATURES so ptest.bbclass creates no package at # all -- asserted rather than assumed, because an image that quietly grew the # feature would install a directory whose runner cannot execute. check dc/no-ptest test ! -d "$R/usr/lib/double-conversion/ptest" # --- the archive's shape ----------------------------------------------------- # # One pass over the archive with one grep, for the reason in `has` above. The # members are bitcode, so these names live in the bitcode string tables and are # reachable with the same tokenise-and-match the other suites use. # # EVERY NEEDLE BELOW WAS SCORED AGAINST BOTH ARMS BEFORE IT WAS WRITTEN DOWN, # because a needle present only in the target's bitcode passes on target and # fails every native validation of this file -- which is the dry run that would # have caught it. Two candidates were rejected that way: # double_conversion::DiyFp::Times and Bignum::MultiplyByUInt64 are present in # the target's bitcode members and ZERO times in the optimised native ELF # archive, having been inlined. That is the same trap fmt's suite hit with # detail::umul128 one ticket earlier. nf=$tmp/bst-dc-needles.$$ hf=$tmp/bst-dc-hits.$$ cat > "$nf" <<'NEEDLES' _ZN17double_conversion23DoubleToStringConverter19EcmaScriptConverterEv _ZN17double_conversion23DoubleToStringConverter13DoubleToAsciiEdNS0_8DtoaModeEiPciPbPiS4_ _ZNK17double_conversion23DoubleToStringConverter7ToFixedEdiPNS_13StringBuilderE _ZNK17double_conversion23DoubleToStringConverter11ToPrecisionEdiPNS_13StringBuilderE _ZNK17double_conversion23DoubleToStringConverter13ToExponentialEdiPNS_13StringBuilderE _ZNK17double_conversion23StringToDoubleConverter14StringToDoubleEPKciPi _ZNK17double_conversion23StringToDoubleConverter13StringToFloatEPKciPi _ZNK17double_conversion23StringToDoubleConverter12StringToIeeeIPKcEEdT_ibPi _ZN17double_conversion8FastDtoaEdNS_12FastDtoaModeEiNS_6VectorIcEEPiS3_ _ZN17double_conversion10BignumDtoaEdNS_14BignumDtoaModeEiNS_6VectorIcEEPiS3_ _ZN17double_conversion13FastFixedDtoaEdiNS_6VectorIcEEPiS2_ _ZN17double_conversion6Bignum21DivideModuloIntBignumERKS0_ _ZN17double_conversion6Bignum20MultiplyByPowerOfTenEi _ZN17double_conversion6Bignum19AssignDecimalStringENS_6VectorIKcEE _ZN17double_conversion6Bignum15AssignHexStringENS_6VectorIKcEE _ZN17double_conversion6Bignum6SquareEv _ZN17double_conversion16PowersOfTenCache32GetCachedPowerForDecimalExponentEiPNS_5DiyFpEPi _ZN17double_conversion16PowersOfTenCache36GetCachedPowerForBinaryExponentRangeEiiPNS_5DiyFpEPi _ZN17double_conversion13StrtodTrimmedENS_6VectorIKcEEi _ZN17double_conversion13StrtofTrimmedENS_6VectorIKcEEi _ZZN17double_conversion12_GLOBAL__N_17ToLowerEcE5cType _ZGVZN17double_conversion12_GLOBAL__N_17ToLowerEcE5cType _ZGVZN17double_conversion23DoubleToStringConverter19EcmaScriptConverterEvE9converter __cxa_guard_acquire __cxa_guard_release NEEDLES cat "$ARCHIVE" 2>/dev/null | tr -c 'A-Za-z0-9_.' '\n' | grep -F -f "$nf" > "$hf" 2>/dev/null HITS=$nl$(cat "$hf" 2>/dev/null)$nl rm -f "$nf" "$hf" 2>/dev/null # The four public renderers and the two public parsers actually got compiled # in, rather than an empty archive that satisfies every file check above. sub dc/sym-ecma-converter "$HITS" "_ZN17double_conversion23DoubleToStringConverter19EcmaScriptConverterEv" sub dc/sym-double-to-ascii "$HITS" "_ZN17double_conversion23DoubleToStringConverter13DoubleToAsciiEdNS0_8DtoaModeEiPciPbPiS4_" sub dc/sym-to-fixed "$HITS" "_ZNK17double_conversion23DoubleToStringConverter7ToFixedEdiPNS_13StringBuilderE" sub dc/sym-to-precision "$HITS" "_ZNK17double_conversion23DoubleToStringConverter11ToPrecisionEdiPNS_13StringBuilderE" sub dc/sym-to-exponential "$HITS" "_ZNK17double_conversion23DoubleToStringConverter13ToExponentialEdiPNS_13StringBuilderE" sub dc/sym-string-to-double "$HITS" "_ZNK17double_conversion23StringToDoubleConverter14StringToDoubleEPKciPi" sub dc/sym-string-to-float "$HITS" "_ZNK17double_conversion23StringToDoubleConverter13StringToFloatEPKciPi" sub dc/sym-string-to-ieee "$HITS" "_ZNK17double_conversion23StringToDoubleConverter12StringToIeeeIPKcEEdT_ibPi" # The three dtoa engines. A port that shipped only the fast path would render # most values correctly and lose exactly the awkward ones -- which is the # failure this whole suite exists to catch, so their presence is asserted # separately rather than folded into one symbol check. sub dc/sym-fast-dtoa "$HITS" "_ZN17double_conversion8FastDtoaEdNS_12FastDtoaModeEiNS_6VectorIcEEPiS3_" sub dc/sym-bignum-dtoa "$HITS" "_ZN17double_conversion10BignumDtoaEdNS_14BignumDtoaModeEiNS_6VectorIcEEPiS3_" sub dc/sym-fixed-dtoa "$HITS" "_ZN17double_conversion13FastFixedDtoaEdiNS_6VectorIcEEPiS2_" # The multiprecision arithmetic underneath the slow path, and the cached powers # of ten both paths index. sub dc/sym-bignum-divmod "$HITS" "_ZN17double_conversion6Bignum21DivideModuloIntBignumERKS0_" sub dc/sym-bignum-mul-pow10 "$HITS" "_ZN17double_conversion6Bignum20MultiplyByPowerOfTenEi" sub dc/sym-bignum-decimal "$HITS" "_ZN17double_conversion6Bignum19AssignDecimalStringENS_6VectorIKcEE" sub dc/sym-bignum-hex "$HITS" "_ZN17double_conversion6Bignum15AssignHexStringENS_6VectorIKcEE" sub dc/sym-bignum-square "$HITS" "_ZN17double_conversion6Bignum6SquareEv" sub dc/sym-cached-decimal "$HITS" "_ZN17double_conversion16PowersOfTenCache32GetCachedPowerForDecimalExponentEiPNS_5DiyFpEPi" sub dc/sym-cached-binary "$HITS" "_ZN17double_conversion16PowersOfTenCache36GetCachedPowerForBinaryExponentRangeEiiPNS_5DiyFpEPi" sub dc/sym-strtod "$HITS" "_ZN17double_conversion13StrtodTrimmedENS_6VectorIKcEEi" sub dc/sym-strtof "$HITS" "_ZN17double_conversion13StrtofTrimmedENS_6VectorIKcEEi" # C++ EVIDENCE THE C ARM CANNOT FORGE. This library has no virtual function # anywhere, so there is no vtable or typeinfo record to point at the way the fmt # suite can. What it does have is two function-local statics -- ToLower's cType # facet reference and EcmaScriptConverter's converter -- each of which the ABI # gives a `_ZGV` guard variable and a __cxa_guard_acquire/release pair. A C # compilation of these sources emits none of the five: C has no name mangling, # no guard variables, and no thread-safe-static ABI. Their presence is a # statement that the wasmc++-glibc opt-in in the bbappend actually took effect. sub dc/cxx-tolower-static "$HITS" "_ZZN17double_conversion12_GLOBAL__N_17ToLowerEcE5cType" sub dc/cxx-tolower-guard "$HITS" "_ZGVZN17double_conversion12_GLOBAL__N_17ToLowerEcE5cType" sub dc/cxx-converter-guard "$HITS" "_ZGVZN17double_conversion23DoubleToStringConverter19EcmaScriptConverterEvE9converter" sub dc/cxx-guard-acquire "$HITS" "__cxa_guard_acquire" sub dc/cxx-guard-release "$HITS" "__cxa_guard_release" # --- the probe: does the shipped archive CONVERT, and convert correctly? ----- if [ ! -f "$PROBE" ]; then bst_notok dc/probe-present "$PROBE missing -- the library cannot be proven to run" elif [ ! -f "$NATIVE" ]; then bst_notok dc/native-present "$NATIVE missing -- no x86-64 control for the probe run" else bst_ok dc/probe-present bst_ok dc/native-present # 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. Stage an # executable copy under TMPDIR, as every probe-driven suite here does. pd=$tmp/bst-dc.$$ p=$pd/dc-probe mkdir -p "$pd" 2>/dev/null if cp "$PROBE" "$p" 2>/dev/null && chmod 0755 "$p" 2>/dev/null && [ -x "$p" ]; then bst_ok dc/probe-exec out=$("$p" 2>"$pd/run.err"); rc=$? errout=$(cat "$pd/run.err" 2>/dev/null) if [ "$rc" -eq 0 ]; then bst_ok dc/probe-rc else bst_notok dc/probe-rc "probe exited $rc"; fi # The library writes nothing to stderr on a successful run. Its only failure # channel is DOUBLE_CONVERSION_ASSERT -> __assert_fail, which prints there # and abort()s -- so a port whose assertion fired on some case would show up # here even if the surviving output still matched line for line. if [ -z "$errout" ]; then bst_ok dc/probe-silent-stderr else bst_notok dc/probe-silent-stderr "$(_bst_1line "$errout")"; fi O=$nl$out$nl # The whole-stream gate. Kept separate from the anchored cases below, # because a probe that died partway would leave those it never reached with # nothing to disagree with and could look like a shorter clean run. case "$O" in *"${nl}dc-probe-end${nl}") bst_ok dc/probe-complete ;; *) bst_notok dc/probe-complete "probe did not reach its final line" ;; esac # The version the probe was COMPILED against, passed in from the recipe's # PV, so a header/archive mismatch is visible rather than inferred. Upstream # ships no version macro in the headers; the recipe filename and the # source's CMake project() version are separate claims and both read 3.3.0 # at SRCREV 4f7a25d8. has dc/probe-version "$O" "dc-probe 3.3.0" # === 1. the byte-compare against x86-64 ================================== if [ "$out" = "$(cat "$NATIVE" 2>/dev/null)" ]; then bst_ok dc/probe-matches-x86-64 else first=$(printf '%s\n' "$out" | diff - "$NATIVE" 2>/dev/null | head -4) bst_notok dc/probe-matches-x86-64 "$(_bst_1line "${first:-output differs from the control}")" fi # === 2. the round-trip contract, stated three ways ======================= # # The ticket's core requirement: print each double shortest, parse the # printed form back, and require the SAME 64 BITS. The probe emits a verdict # token per value; these three cases turn the whole table into pass/fail # without depending on the control. # # THE COUNT IS ASSERTED, not just the absence of a failure token. A probe # that emitted nothing would satisfy "no RT-MISMATCH anywhere" perfectly -- # that is the vacuous-green shape this port's siblings kept finding -- so # the number of successful verdicts is pinned too. 35 = 27 doubles that # round-trip by bits (the 28th is the NaN, which cannot and is checked by # NAN-OK) + 8 floats. hasnt dc/no-rt-mismatch "$O" "RT-MISMATCH" hasnt dc/no-nan-lost "$O" "NAN-LOST" check_eq dc/rt-ok-count 35 "$(printf '%s\n' "$out" | grep -c 'RT-OK')" # === 3. anchored renderings ============================================== # # Fixed by the IEEE-754 value and this library's documented contract, so # they hold whatever the control says. These are the highest-value # assertions in the file. # Shortest round-trip. Dragonbox is absent here -- this library predates it # and uses Grisu3 with a bignum fallback -- so the awkward values are the # ones that fall OUT of the fast path into the multiprecision one. has dc/dbl-tenth "$O" "dbl/shortest-tenth|0.1" has dc/dbl-third "$O" "dbl/shortest-third|0.3333333333333333" has dc/dbl-pi "$O" "dbl/shortest-pi|3.141592653589793" has dc/dbl-max "$O" "dbl/shortest-max|1.7976931348623157e+308" has dc/dbl-min-normal "$O" "dbl/shortest-min-normal|2.2250738585072014e-308" has dc/dbl-denorm-max "$O" "dbl/shortest-denorm-max|2.225073858507201e-308" has dc/dbl-denorm-min "$O" "dbl/shortest-denorm-min|5e-324" has dc/dbl-denorm-neg "$O" "dbl/shortest-denorm-neg|-5e-324" has dc/dbl-denorm-two "$O" "dbl/shortest-denorm-two|1e-323" has dc/dbl-e300 "$O" "dbl/shortest-e300|1e+300" has dc/dbl-em300 "$O" "dbl/shortest-em300|1e-300" has dc/dbl-em7 "$O" "dbl/shortest-em7|1e-7" has dc/dbl-four-35 "$O" "dbl/shortest-four-35|4.35" # 1e23 with both neighbours. This is the canonical shortest-round-trip # counterexample: the double nearest 1e23 is 99999999999999991611392, and a # renderer that stops at 17 significant digits picks the wrong one of the # three. Asserting the neighbours as well is what makes it a real test -- # 1e+23 alone would pass on an implementation that printed 1e+23 for all of # them. has dc/dbl-e23-down "$O" "dbl/shortest-e23-down|9.999999999999997e+22" has dc/dbl-e23 "$O" "dbl/shortest-e23|1e+23" has dc/dbl-e23-up "$O" "dbl/shortest-e23-up|1.0000000000000001e+23" # decimal_in_shortest_high is 21, so 1e20 (21 digits) is still rendered in # full and 1e21 (22 digits) crosses into exponential form. Both sides, so a # port that had lost the boundary in either direction fails one of them. has dc/dbl-e20 "$O" "dbl/shortest-e20|100000000000000000000" has dc/dbl-e21 "$O" "dbl/shortest-e21|1e+21" # 2^53 and 2^53+2 -- the first place doubles stop being consecutive # integers. 9007199254740993 is not representable; printing ...992 for it is # the correct answer rather than a lost digit. has dc/dbl-two-p53 "$O" "dbl/shortest-two-p53|9007199254740992" has dc/dbl-two-p53p2 "$O" "dbl/shortest-two-p53p2|9007199254740994" # Non-finite and the two zeroes. ECMAScript's UNIQUE_ZERO renders -0.0 as # "0"; the probe's second converter, which differs in that one flag alone, # renders it "-0" and round-trips it by bits. Both are asserted, because a # port that had lost the flag would still satisfy the round-trip. has dc/dbl-inf "$O" "dbl/shortest-inf|Infinity" has dc/dbl-ninf "$O" "dbl/shortest-ninf|-Infinity" has dc/dbl-nan "$O" "dbl/shortest-nan|NaN" has dc/dbl-unique-zero "$O" "dbl/unique-zero|0" sub dc/dbl-signed-zero "$O" "dbl/roundtrip-nzero|-0 8000000000000000 8000000000000000 RT-OK" # Single precision. 0.33333334 rather than 0.3333333333333333 is the whole # point: ToShortestSingle must use the FLOAT boundaries, and a port that # widened to double would print far too many digits and still round-trip. sub dc/flt-third "$O" "flt/roundtrip-third|0.33333334 " sub dc/flt-max "$O" "flt/roundtrip-max|3.4028235e+38 " sub dc/flt-min-normal "$O" "flt/roundtrip-min-normal|1.1754944e-38 " sub dc/flt-denorm-min "$O" "flt/roundtrip-denorm-min|1e-45 " # The other three renderers, each a separate algorithm. has dc/fix-tenth-20 "$O" "fix/tenth-20|0.10000000000000000555" has dc/fix-tenth-1 "$O" "fix/tenth-1|0.1" has dc/fix-pi-10 "$O" "fix/pi-10|3.1415926536" has dc/exp-tenth-16 "$O" "exp/tenth-16|1.0000000000000001e-1" has dc/exp-e23-16 "$O" "exp/e23-16|9.9999999999999992e+22" has dc/exp-pi-0 "$O" "exp/pi-0|3e+0" has dc/prec-pi-1 "$O" "prec/pi-1|3" has dc/prec-pi-17 "$O" "prec/pi-17|3.1415926535897931" has dc/prec-e23-17 "$O" "prec/e23-17|9.9999999999999992e+22" has dc/prec-tenth-21 "$O" "prec/tenth-21|0.100000000000000005551" # ToFixed rounds HALF AWAY FROM ZERO -- 2.5 -> "3", 3.5 -> "4" -- which is # ECMAScript's Number.prototype.toFixed and NOT banker's rounding. Both # directions, so a port that rounded half-to-even fails the first rather # than passing a suite that only tested the tie which happens to agree. has dc/fix-half-2p5 "$O" "fix/half-2p5|3" has dc/fix-half-3p5 "$O" "fix/half-3p5|4" # ToFixed's refusal wall, pinned to the ULP: the implementation refuses # `value >= (double)1e60`, so the wall is 1e60 itself and the last accepted # value is one ULP below it. The refusal is contract, not an accident -- a # caller sizes its buffer on 1 + 60 + 1 + 100 characters and relies on the # false return -- so a port that silently rendered something instead would # be a defect no round-trip case could see. Both sides of both walls. has dc/fix-wall-below "$O" "fix/wall-below|ACCEPTED" has dc/fix-wall-at "$O" "fix/wall-at|REFUSED" has dc/fix-wall-neg "$O" "fix/wall-neg|REFUSED" has dc/fix-digits-100 "$O" "fix/digits-100|ACCEPTED" has dc/fix-digits-101 "$O" "fix/digits-101|REFUSED" # === 4. the parser ======================================================= # # Half the library, with failure modes no rendering case can reach. Values # are asserted as 64-bit patterns plus the processed-character count, which # is what a consumer uses to find where a number ended. has dc/parse-plain "$O" "parse/plain|3fb999999999999a 3" has dc/parse-exp "$O" "parse/exp|44b52d02c7e14af6 4" has dc/parse-denorm "$O" "parse/denorm|0000000000000001 6" has dc/parse-max "$O" "parse/max|7fefffffffffffff 22" # Exactly half the smallest subnormal, which must round to even -- i.e. to # zero, not up to the subnormal. The hardest single case in decimal->binary # and the one a truncating implementation gets wrong. has dc/parse-denorm-half "$O" "parse/denorm-half|0000000000000000 23" has dc/parse-overflow "$O" "parse/overflow|7ff0000000000000 5" has dc/parse-underflow "$O" "parse/underflow|0000000000000000 6" # 7ff4... is the probe's junk sentinel, chosen distinct from the quiet NaN a # real "NaN" parses to so a rejection and the word NaN are different lines. has dc/parse-junk-tail "$O" "parse/junk-tail|7ff4000000000000 0" has dc/parse-junk-allowed "$O" "parse/junk-allowed|3ff8000000000000 3" has dc/parse-empty "$O" "parse/empty|0000000000000000 0" has dc/parse-spaces "$O" "parse/spaces|4004000000000000 6" has dc/parse-spaces-denied "$O" "parse/spaces-denied|7ff4000000000000 0" has dc/parse-hex "$O" "parse/hex|406fe00000000000 4" has dc/parse-hexfloat "$O" "parse/hexfloat|3fd0000000000000 6" has dc/parse-octal "$O" "parse/octal|407ed00000000000 4" has dc/parse-separator "$O" "parse/separator|408f440000000000 7" has dc/parse-inf-exact "$O" "parse/inf-exact|7ff0000000000000 8" # THE CASE-INSENSITIVE GROUP IS ALSO THE LOCALE COVERAGE. These are the only # cases that reach ToLower(), and ToLower() is the library's only use of # : std::use_facet >(std::locale::classic()) behind # a function-local static. Passing them means libc++'s locale machinery, its # facet RTTI and the static-init guard all work on this arm at run time -- # which a symbol needle in the archive could only suggest. # # ALLOW_CASE_INSENSITIVITY folds the INPUT only: ConsumeFirstCharacter and # ConsumeSubStringImpl lowercase the input byte and compare it to the symbol # byte unchanged, so the caller must supply the symbol in lowercase. That is # the contract rather than a defect, and both readings are pinned -- the # lowercase-symbol converter matches every spelling, the mixed-case-symbol # one matches none -- because a suite carrying only the second would report # a green while never once entering the path. has dc/parse-inf-ci-upper "$O" "parse/inf-ci-upper|7ff0000000000000 8" has dc/parse-inf-ci-mixed "$O" "parse/inf-ci-mixed|7ff0000000000000 8" has dc/parse-inf-ci-lower "$O" "parse/inf-ci-lower|7ff0000000000000 8" has dc/parse-nan-ci-upper "$O" "parse/nan-ci-upper|7ff8000000000000 3" has dc/parse-nan-ci-mixed "$O" "parse/nan-ci-mixed|7ff8000000000000 3" has dc/parse-ci-cased-symbol "$O" "parse/ci-cased-symbol|7ff4000000000000 0" has dc/parse-ci-denied "$O" "parse/ci-denied|7ff4000000000000 0" # === 5. the multiprecision path ========================================== # # Long exact expansions, where every digit is fixed by the binary value. # These are the longest single statements the suite makes, and the place a # 32-bit arm losing a limb in the bignum arithmetic shows first: a # truncated or carried-wrong limb changes digits in the tail while leaving # the head, and every shortest-round-trip case above, perfectly correct. has dc/bignum-denorm-min-30 "$O" "bignum/denorm-min-30|4.94065645841246544176568792868e-324" has dc/bignum-max-30 "$O" "bignum/max-30|1.79769313486231570814527423732e+308" has dc/bignum-denorm-max-40 "$O" "bignum/denorm-max-40|2.2250738585072008890245868760858598876504e-308" has dc/bignum-tenth-100 "$O" "bignum/tenth-100|0.1000000000000000055511151231257827021181583404541015625000000000000000000000000000000000000000000000" rm -rf "$pd" 2>/dev/null else bst_notok dc/probe-exec "cannot stage an executable copy of the probe" fi fi