test(vetting): a golden reference table is const, and read with .at() - #424
Open
darkclad wants to merge 3 commits into
Open
test(vetting): a golden reference table is const, and read with .at()#424darkclad wants to merge 3 commits into
darkclad wants to merge 3 commits into
Conversation
darkclad
force-pushed
the
main-ref-vals-const
branch
from
August 14, 2026 14:31
12721ca to
e217330
Compare
added 3 commits
August 14, 2026 08:24
… 2D remaining fixture The sweep that moved this header's reference tables out to the files whose assertions read them left three comment blocks behind describing tables that are no longer here, and <gtest/gtest.h> and <string> with nothing using them -- the header asserts nothing, it only builds ROIs, and the five files that include it bring gtest in themselves. Same cleanup test_2d_neighbor_common.h got; this file had emptied out after that fix landed. The ellipse-fixture rationale moves down beside the builder it describes, since its "the fixture above" reference no longer pointed at anything.
…th .at() 58 of the 69 tables were declared without const, and 55 read sites reached them through operator[]. On a missing key operator[] default-inserts 0 rather than failing, so the assertion compares against a golden that does not exist -- and agrees_gt derives its tolerance from the golden, so a golden of 0 gives a tolerance of 0 and the assertion passes whenever the computed value is also exactly 0. That is the case a golden table exists to catch: a feature that silently produced nothing. The inserted key then persists for the rest of the run, so a later .count() guard on it succeeds too. const makes operator[] a compile error and forces .at(), which throws naming the key it could not find. Every site that needed changing surfaced as a build error rather than as a silent change in behaviour. The two neighbour oracle files called .at(label) inside their own presence guard, so an absent label threw instead of asserting; they now guard the label first, as the regression file already did.
The const rule is only worth as much as its enforcement, so check_test_names.py now rejects a reference table declared mutable, alongside the raw-container and _common.h rules. The self-test plants a table whose name, location and type all conform, leaving mutability as its only defect, and asserts the rule does not fire on a const table -- a rule that flags everything is as useless as one that flags nothing. SPEC 6.3.1 and test_ref_vals.h record the rule and why operator[] on a reference table is a correctness problem rather than a style one.
darkclad
force-pushed
the
main-ref-vals-const
branch
from
August 14, 2026 16:01
e217330 to
bdf80aa
Compare
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.
53 files, all under
tests/. Nosrc/nyxchange.Follow-up to #422, which gave every golden table one name, one location and one declaration type.
This adds the property those three could not express: the table is read-only data, and saying so
in the type closes a way for an assertion to pass against a golden that does not exist.
The defect
53 of the 61 reference tables were declared without
const, and 54 read sites reached them throughoperator[]:On a key the table does not hold,
operator[]default-inserts 0 rather than failing. Theassertion then compares against a golden that was never written down — and
agrees_gtderives itsband from the golden:
So a golden of 0 passes exactly when the computed value is also 0. That is not an unreachable
corner: "the feature was not computed and returned 0" is one of the specific failures a golden
table exists to catch, and in that combination the test goes green against a reference that isn't
there. The inserted key also persists for the rest of the run, so a later
.count()guard on thesame key succeeds too.
Same class the #422 review kept surfacing — an assertion that cannot fail on the thing it claims to
check — reached through the container's API instead of through naming or file layout.
The change
conston all 61 tables,.at()at the 54 read sites.operator[]does not exist on aconstmap, so every site needing attention arrived as a compile error, not as a silent change in
behaviour — which is what makes a sweep this wide safe to do mechanically. A missing key now throws
naming the key instead of inventing a zero.
Worth noting for reviewers weighing risk: the first pass keyed the rewrite on table names, and the
compiler caught the two
_ref_tolstolerance tables it missed. The second pass is driven off thedeclarations, so the set is closed by type rather than by spelling.
Two neighbour oracle files guarded a key they had already indexed.
test_2d_neighbor_analytic.hand
test_2d_neighbor_cellprofiler.hwrote..._ref_vals_by_label.at(label).count(feature_name) > 0, so an absent label threw out of.at()with no context rather than failing the assertion. They now guard the label first, as
test_2d_neighbor_regression.halready did.Enforced.
check_test_names.pyrejects a reference table declared withoutconst, beside theexisting raw-container and
_common.hrules. The self-test plants a table whose name, location andtype all conform so that mutability is its only defect, and asserts the rule does not fire on a
consttable — a rule that flags everything is as useless as one that flags nothing. SPEC §6.3.1 andtest_ref_vals.hrecord the rule and why this is a correctness problem rather than a style one.One cleanup that belonged with it.
test_2d_remaining_common.hemptied out when its tables movedto their assertions, and the sweep left
<gtest/gtest.h>and<string>unused plus three commentblocks describing tables no longer in the file. Same fix
test_2d_neighbor_common.hgot in #422; thisfile had emptied after that landed.
What this did and did not find
No existing assertion was wrong. Every test passes, and nothing threw from
.at(), so no test inthe tree was relying on a default-inserted key today. The change closes the hole prospectively and
makes reopening it a build failure; it did not uncover a live bad assertion.
Verification
mechanics tests, absent from a
NOEXTRAS=ONbuild-fsanitize=address,undefined -fno-sanitize-recover=undefined, RelWithDebInfo, gcc); 113 s vs 22 s uninstrumented, so theinstrumentation was live
pytest tests/python/: 85 passed / 1 skipped (7 pre-existing Arrow failures of a tiff-only build)check_test_names.py --checkandcheck_coverage.py --checkclean on both platforms; 61 tablesinspected, 0 raw, 0 non-const, 0 in a
_common.h; vetting self-tests 7/7 with the new casetests/— nosrc/nyxchangegit diff --shortstatand--ignore-all-space --shortstatagree, so nowhitespace-only churn
Commits
test(vetting): drop unused includes and stale table comments from the 2D remaining fixturetest(vetting): make every golden reference table const and read it with .at()test(vetting): reject a golden reference table declared without constNot in this PR
The
constexprform asked for in #422 review.std::unordered_mapwithstd::stringkeysallocates, so the compile-time shape is
constexpr std::array<std::pair<std::string_view, double>, N>with aconstexpraccessor. Thepayoff usually claimed for it — a mistyped key caught at build time — is not available while keys
arrive as runtime
std::stringparameters into the sharedassert_*helpers, and after this PR itchanges no behaviour. Recorded as optional follow-up rather than dropped.