CBOR: Remove useless alloc in Rust tests, add iterator tests#285
Merged
tahina-pro merged 2 commits intoMay 14, 2026
Conversation
Brings the Rust integration test suite into line with the C suite's
"malloc only where strictly necessary" model. Three classes of change,
applied uniformly to both tests/det.rs and tests/nondet.rs:
1. Unroll the two deeply-nested fixtures with a local macro_rules!
instead of looping with a per-iteration `Box::leak`.
`arr_deeply_nested_canonical` (DEPTH=30) and `map_deeply_nested_canonical`
(DEPTH=10) used to walk a `for _ in 0..DEPTH` loop, each iteration
leaking a one-element slice to satisfy the constructor signature
`cbor_*_mk_array<'a>(&'a [CborDet<'a>])` (which forces every level's
storage to outlive the returned value). The new `arr_wrap!` /
`map_wrap!` macros consume one `()` token per level and emit one
fresh `let items = [current]; let current = mk(&items).unwrap();`
pair per token. Macro hygiene gives every expansion its own distinct
`items` binding, so the N intermediate stack arrays nest naturally
in lifetime (`'i1 ⊇ … ⊇ 'iN`) — structurally analogous to the C
suite's single stack buffer `cbor_t levels[31]`.
Const generics alone can't do this: Rust has no syntax for
parameterising the *number of distinct lifetimes* in a signature;
the macro is the smallest construct that supplies N independent
lifetime quantifiers driven by a compile-time constant.
2. Convert 14 single-scope `leak_arr` / `leak_entries` call sites to
stack-local arrays. These never needed heap promotion in the first
place — the original author defaulted to the leak helper everywhere
even when one enclosing function scope could already hold the
backing storage. Affected tests:
- map_empty_canonical: 1 site
- arr_empties_canonical: 3 sites (three independent empty
maps; each needs its own `&mut`
backing array because mk_map's
returned value formally borrows
the slice)
- map_nested_keys_canonical: 2 sites (pair1, pair2)
- tag_array_payload_canonical: 1 site
Empty-entry arrays are annotated as `[CborDetMapEntry<'_>; 0]` so
Rust infers the lifetime per call. Non-empty arrays infer everything.
3. Convert two `Box::leak(Box::new(...))` chains in
`tag_nested_canonical` to three stack locals. Works because
`CborDet<'a>` is covariant in `'a`, so the chain
`'leaf ⊇ 'mid ⊇ 'expected` typechecks naturally; one
coupled `Box::leak` in tag_array_payload_canonical is removed
on the same grounds.
Remaining heap leaks (kept as strictly necessary):
- arr_2200_deep_canonical (det+nondet) — 2200-deep loop;
unrolling would emit 2200 lines per test.
- dnm recursive helper inside map_nested_keys_canonical (det+nondet)
— returns `CborDet<'static>` from a recursive function; eliminating
requires CPS or an arena.
The leak_arr / leak_entries helper definitions stay in both files
(still used by the four sites above); no dead-code warnings.
Verified: full Rust test suite (352 det + 352 nondet = 704 tests)
passes with `cargo test --release` against the existing C-emitted
artefacts in share/everparse/tests/cbor/out/. No new warnings.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Adds iterator-API coverage to share/everparse/tests/cbor/. Until now,
no test exercised cbor_*_array_iterator_* / cbor_*_map_iterator_*; all
walks went through random-access accessors.
New approach: 'parallel walk' — walk parsed via the iterator API,
walk expected via random access (get_array_item / map_get / get_tagged),
compare scalars at every leaf. No reconstruction, so no extra heap or
lifetime hassles; same recursion budget as cbor_*_equal.
Added iter variants for 9 representative existing fixtures and one new
wide-and-deep fixture, in all three languages and both APIs:
* arr_25_iter_canonical wide array of uints
* arr_nested_iter_canonical heterogeneous nesting
* arr_deeply_nested_iter_canonical singleton chain depth 30
* arr_empties_iter_canonical mixed empty arrays/maps/tags
* map_five_iter_canonical 5-entry map
* map_deeply_nested_iter_canonical singleton chain depth 10
* map_nested_keys_iter_canonical nested-map keys
* tag_nested_iter_canonical tag(1234, tag(5678, 1))
* tag_array_payload_iter_canonical tag(99, [1,2,3])
* arr_wide_deep_canonical (new) [[1..3],[4..6],[7..9],[10..12]]
* arr_wide_deep_iter_canonical iterator variant of the above
Per-language details:
C : new cbor_v_arr_iter_* / cbor_v_map_iter_* wrappers unify
the by-value det API and the bool+out nondet API; added
walk_iter_check + run_iter_walk; 11 new test functions
registered in TESTS[].
Python : cbor2 has no separate iterator API, so iter()/items() on
the decoded value is the equivalent surface; added
walk_iter_check_py + a kind="iterator" branch in _run_one;
11 catalogue entries.
Rust : added walk_iter_check<'a> in tests/det.rs and tests/nondet.rs
using the existing IntoIterator impls; 11 new #[test] fns
in each file. The depth-30 / depth-10 / nested-keys
variants reuse the arr_wrap! / map_wrap! macros and the
dnm() helper introduced in the prior cleanup, so still no
new uses of leak_*.
Results:
C det 363/363 PASS, C nondet 363/363 PASS
Python 724 passed, 0 failed, 2 skipped (allow_duplicate_keys)
Rust det 363/363 PASS, Rust nondet 363/363 PASS
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
9e457f8 to
855fae7
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.
No description provided.