Files
claude_mac/lib/tests/fast-libs.test.sh
bmottin a4565c80c3 fix(portability): stop assuming GNU coreutils flags on macOS
BSD userland rejects or silently ignores several GNU spellings the repo used:

- `timeout` is not in a stock macOS at all (Homebrew installs it, and also as
  `gtimeout`). Without it every gates.sh check exited 127 and was recorded
  NOT-MET whatever the check actually did — a systematic false negative.
  The binary is now resolved once, with a pure-bash deadline behind it so the
  124 contract still holds where neither binary exists. GATES_TIMEOUT_BIN is
  overridable with `-` not `:-`, so an empty value forces that fallback: the
  suite passes 64/64 both ways, timeout cases included.
- `touch -d '10 days ago'` is GNU-only; perl's utime is the one spelling both
  platforms ship.
- BSD `wc -l` pads its count with leading spaces, so string compares failed as
  got[      48] want[48].
- `sed -i` needs a suffix argument on BSD AND does not expand \n in the
  replacement, so the release-candidate CHANGELOG edit silently did nothing
  and the assertion failed for the wrong reason. Rewritten in awk; the RC_TAG=0
  mode still REDs on the absent tag, so the test keeps its teeth.
- `/bin/grep` does not exist on macOS (grep lives in /usr/bin), and `stat -c`
  is GNU-only.

fast-libs 11/11, seo-data 221/221, release-candidate 5 GREEN / 0 RED.
2026-09-13 17:21:09 -04:00

56 lines
2.4 KiB
Bash

#!/usr/bin/env bash
# lib/tests/fast-libs.test.sh — fast-libs.sh verbs + ctx7-reminder hook (BDR-078)
set -u
ROOT="$(cd "$(dirname "$0")/../.." && pwd)"
L="$ROOT/lib/fast-libs.sh"
H="$ROOT/hooks/ctx7-reminder.sh"
pass=0; fail=0
check() { if [ "$2" = "$3" ]; then pass=$((pass+1)); else fail=$((fail+1));
printf 'FAIL %s: got[%s] want[%s]\n' "$1" "$2" "$3"; fi; }
tmp="$(mktemp -d)"; trap 'rm -rf "$tmp"' EXIT
# --- detect: JS fast-libs matched, stable deps ignored ---
mkdir -p "$tmp/js"
cat > "$tmp/js/package.json" <<'EOF'
{"dependencies":{"react":"^19","express":"^5","@tanstack/react-query":"^5"},
"devDependencies":{"vite":"^6","lodash":"^4"}}
EOF
check T1-js-detect "$(bash "$L" detect "$tmp/js" | tr '\n' ' ')" \
"@tanstack/react-query react vite "
# react-icons must NOT ride the react match (anchored full-key)
mkdir -p "$tmp/near"
printf '{"dependencies":{"react-icons":"^5","express":"^5"}}' \
> "$tmp/near/package.json"
check T2-near-miss "$(bash "$L" detect "$tmp/near" >/dev/null 2>&1; echo $?)" 1
# --- detect: python manifest + stable-tech project (exit 1) ---
mkdir -p "$tmp/py"
printf 'fastapi==0.115\nrequests>=2\n' > "$tmp/py/requirements.txt"
check T3-py-detect "$(bash "$L" detect "$tmp/py")" "fastapi"
mkdir -p "$tmp/cpp"
check T4-none "$(bash "$L" detect "$tmp/cpp" >/dev/null 2>&1; echo $?)" 1
# --- cache-status: missing / fresh / stale ---
check T5-missing "$(bash "$L" cache-status "$tmp/js" || true)" missing
mkdir -p "$tmp/js/.ctx7-cache"; touch "$tmp/js/.ctx7-cache/react-core.md"
check T6-fresh "$(bash "$L" cache-status "$tmp/js")" fresh
# `touch -d '10 days ago'` is GNU-only; BSD touch (macOS) wants -t with an
# absolute stamp. perl's utime is the one spelling both platforms ship.
perl -e 'my $t = time - 10*86400; utime $t, $t, $ARGV[0]' \
"$tmp/js/.ctx7-cache/react-core.md"
check T7-stale "$(bash "$L" cache-status "$tmp/js" || true)" stale
# --- hook: fires once per session, silent on stable projects ---
hook() { printf '{"prompt":"add a hook","session_id":"%s","cwd":"%s"}' \
"$1" "$2" | TMPDIR="$tmp" bash "$H"; }
check H1-fires "$(hook s1 "$tmp/js" | grep -c 'Fast-moving')" 1
check H2-once "$(hook s1 "$tmp/js" | wc -l | tr -d ' ')" 0
check H3-cpp-quiet "$(hook s2 "$tmp/cpp" | wc -l | tr -d ' ')" 0
check H4-notif-quiet \
"$(printf '{"prompt":"<task-notification>x","session_id":"s3","cwd":"%s"}' \
"$tmp/js" | TMPDIR="$tmp" bash "$H" | wc -l | tr -d ' ')" 0
printf 'PASS=%s FAIL=%s\n' "$pass" "$fail"; [ "$fail" -eq 0 ]