mirror of
https://github.com/cozystack/cozystack.git
synced 2026-10-23 03:27:50 +09:00
The shell translator rewrites test bodies and loses Bats reporting. The unit lane needs complete TAP results and JUnit reports without changing how live-cluster suites run. Sourced production helpers still need a dash pass, and unit test bodies need nounset without exporting shell options into subprocesses. Assisted-by: LLM Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com>
162 lines
8.7 KiB
Bash
162 lines
8.7 KiB
Bash
#!/usr/bin/env bats
|
|
# -----------------------------------------------------------------------------
|
|
# Coverage invariant for the helm-unittest sweep: every package that ships a
|
|
# suite must answer the probe the sweep opens with.
|
|
#
|
|
# hack/helm-unit-tests.sh decides whether to enter a package directory by asking
|
|
# `make -C "$dir" -n test`, and a package that answers "No rule to make target"
|
|
# is skipped without a word. Every other guard in that script — the shadowed
|
|
# target check, the zero-suite check, the positive-evidence check — runs inside
|
|
# a directory the sweep already reached, so a package missing the target escapes
|
|
# all of them at once and the sweep still reports success. The suites under
|
|
# tests/ then read as coverage to anyone opening the directory while nothing
|
|
# executes them, which is worse than having no suite at all: a suite that has
|
|
# never run is where a stale assertion hides. packages/system/gpu-operator sat
|
|
# in exactly that state, with three passing test cases nothing ever ran.
|
|
#
|
|
# hack/helm-unit-tests.bats covers the script's own reactions against synthetic
|
|
# trees. This file makes the complementary claim, about the real tree: every
|
|
# package that ships a suite answers the probe the sweep opens with.
|
|
#
|
|
# That is narrower than "the sweep reaches every suite", and deliberately so.
|
|
# Reach also depends on the hardcoded root list the sweep loops over, so
|
|
# dropping packages/system from it would take every package under that root out
|
|
# of the run while each one keeps its target and this file stays green. That is
|
|
# the same shape as the packages/tests incident recorded in the sweep's own
|
|
# header, and it wants its own guard rather than a looser predicate here.
|
|
#
|
|
# The predicate is "holds at least one tests/*_test.yaml", not "has a tests/
|
|
# directory". That glob is helm-unittest's own default, so a package outside it
|
|
# has nothing of its own for a `test:` target to run and the sweep would reject
|
|
# it for reporting zero suites. packages/system/nfs-driver is the live case:
|
|
# its tests/ holds a PersistentVolumeClaim and a StorageClass to apply by hand,
|
|
# not a suite.
|
|
#
|
|
# "Of its own" is the load-bearing part. `--with-subchart` defaults to true, so
|
|
# a package carrying no suite of its own would still run any that came down
|
|
# with a vendored chart under charts/, and this predicate would not look for it.
|
|
# Only ingress-nginx and reloader vendor such suites today and both ship their
|
|
# own as well, so nothing is out of reach; a package that vendored suites and
|
|
# wrote none itself would need this predicate widened.
|
|
#
|
|
# Probed with `make -n` rather than by grepping the Makefile for `test:`, so the
|
|
# question asked here is the same one the sweep asks — a target reached through
|
|
# an include counts, and so would a rule this file cannot parse. The sweep's
|
|
# other precondition, that `$dir/Makefile` exists, is mirrored rather than left
|
|
# to make, which is looser about the name and about there being a makefile at
|
|
# all.
|
|
#
|
|
# The verdict comes from the sweep's command unchanged. Reading the diagnostic
|
|
# needs `LC_ALL=C` and `--no-print-directory`, and both are visible to a
|
|
# Makefile through `LC_ALL` and `MAKEFLAGS`, so a Makefile branching on either
|
|
# would answer this file and the sweep differently. That is why the failing
|
|
# package is probed a second time to explain rather than once to do both.
|
|
#
|
|
# Answering the probe is not the same as declaring a recipe: a path named `test`
|
|
# beside the Makefile, or an implicit rule that can build one, satisfies it too,
|
|
# and this file would report that package as covered. That is deliberate rather
|
|
# than overlooked. It is the sweep's own gate, so a package passing here is a
|
|
# package the sweep enters once it walks that package's root, which is the
|
|
# whole claim and no more than it: the root list is the caveat above. From
|
|
# inside, the sweep's positive-evidence check refuses whatever does not print
|
|
# the line a helm-unittest run emits. A pattern rule written to run
|
|
# helm-unittest would satisfy that check on its merits, which is the right
|
|
# outcome rather than a hole: the suites would be running.
|
|
#
|
|
# Not the "is up to date" check, which is the near miss worth naming. A path
|
|
# named `test` with no rule behind it makes make print "Nothing to be done for
|
|
# 'test'." and exit 0, which that grep does not match; measured on 3.81 and
|
|
# 4.4.1. "is up to date" is what make prints for the third case, a real recipe
|
|
# shadowed by a file of that name -- the one `.PHONY: test` prevents.
|
|
#
|
|
# Runs under hack/cozytest.sh, which is POSIX /bin/sh: no arrays, no bats `run`,
|
|
# no `$status`.
|
|
# -----------------------------------------------------------------------------
|
|
|
|
load test_helper
|
|
|
|
REPO_ROOT="$(cd "$(dirname "${BATS_TEST_FILENAME:-$0}")/.." && pwd)"
|
|
|
|
@test "every package shipping a helm-unittest suite answers the sweep probe" {
|
|
# An empty violation list means "no violations" only if the scan reached
|
|
# some packages. A renamed directory or a wrong root yields the same empty
|
|
# string, and the test would pass having read nothing.
|
|
scanned=0
|
|
# cozytest.sh injects `set -u`, so every variable the loop reads is seeded
|
|
# here rather than on first append.
|
|
seen=""
|
|
diagnostics=""
|
|
|
|
for suite in "$REPO_ROOT"/packages/*/*/tests/*_test.yaml; do
|
|
[ -f "$suite" ] || continue
|
|
pkg=$(dirname "$(dirname "$suite")")
|
|
# One package may ship several suites; count and probe it once.
|
|
case " $seen " in
|
|
*" $pkg "*) continue ;;
|
|
esac
|
|
seen="$seen $pkg"
|
|
scanned=$((scanned + 1))
|
|
|
|
# The sweep opens with `[ -f "$dir/Makefile" ]` and returns before it
|
|
# probes anything, so mirror that first. make would not: it also accepts
|
|
# GNUmakefile and makefile, and with no makefile at all it still answers
|
|
# 0 for a target a path of that name satisfies. Either shape would pass
|
|
# the probe below while the sweep skipped the package, which is the one
|
|
# thing this file claims cannot happen.
|
|
if [ ! -f "$pkg/Makefile" ]; then
|
|
diagnostics="$diagnostics
|
|
${pkg#"$REPO_ROOT"/}: no Makefile, so the sweep returns before probing"
|
|
continue
|
|
fi
|
|
|
|
# The verdict is taken from the sweep's own command, byte for byte, so
|
|
# that no flag of this file's can separate the two answers. Deciding and
|
|
# explaining are split for that reason: anything added here to make the
|
|
# output readable is a variable a Makefile could branch on.
|
|
if ! make -C "$pkg" -n test >/dev/null 2>&1; then
|
|
# Only now, and only to explain. LC_ALL=C keeps make's wording in
|
|
# the language the remedy text below is written against.
|
|
#
|
|
# --no-print-directory because on modern GNU make `-C` auto-enables
|
|
# `-w`, and the fatal path prints the "Leaving directory" line after
|
|
# the error, so `tail -n 1` would report the directory trace and
|
|
# drop every diagnostic this block exists to surface: a missing rule
|
|
# and a broken include collapse to the same trace line. Measured on
|
|
# 4.4.1, where it happens, and on 3.81 -- still the /usr/bin/make on
|
|
# macOS -- where `-C` prints no trace at all, so a local run cannot
|
|
# see the difference. The version that draws the line was not
|
|
# measured.
|
|
#
|
|
# `|| true` because this re-run is expected to fail and cozytest.sh
|
|
# injects `set -e`; the verdict is already decided above.
|
|
probe=$(LC_ALL=C make --no-print-directory -C "$pkg" -n test 2>&1 || true)
|
|
|
|
# A missing rule is the expected cause, but an unparseable Makefile
|
|
# and a broken include fail the same probe and have a different
|
|
# remedy. Report what make said rather than asserting the cause.
|
|
diagnostics="$diagnostics
|
|
${pkg#"$REPO_ROOT"/}: $(printf '%s' "$probe" | tail -n 1)"
|
|
fi
|
|
done
|
|
|
|
if [ "$scanned" -eq 0 ]; then
|
|
echo "no tests/*_test.yaml found under $REPO_ROOT/packages -- guard is blind." >&2
|
|
return 1
|
|
fi
|
|
|
|
if [ -n "$diagnostics" ]; then
|
|
echo "Packages shipping a helm-unittest suite the sweep cannot reach:" >&2
|
|
# Each entry is appended with a leading newline, so the accumulator
|
|
# opens with an empty one; drop it rather than the reader parsing a
|
|
# blank first line under pressure.
|
|
printf '%s\n' "$diagnostics" | sed '/^$/d' >&2
|
|
echo "hack/helm-unit-tests.sh probes 'make -C <pkg> -n test' to decide whether" >&2
|
|
echo "to enter a package, so these suites never run and the sweep stays green." >&2
|
|
echo "Where the reason is a missing rule, add to that Makefile:" >&2
|
|
echo " .PHONY: test" >&2
|
|
echo " test:" >&2
|
|
echo " helm unittest ." >&2
|
|
return 1
|
|
fi
|
|
}
|