Skip to content

CBOR: Remove useless alloc in Rust tests, add iterator tests#285

Merged
tahina-pro merged 2 commits into
project-everest:masterfrom
tahina-pro:_taramana_cbor_test
May 14, 2026
Merged

CBOR: Remove useless alloc in Rust tests, add iterator tests#285
tahina-pro merged 2 commits into
project-everest:masterfrom
tahina-pro:_taramana_cbor_test

Conversation

@tahina-pro

Copy link
Copy Markdown
Member

No description provided.

tahina-pro and others added 2 commits May 14, 2026 20:23
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>
@tahina-pro tahina-pro force-pushed the _taramana_cbor_test branch from 9e457f8 to 855fae7 Compare May 14, 2026 20:23
@tahina-pro tahina-pro merged commit 739f5db into project-everest:master May 14, 2026
17 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant