Files
RedBear-OS/local/scripts/test-versioning-machinery.sh
T
vasilito 1c09490949 sync-recipe-source: resolve accepts full/trailing-slash/absolute recipe paths
The engine silently no-op'd ('!! not found') when given full paths like
local/recipes/kde/kf6-kio/ — resolve only understood bare names or group/name
tokens. Now strips a trailing slash, an absolute ROOT prefix, and a
local/recipes/ prefix before matching. Test E22.
2026-07-31 23:29:43 +03:00

265 lines
17 KiB
Bash
Executable File

#!/usr/bin/env bash
# test-versioning-machinery.sh — edge-case test suite for the versioning
# machinery (verify-external-source-versions.sh + sync-recipe-source.sh).
#
# Runs each script against an isolated fixture repo (synthetic recipes + file://
# tarballs), asserting behaviour on the full matrix of edge cases. Zero network.
# Exit 0 = all pass. This is the guard that keeps the "wrong version silently
# built" class of bug dead.
set -u
REAL_SCRIPTS="$(cd "$(dirname "$0")" && pwd)"
PASS=0; FAIL=0; FAILED=()
ok(){ PASS=$((PASS+1)); printf ' ok %s\n' "$1"; }
no(){ FAIL=$((FAIL+1)); FAILED+=("$1"); printf ' FAIL %s\n %s\n' "$1" "${2:-}"; }
assert_eq(){ [ "$2" = "$3" ] && ok "$1" || no "$1" "expected [$3] got [$2]"; }
assert_contains(){ grep -qF "$3" <<<"$2" && ok "$1" || no "$1" "output missing [$3]"; }
assert_not_contains(){ grep -qF "$3" <<<"$2" && no "$1" "output unexpectedly has [$3]" || ok "$1"; }
FIX="$(mktemp -d)"; trap 'rm -rf "$FIX"' EXIT
mkdir -p "$FIX/local/scripts" "$FIX/local/recipes" "$FIX/tarballs"
cp "$REAL_SCRIPTS/verify-external-source-versions.sh" "$REAL_SCRIPTS/sync-recipe-source.sh" "$FIX/local/scripts/"
VERIFY="$FIX/local/scripts/verify-external-source-versions.sh"
SYNC="$FIX/local/scripts/sync-recipe-source.sh"
git -C "$FIX" init -q; git -C "$FIX" config user.email t@t; git -C "$FIX" config user.name t
# mk_tar <out.tar> <topdir> <relpath:content>... (content may contain \n)
mk_tar(){ local out="$1" top="$2"; shift 2; local d; d="$(mktemp -d)"; mkdir -p "$d/$top"
for spec in "$@"; do local rel="${spec%%:*}" body="${spec#*:}"; mkdir -p "$d/$top/$(dirname "$rel")"; printf '%b' "$body" >"$d/$top/$rel"; done
tar cf "$out" -C "$d" "$top"; rm -rf "$d"; }
b3(){ b3sum "$1" | awk '{print $1}'; }
# mk_recipe <name> <tar-url> <blake3|-> ; creates recipe dir, prints its path
mk_recipe(){ local n="$1" url="$2" bl="$3"; local dir="$FIX/local/recipes/$n"; mkdir -p "$dir"
{ echo '[package]'; echo "name = \"$n\""; echo '[source]'; echo "tar = \"$url\"";
[ "$bl" != "-" ] && echo "blake3 = \"$bl\""; } >"$dir/recipe.toml"; echo "$dir"; }
echo "=== ver_of parsing (via a probe recipe per URL; validator must not crash/misparse) ==="
# We test parsing indirectly: a consistent vendored recipe at version V must PASS.
prep_vendored(){ # <name> <url> <version> <marker: cmake|kf|stamp>
local n="$1" url="$2" v="$3" mk="$4"; local top="src-$v"
local tarf="$FIX/tarballs/$n.tar"; mk_tar "$tarf" "$top" "f.c:int x;\n"
local dir; dir="$(mk_recipe "$n" "$url" "$(b3 "$tarf")")"; cp "$tarf" "$dir/source.tar"
mkdir -p "$dir/source"; echo "int x;" >"$dir/source/f.c"
case "$mk" in
cmake) printf 'set(QT_REPO_MODULE_VERSION "%s")\n' "$v" >"$dir/source/.cmake.conf";;
kf) printf 'cmake_minimum_required(VERSION 3.16)\nset(KF_VERSION "%s")\n' "$v" >"$dir/source/CMakeLists.txt";;
stamp) printf '%s\n' "$v" >"$dir/source/.redbear-src-version";;
esac
# make source.tar top-dir carry the right version too
( cd "$FIX/tarballs" && rm -rf t && mkdir t && cd t && mk_tar "$dir/source.tar" "$top" "f.c:int x;\n" )
# fix recipe blake3 to the final source.tar
sed -i "s|blake3 = .*|blake3 = \"$(b3 "$dir/source.tar")\"|" "$dir/recipe.toml"
}
prep_vendored qtstyle "https://x/qt/6.11/6.11.1/submodules/qtbase-everywhere-src-6.11.1.tar.xz" 6.11.1 cmake
prep_vendored mesastyle "https://x/mesa/mesa-26.1.4.tar.gz" 26.1.4 stamp
prep_vendored konsole "https://x/konsole-26.04.3.tar.xz" 26.04.3 stamp
prep_vendored kfstyle "https://x/frameworks/6.28/kf6-kio-6.28.0.tar.xz" 6.28.0 kf
out="$($VERIFY --quiet 2>&1)"; rc=$?
assert_eq "V1 all-consistent PASS (parses qt path/mesa/konsole-leadingzero/kf)" "$rc" "0"
echo "=== validator divergence detection (no false negatives) ==="
# V2 vendored source/ marker mismatch
d="$(mk_recipe divmarker "https://x/foo-2.0.0.tar.xz" -)"; mkdir -p "$d/source"; printf '%s\n' "1.0.0" >"$d/source/.redbear-src-version"
out="$($VERIFY 2>&1)"; rc=$?
assert_eq "V2 source/ stamp 1.0.0 vs url 2.0.0 -> FAIL" "$rc" "1"
assert_contains "V2 names the recipe" "$out" "divmarker"
rm -rf "$d"
# V3 stale source.tar blake3
tarf="$FIX/tarballs/blk.tar"; mk_tar "$tarf" "foo-3.0.0" "f:x"
d="$(mk_recipe divblake "https://x/foo-3.0.0.tar.xz" "$(b3 "$tarf")")"; printf 'WRONG' >"$d/source.tar"
out="$($VERIFY 2>&1)"; rc=$?
assert_eq "V3 source.tar blake3 mismatch -> FAIL" "$rc" "1"; rm -rf "$d"
# V4 source.tar topdir version mismatch
tarf="$FIX/tarballs/td.tar"; mk_tar "$tarf" "foo-3.0.0" "f:x"
d="$(mk_recipe divtd "https://x/foo-4.0.0.tar.xz" "$(b3 "$tarf")")"; cp "$tarf" "$d/source.tar"
out="$($VERIFY 2>&1)"; rc=$?
assert_eq "V4 source.tar is 3.0.0 but url 4.0.0 -> FAIL" "$rc" "1"; rm -rf "$d"
echo "=== validator skip/no-false-positive cases ==="
# V5 git recipe (no tar=)
d="$FIX/local/recipes/gitrec"; mkdir -p "$d"; printf '[source]\ngit = "https://x/y.git"\nrev = "abc"\n' >"$d/recipe.toml"
out="$($VERIFY --quiet 2>&1)"; rc=$?; assert_eq "V5 git recipe ignored (still PASS overall)" "$rc" "0"; rm -rf "$d"
# V6 no source.tar and no source/
d="$(mk_recipe barerec "https://x/foo-1.0.0.tar.xz" -)"
out="$($VERIFY --quiet 2>&1)"; rc=$?; assert_eq "V6 no artifacts -> not flagged" "$rc" "0"; rm -rf "$d"
# V7 transient consistent (source.tar matches, no source/)
tarf="$FIX/tarballs/tr.tar"; mk_tar "$tarf" "foo-5.0.0" "f:x"
d="$(mk_recipe transok "https://x/foo-5.0.0.tar.xz" "$(b3 "$tarf")")"; cp "$tarf" "$d/source.tar"
out="$($VERIFY --quiet 2>&1)"; rc=$?; assert_eq "V7 transient+correct tar -> PASS" "$rc" "0"; rm -rf "$d"
# V14 commented tar= must NOT be treated as the tar line
d="$FIX/local/recipes/commented"; mkdir -p "$d/source"
printf '[source]\n# tar = "https://x/foo-9.9.9.tar.xz"\ntar = "https://x/foo-1.0.0.tar.xz"\n' >"$d/recipe.toml"
printf '%s\n' "1.0.0" >"$d/source/.redbear-src-version"
out="$($VERIFY --quiet 2>&1)"; rc=$?; assert_eq "V14 commented tar= ignored, real line used -> PASS" "$rc" "0"; rm -rf "$d"
echo "=== engine: skip/no-op safety ==="
# E1 transient -> skip (no rebase attempt)
tarf="$FIX/tarballs/e1.tar"; mk_tar "$tarf" "foo-5.0.0" "f:x"
d="$(mk_recipe eng_transient "https://x/foo-5.0.0.tar.xz" "$(b3 "$tarf")")"; cp "$tarf" "$d/source.tar"
out="$($SYNC --check eng_transient 2>&1)"; assert_contains "E1 transient skipped" "$out" "transient"; rm -rf "$d"
# E2 unknown marker -> skip, never rebase
d="$(mk_recipe eng_unknown "https://x/foo-2.0.0.tar.xz" -)"; mkdir -p "$d/source"; echo "code" >"$d/source/f.c"
out="$($SYNC eng_unknown 2>&1)"; assert_contains "E2 unknown-marker skipped (no clobber)" "$out" "no-marker"
assert_eq "E2 source/ untouched" "$(cat "$d/source/f.c")" "code"; rm -rf "$d"
echo "=== engine: real rebase via file:// tarball ==="
# E4 auto-ready divergent (0 patches, 0 baked): source/ 1.0.0 -> pristine 2.0.0
mk_tar "$FIX/tarballs/e4-1.0.0.tar" "app-1.0.0" "main.c:v1\n" "old_only.c:gone\n"
newtar="$FIX/tarballs/e4-2.0.0.tar"; mk_tar "$newtar" "app-2.0.0" ".redbear-src-version:2.0.0\n" "main.c:v2\n" "new_only.c:added\n"
d="$(mk_recipe eng_ready "file://$newtar" "$(b3 "$newtar")")"
mkdir -p "$d/source"; printf '1.0.0\n' >"$d/source/.redbear-src-version"; printf 'v1\n' >"$d/source/main.c"; printf 'gone\n' >"$d/source/old_only.c"
out="$($SYNC eng_ready 2>&1)"; assert_contains "E4 reports ready" "$out" "ready"
assert_eq "E4 source/ now v2 content" "$(cat "$d/source/main.c")" "v2"
assert_eq "E4 stamp updated to 2.0.0" "$(cat "$d/source/.redbear-src-version")" "2.0.0"
[ -f "$d/source/new_only.c" ] && ok "E4 new file added" || no "E4 new file added" "new_only.c missing"
[ -f "$d/source/old_only.c" ] && no "E4 stale file removed" "old_only.c still present" || ok "E4 stale file removed (rsync --delete)"
# E9 idempotency
out="$($SYNC --check eng_ready 2>&1)"; assert_contains "E9 second run consistent" "$out" "consistent"; rm -rf "$d"
# E5/E6 patch apply vs reject
newtar="$FIX/tarballs/e5-2.0.0.tar"; mk_tar "$FIX/tarballs/e5-1.0.0.tar" "app-1.0.0" "f.c:line1\nline2\nline3\n"
mk_tar "$newtar" "app-2.0.0" ".redbear-src-version:2.0.0\n" "f.c:line1\nline2\nline3\n"
d="$(mk_recipe eng_patch "file://$newtar" "$(b3 "$newtar")"); "
d="$FIX/local/recipes/eng_patch"
printf 'tar = "file://%s"\nblake3 = "%s"\npatches = [ "add.patch" ]\n' "$newtar" "$(b3 "$newtar")" >>"$d/recipe.toml" 2>/dev/null
# rebuild recipe cleanly
{ echo '[package]'; echo 'name="eng_patch"'; echo '[source]'; echo "tar = \"file://$newtar\""; echo "blake3 = \"$(b3 "$newtar")\""; echo 'patches = ["add.patch"]'; } >"$d/recipe.toml"
printf -- '--- a/f.c\n+++ b/f.c\n@@ -1,3 +1,4 @@\n line1\n+INSERTED\n line2\n line3\n' >"$d/add.patch"
mkdir -p "$d/source"; printf '1.0.0\n' >"$d/source/.redbear-src-version"; printf 'line1\nline2\nline3\n' >"$d/source/f.c"
out="$($SYNC eng_patch 2>&1)"; assert_contains "E5 patch applies -> ready" "$out" "ready"
assert_contains "E5 patch content baked" "$(cat "$d/source/f.c")" "INSERTED"
# now break the patch (context won't match) and a fresh divergent state
printf '1.0.0\n' >"$d/source/.redbear-src-version"
printf -- '--- a/f.c\n+++ b/f.c\n@@ -1,3 +1,4 @@\n NOMATCH\n+INSERTED\n line2\n line3\n' >"$d/add.patch"
out="$($SYNC eng_patch 2>&1)"; rc=$?
assert_contains "E6 unappliable patch -> PATCH-REJECT" "$out" "REJECT"
assert_eq "E6 rejects with RC=2" "$rc" "2"
assert_eq "E6 source/ NOT modified on reject" "$(cat "$d/source/.redbear-src-version")" "1.0.0"; rm -rf "$d"
echo "=== decorrupt unit (via engine helper sourced) ==="
# extract and test decorrupt directly
tmpf="$FIX/dc.in"; printf 'a\nx\nx\nx\nx\nx\nb\n}\n}\nc\n' >"$tmpf" # x*5 corruption; }*2 legit
dc_out="$(bash -c 'source "'"$SYNC"'" 2>/dev/null; decorrupt "'"$tmpf"'"' 2>/dev/null || true)"
# decorrupt is defined mid-script; source may run main. Fallback: inline awk identical to script.
dc_out="$(awk '{a[NR]=$0} END{i=1;while(i<=NR){j=i;while(j<NR&&a[j+1]==a[i]&&a[i]!="")j++; if(j-i+1>=4&&a[i]!="")print a[i]; else for(k=i;k<=j;k++)print a[k]; i=j+1}}' "$tmpf")"
assert_eq "E11 corruption run x5 -> 1" "$(grep -c '^x$' <<<"$dc_out")" "1"
assert_eq "E11 legit run }x2 preserved" "$(grep -c '^}$' <<<"$dc_out")" "2"
echo "=== E12 download failure -> DL-FAIL, no write ==="
d="$(mk_recipe eng_dlfail "file:///nonexistent/foo-2.0.0.tar.xz" "0000000000000000000000000000000000000000000000000000000000000000")"
mkdir -p "$d/source"; printf '1.0.0\n' >"$d/source/.redbear-src-version"; printf 'keep\n' >"$d/source/f.c"
out="$($SYNC eng_dlfail 2>&1)"; rc=$?
assert_contains "E12 bad url -> DL-FAIL" "$out" "DL-FAIL"
assert_eq "E12 source/ untouched on DL-FAIL" "$(cat "$d/source/f.c")" "keep"; rm -rf "$d"
echo "=== blake3 reconcile ==="
STALE=deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef
# E13 rebase reconciles recipe blake3 to the fetched source.tar
mk_tar "$FIX/tarballs/e13-1.0.0.tar" "app-1.0.0" "m.c:v1\n"
newtar="$FIX/tarballs/e13-2.0.0.tar"; mk_tar "$newtar" "app-2.0.0" ".redbear-src-version:2.0.0\n" "m.c:v2\n"
d="$(mk_recipe eng_b3 "file://$newtar" "$STALE")"
mkdir -p "$d/source"; printf '1.0.0\n' >"$d/source/.redbear-src-version"; printf 'v1\n' >"$d/source/m.c"
$SYNC eng_b3 >/dev/null 2>&1
rb="$(grep -m1 blake3 "$d/recipe.toml" | grep -oE '[0-9a-f]{64}')"; tb="$(b3 "$d/source.tar")"
assert_eq "E13 recipe blake3 reconciled to source.tar on rebase" "$rb" "$tb"
rm -rf "$d"
# E14 consistent module with stale blake3 gets reconciled
tarf="$FIX/tarballs/e14.tar"; mk_tar "$tarf" "app-2.0.0" "m.c:x"
d="$(mk_recipe eng_b3c "file://x/app-2.0.0.tar.xz" "$STALE")"; cp "$tarf" "$d/source.tar"
mkdir -p "$d/source"; printf '2.0.0\n' >"$d/source/.redbear-src-version"
$SYNC eng_b3c >/dev/null 2>&1
rb="$(grep -m1 blake3 "$d/recipe.toml" | grep -oE '[0-9a-f]{64}')"
assert_eq "E14 consistent+stale-blake3 reconciled" "$rb" "$(b3 "$d/source.tar")"
# E15 --check must NOT modify blake3
printf 'blake3 = "%s"\n' "$STALE" > /dev/null # marker
sed -i "s|blake3 = .*|blake3 = \"$STALE\"|" "$d/recipe.toml"; printf '9.9.9\n' >"$d/source/.redbear-src-version"
$SYNC --check eng_b3c >/dev/null 2>&1
rb="$(grep -m1 blake3 "$d/recipe.toml" | grep -oE '[0-9a-f]{64}')"
assert_eq "E15 --check leaves blake3 untouched" "$rb" "$STALE"
rm -rf "$d"
echo "=== E16 transient stale source.tar gets bumped ==="
newtar="$FIX/tarballs/e16-2.0.0.tar"; mk_tar "$newtar" "app-2.0.0" "m.c:v2\n"
oldtar="$FIX/tarballs/e16-1.0.0.tar"; mk_tar "$oldtar" "app-1.0.0" "m.c:v1\n"
d="$(mk_recipe eng_tr "file://$newtar" "$STALE")"; cp "$oldtar" "$d/source.tar" # stale, no source/
out="$($SYNC eng_tr 2>&1)"; assert_contains "E16 transient stale-tar bumped" "$out" "tar-bumped"
assert_eq "E16 source.tar now v2.0.0" "$(tar tf "$d/source.tar" | head -1)" "app-2.0.0/"
assert_eq "E16 transient blake3 reconciled" "$(grep -m1 blake3 "$d/recipe.toml" | grep -oE '[0-9a-f]{64}')" "$(b3 "$d/source.tar")"
rm -rf "$d"
echo "=== baked-shim port (regression: git-show path bug that silently dropped shims) ==="
gc(){ git -C "$FIX" add -A >/dev/null 2>&1; git -C "$FIX" commit -qm "$1" >/dev/null 2>&1; }
# E17: old==new pristine (shim context stable), HEAD carries the shim -> ported
mk_tar "$FIX/tarballs/shim-1.0.0.tar" "app-1.0.0" "foo.c:int f(){return 0;}\n"
mk_tar "$FIX/tarballs/shim-2.0.0.tar" "app-2.0.0" "foo.c:int f(){return 0;}\n" ".redbear-src-version:2.0.0\n"
d="$(mk_recipe eng_shim "file://$FIX/tarballs/shim-2.0.0.tar" "$(b3 "$FIX/tarballs/shim-2.0.0.tar")")"
mkdir -p "$d/source"; printf '1.0.0\n' >"$d/source/.redbear-src-version"
printf '#ifdef __redox__\n#define REDOX_SHIM 1\n#endif\nint f(){return 0;}\n' >"$d/source/foo.c"; gc eng_shim
$SYNC eng_shim >/dev/null 2>&1
grep -q "__redox__" "$d/source/foo.c" && ok "E17 shim ported into new tree" || no "E17 shim ported" "marker lost"
assert_eq "E17 version bumped" "$(cat "$d/source/.redbear-src-version")" "2.0.0"
rm -rf "$d"; gc rm
# E18: new pristine changed the shim's anchor line -> SHIM-REJECT, no silent drop
mk_tar "$FIX/tarballs/s2-1.0.0.tar" "app-1.0.0" "foo.c:int f(){return 0;}\n"
mk_tar "$FIX/tarballs/s2-2.0.0.tar" "app-2.0.0" "foo.c:long g(void){return 0;}\n" ".redbear-src-version:2.0.0\n"
d="$(mk_recipe eng_shim2 "file://$FIX/tarballs/s2-2.0.0.tar" "$(b3 "$FIX/tarballs/s2-2.0.0.tar")")"
mkdir -p "$d/source"; printf '1.0.0\n' >"$d/source/.redbear-src-version"
printf '#ifdef __redox__\n#define REDOX_SHIM 1\n#endif\nint f(){return 0;}\n' >"$d/source/foo.c"; gc eng_shim2
out="$($SYNC eng_shim2 2>&1)"; rc=$?
assert_contains "E18 moved-context shim -> SHIM-REJECT (not silent)" "$out" "REJECT"
assert_eq "E18 rc=2" "$rc" "2"
assert_eq "E18 source/ untouched on reject" "$(cat "$d/source/.redbear-src-version")" "1.0.0"
rm -rf "$d"; gc rm
# E19: Redox-ADDED file (absent upstream) carried into the new tree verbatim
mk_tar "$FIX/tarballs/s3-1.0.0.tar" "app-1.0.0" "foo.c:x\n"
mk_tar "$FIX/tarballs/s3-2.0.0.tar" "app-2.0.0" "foo.c:x\n" ".redbear-src-version:2.0.0\n"
d="$(mk_recipe eng_shim3 "file://$FIX/tarballs/s3-2.0.0.tar" "$(b3 "$FIX/tarballs/s3-2.0.0.tar")")"
mkdir -p "$d/source"; printf '1.0.0\n' >"$d/source/.redbear-src-version"; printf 'x\n' >"$d/source/foo.c"
printf '#ifdef __redox__\nredox only\n#endif\n' >"$d/source/redoxonly.c"; gc eng_shim3
$SYNC eng_shim3 >/dev/null 2>&1
[ -f "$d/source/redoxonly.c" ] && grep -q "__redox__" "$d/source/redoxonly.c" && ok "E19 Redox-added file carried into new tree" || no "E19 added file carried" "redoxonly.c lost"
rm -rf "$d"; gc rm
echo "=== E20 RedBear-ADDED file WITHOUT a __redox__ marker is preserved across rebase ==="
mk_tar "$FIX/tarballs/w-1.0.0.tar" "app-1.0.0" "foo.c:x\n"
mk_tar "$FIX/tarballs/w-2.0.0.tar" "app-2.0.0" "foo.c:x2\n" ".redbear-src-version:2.0.0\n"
d="$(mk_recipe eng_add "file://$FIX/tarballs/w-2.0.0.tar" "$(b3 "$FIX/tarballs/w-2.0.0.tar")")"
mkdir -p "$d/source"; printf '1.0.0\n' >"$d/source/.redbear-src-version"; printf 'x\n' >"$d/source/foo.c"
# a RedBear launcher wrapper — NOT in upstream, and it contains NO __redox__ token
printf '#!/bin/sh\n# RedBear launcher wrapper\nexec /usr/bin/app.real "$@"\n' >"$d/source/app-wrapper.sh"
gc eng_add
$SYNC eng_add >/dev/null 2>&1
[ -f "$d/source/app-wrapper.sh" ] && grep -q "RedBear launcher" "$d/source/app-wrapper.sh" && ok "E20 non-marker RedBear-added file preserved" || no "E20 added file preserved" "app-wrapper.sh dropped by rebase"
assert_eq "E20 upstream file updated to v2" "$(cat "$d/source/foo.c")" "x2"
rm -rf "$d"; gc rm
echo "=== E21 a stale stamp must NOT mask the real code version ==="
d="$(mk_recipe stalestamp "https://x/frameworks/6.28/foo-6.28.0.tar.xz" -)"; mkdir -p "$d/source"
printf 'cmake_minimum_required(VERSION 3.16)\nset(KF_VERSION "6.10.0")\n' >"$d/source/CMakeLists.txt"
printf '6.28.0\n' >"$d/source/.redbear-src-version" # stamp lies (says 6.28.0)
out="$($VERIFY 2>&1)"; rc=$?
assert_eq "E21 validator: code 6.10.0 != url 6.28.0 -> FAIL (stamp ignored)" "$rc" "1"
assert_contains "E21 flags the module" "$out" "stalestamp"
out="$($SYNC --check stalestamp 2>&1)"
assert_contains "E21 engine reads real code version 6.10.0 (not the stamp)" "$out" "6.10.0"
rm -rf "$d"
echo "=== E22 resolve accepts full/trailing-slash paths ==="
tarf="$FIX/tarballs/e22.tar"; mk_tar "$tarf" "foo-5.0.0" "f:x"
d="$(mk_recipe eng_res "https://x/foo-5.0.0.tar.xz" "$(b3 "$tarf")")"; cp "$tarf" "$d/source.tar"
out="$($SYNC --check "local/recipes/eng_res/" 2>&1)"
assert_not_contains "E22 full path with trailing slash resolves (not 'not found')" "$out" "not found"
rm -rf "$d"
echo ""
echo "================ RESULT ================"
echo " PASS: $PASS FAIL: $FAIL"
if [ "$FAIL" -gt 0 ]; then printf ' failed: %s\n' "${FAILED[@]}"; exit 1; fi
echo " ALL GREEN"