mirror of
https://github.com/cozystack/cozystack.git
synced 2026-11-09 05:25:14 +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>
152 lines
7.2 KiB
Bash
152 lines
7.2 KiB
Bash
#!/usr/bin/env bats
|
|
# -----------------------------------------------------------------------------
|
|
# Unit tests for the pod-label census in
|
|
# hack/e2e-chainsaw/_lib/pod-label-census.sh.
|
|
#
|
|
# The census exists because a `podLogs` collector cannot report that its
|
|
# selector matched nothing: an empty capture and a stale selector are the same
|
|
# artifact. It prints the instance labels that actually exist, so a reader can
|
|
# tell the two apart.
|
|
#
|
|
# What these tests pin is the discrimination between its three outcomes, which
|
|
# is where the value is and where it is easy to lose. In particular the fourth
|
|
# case below: kubectl exits 0 while logging a klog line about an API group it
|
|
# could not reach, which is the normal shape of a degraded cluster and so the
|
|
# normal shape of a run where this catch fires at all. An earlier form captured
|
|
# with `2>&1`, and that klog line then made the value non-empty -- the "no pods"
|
|
# branch became unreachable and the error printed under the census heading as
|
|
# though it were a pod. Separating the streams is the fix; these tests are what
|
|
# keeps it separated.
|
|
#
|
|
# The report half is a pure function of (rc, stdout, stderr, namespace), so it
|
|
# needs no cluster. The last test drives the kubectl-calling half through a stub
|
|
# on PATH, to prove the streams stay apart end to end rather than only in the
|
|
# half that never touches kubectl.
|
|
#
|
|
# CI runs this file under Bats through `make bats-unit-tests`. It also remains
|
|
# compatible with the legacy `hack/cozytest.sh` translator, whose awk parser
|
|
# recognizes only @test blocks and a bare `}` on its own line. The tests avoid
|
|
# `run`, `$status`, setup(), and teardown() for that compatibility path and use
|
|
# direct shell assertions. Titles remain distinguishable after stripping all
|
|
# but [A-Za-z0-9], as required by the legacy translator.
|
|
#
|
|
# Run with: bats hack/pod-label-census_test.bats
|
|
# -----------------------------------------------------------------------------
|
|
|
|
load test_helper
|
|
|
|
HACK_DIR="$(cd "$(dirname "${BATS_TEST_FILENAME:-$0}")" && pwd)"
|
|
# shellcheck source=/dev/null
|
|
. "$HACK_DIR/e2e-chainsaw/_lib/pod-label-census.sh"
|
|
|
|
@test "census prints the rows it was given under the census heading" {
|
|
out="$(pod_label_census_report 0 "pod-a harbor-test-system" "" tenant-test)"
|
|
echo "$out" | grep -q 'app.kubernetes.io/instance per pod'
|
|
echo "$out" | grep -q 'pod-a harbor-test-system'
|
|
}
|
|
|
|
@test "census names the namespace when the lookup ran and matched nothing" {
|
|
out="$(pod_label_census_report 0 "" "" tenant-test)"
|
|
echo "$out" | grep -q 'no pods in tenant-test'
|
|
# An empty result is an answer, not a failure: saying FAILED here would
|
|
# report a healthy empty namespace as an unreachable apiserver.
|
|
#
|
|
# Counted rather than written `! ... | grep -q`: POSIX exempts a command
|
|
# whose status is inverted with `!` from `set -e`, so that form cannot fail
|
|
# a test here -- it would pass whatever the output said.
|
|
[ "$(echo "$out" | grep -c 'FAILED')" -eq 0 ]
|
|
}
|
|
|
|
@test "census says the lookup did not run and does not call it no pods" {
|
|
out="$(pod_label_census_report 1 "" "Unable to connect to the server" tenant-test)"
|
|
echo "$out" | grep -q 'FAILED'
|
|
echo "$out" | grep -q 'Unable to connect to the server'
|
|
# The distinction this whole helper exists for: a lookup that never
|
|
# returned must not be reported as an empty namespace. Counted, not
|
|
# `! ... | grep -q`, for the reason given in the empty-result test above.
|
|
#
|
|
# Matched on the empty-result sentence rather than on "no pods": the FAILED
|
|
# line quotes that phrase itself, to say what it is not.
|
|
[ "$(echo "$out" | grep -c 'no pods in')" -eq 0 ]
|
|
}
|
|
|
|
@test "census keeps a zero exit with a klog line out of the rows" {
|
|
klog='E0805 memcache.go:265 Unhandled Error: couldnt get API group list'
|
|
out="$(pod_label_census_report 0 "" "$klog" tenant-test)"
|
|
# The regression: with the streams folded together this printed the klog
|
|
# line under the census heading, as if the API error were a pod.
|
|
echo "$out" | grep -q 'no pods in tenant-test'
|
|
echo "$out" | grep -q 'may be partial'
|
|
echo "$out" | grep -q 'memcache.go'
|
|
}
|
|
|
|
@test "census marks rows as possibly partial when kubectl also logged an error" {
|
|
klog='E0805 memcache.go:265 Unhandled Error: couldnt get API group list'
|
|
out="$(pod_label_census_report 0 "pod-a harbor-test-system" "$klog" tenant-test)"
|
|
echo "$out" | grep -q 'pod-a harbor-test-system'
|
|
echo "$out" | grep -q 'may be partial'
|
|
}
|
|
|
|
@test "shared report keeps the three outcomes apart for the cleanup wording too" {
|
|
# The qdrant cleanup catch feeds the same helper with its own messages, so
|
|
# the discrimination is tested once and used twice rather than living
|
|
# inline in YAML where nothing can pin it.
|
|
failed="cleanup lookup FAILED"
|
|
empty="matched no objects"
|
|
heading="cleanup objects still present:"
|
|
|
|
out="$(lookup_report 1 "" "Unable to connect to the server" "$failed" "$empty" "$heading")"
|
|
echo "$out" | grep -q 'cleanup lookup FAILED'
|
|
# A lookup that never ran must not read as "nothing left to clean up".
|
|
[ "$(echo "$out" | grep -c 'matched no objects')" -eq 0 ]
|
|
|
|
out="$(lookup_report 0 "" "" "$failed" "$empty" "$heading")"
|
|
echo "$out" | grep -q 'matched no objects'
|
|
|
|
out="$(lookup_report 0 "job.batch/qdrant-test-qdrant-cleanup" "" "$failed" "$empty" "$heading")"
|
|
echo "$out" | grep -q 'cleanup objects still present'
|
|
echo "$out" | grep -q 'job.batch/qdrant-test-qdrant-cleanup'
|
|
}
|
|
|
|
@test "shared report flags a zero exit with stderr as possibly partial for any wording" {
|
|
klog='E0805 memcache.go:265 Unhandled Error'
|
|
out="$(lookup_report 0 "" "$klog" "FAILED-MSG" "EMPTY-MSG" "ROWS-MSG")"
|
|
# Same regression as the census case: folded into the value this klog line
|
|
# would suppress the empty branch and print as though it were a result.
|
|
echo "$out" | grep -q 'EMPTY-MSG'
|
|
echo "$out" | grep -q 'may be partial'
|
|
[ "$(echo "$out" | grep -c 'ROWS-MSG')" -eq 0 ]
|
|
}
|
|
|
|
@test "census driven through a kubectl stub keeps stderr out of the value" {
|
|
stubdir="$(mktemp -d)"
|
|
printf '#!/bin/sh\necho "E0805 memcache.go:265 Unhandled Error" >&2\nexit 0\n' \
|
|
> "$stubdir/kubectl"
|
|
chmod +x "$stubdir/kubectl"
|
|
out="$(PATH="$stubdir:$PATH" pod_label_census tenant-test)"
|
|
rm -rf "$stubdir"
|
|
# End to end: kubectl exited 0 and wrote only to stderr, so the namespace
|
|
# really is empty and the klog line is a caveat, not a row.
|
|
echo "$out" | grep -q 'no pods in tenant-test'
|
|
echo "$out" | grep -q 'may be partial'
|
|
}
|
|
|
|
@test "census returns zero even when the lookup failed so a catch cannot mask the real error" {
|
|
stubdir="$(mktemp -d)"
|
|
printf '#!/bin/sh\necho "Unable to connect to the server" >&2\nexit 1\n' \
|
|
> "$stubdir/kubectl"
|
|
chmod +x "$stubdir/kubectl"
|
|
# The call goes in the `if` condition, not on a line of its own: these
|
|
# tests run under `set -e`, which exempts a condition but would abort the
|
|
# test before a following `rc=$?` could ever read a non-zero. Read after
|
|
# the fact, that assertion could only ever see 0 and would pass whatever
|
|
# the function returned.
|
|
if PATH="$stubdir:$PATH" pod_label_census tenant-test > /dev/null; then
|
|
rc=0
|
|
else
|
|
rc=1
|
|
fi
|
|
rm -rf "$stubdir"
|
|
[ "$rc" -eq 0 ]
|
|
}
|