Files
cozystack/hack/test_helper.bash
Myasnikov Daniil 9f875e7874 test(hack): restore set -u and refresh the cozytest-era headers
The layer below moved the unit suite to bats(1), which enforces `set -e`
but not `set -u`. cozytest.sh ran every test body under `set -eu -x`, so
without this a test that reads an unset variable silently sees an empty
string and passes.

There is no runner-level way to inject it, which is why this needs a
per-file load rather than a Makefile flag. Two mechanisms were measured and
rejected: a setup() defined in --setup-suite-file does not reach test files
at all, and SHELLOPTS=nounset does reach them but is exported, so it also
applies to the hack/*.sh scripts the tests exercise as subprocesses --
changing the behaviour of the code under test rather than the tests, and
dropping two tests outright. `set -u` inside setup() is a shell option
rather than an exported one, so it stays scoped to the test body.

hack/test_helper.bash therefore defines the shared setup(), and all 32 unit
files load it. The restoration is mutation-checked, not assumed: a canary
test reading an unset variable aborts with "unbound variable" with the load
in place and passes vacuously without it. Suite is 328/328 green either
way, so nothing in the tree was relying on the laxer behaviour.

The headers are the other half. 27 of the 32 files documented the cozytest
contract in prose -- "there is no bats `run` or `$status`",
"setup()/teardown() are not honored", "Run with: hack/cozytest.sh ...",
title-sanitization rules from the awk parser, and instructions to keep `}`
off column 0 so the parser would not truncate a test. Every one of those
statements is now false or vacuous, and a false comment about the harness
is worse than none: the next author reads "setup() is not honored" and
hand-rolls per-test cleanup that the runner would have done.

Where a constraint merely stopped binding rather than reversing, the
comment says so instead of deleting the line -- the column-0 heredoc
indentation and the manual status capture in migration-seaweedfs-db-adopt
are both kept, now marked belt-and-braces. Claims that survived the move
are left alone: `! cmd` really is still vacuous under `set -e`, since bash
suppresses errexit for a negated command exactly as dash did.

hack/seaweedfs-naming-audit.bats gains a note that its subject is POSIX sh
executed by /bin/sh but sourced into bats' bash, so shellcheck's shell=sh
directive is now the only thing guarding that gap.

Refs: #3453
Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com>
2026-07-31 12:09:12 +05:00

26 lines
1.1 KiB
Bash

# Shared setup for the hack/*.bats unit suite.
#
# Bats enforces `set -e` on a test body but does not enable `set -u`, while
# hack/cozytest.sh -- the runner this suite used before #3453 -- ran every
# body under `set -eu -x`. Without this file a test that reads an unset
# variable silently sees an empty string and passes, which is the one
# strictness property the move to bats would otherwise drop.
#
# `set -u` here is deliberately scoped to the test body. It is a shell
# option, not an exported one, so it does not reach the hack/*.sh scripts
# the tests exercise as subprocesses. Exporting it instead (SHELLOPTS=nounset
# in the environment) does propagate, changes the behaviour of the scripts
# under test rather than the tests themselves, and was measured to break the
# suite -- so it is not an alternative to loading this file.
#
# A test file that needs its own fixture setup must call `strict_setup`
# from its `setup()` rather than relying on the definition below, since a
# later `setup()` in the file silently replaces this one.
strict_setup() {
set -u
}
setup() {
strict_setup
}