. "$BST_LIB" # BST-TIMEOUT: 1200 # THREE python3 starts, and they are the whole cost. Every # # other assertion below reads the filesystem or dpkg with # # shell builtins, or greps the output of one of those three. # # # # The three are: a bare `import', a second import whose # # STDERR is the assertion (`import-quiet'), and the probe, # # which takes ONE start for eighty-odd measurements. # # # # There is no fourth. The recipe declares no # # `[project.scripts]' and the package installs no # # executable, so there is nothing to reach through a # # shebang; `no-bin-script' asserts that absence rather than # # leaving it unstated. # # # # The work inside each start is a few dozen xxHash digests # # over inputs under 20 bytes -- microseconds beside an # # interpreter start on this arm, which is tens of seconds # # before the first line of the program runs. # # # # 1200 is 400s per start, matching 99-python3-pyparsing's # # budget for its own three and roughly six times the ~60s a # # python3 start has measured at on this arm. # # # # A suite-timeout red is a batch-wide cost, so if the three # # starts prove slower than that on target the RIGHT fix is # # this number, not fewer cases. # # # # NOT MEASURED ON TARGET YET: this port's first on-target # # run is the batch verify, and the measured elapsed replaces # # this note in the test plan rather than in this comment, # # which would cost an image build to keep the shipped suite # # byte-identical. # # python3-xxhash 3.4.1 (meta-openembedded/meta-python # recipes-devtools/python/python3-xxhash_3.4.1.bb, `inherit pypi # python_setuptools_build_meta ptest', PyPI sdist) on the wasm32-hwjs glibc # image. # # ============================================================================ # WHAT THE PACKAGE DOES. # ============================================================================ # # xxHash is a NON-CRYPTOGRAPHIC hash built to keep up with I/O rather than to # resist an adversary. This distribution is the Python binding for it, and it # exposes the whole family -- XXH32, XXH64, XXH3_64 and XXH3_128 -- twice over: # as one-shot `*_intdigest' / `*_hexdigest' / `*_digest' functions, and as # incremental objects carrying the `hashlib' interface (`update', `digest', # `hexdigest', `copy', `reset', `digest_size', `block_size', `name'). # # ============================================================================ # THIS IS THE FIRST PYTHON PORT ON THIS ARM WHOSE MODULE IS COMPILED CODE, # AND THAT IS THE ONE THING TO READ BEFORE ANYTHING ELSE HERE. # ============================================================================ # # Every python3 package ported to this image before it was PURE PYTHON. This one # is not, and it has no pure-Python half to fall back to: `xxhash/__init__.py' is # fourteen lines of `from ._xxhash import *' over a `.so' the recipe builds from # the xxHash sources the sdist vendors. So the module either loads a compiled # extension or does not import at all -- there is no third outcome, and no # silently-slow path this suite would have to distinguish. # # THE PLATFORM QUESTION THAT MAKES THAT INTERESTING. This image's python3 is ONE # STATIC BINARY: `configure' picks `MODULE_BUILDTYPE=static' from # `host_cpu=wasm32', every stdlib extension is linked into the interpreter, and # `lib-dynload' is EMPTY BY CONSTRUCTION (BRINTOS-1476, and 99-python3.test # asserts that emptiness). Nothing about that construction settles what happens # to a THIRD-PARTY extension, and the two facts point opposite ways: # # - the target `pyconfig-32.h' this port built against defines HAVE_DLOPEN, # HAVE_DLFCN_H and HAVE_DYNAMIC_LOADING, so CPython's `dynload_shlib' path is # compiled in and `imp.create_dynamic' exists; # - and the arm is `static-only ... until the HWJS-5 dlopen substrate is wired # in' (conf/machine/include/tune-wasm32.inc), with the glibc arm's dynamic # linking exercised so far at EXEC time through NEEDED (BRINTOS-1638), not # through a runtime `dlopen(3)' of a side module at an arbitrary path. # # The recipe's `.so' IS a real wasm side module -- it carries a `dylink.0' # section, the same shape as the thirteen converted libraries BRINTOS-1415 and # BRINTOS-1442 produced. Whether the runtime can dlopen one is what `import' # below MEASURES. This suite therefore front-loads the import: `import', # `probe-run' and `ext-*' come before any digest, so that a red is legible as # "the loader could not take it" rather than as eighty broken hashes. # # THE PREDICTION, LABELLED AS ONE. Nothing in this file was run on target when it # was written -- phase A of a batched Epic builds at recipe scope and never boots # an image -- so the paragraph above is a reading of the source and the config, # not a result. If `import' reds with a loader error, that is a PLATFORM GAP to # be attributed, not a defect in this port: the recipe builds clean and the # package installs. The test plan carries the measured outcome; this comment # carries only what was expected and why. # # ============================================================================ # WHAT THE DIGEST CASES ASSERT, AND WHY THEY ARE LITERALS. # ============================================================================ # # A hash has PUBLISHED ANSWERS, so the assertion is a literal rather than a round # trip: a round trip cannot tell a correct implementation from a consistently # wrong one. Two inputs carry it -- the empty string, which no broken # finalisation can hide behind, and `123456789', xxHash's own canonical vector -- # each in all four variants, at the default seed and at a non-zero seed, in # integer and hexadecimal form. # # ENDIANNESS IS THE CASE THAT MATTERS MOST ON A NEW ARM, and it is the one a # hex-only suite would miss entirely. `intdigest()' and `digest()' are two # renderings of one digest, and `digest()' is the BIG-ENDIAN encoding of the # integer. A build that got byte order wrong would still be self-consistent in # hex and would still agree with itself across every incremental case; it shows # up only where the two renderings are compared against each other AND against # the published vector. `*-digest-be' and `*-hex-is-digest' close that triangle. # # THE SEED IS ASSERTED TWICE, as a literal and as a DIFFERENCE. A seed argument # that is accepted and dropped produces a perfectly coherent set of digests, all # of them the unseeded ones; `*-seed-differs' is what turns that into a red # rather than into a duplicate green. # # THE INCREMENTAL PATH IS ASSERTED AGAINST THE ONE-SHOT PATH rather than against # a second literal, because what is being measured is that `update()' over the # pieces agrees with one call over the whole -- the property every streaming # consumer depends on. The fixture is deliberately NOT ASCII and the splits land # INSIDE multi-byte UTF-8 sequences (2-, 3- and 4-byte): xxhash hashes BYTES and # must not care, so a mid-sequence split is what would catch an implementation # that had grown an opinion about character boundaries. # # ============================================================================ # `-ptest' IS INHERITED AND CANNOT BE INSTALLED, WHICH IS WHY THE SUITE IS HERE # AND NOT UPSTREAM'S. # ============================================================================ # # The recipe inherits `ptest' and installs the upstream `tests/' into # ${PTEST_PATH}. The `-ptest' sub-package's own RDEPENDS reach `python3-pytest' # and `python3-unittest-automake-output', neither of which is ported or ticketed, # so it cannot be installed on this image and the round does not install it. This # suite drives the public API directly, using the upstream tests as the reference # for WHAT to assert rather than as the mechanism. `no-ptest-dir' asserts the # absence so that an image which later gained the sub-package is noticed here. # # ============================================================================ # MEASURED ON AN x86-64 CONTROL AT THE SAME DISTRIBUTION VERSION -- xxhash 3.4.1 # over vendored xxHash 0.8.2 -- and every expected value below is that control's # OUTPUT rather than a reading of the documentation. That distinction earned its # keep immediately: `xxh3_64''s `block_size' is 32 and `xxh3_128''s is 64, which # is not the symmetry the names suggest. The cases that could not be measured # there are the packaging ones, whose paths and control stanza differ on a # Debian host by construction. # ============================================================================ P=python3-xxhash # `suite-canary' is emitted FIRST and unconditionally. A suite that dies before # its first result line is indistinguishable from one that was never scheduled, # so this one line is what separates "ran and found nothing" from "did not run". bst_ok $P/suite-canary require python3 $P/python3-present SITE=/usr/lib/python3.12/site-packages PKG=$SITE/xxhash DI=$SITE/xxhash-3.4.1.dist-info EXT=$PKG/_xxhash.cpython-312.so PKGLIST=/var/lib/dpkg/info/python3-xxhash.list PROBE=$BST_DATA/python3-xxhash-probe.py tmp=${TMPDIR:-/tmp} W=$tmp/bst-xxhash.$$ mkdir -p "$W" || { bst_notok $P/workdir "cannot create $W"; exit 0; } # ---------------------------------------------------------------- packaging -- # WHERE THE PACKAGING SAYS THE MODULE LANDS. These run before any import, so a # red here says the .deb is wrong rather than that the module misbehaves. check $P/site-packages-dir test -d "$SITE" check $P/package-dir test -d "$PKG" check $P/package-init test -s "$PKG/__init__.py" check $P/module-version test -s "$PKG/version.py" # It is a PACKAGE, not a single module. A release that flattened it would still # import and still pass every behavioural case, so the shape is asserted. check $P/no-flat-module test ! -f "$SITE/xxhash.py" # THE COMPILED EXTENSION, AS A FILE. This is the case that separates "the # packaging shipped the .so" from "the loader could take it" -- the second is # `import' below, and keeping them apart is what makes a loader red legible. check $P/ext-present test -s "$EXT" # The SOABI tag is the interpreter this image ships (CPython 3.12). A .so built # for another would install cleanly and never be found by the import machinery. check $P/ext-soabi test -f "$PKG/_xxhash.cpython-312.so" # ...and there is exactly one, so a stale second copy from another SOABI cannot # sit beside it unnoticed. check_eq $P/ext-count "1" "$(ls "$PKG"/*.so 2>/dev/null | wc -l | tr -d ' ')" # The typing marker and the stub, which setuptools ships as package data. Their # absence would not break a single runtime case, which is exactly why they need # their own assertions. check $P/py-typed test -f "$PKG/py.typed" check $P/pyi-stub test -s "$PKG/__init__.pyi" # NO EXECUTABLE. The project declares no `[project.scripts]', so nothing lands # in /usr/bin. Asserted so that a future release which started shipping one is # noticed here. check $P/no-bin-script test ! -e /usr/bin/xxhash # `-ptest' IS NOT INSTALLED -- see the header. The sub-package's RDEPENDS cannot # be satisfied on this image, so the upstream suite is absent by design. check $P/no-ptest-dir test ! -d /usr/lib/python3-xxhash/ptest # --------------------------------------------------------------- dist-info --- # The version is read from METADATA rather than from the module, so that a # mismatch between what the packaging claims and what imports is visible AS a # mismatch (`version-attr' below reads the other side). check $P/dist-info-dir test -d "$DI" check $P/dist-info-metadata test -f "$DI/METADATA" check_out $P/dist-info-version "Version: 3.4.1" cat "$DI/METADATA" check_out $P/dist-info-name "Name: xxhash" cat "$DI/METADATA" check $P/dist-info-wheel test -f "$DI/WHEEL" # NOT PURE PYTHON, stated by the packaging itself. `Root-Is-Purelib: false' is # the wheel's own claim that something in it is architecture-specific -- the # opposite of every python3 port before this one on this arm, and the property # this whole suite is about. check_out $P/dist-info-purelib "Root-Is-Purelib: false" cat "$DI/WHEEL" # THE WHEEL TAG SAYS `linux_x86_64' AND THAT IS A CROSS-BUILD ARTEFACT, NOT A # WRONG BINARY. `bdist_wheel' names the tag from the BUILD host's platform; # nothing consumes the tag here, because bitbake unpacks the wheel itself and # installs the tree, and `ext-soabi' above is what actually pins the object to # this interpreter. It is asserted so the artefact is recorded rather than # rediscovered by the next reader of a `.dist-info' on this image. check_out $P/dist-info-wheel-tag "Tag: cp312-cp312-linux_x86_64" cat "$DI/WHEEL" # `top_level.txt' names BOTH the package and the extension, which is the # packaging's own statement that the two ship together. check_out $P/dist-info-top-level-pkg "xxhash" cat "$DI/top_level.txt" check_out $P/dist-info-top-level-ext "_xxhash" cat "$DI/top_level.txt" # ------------------------------------------------------------ the .deb file --- # The installed file list, read once into $W. The copy is what the loop below # redirects from: a stdin redirect the top-level shell performs on the virtiofs # root makes dup2(2) return 513 and ENDS the suite silently (brintos/linux#73), # and $W is on tmpfs. cat "$PKGLIST" > "$W/pkgf" 2>/dev/null || : > "$W/pkgf" check $P/pkg-list-present test -s "$W/pkgf" # EXACTLY ONE COMPILED OBJECT SHIPS, asserted off the shipped file list rather # than off the source. Every python3 port before this one asserted `no .so at # all'; this one inverts that case, and the count is what says a second # architecture's object did not come along. check_eq $P/pkg-one-so "1" \ "$(grep -c '\.so$' "$W/pkgf" 2>/dev/null | tr -d ' ')" # Every payload path the package ships is under site-packages, and is a .py, a # .pyc, a .pyi, the one .so, or the typing marker. Anything else is a file this # port did not expect to be shipping and wants looking at. _bad="" while IFS= read -r _f; do case "$_f" in ''|/usr/lib/python3.12/site-packages) continue ;; */) continue ;; esac [ -d "$_f" ] && continue case "$_f" in *.py|*.pyc|*.pyi|*.so|*/py.typed) ;; # dist-info metadata. Which of these the backend writes is a property of the # BUILD BACKEND rather than of this package, so the whole standard set is # allowed. `pkg-one-so' above carries the exact claim. */METADATA|*/WHEEL|*/RECORD|*/INSTALLER|*/LICENSE|*/entry_points.txt|*/top_level.txt) ;; *) _bad="$_bad $_f" ;; esac done < "$W/pkgf" check_eq $P/pkg-only-expected "" "$_bad" # ------------------------------------------------------------- dpkg status --- sed -n '/^Package: python3-xxhash$/,/^$/p' /var/lib/dpkg/status > "$W/st" 2>/dev/null check $P/pkg-known test -s "$W/st" check_out $P/pkg-installed "Status: install ok installed" cat "$W/st" # THE DEPENDENCY SET IS THE PORT'S CLAIM THAT IT WAITS ON NOTHING. `python3-core' # is the whole of it -- the binding imports nothing outside the interpreter -- # and it is asserted individually rather than as "the Depends line exists". grep '^Depends:' "$W/st" > "$W/dep" 2>/dev/null || : > "$W/dep" check $P/pkg-depends-line test -s "$W/dep" check_out $P/pkg-depends-python3-core "python3-core" cat "$W/dep" # ------------------------------------------------------------------ import --- # THE CASE THIS PORT TURNS ON. Everything below it is a statement about a module # that loaded; this is the one that says whether the runtime can dlopen a wasm # side module out of site-packages at all. See the header -- a red here is a # platform gap to attribute, not a broken recipe. check $P/import python3 -c 'import xxhash' # A package that imports but WARNS on the way in is a different defect from one # that fails, and it is invisible to the case above because the exit status is 0 # either way. The assertion is that stderr is EMPTY. check_eq $P/import-quiet "" \ "$(python3 -c 'import xxhash' 2>&1 >/dev/null)" # ------------------------------------------------------------------- probe --- if [ ! -f "$PROBE" ]; then bst_notok $P/probe-present "probe missing at $PROBE" exit 0 fi bst_ok $P/probe-present # THE THIRD START, and the one that carries the suite. Bounded at 900s inside the # 1200s suite budget so that a hung probe is reported as a probe overrun with the # last line it printed, rather than as a suite timeout that says nothing about # where it stopped. bst_probe $P/probe-run "$W/probe" 900 python3 "$PROBE" OUT="$W/probe" # pv : the value the probe emitted for , or empty. `head -n 1' because # a key is emitted once and a duplicate would otherwise concatenate; `cut -f2-' # because a value may legitimately contain `='. pv() { grep "^$1=" "$OUT" 2>/dev/null | head -n 1 | cut -d= -f2-; } # The probe reached its end. Every case below reads a value the probe printed, so # a probe that stopped early would otherwise turn into a run of empty-string # comparisons that each look like their own finding. check_eq $P/probe-done "yes" "$(pv probe_done)" check_eq $P/probe-count "91" "$(pv emitted_count)" # ---------------------------------------------------------------- identity --- check_eq $P/module-file "$PKG/__init__.py" "$(pv module_file)" check_eq $P/is-package "yes" "$(pv is_package)" check_eq $P/version-attr "3.4.1" "$(pv version_attr)" check_eq $P/version-tuple "3.4.1" "$(pv version_tuple)" # The VENDORED library's version, which is a different number from the binding's # and the one a digest is actually a property of. check_eq $P/xxhash-version "0.8.2" "$(pv xxhash_version)" # THE EXTENSION IS WHAT ANSWERED. `ext-present' above says the file shipped; # these say the import machinery loaded THAT file and that a pure-Python # fallback is not what is being measured below. There is no such fallback in # this distribution, which is precisely why its absence must be asserted rather # than assumed. check_eq $P/ext-loaded "yes" "$(pv ext_present)" check_eq $P/ext-file "$EXT" "$(pv ext_file)" check_eq $P/ext-is-so "yes" "$(pv ext_is_so)" check_eq $P/ext-not-py "yes" "$(pv ext_not_py)" check_eq $P/algorithms "xxh128,xxh32,xxh3_128,xxh3_64,xxh64" \ "$(pv algorithms_available)" # ------------------------------------------------------- constructor facts --- # The `hashlib' interface's three metadata attributes, per variant. MEASURED on # the control: xxh3_64's block_size is 32 and xxh3_128's is 64, which is not the # symmetry the names suggest and is the reason these are not four copies of one # guess. check_eq $P/xxh32-name "XXH32" "$(pv xxh32_name)" check_eq $P/xxh32-digest-size "4" "$(pv xxh32_digest_size)" check_eq $P/xxh32-block-size "16" "$(pv xxh32_block_size)" check_eq $P/xxh64-name "XXH64" "$(pv xxh64_name)" check_eq $P/xxh64-digest-size "8" "$(pv xxh64_digest_size)" check_eq $P/xxh64-block-size "32" "$(pv xxh64_block_size)" check_eq $P/xxh3-64-name "XXH3_64" "$(pv xxh3_64_name)" check_eq $P/xxh3-64-digest-size "8" "$(pv xxh3_64_digest_size)" check_eq $P/xxh3-64-block-size "32" "$(pv xxh3_64_block_size)" check_eq $P/xxh3-128-name "XXH3_128" "$(pv xxh3_128_name)" check_eq $P/xxh3-128-digest-size "16" "$(pv xxh3_128_digest_size)" check_eq $P/xxh3-128-block-size "64" "$(pv xxh3_128_block_size)" # ------------------------------------------------- vectors: the empty input --- # The input no broken finalisation can hide behind. XXH32("") and XXH64("") are # xxHash's own published constants; the XXH3 pair are the control's output at # vendored 0.8.2. check_eq $P/xxh32-empty-hex "02cc5d05" "$(pv xxh32_empty_hex)" check_eq $P/xxh32-empty-int "46947589" "$(pv xxh32_empty_int)" check_eq $P/xxh64-empty-hex "ef46db3751d8e999" "$(pv xxh64_empty_hex)" check_eq $P/xxh64-empty-int "17241709254077376921" "$(pv xxh64_empty_int)" check_eq $P/xxh3-64-empty-hex "2d06800538d394c2" "$(pv xxh3_64_empty_hex)" check_eq $P/xxh3-64-empty-int "3244421341483603138" "$(pv xxh3_64_empty_int)" check_eq $P/xxh3-128-empty-hex "99aa06d3014798d86001c324468d497f" \ "$(pv xxh3_128_empty_hex)" check_eq $P/xxh3-128-empty-int "204254712233039002205064565430793619839" \ "$(pv xxh3_128_empty_int)" # ENDIANNESS on the empty input: `digest()' re-encoded from `intdigest()' # big-endian must reproduce the bytes, and the hex rendering must be those same # bytes. See the header -- this is the slip a hex-only suite cannot see. check_eq $P/xxh32-empty-digest-be "yes" "$(pv xxh32_empty_digest_be)" check_eq $P/xxh64-empty-digest-be "yes" "$(pv xxh64_empty_digest_be)" check_eq $P/xxh3-64-empty-digest-be "yes" "$(pv xxh3_64_empty_digest_be)" check_eq $P/xxh3-128-empty-digest-be "yes" "$(pv xxh3_128_empty_digest_be)" check_eq $P/xxh32-empty-hex-is-digest "yes" "$(pv xxh32_empty_hex_is_digest)" check_eq $P/xxh64-empty-hex-is-digest "yes" "$(pv xxh64_empty_hex_is_digest)" check_eq $P/xxh3-64-empty-hex-is-digest "yes" "$(pv xxh3_64_empty_hex_is_digest)" check_eq $P/xxh3-128-empty-hex-is-digest "yes" "$(pv xxh3_128_empty_hex_is_digest)" # THE SEED, at 1. Asserted as a literal and as a difference from the unseeded # digest, because a seed that is accepted and dropped is otherwise invisible. check_eq $P/xxh32-empty-seed-hex "0b2cb792" "$(pv xxh32_empty_seed_hex)" check_eq $P/xxh64-empty-seed-hex "d5afba1336a3be4b" "$(pv xxh64_empty_seed_hex)" check_eq $P/xxh3-64-empty-seed-hex "4dc5b0cc826f6703" "$(pv xxh3_64_empty_seed_hex)" check_eq $P/xxh3-128-empty-seed-hex "d9265cc53bb2b9ae6131b78f753823cd" \ "$(pv xxh3_128_empty_seed_hex)" check_eq $P/xxh32-empty-seed-differs "yes" "$(pv xxh32_empty_seed_differs)" check_eq $P/xxh64-empty-seed-differs "yes" "$(pv xxh64_empty_seed_differs)" check_eq $P/xxh3-64-empty-seed-differs "yes" "$(pv xxh3_64_empty_seed_differs)" check_eq $P/xxh3-128-empty-seed-differs "yes" "$(pv xxh3_128_empty_seed_differs)" # ------------------------------------------ vectors: the canonical `123456789' -- check_eq $P/xxh32-canon-hex "937bad67" "$(pv xxh32_canon_hex)" check_eq $P/xxh32-canon-int "2474356071" "$(pv xxh32_canon_int)" check_eq $P/xxh64-canon-hex "8cb841db40e6ae83" "$(pv xxh64_canon_hex)" check_eq $P/xxh64-canon-int "10139926970967174787" "$(pv xxh64_canon_int)" check_eq $P/xxh3-64-canon-hex "72dcb18b67a17dff" "$(pv xxh3_64_canon_hex)" check_eq $P/xxh3-64-canon-int "8276685427497336319" "$(pv xxh3_64_canon_int)" check_eq $P/xxh3-128-canon-hex "33119477ede5dcd5e9716427681d5860" \ "$(pv xxh3_128_canon_hex)" check_eq $P/xxh3-128-canon-int "67881908130024315439412682931295836256" \ "$(pv xxh3_128_canon_int)" check_eq $P/xxh32-canon-digest-be "yes" "$(pv xxh32_canon_digest_be)" check_eq $P/xxh64-canon-digest-be "yes" "$(pv xxh64_canon_digest_be)" check_eq $P/xxh3-64-canon-digest-be "yes" "$(pv xxh3_64_canon_digest_be)" check_eq $P/xxh3-128-canon-digest-be "yes" "$(pv xxh3_128_canon_digest_be)" check_eq $P/xxh32-canon-hex-is-digest "yes" "$(pv xxh32_canon_hex_is_digest)" check_eq $P/xxh64-canon-hex-is-digest "yes" "$(pv xxh64_canon_hex_is_digest)" check_eq $P/xxh3-64-canon-hex-is-digest "yes" "$(pv xxh3_64_canon_hex_is_digest)" check_eq $P/xxh3-128-canon-hex-is-digest "yes" "$(pv xxh3_128_canon_hex_is_digest)" check_eq $P/xxh32-canon-seed-hex "f261918c" "$(pv xxh32_canon_seed_hex)" check_eq $P/xxh64-canon-seed-hex "1a4cc2c9e8079790" "$(pv xxh64_canon_seed_hex)" check_eq $P/xxh3-64-canon-seed-hex "e967c19057995816" "$(pv xxh3_64_canon_seed_hex)" check_eq $P/xxh3-128-canon-seed-hex "e3ede0d7b3c8aeaef35243003decde66" \ "$(pv xxh3_128_canon_seed_hex)" check_eq $P/xxh32-canon-seed-differs "yes" "$(pv xxh32_canon_seed_differs)" check_eq $P/xxh64-canon-seed-differs "yes" "$(pv xxh64_canon_seed_differs)" check_eq $P/xxh3-64-canon-seed-differs "yes" "$(pv xxh3_64_canon_seed_differs)" check_eq $P/xxh3-128-canon-seed-differs "yes" "$(pv xxh3_128_canon_seed_differs)" # ------------------------------------------------------------- incremental --- # The fixture is 18 bytes with 2-, 3- and 4-byte UTF-8 sequences in it, split at # eleven offsets INCLUDING inside each of those sequences. `*-splits' pins the # table size so a probe that silently stopped testing is not read as a pass; # `*-bad' is EMPTY on agreement and otherwise names the offsets that disagreed, # which is the fact a bare `no' would have withheld. check_eq $P/utf8-len "18" "$(pv utf8_len)" check_eq $P/xxh32-utf8-hex "6802d704" "$(pv xxh32_utf8_hex)" check_eq $P/xxh64-utf8-hex "a921866aa38a4e2d" "$(pv xxh64_utf8_hex)" check_eq $P/xxh3-64-utf8-hex "ba15aea7a6945ebf" "$(pv xxh3_64_utf8_hex)" check_eq $P/xxh3-128-utf8-hex "63f988058c5c67ddda93a2a1d0ced0b1" \ "$(pv xxh3_128_utf8_hex)" check_eq $P/xxh32-incremental-splits "11" "$(pv xxh32_incremental_splits)" check_eq $P/xxh64-incremental-splits "11" "$(pv xxh64_incremental_splits)" check_eq $P/xxh3-64-incremental-splits "11" "$(pv xxh3_64_incremental_splits)" check_eq $P/xxh3-128-incremental-splits "11" "$(pv xxh3_128_incremental_splits)" check_eq $P/xxh32-incremental-bad "" "$(pv xxh32_incremental_bad)" check_eq $P/xxh64-incremental-bad "" "$(pv xxh64_incremental_bad)" check_eq $P/xxh3-64-incremental-bad "" "$(pv xxh3_64_incremental_bad)" check_eq $P/xxh3-128-incremental-bad "" "$(pv xxh3_128_incremental_bad)" # ------------------------------------------------------------ copy / reset --- # `copy()' on a PARTIALLY FED object continues independently: the copy fed the # rest reaches the one-shot digest, and the original fed something else does not. # The second half is what says the two states are separate rather than shared. check_eq $P/copy-reaches-oneshot "yes" "$(pv copy_reaches_oneshot)" check_eq $P/copy-independent "yes" "$(pv copy_independent)" check_eq $P/copy-original-hex "d1b0272033fc798e" "$(pv copy_original_hex)" # `reset()' returns the object to its SEEDED initial state, not to seed 0 -- # the distinction a caller reusing a seeded hasher depends on. check_eq $P/reset-matches-seeded-oneshot "yes" "$(pv reset_matches_seeded_oneshot)" check_eq $P/seed-attr "1" "$(pv seed_attr)" # ---------------------------------------------------------------- xxh128 ---- # `xxh128' is documented as the same function as `xxh3_128'. Asserted rather than # assumed: they are separate exports, and a binding that wired one of them to the # 64-bit variant would be self-consistent everywhere else in this suite. check_eq $P/xxh128-is-xxh3-128 "yes" "$(pv xxh128_is_xxh3_128)" rm -rf "$W"