test(protocol): make the cyclic all() prove it reaches every variant (improvise-5ubs)
AppMode::all() and Rejection::all() walk a total cyclic after(), and both doc comments claimed a new variant could not be omitted. Half true, wrong half: answering after() FOR a new variant is compiler-forced, pointing an existing arm AT it is not, so a variant nothing names is never walked -- measured by the PR #78 reviewer as all().len() == 17 against 18 variants, suite green. Closing it needs an enumeration independent of after(). Stable Rust has none for an enum with data -- variant_count is nightly, a derive macro is a new proc-macro crate, and strum's EnumIter cannot construct AppMode::ItemAdd or Editing at all. serde can: the Deserialize derive already builds the complete variant-name list from the enum definition and publishes it in its "unknown variant ... expected one of ..." message. variants.rs reads that back and diffs it against the names the cycle reached, each taken off the variant's own serialization rather than off Debug. The helper is defensive because an unparsed message would return an empty list, and an empty list passes every cycle; a should_panic test points it at a struct and asserts the message, not merely that it panics. Both overclaiming doc comments replaced. The fourth instance of this shape -- assert_eq!(cases.len(), 13) in ui/effect.rs -- is over a hand-built list of effects rather than enum variants, so serde has nothing to say about it; left filed rather than bodged. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FC2jVn8Au7E9JPkw6bwXXH
This commit is contained in:
@@ -462,3 +462,39 @@ against an enum that really did have the variant.
|
||||
|
||||
Proved discriminating by re-adding the variant with an empty `apply` arm: the
|
||||
retired spelling parses again and the test fails on `expect_err`.
|
||||
|
||||
|
||||
### boundary_tests::the_app_mode_cycle_reaches_every_variant_serde_declares
|
||||
|
||||
### basis::tests::the_rejection_cycle_reaches_every_variant_serde_declares
|
||||
|
||||
improvise-5ubs. Both `all()` functions walk a cyclic `after()`, and both doc
|
||||
comments claimed a new variant could not be omitted. Answering `after()` for a
|
||||
new variant is compiler-forced; pointing an existing arm at it is not, so a
|
||||
variant nothing names is never walked. The reviewer of PR #78 measured it:
|
||||
`AppMode::all().len()` came back 17 against 18 variants, suite green.
|
||||
|
||||
The independent enumeration is serde's — the `Deserialize` derive builds the
|
||||
variant-name list from the enum definition and publishes it in its
|
||||
`unknown variant ... expected one of ...` message. `variants.rs` reads it back
|
||||
and diffs it against the names the cycle reached, each name taken off the
|
||||
variant's own serialization rather than off `Debug`.
|
||||
|
||||
Fault injected 2026-09-21: a `Rejection::Probe` variant added to the enum, with
|
||||
an `after()` arm returning `DocumentReplaced` and **nothing pointing at it** —
|
||||
precisely the shape the reviewer probed. `the_rejection_cycle_reaches_every_variant_serde_declares`
|
||||
fails naming `["Probe"]`; the other 120 tests in `improvise-protocol`'s lib pass,
|
||||
including `the_rejection_cycle` half of every basis test. (The workspace does not
|
||||
compile with the probe, because `improvise-wasm-client/src/socket.rs` matches
|
||||
`Rejection` exhaustively — which is a *different* guard and does not catch the
|
||||
omission, since the omitted variant there is one it was forced to name.)
|
||||
|
||||
### variants::tests::a_message_that_is_not_an_unknown_variant_is_refused
|
||||
|
||||
The checker's own checker. A parse of serde's message that silently fails would
|
||||
return an empty name list, and an empty list is a subset of everything — every
|
||||
cycle would pass and the guard would be worse than absent. Pointing `declared`
|
||||
at `Basis`, a struct, produces a message with no `expected one of` clause; the
|
||||
helper must panic rather than return. Asserting the panic *message* and not
|
||||
merely that it panics, because a helper that panicked for some other reason
|
||||
would satisfy a bare `should_panic`.
|
||||
|
||||
Reference in New Issue
Block a user