. "$BST_LIB" # BST-TIMEOUT: 2400 # SIX python3 starts, and they are the whole cost. Every # # assertion below either reads the filesystem/dpkg with # # shell builtins or greps the output of one of those six. # # # # Five are one-line imports -- `import flexcache', the # # submodule, the class set, a second bare import whose # # STDERR is the assertion (`import-quiet'), and `import # # hashlib' -- and the sixth is the probe, which takes ONE # # start for 127 measurements. # # # # The work inside the probe is sha1 over a few hundred # # bytes and pickle round-trips over a dozen cache entries, # # microseconds beside an interpreter start on this arm, # # which is tens of seconds before the first line of the # # program runs. Its two deliberate waits are bounded: the # # mtime-granularity loop is 200 rewrites of a one-byte file, # # and the settle is capped at 2s by the probe itself. # # # # 2400 is 400s per start, the same per-start budget # # 99-python3-asyncio-throttle and 99-python3-dateutil set. # # # # A suite-timeout red is a batch-wide cost, so if the six # # 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-flexcache 0.3 (meta-openembedded/meta-python # recipes-devtools/python/python3-flexcache_0.3.bb, `inherit pypi # python_setuptools_build_meta ptest', PyPI sdist) on the wasm32-hwjs glibc # image. # # ============================================================================ # WHAT THE PACKAGE DOES. # ============================================================================ # # A disk cache for EXPENSIVE CONVERSIONS of a source file. `DiskCache.load(src, # converter=f)' returns `f(src)', and on a later call returns the same value off # disk without calling `f' again. The two shipped strategies differ ONLY in how # they decide the cached copy is still good: # # DiskCacheByHash names the entry after the sha1 of the source's CONTENT, so # editing the source names a DIFFERENT entry and the old one # stays on disk. # DiskCacheByMTime names the entry after the sha1 of the source's PATH and # stores the mtime in a header, so editing the source # invalidates and REWRITES the one entry. # # The value is stored with pickle; by-hash also writes a small JSON header. # That is the whole surface, so this suite asserts all of it rather than a # sample -- 127 probe measurements plus the packaging cases below. # # ============================================================================ # WHY THIS PORT NEEDED A BBAPPEND: hashlib IS AN UNDECLARED SPLIT. # ============================================================================ # # `flexcache/flexcache.py' does a bare module-scope `import hashlib', and # `DiskCache._hasher' IS `hashlib.sha1' -- the cache entry's whole filename is # that hash's hexdigest, so hashlib is not a corner of this package but its # naming scheme. In poky's python3-manifest.json hashlib.py belongs to the # `crypt' split, and meta-python's RDEPENDS names compression, email, json, # pickle and typing-extensions -- NOT crypt. # # It imports today anyway, by luck: python3-email's own Depends include crypt, # so crypt arrives on the image through email's closure. `pkg-depends-crypt' # below asserts the DECLARATION this port's bbappend adds, not the arrival -- # the arrival is what already worked and is exactly what would go on working # right up until email's closure changed underneath it. # # ============================================================================ # WHAT IS IN THE PACKAGE, MEASURED FROM THE BUILT .deb. # ============================================================================ # # Two modules at the top level, a py.typed marker that is ZERO BYTES (so every # case for it is `test -f' and an explicit size assertion -- `test -s' would # report the correct file as missing), and a NESTED `testsuite/' of five more # modules that the main package ships rather than splitting into -ptest. The # dist-info carries AUTHORS, LICENSE, METADATA, RECORD, WHEEL and top_level.txt. # # ============================================================================ # THE THREE THINGS THAT ARE THE HOST'S, NOT THE PORT'S. # ============================================================================ # # Each is scored as a RELATIONSHIP that holds on any host, with the raw number # reported beside it, because scoring the raw number would make this suite flap # on a property of the filesystem or of who ran it: # # mtime granularity `mtime-granularity' skips, rather than reds, on a # filesystem whose stamp does not move inside 200 rewrites. # `bymtime-settled-hit' is the decisive case either way -- # the probe settles past ONE MEASURED tick before asserting. # the unsettled race `bymtime-unsettled-hits-of-5' is a count, and only # `-in-range' is scored. 5 means the tick is finer than the # round, 0 means it bites every time; both are the # filesystem's answer and neither is a defect in flexcache. # euid this image runs its selftests as ROOT, where mode 000 does # not refuse a read, so the documented PermissionError # cannot be provoked. `unreadable-matches-euid' scores the # relationship -- root reading it fine, OR a normal account # being refused -- and the euid itself is reported. # # ============================================================================ # EXPECTATIONS ARE MEASURED, NOT READ OFF THE README. # ============================================================================ # # Every value below was measured by running THIS probe against the flexcache # 0.3 sdist the recipe's SRC_URI sha256 pins, on CPython 3.12 -- and the # packaging cases against the .deb this recipe built. flexcache is pure Python, # so the semantic answers are properties of that source and not of the arm; what # is genuinely arm-dependent is fenced above. # # MEASURED ON THIS ARM, batch-2436's verify of 2026-09-09: 177 cases in 319s of # the 2400s bound, and THREE reds -- every one of them a finding about this # suite rather than about the arm: # # testsuite-init `test -s' on a ZERO-BYTE __init__.py, which is the # py.typed trap this file names 60 lines above and then # walked into. Now `test -f' plus an explicit size case. # probe-no-cwd-cache asserted that /cache does not exist. This image # SHIPS a top-level /cache and pid 1's cwd is `/', so # the case asserted a property of the rootfs. Now it # compares against a sample taken before the run. # unreadable-matches-euid # chmod'd the entry `empty-cache' had just truncated, so # the load raised EOFError from pickle rather than # anything to do with the mode bits -- unsatisfiable on # a root image by construction. The case now gets its # own intact entry, guarded by `unreadable-entry-ok'. # # None of the three was reachable from the x86-64 control: two are facts about # THIS rootfs, and the third was a sequencing error the control shared. P=python3-flexcache bst_ok $P/suite-canary require python3 $P/python3-present SITE=/usr/lib/python3.12/site-packages PKGDIR=$SITE/flexcache TSDIR=$PKGDIR/testsuite DI=$SITE/flexcache-0.3.dist-info PKGLIST=/var/lib/dpkg/info/python3-flexcache.list PROBE=$BST_DATA/python3-flexcache-probe.py tmp=${TMPDIR:-/tmp} W=$tmp/bst-flexcache.$$ mkdir -p "$W" || { bst_notok $P/workdir "cannot create $W"; exit 0; } # ------------------------------------------------------------ installed tree --- check $P/site-packages-dir test -d "$SITE" check $P/package-dir test -d "$PKGDIR" check $P/no-module-py test ! -f "$SITE/flexcache.py" check $P/init-file test -s "$PKGDIR/__init__.py" check $P/flexcache-py test -s "$PKGDIR/flexcache.py" check $P/pycache-init test -s "$PKGDIR/__pycache__/__init__.cpython-312.pyc" check $P/pycache-flexcache test -s "$PKGDIR/__pycache__/flexcache.cpython-312.pyc" check_eq $P/module-count "2" \ "$(find "$PKGDIR" -maxdepth 1 -name '*.py' 2>/dev/null | wc -l | tr -d ' ')" # py.typed is ZERO BYTES and `test -s' would call the correct file missing. check $P/py-typed-present test -f "$PKGDIR/py.typed" check_eq $P/py-typed-empty "0" \ "$(wc -c < "$PKGDIR/py.typed" 2>/dev/null | tr -d ' ')" # The testsuite ships INSIDE the main package rather than in a -ptest split. check $P/testsuite-dir test -d "$TSDIR" # testsuite/__init__.py is ZERO BYTES -- the same trap as py.typed above, where # `test -s' reports the correct file as missing. It is what makes the directory # a package, so its SIZE is asserted rather than assumed. check $P/testsuite-init test -f "$TSDIR/__init__.py" check_eq $P/testsuite-init-empty "0" \ "$(wc -c < "$TSDIR/__init__.py" 2>/dev/null | tr -d ' ')" check $P/testsuite-byhash test -s "$TSDIR/test_byhash.py" check $P/testsuite-bymtime test -s "$TSDIR/test_bymtime.py" check $P/testsuite-custom-diskcache test -s "$TSDIR/test_custom_diskcache.py" check $P/testsuite-header test -s "$TSDIR/test_header.py" check_eq $P/testsuite-module-count "5" \ "$(find "$TSDIR" -maxdepth 1 -name '*.py' 2>/dev/null | wc -l | tr -d ' ')" check $P/no-cli test ! -e /usr/bin/flexcache check $P/no-entry-points test ! -f "$DI/entry_points.txt" # --------------------------------------------------------------- dpkg file list --- cat "$PKGLIST" > "$W/pkgf" 2>/dev/null || : > "$W/pkgf" check $P/pkg-list-present test -s "$W/pkgf" # This image's python3 is ONE STATIC BINARY with an empty lib-dynload and no # dynamic loader (BRINTOS-1476), so a module carrying a compiled extension could # not be imported whatever it built to. flexcache is pure Python; these two # assert that negative directly rather than trusting the recipe's `inherit'. check_eq $P/pkg-no-so "" \ "$(grep -E '\.so($|\.)' "$W/pkgf" 2>/dev/null)" check_eq $P/tree-no-so "" \ "$(find "$PKGDIR" -name '*.so*' 2>/dev/null)" # Everything the package ships is Python, its bytecode, the dist-info, or the # py.typed marker. py.typed is named explicitly: it is the one non-Python file # in the package and leaving it out of this filter would red a correct package. _bad="" while IFS= read -r _f; do [ -f "$_f" ] || continue case "$_f" in *.py|*.pyc) continue ;; */__pycache__/*) continue ;; */*.dist-info/*) continue ;; */py.typed) continue ;; esac _bad="$_bad $_f" done < "$W/pkgf" check_eq $P/pkg-only-python "" "$_bad" check_eq $P/no-dev-installed "" \ "$(sed -n '/^Package: python3-flexcache-dev$/p' /var/lib/dpkg/status 2>/dev/null)" # ------------------------------------------------------------------- dist-info --- check $P/dist-info-dir test -d "$DI" check $P/dist-info-metadata test -f "$DI/METADATA" check_out $P/dist-info-version "Version: 0.3" cat "$DI/METADATA" check_out $P/dist-info-name "Name: flexcache" cat "$DI/METADATA" check_out $P/dist-info-purelib "Root-Is-Purelib: true" cat "$DI/WHEEL" check_out $P/dist-info-tag "Tag: py3-none-any" cat "$DI/WHEEL" check_out $P/dist-info-top-level "flexcache" cat "$DI/top_level.txt" check $P/dist-info-license test -s "$DI/LICENSE" check $P/dist-info-authors test -s "$DI/AUTHORS" check $P/dist-info-record test -s "$DI/RECORD" # ---------------------------------------------------------------- dpkg status --- sed -n '/^Package: python3-flexcache$/,/^$/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" grep '^Depends:' "$W/st" > "$W/dep" 2>/dev/null || : > "$W/dep" check $P/pkg-depends-line test -s "$W/dep" # THE ONE THIS PORT ADDED. See the bbappend header: hashlib is a module-scope # import and lives in the `crypt' split, which meta-python does not declare. check_out $P/pkg-depends-crypt "python3-crypt" cat "$W/dep" check_out $P/pkg-depends-core "python3-core" cat "$W/dep" check_out $P/pkg-depends-compression "python3-compression" cat "$W/dep" check_out $P/pkg-depends-email "python3-email" cat "$W/dep" check_out $P/pkg-depends-json "python3-json" cat "$W/dep" check_out $P/pkg-depends-pickle "python3-pickle" cat "$W/dep" check_out $P/pkg-depends-typing-ext "python3-typing-extensions" cat "$W/dep" # --------------------------------------------------------------------- imports --- check $P/import python3 -c 'import flexcache' check $P/import-submodule python3 -c 'import flexcache.flexcache' check $P/import-classes python3 -c 'from flexcache import DiskCache, DiskCacheByHash, DiskCacheByMTime, BaseHeader' check_eq $P/import-quiet "" \ "$(python3 -c 'import flexcache' 2>&1)" # The split the bbappend declares, asserted on its own so a red here separates # "hashlib is missing from the image" from "flexcache is broken". check $P/import-hashlib python3 -c 'import hashlib' # ----------------------------------------------------------------------- probe --- if [ ! -f "$PROBE" ]; then bst_notok $P/probe-present "$PROBE did not ship" rm -rf "$W" exit 0 fi bst_ok $P/probe-present bst_probe $P/probe-run "$W/probe" 1800 python3 "$PROBE" OUT="$W/probe" pv() { grep "^$1=" "$OUT" 2>/dev/null | head -n 1 | cut -d= -f2-; } if [ -s "$OUT" ]; then bst_ok $P/probe-output else bst_notok $P/probe-output "the probe emitted nothing -- python3 did not start, or died before its first line; every CASE below is unscorable" fi check_eq $P/probe-complete "yes" "$(pv probe_done)" check_eq $P/probe-count "131" "$(pv emitted_count)" # ------------------------------------------------------------------- identity --- check_eq $P/module-answered "$PKGDIR/__init__.py" "$(pv module_file)" check_eq $P/is-package "yes" "$(pv is_package)" check_eq $P/version-attr "0.3" "$(pv version_attr)" # __version__ is importlib.metadata.version(), NOT a literal -- so `unknown' # would mean the dist-info is installed where importlib.metadata cannot see it. check_eq $P/version-not-unknown "no" "$(pv version_unknown)" check_eq $P/version-metadata "0.3" "$(pv version_metadata)" check_eq $P/has-all "yes" "$(pv has___all__)" check_eq $P/all-count "15" "$(pv all_count)" check_eq $P/all-names \ "BaseHeader,BasicPythonHeader,DiskCache,DiskCacheByHash,DiskCacheByMTime,InvalidateByExist,InvalidateByMultiPathsMtime,InvalidateByPathMTime,NameByFields,NameByFileContent,NameByHashIter,NameByMultiPaths,NameByObj,NameByPath,__version__" \ "$(pv all_sorted_joined)" check_eq $P/submodule-name "flexcache.flexcache" "$(pv submodule_name)" # typing-extensions is a DECLARED dependency that importing flexcache does not # pull in -- it is used in annotations only. Asserted so a release that starts # importing it at module scope is a red here rather than a surprise. check_eq $P/typing-extensions-not-imported "no" "$(pv typing_extensions_imported)" # ------------------------------------------------------------------- platform --- check_eq $P/plat-system "Linux" "$(pv plat_system)" check_eq $P/plat-implementation "CPython" "$(pv plat_implementation)" check_eq $P/plat-python-series "3.12" "$(pv plat_python_series)" check_eq $P/sys-platform "linux" "$(pv sys_platform)" # The micro version is the image's to choose; the SERIES is what the # site-packages path above hard-codes, so a mismatch would mean the two # disagree about where modules live. check_out $P/plat-python-version "3.12" echo "$(pv plat_python_version)" # ---------------------------------------------------------------- by-hash --- check_eq $P/workdir-created "yes" "$(pv workdir_created)" check_eq $P/byhash-folder-created "yes" "$(pv byhash_folder_created)" check_eq $P/byhash-folder-is-path "yes" "$(pv byhash_folder_is_path)" check_eq $P/byhash-first-value "HELLO FLEXCACHE\n" "$(pv byhash_first_value)" check_eq $P/byhash-calls-after-first "1" "$(pv byhash_calls_after_first)" check_eq $P/byhash-stem-len "40" "$(pv byhash_stem_len)" check_eq $P/byhash-stem-is-hex "yes" "$(pv byhash_stem_is_hex)" # sha1 of the source's CONTENT: a fixed string in the probe, so this stem is the # same on every host and a change to it is a change to flexcache's naming. check_eq $P/byhash-stem "a2cb8918f5d7dbf0ba15167b0b09f3f12893d950" "$(pv byhash_stem)" check_eq $P/byhash-stem-recomputed "yes" "$(pv byhash_stem_recomputed)" check_eq $P/byhash-pickle-exists "yes" "$(pv byhash_pickle_exists)" check_eq $P/byhash-json-exists "yes" "$(pv byhash_json_exists)" check_eq $P/byhash-store-header "yes" "$(pv byhash_store_header_flag)" check_eq $P/byhash-hasher "sha1" "$(pv byhash_hasher)" check_eq $P/byhash-cache-entries "2" "$(pv byhash_cache_entries)" check_eq $P/byhash-pickle-payload "HELLO FLEXCACHE\n" "$(pv byhash_pickle_payload)" check_eq $P/byhash-json-keys "converter_id,source" "$(pv byhash_json_keys)" check_eq $P/byhash-json-converter-id "upper" "$(pv byhash_json_converter_id)" check_eq $P/byhash-json-source-basename "src.txt" "$(pv byhash_json_source_basename)" check_eq $P/byhash-json-source-is-srcpath "yes" "$(pv byhash_json_source_is_srcpath)" check_eq $P/byhash-json-source-is-str "yes" "$(pv byhash_json_source_is_str)" # A SECOND load is the cache hit: same value, converter NOT called again. check_eq $P/byhash-second-value "HELLO FLEXCACHE\n" "$(pv byhash_second_value)" check_eq $P/byhash-calls-after-second "1" "$(pv byhash_calls_after_second)" check_eq $P/byhash-stem-stable "yes" "$(pv byhash_stem_stable)" # A FRESH DiskCache over the same folder still hits -- the cache is on disk, not # in the instance. check_eq $P/byhash-crossinstance-value "HELLO FLEXCACHE\n" "$(pv byhash_crossinstance_value)" check_eq $P/byhash-crossinstance-stem-same "yes" "$(pv byhash_crossinstance_stem_same)" check_eq $P/byhash-calls-after-crossinstance "1" "$(pv byhash_calls_after_crossinstance)" # EDITING THE SOURCE names a DIFFERENT entry, and the old one stays on disk -- # that is by-hash's whole invalidation model, and its cost. check_eq $P/byhash-after-edit-value "GOODBYE FLEXCACHE\n" "$(pv byhash_after_edit_value)" check_eq $P/byhash-after-edit-reparsed "yes" "$(pv byhash_after_edit_reparsed)" check_eq $P/byhash-after-edit-calls "2" "$(pv byhash_after_edit_calls)" check_eq $P/byhash-after-edit-stem-differs "yes" "$(pv byhash_after_edit_stem_differs)" check_eq $P/byhash-after-edit-stem "5642213e116b68892d66b462223159e7903e2230" "$(pv byhash_after_edit_stem)" check_eq $P/byhash-old-pickle-still-there "yes" "$(pv byhash_old_pickle_still_there)" check_eq $P/byhash-entries-after-edit "4" "$(pv byhash_entries_after_edit)" # RESTORING the original content re-names the ORIGINAL entry, which is still # there -- so the converter is not called a third time. check_eq $P/byhash-restored-value "HELLO FLEXCACHE\n" "$(pv byhash_restored_value)" check_eq $P/byhash-restored-stem-same "yes" "$(pv byhash_restored_stem_same)" check_eq $P/byhash-calls-after-restore "2" "$(pv byhash_calls_after_restore)" # A NEWER MTIME with unchanged content still hits: by-hash does not look at it. check_eq $P/byhash-newer-source-still-hits "yes" "$(pv byhash_newer_source_still_hits)" check_eq $P/byhash-calls-after-newer-source "2" "$(pv byhash_calls_after_newer_source)" # ---------------------------------------------------------------- by-mtime --- check_eq $P/bymtime-first-value "MTIME SOURCE\n" "$(pv bymtime_first_value)" check_eq $P/bymtime-calls-after-first "1" "$(pv bymtime_calls_after_first)" check_eq $P/bymtime-stem-len "40" "$(pv bymtime_stem_len)" # named after the sha1 of the PATH, not the content -- the relationship, since # the path is the probe's temporary directory and differs per run. check_eq $P/bymtime-stem-is-sha1-of-path "yes" "$(pv bymtime_stem_is_sha1_of_path)" check_eq $P/bymtime-pickle-exists "yes" "$(pv bymtime_pickle_exists)" check_eq $P/bymtime-second-value "MTIME SOURCE\n" "$(pv bymtime_second_value)" check_eq $P/bymtime-calls-after-second "1" "$(pv bymtime_calls_after_second)" check_eq $P/bymtime-stem-stable "yes" "$(pv bymtime_stem_stable)" # EDITING the source REWRITES the one entry -- the stem is the path's and does # not move, which is the opposite of by-hash above. check_eq $P/bymtime-after-touch-value "MTIME SOURCE EDITED\n" "$(pv bymtime_after_touch_value)" check_eq $P/bymtime-after-touch-reparsed "yes" "$(pv bymtime_after_touch_reparsed)" check_eq $P/bymtime-after-touch-stem-same "yes" "$(pv bymtime_after_touch_stem_same)" check_eq $P/bymtime-entries "2" "$(pv bymtime_entries)" check_eq $P/bymtime-pickle-rewritten "MTIME SOURCE EDITED\n" "$(pv bymtime_pickle_rewritten)" # An EQUAL mtime re-parses: the header check is `>=', not `=='. check_eq $P/bymtime-equal-mtime-reparses "yes" "$(pv bymtime_equal_mtime_reparses)" check_eq $P/bymtime-equal-mtime-value "MTIME SOURCE EDITED\n" "$(pv bymtime_equal_mtime_value)" # ------------------------------------------- the filesystem's clock, not ours --- # Scored as a skip rather than a red where the stamp does not move: a coarse # tick is this image's property, and `bymtime-settled-hit' below is decisive # either way because the probe settles past ONE MEASURED tick first. if [ "$(pv mtime_granularity_measured)" = "yes" ]; then bst_ok $P/mtime-granularity else bst_skip $P/mtime-granularity "the mtime stamp never moved inside 200 rewrites: this filesystem's tick is coarser than the whole loop, so the probe settles a full second instead" fi if [ "$(pv mtime_subsecond)" = "yes" ]; then bst_ok $P/mtime-subsecond else bst_skip $P/mtime-subsecond "this filesystem's mtime tick is 1s or coarser (granularity_ns=$(pv mtime_granularity_ns)); flexcache is unaffected, its header compares whatever the stamp reports" fi check_eq $P/bymtime-settled-hit "yes" "$(pv bymtime_settled_hit)" check_eq $P/bymtime-settled-calls "1" "$(pv bymtime_settled_calls)" # The UNSETTLED race is reported as a count and only scored for range: 5 means # the tick is finer than the round, 0 means it bites every time, and both are # the filesystem's answer rather than a defect in the package. check_eq $P/bymtime-unsettled-in-range "yes" "$(pv bymtime_unsettled_in_range)" # ------------------------------------------------------- folder construction --- check_eq $P/deep-folder-created "yes" "$(pv deep_folder_created)" check_eq $P/existing-folder-reused "yes" "$(pv existing_folder_reused)" check_eq $P/folder-from-path-ok "yes" "$(pv folder_from_path_ok)" check_eq $P/folder-over-file "!FileExistsError" "$(pv folder_over_file)" check_eq $P/folder-under-file "!NotADirectoryError" "$(pv folder_under_file)" # --------------------------------------------------------- damaged cache files --- # A corrupt or truncated entry RAISES rather than falling back to re-parsing -- # a caller who assumed a silent re-parse loses the call, so both are asserted. check_eq $P/corrupt-cache "!UnpicklingError" "$(pv corrupt_cache)" check_eq $P/empty-cache "!EOFError" "$(pv empty_cache)" # Scored as the RELATIONSHIP: root reads mode 000 fine, a normal account is # refused, and either is correct. The euid itself is reported next to it. # # `unreadable-entry-ok' is what makes that scorable. The entry being chmod'd has # to be a GOOD one: measured on this batch's verify, the case was reusing the # entry `empty-cache' had just truncated, so the load raised EOFError out of # pickle no matter what the open did, and the relationship read `no' on a root # image whatever the filesystem's answer had been. check_eq $P/unreadable-entry-ok "yes" "$(pv unreadable_entry_ok)" check_eq $P/unreadable-matches-euid "yes" "$(pv unreadable_matches_euid)" if [ "$(pv unreadable_euid)" = "0" ]; then bst_skip $P/unreadable-permissionerror "euid 0: mode 000 does not refuse a read, so the documented PermissionError cannot be provoked on this image; unreadable-matches-euid scores the relationship instead, and the load returned: $(pv unreadable_result)" else check_eq $P/unreadable-permissionerror "!PermissionError" "$(pv unreadable_result)" fi # A SOURCE THAT DISAPPEARS between loads raises from BOTH strategies, and from # different places -- by-hash reads it to NAME the entry, by-mtime stats it to # VALIDATE one. Neither serves the cached value it still holds on disk. check_eq $P/gone-byhash "!FileNotFoundError" "$(pv gone_byhash)" check_eq $P/gone-bymtime "!FileNotFoundError" "$(pv gone_bymtime)" check_eq $P/absent-byhash "!FileNotFoundError" "$(pv absent_byhash)" check_eq $P/absent-bymtime "!FileNotFoundError" "$(pv absent_bymtime)" # ---------------------------------------------------------- converter results --- # A FALSY converted value is written to disk but never served: the hit test is # the value's truthiness, so an empty string re-converts every single time. # That is a real performance trap and it is asserted rather than described. check_eq $P/falsy-value "''" "$(pv falsy_value_repr)" check_eq $P/falsy-calls "2" "$(pv falsy_calls)" check_eq $P/falsy-reconverts "yes" "$(pv falsy_reconverts_every_time)" check_eq $P/falsy-file-written "yes" "$(pv falsy_cache_file_written)" check_eq $P/truthy-calls "1" "$(pv truthy_calls)" # NO converter at all: `load' returns None and writes nothing. check_eq $P/noconverter-value "None" "$(pv noconverter_value)" check_eq $P/noconverter-stem-len "40" "$(pv noconverter_stem_len)" check_eq $P/noconverter-wrote-nothing "yes" "$(pv noconverter_wrote_nothing)" # The converter's IDENTITY is part of the entry's name, so two converters over # one source do not collide. check_eq $P/strconv-value "None" "$(pv strconv_value)" check_eq $P/strconv-names-differ "yes" "$(pv strconv_names_differ)" check_eq $P/strconv-alpha-recomputed "yes" "$(pv strconv_alpha_stem_recomputed)" check_eq $P/lambda-converter-id "yes" "$(pv lambda_converter_id_is_lambda)" check_eq $P/callable-object-empty-id "yes" "$(pv callable_object_empty_id)" # ------------------------------------------------------------ explicit naming --- check_eq $P/pass-hash-matches-stem "yes" "$(pv pass_hash_value_matches_stem)" check_eq $P/save-stem-recomputed "yes" "$(pv save_stem_recomputed)" check_eq $P/save-then-load "PRECOMPUTED" "$(pv save_then_load)" # -------------------------------------------------------------- the base class --- # `DiskCache' itself has NO header classes registered, so loading through it is # a TypeError -- the base is abstract in practice, and registering a header # makes it work. check_eq $P/base-diskcache-load "!TypeError" "$(pv base_diskcache_load)" check_eq $P/base-header-classes-empty "yes" "$(pv base_header_classes_empty)" check_eq $P/base-registered-value "HELLO FLEXCACHE\n" "$(pv base_registered_value)" check_eq $P/base-registered-calls "1" "$(pv base_registered_calls)" check_eq $P/int-source "!TypeError" "$(pv int_source)" check_eq $P/path-and-str-same-stem "yes" "$(pv path_and_str_same_stem)" # ------------------------------------------------------------------- headers --- check_eq $P/header-frozen "!FrozenInstanceError" "$(pv header_frozen)" check_eq $P/header-source-type "PosixPath" "$(pv header_source_type)" check_eq $P/header-is-valid-missing "no" "$(pv header_is_valid_missing)" check_eq $P/header-is-valid-present "yes" "$(pv header_is_valid_present)" check_eq $P/header-wrong-source-type "!TypeError" "$(pv header_wrong_source_type)" check_eq $P/namebyfields-version-changes-name "yes" "$(pv namebyfields_version_changes_name)" check_eq $P/namebyfields-stable "yes" "$(pv namebyfields_stable)" check_eq $P/byhash-is-diskcache "yes" "$(pv byhash_is_diskcache)" check_eq $P/bymtime-is-diskcache "yes" "$(pv bymtime_is_diskcache)" check_eq $P/byhash-header-bases "NameByFileContent,InvalidateByExist,BaseHeader" "$(pv byhash_header_bases)" check_eq $P/bymtime-header-bases "NameByPath,InvalidateByPathMTime,BaseHeader" "$(pv bymtime_header_bases)" # ------------------------------------------------------------------- hygiene --- # The probe worked under TMPDIR and left nothing in the cwd -- a cache written # into the rootfs would be a finding about the suite, not about flexcache. check_eq $P/probe-workdir-is-tmp "yes" "$(pv workdir_is_tmp)" check_eq $P/probe-no-cwd-cache "yes" "$(pv no_cwd_cache)" check_eq $P/probe-workdir-removed "yes" "$(pv workdir_removed)" rm -rf "$W"