Repository navigation
A negated command only asserts in final position, and one that could never pass - #16
Merged
Merged
Conversation
`! cmd` on its own line asserts nothing in a bats body unless it happens to
be the last command of that body: bash does not apply errexit to a negated
command, so the verdict is the exit status of the final command and every
earlier `! cmd` is inert. shellcheck names the class SC2314 and grades the
two cases apart, error for the inert ones and note for the rest.
Six negations here were inert, and all six are about trusting a proxy:
- nginx.bats, the shipped conf.d default: it trusts nobody and it never
matches geo on `$remote_addr`. Two of the four assertions ran.
- nodebb.bats, `nodebb_valid_proxy`: `"2001:db8::13; }"`, the value that
would close the geo block and append directives of its own, was the inert
one. Only `hello` decided anything.
- nodebb.bats, the rendered file: that geo is on `$realip_remote_addr` and
never on `$remote_addr`, which is the redirect loop the file's own comment
warns about, and that no address means no trust.
All of them become `run !`, together with the eight that were in final
position and did assert, because a line whose meaning depends on its
position is the trap itself.
Turning one on found a second bug in the same test. "proxy_conf without an
address trusts nobody" asserted `! grep -q set_real_ip_from`, unanchored,
against a file whose own comment explains the directive:
# that is not a detail. This same file sets set_real_ip_from with
So that assertion could never have held, for any input, and nobody could
know because it never ran. It is anchored now, `^set_real_ip_from`, which is
the property meant and the spelling the positive case at line 167 already
used. The rendered file is right; only the assertion was wrong.
Two tests also needed the rendered file kept in a local before the
refutations: `run` replaces `$output`, so a second `run` reading
`<<< "$output"` reads the first refutation's empty output and passes
vacuously, which is the same defect in a new shape.
Suite green, 134 tests. Coverage unchanged, threshold 95:
zz-project-packages 100.00, nodebb.sh 100.00, 40nodebb 96.97,
boot-test-lib.sh 100.00, keel-archive-check 100.00.
Contributor
Author
|
Reviewed: every converted refutation goes red when its property is broken; emitting set_real_ip_from with no trusted address fails the anchored check. None reads the output of the run it replaced. No changes needed; merged main so the renamed appliance check runs on this head. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Every negation in these suites now asserts wherever it stands. Six did not assert at all — and turning one on found a second bug in the same test.
Closes #15. Part of Keel-Linux/tracker#19, which has the organization-wide sweep.
Why a bare
!is inertA bats test body has no assertions of its own: its verdict is the exit status of the last command it ran. Bash does not apply errexit to a negated command, so
! cmddecides the test in final position and is inert everywhere else. shellcheck grades the two apart,error:for the inert ones andnote:for the rest:What was not being checked
All six are about trusting a proxy.
conf.ddefault trusts nobody, and that it never matchesgeoon$remote_addr. Two of those four assertions ran.nodebb_valid_proxy "2001:db8::13; }"— the value that would close thegeoblock and append directives of its own. The injection case. Onlyhellodecided anything.geois on$realip_remote_addrand never on$remote_addr— the redirect loop the file's own comment warns about at length.All of them are
run !now, together with the eight that were in final position and did assert: a line whose meaning depends on its position is the trap itself.The bug this found
nodebb.bats, "proxy_conf without an address trusts nobody", asserted:Unanchored — against a file whose own explanatory comment names the directive:
So that assertion could never have held, for any input, and nobody could know, because nothing ever ran it. It is anchored now:
which is the property that was meant, and the spelling the positive case at line 167 already used (
^set_real_ip_from 2001:db8::13;$). The rendered file is correct — with no address it emits noset_real_ip_fromdirective. Only the assertion was wrong, so nothing shipped broken.A second shape of the same defect
runreplaces$output,$statusand$lines. Two tests here dorun nodebb_proxy_conf …and then grep<<< "$output"several times; once the first of those becomes arun !, the next one greps the refutation's empty output and passes for a new reason. Both tests now keep the rendered file in a local first:That was caught by an audit over every converted site, not by the suite — the vacuous pass is green by construction. It is written up in the
docs/traps.mdentry that goes with this sweep.What else was verified
The shipped
overlay/etc/nginx/conf.d/nodebb-proxy.confand the rendered output were both read directly, andnodebb_valid_proxywas run against all five of its cases by hand, before the conversion. Everything except the assertion above is correct.Test plan
The validator's five cases and both rendered files verified by hand, before the conversion.
shellcheck -f gcc --shell=bash --severity=error --include=SC2314 tests/*.batsreports nothing.Every converted site audited for
runclobbering$output/$status/$lines; the two real cases fixed.bats tests/*.batsgreen, 134 tests.tests/coverage.sh, threshold 95, unchanged:Tests ship nothing, so
package / changelogpasses by reporting that nothing that ships changed. No changelog entry and no version bump.