A released schema version is frozen, so its values stop tracking the
parsers that read them. Tighten bees_parse_size and a literal written for
an earlier release can quietly stop being accepted, with nothing to notice
until a daemon that pinned that version fails to start -- on whichever
option happened to be read first, which says nothing about the real
problem. Chaining guarantees an option is present; it says nothing about
whether the value is still valid.
Check both properties for every registered version. Every option any
version defines has to resolve from every version, and every value has to
parse as the kind that option is declared to have.
Kinds are keyed by option name, since an option means the same thing in
each section it appears in, with full section.key overriding the two
places that is not true. The table has to be exhaustive: an option
without a kind fails the test rather than going unchecked, because
coverage that shrinks silently is worse than none.
Substitution variables are resolved against the filesystem at startup and
a unit test has none, so the test substitutes stand-in values instead of
skipping those options. They are the most complex expressions in the
schema -- state.hash.size and thread.thread-max among them -- and are
exactly the ones worth parsing.
config-parse now links the version objects; without them nothing is
registered and the test would pass while checking nothing.
BeesConfig::registered_versions() exposes the list, so the test covers
whatever a build registers rather than a copy of it that can drift.
Verified by mutation: misclassifying an option's kind, or dropping one
from the table, each fail with the version, option and value named.