Problem
The #[contract] macro's test surface has a structural gap. Today's layers:
| Layer |
Coverage |
Unit tests in src/ modules |
Pure-Rust helpers — extract::*, validate::*, resolve::*. No macro expansion involved. |
tests/compile_fail.rs + tests/compile-fail/ |
A handful of trybuild fixtures asserting invalid inputs are rejected. |
tests/test-contract/ |
One reference contract that exercises the macro end-to-end into a WASM build. |
What's missing is "this attribute combination expands and compiles" coverage of variations. The single test-contract pins one fixed shape; the compile-fail bench is sparse relative to the dozens of validation paths in validate.rs. There is no compile-pass harness at all.
Recent macro-internal refactors have shown that validator unit tests aren't sufficient: a validate.rs change can leave the validation function happy while the downstream generate.rs chokes on the resulting IR. That regression class needs a dedicated guard.
Proposal
Build out the test-harness layer:
- Reorganize existing compile-fail fixtures under topic dirs (
directives/, feature_gates/, methods/, traits/, events/).
- Add one compile-fail fixture per rejection rule in
validate.rs, with a // Pins: <rule-id> header tying each fixture back to the reject branch it guards.
- Add a compile-pass harness covering valid contract shapes that the reference
test-contract does not exercise (e.g. new() -> ContractName instead of -> Self, contracts without an init method, init(&mut self) with no parameters).
- Document the topic taxonomy and fixture conventions in
tests/README.md so contributors adding a rule know where the fixture goes and what header it needs.
Out of scope
- Changes to
validate.rs itself. If a rule is broken, unreachable, or duplicated, that's a separate issue.
- Changes to
tests/test-contract/ (the reference contract stays as-is).
macrotest-style token-stream drift detection. The existing make expand / make expand-dd baselines already cover that for the single test-contract shape; a parameterised version is deferrable.
Problem
The
#[contract]macro's test surface has a structural gap. Today's layers:src/modulesextract::*,validate::*,resolve::*. No macro expansion involved.tests/compile_fail.rs+tests/compile-fail/tests/test-contract/What's missing is "this attribute combination expands and compiles" coverage of variations. The single test-contract pins one fixed shape; the compile-fail bench is sparse relative to the dozens of validation paths in
validate.rs. There is no compile-pass harness at all.Recent macro-internal refactors have shown that validator unit tests aren't sufficient: a
validate.rschange can leave the validation function happy while the downstreamgenerate.rschokes on the resulting IR. That regression class needs a dedicated guard.Proposal
Build out the test-harness layer:
directives/,feature_gates/,methods/,traits/,events/).validate.rs, with a// Pins: <rule-id>header tying each fixture back to the reject branch it guards.test-contractdoes not exercise (e.g.new() -> ContractNameinstead of-> Self, contracts without aninitmethod,init(&mut self)with no parameters).tests/README.mdso contributors adding a rule know where the fixture goes and what header it needs.Out of scope
validate.rsitself. If a rule is broken, unreachable, or duplicated, that's a separate issue.tests/test-contract/(the reference contract stays as-is).macrotest-style token-stream drift detection. The existingmake expand/make expand-ddbaselines already cover that for the single test-contract shape; a parameterised version is deferrable.