test: add codegen fidelity tests for generated structs - #347
Conversation
|
Thanks — I verified this before replying, and the My hesitation is about where the tests live. The regressions these catch are all The version I'd want drives That said, not all of this churns. What actually caught the #345 regression is Would you be up for trimming to that core? Keep the NSID and associated-type One nit either way: |
`cargo build` does not compile the test target, so nothing catches codegen dropping a `Collection` impl. atrium-rs#345 fixed exactly that: `app.bsky.actor. contentVisibilityDeclaration` is the first record whose NSID leaf is camelCase, and the NSID was rebuilt from the snake_case'd file stem, so the record never matched its own schema and got no `Collection` impl. `KnownRecord` is keyed on schema ids, so it *did* gain the variant, leaving downstream crates with an arm they could not satisfy. Two assertions, neither coupled to lexicon contents: - Naming `ContentVisibilityDeclaration::NSID` requires the `Collection` impl to exist; comparing it against the literal requires it to carry the NSID verbatim rather than a mangled form. - A never-called function taking `<ContentVisibilityDeclaration as Collection>::Record` and returning the corresponding `KnownRecord` variant asserts at compile time that the two halves agree on the record type. Drifting the associated type fails to build here while the NSID assertions still pass, so this catches a case the runtime checks cannot. Verified by reintroducing the atrium-rs#345 breakage against the current tree: deleting the `Collection` impl fails the test target to compile, as does pointing its `Record` at a different record type. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
832c7f1 to
6596489
Compare
|
Trimmed, and dropped the dev-dependency — you're right that it's already an On placement: agreed, and the case I couldn't answer for is a required field I went slightly further than you asked, because the actor test still had a #[allow(dead_code)]
fn collection_record_is_the_known_record_payload(
record: <ContentVisibilityDeclaration as Collection>::Record,
) -> KnownRecord {
KnownRecord::AppBskyActorContentVisibilityDeclaration(Box::new(record))
}That keeps the half of the I reintroduced both breakages against the current tree rather than assuming:
Result is 39 lines in one file, no payload, Happy to leave |
Stacked on #346 — based on
update/lexicon-5c3b7c9c8so the diff stays at two files rather than pulling in the whole regeneration. Happy to retarget tomainonce #346 lands (GitHub should do it automatically). The tests reference types that only exist after the regen, which is why they can't be based onmaintoday.Why
cargo builddoesn't compile the test target, so it can't catch a regeneration breaking hand-written fixtures or silently dropping a field. #346's own catch-up commit ("New required fields in test fixtures across atrium-api, bsky-sdk and bsky-cli") is exactly the class of breakage that stays invisible until someone runs the tests — so it seemed worth having a gate that fails loudly at regen time.What it asserts
Each case checks three invariants against a lexicon-shaped payload:
Object::extra_datastays empty.Invariant 2 is the one that does the real work. Round-trip alone isn't sufficient, because
extra_dataround-trips unknown fields too — a dropped field falls through toextra_datarather than failing to compile, so the payload still survives a round trip and the regression passes unnoticed. A field is only proven typed when it's both reachable as a struct field and absent fromextra_data.Coverage
chat.bsky.convo.defs#messageView/#messageInputreplyTo, including the recursive union variant resolving rather than falling intoUnion::Unknowntools.ozone.report.queryActivitiesapp.bsky.actor.contentVisibilityDeclarationThe last one guards the camelCase record NSID case fixed in #345. Referring to the record through
<ContentVisibilityDeclaration as Collection>::Recordturns a missingCollectionimpl back into a compile error, and the assertions catch theCollectionimpl and theKnownRecordvariant disagreeing on the NSID or the record type — the specific mismatch that left downstream crates with aKnownRecordarm they couldn't satisfy.Notes
--all-features.serde_jsonas anatrium-apidev-dependency.cargo fmt-no-gen --checkclean;cargo clippy -p atrium-api --all-features --all-targetsclean under-D warnings.🤖 Generated with Claude Code