# Test Matrix
Every test in the repository has a row here. The component sections cover the
unit tests inside [`src/`](../src/), one component per section;
[Integration Suites](#integration-suites) covers the test binaries under
[`tests/`](../tests/), one subsection per binary. Each row carries the test's
name, the property it holds, and what it actually does — geometries, seeds,
sample counts and the exact asserted numbers.
A test generated by a `macro_rules!` matrix shares its body with its siblings,
so those get **one row per family**: the name column carries the family's shape
(`countmin_input_{1..12}_grid_satisfies_the_count_min_model`) and the third
column enumerates every generated name with the parameter it was invoked with.
## How To Run
```bash
cargo test
```
Two feature gates hide tests from that command: `tests/e2e_experimental.rs` and
scattered `#[cfg(feature = "experimental")]` tests need
`cargo test --features experimental`, and the `runtime_tests` module in
`src/sketch_framework/octo.rs` needs `cargo test --features octo-runtime`.
## Sketches
### CountMin
Test file: [`src/sketches/countminsketch.rs`](../src/sketches/countminsketch.rs)
Wire tests: [`src/sketches/countminsketch/wire.rs`](../src/sketches/countminsketch/wire.rs)
| test_name | test_description | what_is_tested |
| --- | --- | --- |
| `dimension_test` | Default/custom dimensions initialize zeroed counters. | Verifies default dimensions (`rows=3`, `cols=4096`), custom dimensions (`3x17`), and zero-initialized counters after construction. |
| `fast_insert_same_estimate` | Fast and regular insert paths produce identical estimates. | Inserts five string keys once into both `RegularPath` and `FastPath` sketches (`3x64`) and asserts equal estimates for every key. |
| `merge_adds_counters_element_wise` | Merge sums counters element-wise for matching dimensions. | Merges two `2x32` sketches after inserting the same key (`1` on left, `2` on right) and checks merged per-row target counters equal `3`. |
| `countmin_insert_emit_delta_emits_at_threshold_and_resets_period` | Worker-path delta emission fires at promotion threshold and resets. | Inserts key into `3x64` CMS via `insert_emit_delta`; verifies no delta emitted before `CM_PROMASK` inserts, then exactly `3` deltas (one per row) with `value == CM_PROMASK` at threshold, no extra deltas in next sub-threshold window, and another batch of `3` at the next threshold. |
| `countmin_apply_delta_increments_parent_counter` | Apply delta increments parent counter. | Constructs a `CmDelta{row=1, col=5, value=CM_PROMASK}`, applies it to a `3x64` parent CMS, and verifies the target counter at `(1,5)` equals `CM_PROMASK`. |
| `cm_regular_path_correctness` | Regular-path hashing, counters, and estimates are exact on a deterministic stream. | Recomputes expected counter indices for `I32(0..9)` using per-row hashing, asserts exact full-matrix equality after one pass, doubled counters after second pass, and estimate `== 2` for each inserted key. |
| `cm_fast_path_correctness` | Fast-path counter placement matches bit-sliced hash mapping. | Recomputes expected fast-path indices for `I32(0..9)` from one hash plus row bit-slices/mask bits and asserts exact full-matrix equality. |
| `count_min_round_trip_serialization` | Serialization round trip preserves full sketch state. | Serializes/deserializes a populated `3x8` regular-path sketch and verifies dimensions plus the full counter array are unchanged. |
| `count_min_custom_hasher_profile_round_trips_and_is_self_describing` | The metadata describes the hasher that built the sketch rather than a hardcoded profile. | For a `3x8` sketch over a hasher declaring its own `HashProfile`, verifies the counter array round-trips, the bytes differ from the standard-profile sketch's over the same inserts, and a standard-profile decode rejects them. |
| `count_min_f64_and_mode_in_metadata_round_trip` | The `f64` counter type and the `mode` both travel in the metadata. | Round-trips a `4x16` fast-path `Vector2D<f64>` sketch fed fractional weights, verifies the counter array is preserved, then that the same bytes fail to decode as an `i64` regular-path sketch. |
| `count_min_rejects_zero_dimension_payload` | A zero dimension is a decode error, not a `Vector2D::from_fn` panic. | Verifies a crafted `4x0` envelope with an empty `counts` payload fails rather than panicking in the `cols.ilog2()` mask derivation. |
| `cms_metadata_rejects_unknown_keys` | An unexpected metadata key fails closed. | Encodes the eleven `CmsMetadata` fields plus a `bogus_field` as a named map and verifies it does not decode as `CmsMetadata`. |
| `count_min_i32_round_trips_and_is_pinned_by_counter_type` | The `i32` wire config round-trips and its width is identity, not a detail. | Round-trips a `2x4` `Vector2D<i32>` sketch, then verifies its bytes differ from the numerically equal `i64` sketch's, that `i32` bytes fail to decode as `i64`, and that `i64` bytes fail to decode as `i32`. |
| `count_min_counter_types_reject_each_other` | Each wire counter type refuses the others' bytes. | Verifies a `2x4` `f64` envelope fails to decode as both an `i32` and an `i64` sketch, and that an `i32` envelope fails to decode as an `f64` one. |
| `count_min_rejects_too_many_rows` | More rows than the seed list has seeds is refused on both sides. | Verifies a sketch past `MATRIX_MAX_ROWS` fails to serialize, that a crafted envelope of that geometry fails to decode with a message naming `MATRIX_MAX_ROWS`, and that the boundary row count still serializes. |
| `estimate_does_not_clamp_i64_counts_above_i32_max` | An `i64` counter's estimate is not clamped at `i32::MAX`. | Inserts `Str("pkt_len")` with weight `35_000_000_000` into a `3x64` `CountMin<Vector2D<i64>, RegularPath>` through `insert_many` and verifies `estimate` is at or above that count and is not `i32::MAX as i64`. |
| `merge_requires_matching_dimensions` | Merging across row counts panics. | Verifies merging a `3x32` `CountMin<Vector2D<i32>, RegularPath>` into a `2x32` one panics with "dimension mismatch while merging CountMin sketches". |
### Count
Test file: [`src/sketches/countsketch.rs`](../src/sketches/countsketch.rs)
Wire tests: [`src/sketches/countsketch/wire.rs`](../src/sketches/countsketch/wire.rs)
| test_name | test_description | what_is_tested |
| --- | --- | --- |
| `default_initializes_expected_dimensions` | Default dimensions initialize zeroed counters. | Verifies default `Count` dimensions (`rows=3`, `cols=4096`) and that all counters are zero after construction. |
| `with_dimensions_uses_custom_sizes` | Custom dimensions initialize zeroed rows. | Verifies `with_dimensions(3, 17)` applies requested shape and each row slice is zero-initialized. |
| `insert_updates_signed_counters_per_row` | Regular insert applies per-row signed updates. | After one insert of key `"alpha"` into a `3x64` sketch, checks each row’s hashed counter equals that row’s expected sign (`+1` or `-1`). |
| `fast_insert_produces_consistent_estimates` | Fast-path single inserts return unit estimates. | Inserts five string keys once into a fast-path sketch (`4x128`) and asserts estimate `== 1.0` for each key. |
| `insert_produces_consistent_estimates` | Regular-path single inserts return unit estimates. | Inserts five string keys once into a regular-path sketch (`3x64`) and asserts estimate `== 1.0` for each key. |
| `estimate_recovers_frequency_for_repeated_key` | Regular path recovers repeated-key frequency. | Inserts key `"theta"` 37 times into a regular-path sketch (`3x64`) and asserts estimate `== 37.0`. |
| `fast_path_recovers_repeated_insertions` | Fast path recovers repeated insertions across keys. | Inserts five keys for 5 rounds into a fast-path sketch (`4x256`) and asserts estimate `== 5.0` for each key. |
| `merge_adds_counters_element_wise` | Merge sums signed counters for matching dimensions. | Merges two regular-path `2x32` sketches after inserting the same key (`1` on left, `2` on right) and checks per-row target counters equal `sign(row,key) * 3`. |
| `count_child_insert_emits_at_threshold` | Worker-path delta emission fires after sufficient inserts. | Inserts key into `3x64` `Count` via `insert_emit_delta` for `200` iterations and verifies at least `3` deltas (one per row) are emitted. |
| `zipf_stream_stays_within_twenty_percent_for_most_keys` | Zipf stream keeps relative error under 20% for most keys. | On Zipf stream (`rows=5`, `cols=8192`, `domain=8192`, `exponent=1.1`, `N=200_000`), computes per-key relative error and requires at least 70% of keys with error `< 0.20`. |
| `cs_regular_path_correctness` | Regular-path counter/sign mapping and estimates are exact on deterministic inserts. | Recomputes expected signed counter updates for `I32(0..9)` using regular hashing/sign logic, asserts exact matrix match after one pass, doubled counters after second pass, and estimate `== 2.0` for each inserted key. |
| `cs_fast_path_correctness` | Fast-path row-hash/sign mapping matches expected counters. | Recomputes expected fast-path updates for `I32(0..9)` using matrix hash row slices and row signs, then asserts exact full-matrix equality. |
| `count_sketch_round_trip_serialization` | The envelope frames a sketch under kind_id `0x04 0x00`, and the state survives a round trip. | Serializes a populated `3x8` regular-path `Vector2D<i64>` sketch and verifies the bytes open with the ASAPv1 magic, a `kind_id_len` of `2`, and `0x04 0x00`, then that the decode preserves rows, cols, and the full counter array. |
| `count_sketch_negative_counters_round_trip` | Signed cells reach the wire and come back unchanged. | Round-trips a `2x4` matrix holding alternating positive and negative counters and verifies the decoded slice equals the source and still holds a negative cell. |
| `count_sketch_custom_hasher_profile_round_trips_and_is_self_describing` | The metadata describes the hasher that built the sketch rather than a hardcoded profile. | For a `3x8` sketch over a hasher declaring its own `HashProfile`, verifies the bytes round-trip, differ from the standard-profile sketch's bytes over the same inserts, and are rejected by a standard-profile decode. |
| `count_sketch_mode_in_metadata_round_trips` | The metadata `mode` pins which column derivation built the sketch. | Round-trips a `4x16` fast-path sketch and verifies the counter array is preserved, then that the same bytes fail to decode as a `RegularPath` sketch. |
| `count_sketch_rejects_foreign_kind_id` | Count-Min's kind_id is refused although the payload shape is identical. | Verifies a `3x8` `CountMin<Vector2D<i64>, RegularPath>` envelope fails to decode as a `Count`. |
| `count_sketch_rejects_zero_dimension_payload` | A zero dimension is a decode error, not a `Vector2D::from_fn` panic. | Verifies a crafted `4x0` envelope with an empty `counts` payload fails rather than panicking in the `cols.ilog2()` mask derivation. |
| `count_sketch_rejects_dimension_length_mismatch` | The length check fires from the declared dimensions, before any allocation is sized from them. | Verifies a crafted envelope declaring `MATRIX_MAX_ROWS x 2^24` while carrying three counters fails. |
| `count_sketch_rejects_serializing_an_unfilled_matrix` | The encode side refuses a matrix its own decoder would reject. | Verifies `Vector2D::init(2, 4)`, which reserves eight cells without filling them, fails to serialize rather than emitting a `2x4` envelope carrying an empty `counts` array. |
| `count_sketch_rejects_too_many_rows` | More rows than the seed list has seeds is refused on both sides. | Verifies a sketch past `MATRIX_MAX_ROWS` fails to serialize, that a crafted envelope of that geometry fails to decode with a message naming `MATRIX_MAX_ROWS`, and that the boundary row count still serializes. |
| `cs_metadata_rejects_unknown_keys` | An unexpected metadata key fails closed. | Encodes the eleven `CsMetadata` fields plus a `bogus_field` as a named map and verifies it does not decode as `CsMetadata`. |
| `cs_metadata_rejects_a_missing_counter_type_key` | `counter_type` is required and can never be silently defaulted. | Encodes the other ten `CsMetadata` fields as a named map with `counter_type` omitted and verifies it does not decode as `CsMetadata`. |
| `cs_metadata_rejects_a_foreign_counter_type_name` | A Count-Min-only counter type name is not a Count Sketch one. | Wraps metadata naming `counter_type: "f64"` around a valid 2x4 payload and verifies both the `i64` and the `i32` sketch reject it. |
| `count_sketch_i32_round_trips_and_is_pinned_by_counter_type` | The `i32` wire config round-trips and its width is identity, not a detail. | Round-trips a `2x4` `Vector2D<i32>` sketch, then verifies its bytes differ from the numerically equal `i64` sketch's, that `i32` bytes fail to decode as `i64`, and that `i64` bytes fail to decode as `i32`. |
| `countsketch_error_stays_rank_independent_across_frequency_deciles` | Mean absolute error does not track key frequency. | On a Zipf stream (`rows=5`, `cols=4096`, `domain=8192`, `exponent=1.1`, `N=200_000`, seed `1007`) into a `Count<Vector2D<i64>, RegularPath>`, sorts the keys by true count into 10 equal deciles and verifies the largest decile mean `\|estimate - truth\|` is at most `3x` the smallest; a spread up to that 3x band passes. |
| `merge_requires_matching_dimensions` | Merging across row counts panics. | Verifies merging a `3x32` `Count<Vector2D<i32>, RegularPath>` into a `2x32` one panics with "dimension mismatch while merging CountMin sketches". |
### HyperLogLog
Test file: [`src/sketches/hll.rs`](../src/sketches/hll.rs)
Wire tests: [`src/sketches/hll/wire.rs`](../src/sketches/hll/wire.rs)
| test_name | test_description | what_is_tested |
| --- | --- | --- |
| `hll_child_insert_emits_on_improvement` | Child insert emits delta only on register improvement. | Inserts a key via `insert_emit_delta` into `HyperLogLog<Classic>`; verifies exactly `1` delta emitted on the first insert and `0` additional deltas on a duplicate insert. |
| `hyperloglog_p12_accuracy_within_two_percent` | P12 Classic HyperLogLog stays within P12 error tolerance across scale checkpoints. | Applies the same checkpointed unique-stream accuracy test to `HyperLogLogP12<Classic>`, requiring relative error `<= P12_ERROR_TOLERANCE` at each target cardinality. |
| `hll_ertl_p12_accuracy_within_two_percent` | P12 ErtlMLE HyperLogLog stays within P12 error tolerance across scale checkpoints. | Applies the same checkpointed accuracy test to `HyperLogLogP12<ErtlMLE>`, requiring relative error `<= P12_ERROR_TOLERANCE`. |
| `hllds_p12_accuracy_within_two_percent` | P12 HIP HyperLogLog stays within P12 error tolerance across scale checkpoints. | Applies the same checkpointed accuracy test to `HyperLogLogHIPP12`, requiring relative error `<= P12_ERROR_TOLERANCE`. |
| `hyperloglog_p12_merge_within_two_percent` | P12 Classic HyperLogLog merge remains within P12 error tolerance. | Applies the same even/odd split merge scenario to `HyperLogLogP12<Classic>`, requiring merged relative error `<= P12_ERROR_TOLERANCE`. |
| `hll_ertl_p12_merge_within_two_percent` | P12 ErtlMLE HyperLogLog merge remains within P12 error tolerance. | Applies the same even/odd split merge scenario to `HyperLogLogP12<ErtlMLE>`, requiring merged relative error `<= P12_ERROR_TOLERANCE`. |
| `hyperloglog_round_trip_serialization` | Classic HyperLogLog round trip preserves bytes and estimate stability. | After inserting `100_000` unique values, verifies serialized payload is non-empty, `deserialize -> reserialize` bytes are identical, and estimate drift is within `0.02 * max(original_est, 1.0)`. |
| `hll_ertl_round_trip_serialization` | ErtlMLE HyperLogLog round trip preserves bytes and estimate stability. | Applies the same `100_000`-value serialization round-trip checks: non-empty bytes, byte-for-byte reserialization equality, and bounded estimate drift. |
| `hllds_round_trip_serialization` | HIP HyperLogLog round trip preserves bytes and estimate stability. | Applies the same `100_000`-value serialization round-trip checks for `HyperLogLogHIP`: non-empty bytes, byte-for-byte reserialization equality, and bounded estimate drift. |
| `hyperloglog_p12_round_trip_serialization` | P12 Classic HyperLogLog round trip preserves bytes and estimate stability. | Applies the same `100_000`-value serialization round-trip checks for `HyperLogLogP12<Classic>`: non-empty bytes, byte-for-byte reserialization equality, and bounded estimate drift. |
| `hll_ertl_p12_round_trip_serialization` | P12 ErtlMLE HyperLogLog round trip preserves bytes and estimate stability. | Applies the same `100_000`-value serialization round-trip checks for `HyperLogLogP12<ErtlMLE>`: non-empty bytes, byte-for-byte reserialization equality, and bounded estimate drift. |
| `hllds_p12_round_trip_serialization` | P12 HIP HyperLogLog round trip preserves bytes and estimate stability. | Applies the same `100_000`-value serialization round-trip checks for `HyperLogLogHIPP12`: non-empty bytes, byte-for-byte reserialization equality, and bounded estimate drift. |
| `hll_correctness_test` | Register update logic matches expected bucket/index behavior for all HLL variants. | Runs fixed hashed inserts against Classic, ErtlMLE, and HIP variants; asserts exact expected register values at specific bucket indices and confirms an untouched bucket remains zero. |
| `hll_envelope_structure_and_kind_id_guard` | The envelope frames an Ertl-MLE sketch under kind_id `0x01 0x02`, and a Classic decoder refuses it. | For 1,000 inserts into `HyperLogLog<ErtlMLE>`, verifies the bytes open with the ASAPv1 magic, `envelope::VERSION`, a `kind_id_len` of `2`, and `0x01 0x02`, that the decoded registers match the source, and that a `HyperLogLog<Classic>` decode fails. |
| `hll_hip_round_trip_preserves_state` | The HIP running scalars travel beside the registers. | For 1,000 inserts into `HyperLogLogHIP`, verifies the bytes carry kind_id `0x01 0x03` and that the decoded sketch matches the source on the registers and on `kxq0`, `kxq1`, and `est`. |
| `native_and_portable_hll_bytes_match` | The native and portable encoders emit the same envelope. | For 1,000 inserts each, verifies an `ErtlMLE` sketch's bytes equal the portable `HllSketch` `Datafusion` encoding of its registers, and a `HyperLogLogHIP` sketch's bytes equal the portable `Hip` encoding of its registers plus `kxq0`, `kxq1`, and `est`. |
| `hll_custom_hasher_profile_round_trips_and_is_self_describing` | The metadata describes the hasher that built the sketch rather than a hardcoded profile. | For a P14 `ErtlMLE` sketch over a hasher declaring its own `HashProfile`, verifies the registers round-trip, the bytes differ from the standard-profile sketch's over the same 1,000 inserts, and a standard-profile decode rejects them. |
| `hll_metadata_rejects_unknown_keys` | An unexpected metadata key fails closed. | Encodes the eight `HllMetadata` fields plus a `bogus_field` as a named map and verifies it does not decode as `HllMetadata`. |
| `hll_precision_cross_rejection` | The metadata `precision` pins the register storage the bytes belong to. | Verifies a populated `HyperLogLogP12<Classic>` envelope fails to decode as the P14 `HyperLogLog<Classic>`. |
| `hll_hip_kind_id_rejected_by_classic` | The HIP kind_id is refused by the Classic decoder. | Verifies a populated `HyperLogLogHIP` envelope fails to decode as `HyperLogLog<Classic>`. |
| `classic_estimate_holds_past_the_32_bit_range` | The Classic estimator holds its closed form at ranks whose estimate passes the 32-bit range. | For ranks `12`, `16`, `18`, and `20`, drives one crafted hash per bucket through `HyperLogLog::<Classic>::insert_with_hash` so all `16_384` P14 registers read that rank, and verifies `estimate()` is within a relative `1e-6` of `alpha_m * 16_384 * 2^rank` for `alpha_m = 0.7213 / (1 + 1.079 / 16_384)`. |
### KLL
Test file: [`src/sketches/kll.rs`](../src/sketches/kll.rs)
Wire tests: [`src/sketches/kll/wire.rs`](../src/sketches/kll/wire.rs)
| test_name | test_description | what_is_tested |
| --- | --- | --- |
| `coin_bit_cache_behavior` | Coin consumes cached random bits in deterministic bit order. | From a fixed seed, validates 3 successive 64-bit RNG blocks are consumed bit-by-bit (`0..63`) before refill, matching expected xorshift-derived bits exactly. |
| `coin_state_never_zero` | Coin state is never zero, including zero-seed initialization. | Verifies `Coin::from_seed(0)` normalizes to non-zero state and remains non-zero across 128 tosses. |
| `test_data_input_api` | DataInput numeric API is accepted and non-numeric input is rejected. | Inserts `I32`, `I64`, `F64`, `F32`, and `U32` values, checks median query lies between `20.0` and `40.2`, and verifies string input returns error `KLL sketch only accepts numeric inputs`. |
| `test_forced_compact` | Small-capacity KLL triggers compaction and keeps median in valid compacted outcomes. | With `KLL::init(3,3)` and inserts `[10,20,30,40,50]`, asserts median query is one of `{30.0, 40.0}` under forced compaction. |
| `test_no_compact` | Larger-capacity KLL avoids compaction for small stream and returns exact median. | With `KLL::init_kll(8)` and inserts `[10,20,30,40,50]`, asserts median query equals `30.0`. |
| `merge_preserves_quantiles_within_tolerance` | Merging two KLL sketches preserves quantiles within 2% rank tolerance. | Splits 10,000 uniform samples (`1,000,000..10,000,000`, seed `0xC0FFEE`) across two `k=200` sketches by index parity, merges, and checks quantiles `{0,0.1,0.25,0.5,0.75,0.9,1}` remain within `q +/- 0.02` truth bounds. |
| `cdf_handles_empty_sketch` | Empty KLL CDF queries return zero-valued defaults. | For empty `KLL::init_kll(64)`, asserts `cdf.quantile(123.0) == 0.0`, `cdf.query(0.5) == 0.0`, and `cdf.query_li(0.5) == 0.0`. |
| `kll_round_trip_rmp` | RMP round trip preserves KLL structure, packed data, and queried quantiles. | Serializes/deserializes `KLL::init_kll(256)` after 5,000 uniform updates (`0..1,000,000`, seed `0xDEAD_BEEF`), verifies non-empty bytes, core fields and packed arrays (`levels`, `items`) are identical, and CDF queries at `{0,0.1,0.25,0.5,0.75,0.9,1}` match within `f64::EPSILON`. |
| `generic_kll_i64_sanity` | Generic `KLL<T>` path works for non-`f64` numeric types. | Builds `KLL<i64>`, inserts `1..=20_000` through the typed `update(&T)` API, checks approximate count and p50/p90 quantiles, verifies merge on two `KLL<i64>` instances, and confirms MessagePack round-trip preserves weighted count. |
| `kll_envelope_structure_and_round_trip` | The envelope frames a compact sketch under kind_id `0x06 0x00`, and the bytes are stable across a round trip. | For `k=200` seeded at `42` over 200,000 updates, verifies the bytes open with the ASAPv1 magic, `envelope::VERSION`, a `kind_id_len` of `2`, and `0x06 0x00`, that the decoded sketch re-serializes to the same bytes, and that quantiles at `{0, 0.01, 0.25, 0.5, 0.75, 0.99, 1}` match exactly. |
| `kll_empty_round_trip` | A sketch that saw nothing round-trips. | Verifies `KLL::<f64>::init_kll_with_seed(200, 7)` decodes back with a `count` of `0` and identical re-serialized bytes. |
| `kll_i64_round_trip` | The generic `KLL<T>` path reaches the wire under the same kind_id. | For `KLL<i64>` seeded at `5` over 50,000 updates, verifies the bytes carry `0x06 0x00`, re-serialize identically after a decode, and preserve `count`. |
| `kll_item_type_cross_rejection` | The metadata `item_type` pins the element type. | Verifies an `f64` `KLL` envelope fails to decode as a `KLL<i64>`. |
| `kll_metadata_rejects_unknown_keys` | An unexpected metadata key fails closed. | Encodes the four required `KllMetadata` fields plus a `bogus_field` as a named map and verifies it does not decode as `KllMetadata`. |
| `kll_rejects_inconsistent_levels` | A level layout the items do not fill is refused rather than panicking. | Verifies a crafted envelope whose `levels` end at `3` while `items` carries two entries fails to decode. |
| `kll_rejects_out_of_range_k_m` | A crafted `k`/`m` is refused before `compute_max_capacity` sizes anything. | Verifies crafted envelopes at `(u32::MAX, u32::MAX)`, `(MAX_CACHEABLE_K + 1, 8)`, and `(200, 1)` each fail to decode rather than driving a giant allocation. |
| `kll_seed_present_when_seeded_omitted_when_unseeded` | The seed key is present exactly when the sketch has one. | Verifies `init_kll_with_seed(200, 42)` emits metadata carrying `seed` `Some(42)`, while an `init_kll(200)` sketch omits the key entirely. |
| `kll_unseeded_round_trip_byte_stable` | The absent-seed key decodes as well as it encodes. | For an unseeded `k=200` sketch over 2,000 updates, verifies the decoded sketch re-serializes to the same bytes and keeps `count`. |
| `kll_seed_survives_round_trip_so_clear_stays_deterministic` | Carrying the seed keeps `clear` deterministic after a decode. | Decodes a `k=200` sketch seeded at `42` over 5,000 updates, calls `clear` on it and on a freshly seeded twin, feeds both 3,000 updates, and verifies their bytes are identical. |
| `kll_rejects_weighted_count_overflow` | A level layout whose weighted count overflows is refused rather than handed back. | Verifies a crafted envelope parking 16 items at compactor level 60, so that `16 * 2^60` overflows `usize` in `count()`, fails to decode. |
| `kll_dynamic_kind_id_rejected_by_compact` | The dynamic kind_id is refused by the compact decoder. | Verifies a crafted envelope carrying valid compact metadata and payload under `0x06 0x01` fails to decode as a `KLL<f64>`. |
| `cdf_cached_matches_uncached_across_lifecycle` | The memoized CDF agrees with the from-scratch rebuild at every lifecycle stage. | For `KLL::<f64>::init_with_seed(200, 8, 42)`, verifies `quantile_cached` equals `quantile` while empty at `{0.1, 0.5, 0.9}`, at `{0.01, 0.1, 0.25, 0.5, 0.75, 0.9, 0.99}` after 20,000 uniform samples in `[0, 1000)` (seed `0xACAC_0001`), and at `{0.1, 0.5, 0.9}` after merging a seed-43 sketch over 5,000 samples in `[-5000, -4000)` (seed `0xACAC_0002`); after `clear`, `quantile_cached(0.5)` is `0.0` and `count` is `0`. |
| `cdf_cache_invalidated_by_subsequent_updates` | Updates after a cached query invalidate the cache instead of serving a stale CDF. | Takes `quantile_cached(0.5)` on a `init_with_seed(200, 8, 42)` sketch over 10,000 uniform samples in `[0, 100)` (seed `0xACAC_0003`), then inserts `999_999.0` 10,000 times and verifies the cached median rises by more than `50.0`. |
| `kllwire_serde_rejects_crafted_dimensions` | The nested serde decoder refuses an out-of-range `k` before it sizes anything. | Encodes a `KLLWire<f64>` with no items, `levels` of `[0, 0]`, `k` of `usize::MAX`, `m` of `8`, `num_levels` `1`, and `Coin::from_seed(1)`, and verifies it does not decode as a `KLL<f64>` rather than overflowing `compute_max_capacity`. |
| `from_portable_state_reproduces_source_exactly` | Reconstruction from portable state is bit-exact, not a lossy replay. | Extracts the compacted `items` and `levels` from a `KLL::<f64>::init_kll(200)` sketch over 200,000 updates of `i * 0.0007 + 3.0`, and verifies `from_portable_state` reproduces the source's quantiles at `{0, 0.01, 0.1, 0.25, 0.5, 0.75, 0.9, 0.99, 1}` exactly; an empty reconstruction is verified to report `num_levels` `1` with `levels[0]` at `max_capacity`. |
| `seeded_sketches_are_byte_identical` | Same seed and same input give byte-identical sketches. | Feeds 5,000 uniform samples in `[0, 1_000_000)` (seed `7`) to two `init_kll_with_seed(200, 42)` sketches and verifies their serialized bytes are equal. |
| `different_seeds_produce_different_bytes` | The seed reaches `toss` rather than sitting unused on the struct. | Feeds the same 5,000 uniform samples in `[0, 1_000_000)` (seed `11`) to `init_kll_with_seed(200, 1)` and `init_kll_with_seed(200, 2)` and verifies their serialized bytes differ. |
| `clear_preserves_seed_determinism` | `clear` re-seeds from the stored seed, so determinism survives a window rotation. | Burns 1,500 unrelated samples (seed `99`) through a `init_kll_with_seed(200, 1234)` sketch, clears it, then feeds it and a fresh seed-1234 twin the same 3,000 samples (seed `13`) and verifies their serialized bytes are equal. |
| `merge_into_empty_target_preserves_weight_issue_68_repro` | Merging into an empty target preserves the total weight exactly. | Builds a `k=200` source over `1..=1000`, checks its `count` falls in `980..=1020`, merges it into an empty `k=200` target, and verifies the target's `count` equals the source's exactly and its median lands in `475.0..=525.0`. |
| `merge_two_nonempty_sketches_preserves_weight_and_quantiles` | Merging two non-empty sketches is a genuinely weighted merge, not just the empty-target special case. | Builds one `k=200` sketch over 50,000 uniform samples in `[0, 1_000_000)` (seed `0xA11CE`) and another over 50,000 Zipf samples (8,192 distinct, exponent `1.1`, seed `0xB0B`), verifies each pre-merge `count` is within 3% of `50_000`, that the merged `count` is within 3% of their sum, and that `assert_quantiles_within_error` holds at `{0, 0.1, 0.25, 0.5, 0.75, 0.9, 1}` within a rank tolerance of `0.03` against the sorted union. |
| `bulk_update_equivalent_to_loop_and_empty_is_noop` | `bulk_update` is the loop it replaces, and an empty batch changes nothing. | Verifies `bulk_update(&[])` on a seed-42 `init_with_seed(200, 8, 42)` sketch holding `[1.0, 2.0, 3.0]` leaves `count`, `quantile(0.5)`, and the serialized bytes untouched; that 20,000 uniform samples in `[0, 1000)` (seed `0xBEEF_1234`) through `bulk_update` match the one-at-a-time loop on `count`, bytes, and quantiles `{0.1, 0.5, 0.9}` for two seed-99 sketches; that 100 `DataInput::F64` values through `bulk_update_data_input` match the loop's bytes at seed 77; and that `bulk_update_data_input` over `[F64(1.0), String("x"), F64(2.0)]` errors with `count` left at `1`. |
### KLLDynamic
Test file: [`src/sketches/kll_dynamic.rs`](../src/sketches/kll_dynamic.rs)
Wire tests: [`src/sketches/kll_dynamic/wire.rs`](../src/sketches/kll_dynamic/wire.rs)
| test_name | test_description | what_is_tested |
| --- | --- | --- |
| `test_data_input_api` | `KLLDynamic<f64>` accepts numeric `DataInput` and rejects non-numeric input. | Inserts `I32`, `I64`, `F64`, `F32`, and `U32` values through `update_data_input`, checks median query lies between `20.0` and `40.2`, and verifies string input returns error `KLL sketch only accepts numeric inputs`. |
| `test_forced_compact` | Small-capacity KLLDynamic triggers compaction and keeps median in valid compacted outcomes. | With `KLLDynamic::init(3,3)` and typed inserts `[10,20,30,40,50]`, asserts median query is one of `{30.0, 40.0}` under forced compaction. |
| `test_no_compact` | Larger-capacity KLLDynamic avoids compaction for small stream and returns exact median. | With `KLLDynamic::init_kll(8)` and typed inserts `[10,20,30,40,50]`, asserts median query equals `30.0`. |
| `merge_preserves_quantiles_within_tolerance` | Merging two KLLDynamic sketches preserves quantiles within 2% rank tolerance. | Splits 10,000 uniform samples (`1,000,000..10,000,000`, seed `0xC0FFEE`) across two `k=200` sketches by index parity, merges, and checks quantiles `{0,0.1,0.25,0.5,0.75,0.9,1}` remain within `q +/- 0.02` truth bounds. |
| `cdf_handles_empty_sketch` | Empty KLLDynamic CDF queries return zero-valued defaults. | For empty `KLLDynamic::<f64>::init_kll(64)`, asserts `cdf.quantile(123.0) == 0.0`, `cdf.query(0.5) == 0.0`, and `cdf.query_li(0.5) == 0.0`. |
| `kll_dynamic_round_trip_rmp` | RMP round trip preserves KLLDynamic structure, packed data, and queried quantiles. | Serializes/deserializes `KLLDynamic::init_kll(256)` after 5,000 uniform updates (`0..1,000,000`, seed `0xDEAD_BEEF`), verifies non-empty bytes, core fields and packed arrays (`levels`, `items`) are identical, and CDF queries at `{0,0.1,0.25,0.5,0.75,0.9,1}` match within `f64::EPSILON`. |
| `generic_kll_dynamic_i64_sanity` | Generic `KLLDynamic<T>` path works for non-`f64` numeric types. | Builds `KLLDynamic<i64>`, inserts `1..=20_000` through the typed `update(&T)` API, checks approximate count and p50/p90 quantiles, and confirms MessagePack round-trip preserves weighted count. |
| `kll_dynamic_envelope_structure_and_round_trip` | The envelope frames a dynamic sketch under kind_id `0x06 0x01`, and the bytes are stable across a round trip. | For `k=200` over 200,000 updates, verifies the bytes open with the ASAPv1 magic, `envelope::VERSION`, a `kind_id_len` of `2`, and `0x06 0x01`, that the decoded sketch re-serializes to the same bytes, and that quantiles at `{0, 0.01, 0.25, 0.5, 0.75, 0.99, 1}` match exactly. |
| `kll_dynamic_empty_round_trip` | A sketch that saw nothing round-trips. | Verifies `KLLDynamic::<f64>::init_kll(200)` decodes back and re-serializes to identical bytes. |
| `kll_dynamic_i64_round_trip` | The generic `KLLDynamic<T>` path reaches the wire under the same kind_id. | For `KLLDynamic<i64>` over 50,000 updates, verifies the bytes carry `0x06 0x01` and re-serialize identically after a decode. |
| `kll_dynamic_item_type_cross_rejection` | The metadata `item_type` pins the element type. | Verifies an `f64` `KLLDynamic` envelope fails to decode as a `KLLDynamic<i64>`. |
| `merge_into_empty_target_preserves_weight_issue_68_repro` | Merging into an empty target preserves the total weight exactly. | Builds a `k=200` source over `1..=1000`, checks its `count` falls in `980..=1020`, merges it into an empty `k=200` target, and verifies the target's `count` equals the source's exactly and its median lands in `475.0..=525.0`. |
| `merge_two_nonempty_sketches_preserves_weight_and_quantiles` | Merging two non-empty sketches is a genuinely weighted merge, not just the empty-target special case. | Builds one `k=200` sketch over 50,000 uniform samples in `[0, 1_000_000)` (seed `0xA11CE`) and another over 50,000 Zipf samples (8,192 distinct, exponent `1.1`, seed `0xB0B`), verifies each pre-merge `count` is within 3% of `50_000`, that the merged `count` is within 3% of their sum, and that `assert_quantiles_within_error` holds at `{0, 0.1, 0.25, 0.5, 0.75, 0.9, 1}` within a rank tolerance of `0.03` against the sorted union. |
| `merge_handles_operand_level_that_is_not_a_single_sorted_run` | A merge sorts an operand level that is a concatenation of separately-sorted chunks. | Hand-builds a `KLLDynamic::<f64>::init(50, 4)` operand whose level 1 is `[30.0, 40.0, 10.0, 20.0]` - two ascending chunks out of order - with `levels` `[0, 4, 5]` and `num_levels` `2`, checks `capacity_for_level(1)` is at least `4` so the level is never itself compacted, merges it into an empty `init(50, 4)` target, and verifies every level above 0 is a single ascending run afterwards. |
| `bulk_update_equivalent_to_loop` | `bulk_update` tracks the loop it replaces. | Feeds 10,000 uniform samples in `[0, 1000)` (seed `0xCAFE_1234`) to two `init_kll(200)` sketches, one value at a time and one through `bulk_update`, and verifies their counts agree within 5% relative; then that 100 `DataInput::F64` values through `bulk_update_data_input` give the same `count` as the loop. Only counts are compared - quantiles and bytes are not, since the wall-clock `Coin` makes them non-deterministic. |
### DDSketch
Test file: [`src/sketches/ddsketch.rs`](../src/sketches/ddsketch.rs)
Wire tests: [`src/sketches/ddsketch/wire.rs`](../src/sketches/ddsketch/wire.rs)
| test_name | test_description | what_is_tested |
| --- | --- | --- |
| `insert_and_query_basic` | Basic insert/query preserves count semantics and quantile monotonicity. | Inserts mixed values `[0.0, -5.0, 1.0, 2.0, 3.0, 10.0, 50.0, 100.0, 1000.0]`, verifies non-positive values are ignored (`count == 7`), and checks queried quantiles at `{0.0, 0.5, 0.9, 0.99, 1.0}` are monotone and bounded by sketch min/max. |
| `empty_quantile_returns_none` | Empty sketch returns no quantiles and zero count. | For a new `DDSketch(alpha=0.01)`, asserts `get_value_at_quantile` returns `None` for `p in {0.0, 0.5, 1.0}` and `get_count() == 0`. |
| `merge_two_sketches_combines_counts_and_bounds` | Merge combines counts and preserves quantile boundary invariants. | Merges sketches built from `[1,2,3,4]` and `[5,10,20]`, then verifies merged `count=7`, `min=1`, `max=20`, exact boundary quantiles (`q0=1`, `q1=20`), and median lies within `[1,20]`. |
| `dds_serialization_round_trip` | Serialization round trip preserves count, sum, bounds, and selected quantiles. | Serializes/deserializes a populated sketch (`alpha=0.01`), verifies non-empty bytes, equal `count/sum/min/max`, and exact quantile matches at `{0.0, 0.1, 0.5, 0.9, 1.0}`. |
| `ddsketch_envelope_structure_and_round_trip` | The envelope frames a sketch under kind_id `0x05 0x00`, and the bytes are stable across a round trip. | For a sketch at `alpha = 0.01` over eight values, verifies the bytes open with the ASAPv1 magic, a `kind_id_len` of `2`, and `0x05 0x00`, that the metadata carries `metadata_version` `1` and that alpha, that the decoded store counts and offset match, that re-serializing reproduces the bytes, and that quantiles at `{0, 0.1, 0.5, 0.9, 1}` are unchanged. |
| `ddsketch_scalars_survive_exactly` | `sum`, `min`, and `max` are carried, not recomputed from the buckets. | Verifies the decoded sketch reports the source's `sum` and `alpha`, a `min` of exactly `0.25`, and a `max` of exactly `1000.0`, rather than the alpha-bounded bucket representatives a recomputation would give. |
| `ddsketch_count_is_recovered_from_the_buckets` | The payload carries no `count` field. | Verifies the payload reads back as a five-element array whose bucket counts sum to `get_count()`, that a six-element read fails, and that the decoded sketch reports the same count. |
| `ddsketch_empty_round_trip` | A sketch that saw nothing round-trips. | Verifies a fresh `DDSketch(alpha=0.01)` decodes back with a `count` of `0`, `min` and `max` of `None`, an empty store, and identical re-serialized bytes. |
| `ddsketch_merged_round_trip` | A store grown on both sides of a merge round-trips. | Merges 200 values against the same 200 scaled by `0.001`, then verifies the decoded sketch matches the source on `count`, `sum`, `min`, and `max` and re-serializes to the same bytes. |
| `ddsketch_rejects_foreign_kind_id` | Another sketch's kind_id is refused even when the rest parses cleanly. | Verifies a `3x8` Count-Min envelope fails to decode as a `DDSketch`, and that well-formed DDSketch metadata and payload wrapped under kind_id `0x02 0x00` fail too. |
| `dd_metadata_rejects_unknown_keys` | An unexpected metadata key fails closed. | Encodes the two `DdMetadata` fields plus a `bogus_field` as a named map and verifies it does not decode as `DdMetadata`. |
| `dd_metadata_rejects_a_missing_alpha_key` | `alpha` is required and can never be silently defaulted. | Encodes a named map holding only `metadata_version` and verifies it does not decode as `DdMetadata`. |
| `ddsketch_rejects_alpha_outside_the_unit_interval` | An `alpha` outside `(0, 1)` makes every bucket index meaningless and is refused. | Verifies crafted envelopes at `alpha` of `0.0`, `1.0`, `-0.5`, `2.0`, `NaN`, and infinity each fail with an alpha or metadata-mismatch complaint, while the same payload at `0.01` decodes. |
| `ddsketch_rejects_a_store_span_past_i32` | The span rule fires from the offset and the array length, before the store is rebuilt. | Verifies a crafted store of ten buckets at offset `i32::MAX - 2` fails with a "store span past i32" complaint, while the same payload three buckets long decodes. |
| `ddsketch_rejects_a_nonzero_offset_on_an_empty_store` | An empty store has exactly one encoding. | Verifies a crafted empty store at offset `42` fails with an "empty store must be at offset 0" complaint. |
| `ddsketch_rejects_a_total_count_overflow` | Bucket counts that overflow the recovered total are refused rather than wrapped. | Verifies a crafted payload of `[u64::MAX, 1]` fails with an "overflow the total sample count" complaint. |
| `ddsketch_rejects_inconsistent_scalars` | The scalars the buckets do not determine are still bounded by them. | Verifies six crafted payloads each fail on a scalar rule: a populated store carrying the empty-store sentinels, `min` above `max`, a non-positive `min`, a `sum` below the smallest ingested value, an empty store carrying a non-zero `sum`, and all-zero buckets carrying populated-store scalars. |
| `ddsketch_rejects_serializing_a_store_span_past_i32` | The encode side refuses a store its own decoder would reject. | Verifies a sketch whose store holds ten buckets at offset `i32::MAX - 2` fails to serialize. |
| `ddsketch_rejects_serializing_an_overflowing_bucket_total` | The encode side enforces the total-count rule too. | Verifies a sketch whose store holds `[u64::MAX, 1]` fails to serialize. |
| `representative_within_alpha_at_bucket_edges` | Every bucket's representative is within `alpha` of both of its edges. | For `alpha` in `{0.001, 0.01, 0.05, 0.1}` and bucket indices `{-100, -1, 0, 1, 7, 500}`, verifies `bin_representative(k)` lies in `[lower_bound(k), lower_bound(k + 1)]` and its relative error against each edge is at most `alpha + 1e-9`. |
| `merge_alpha_mismatch_is_a_real_runtime_error` | Merging across index mappings is an error, and a matched merge is not. | Verifies merging an `alpha = 0.02` sketch into an `alpha = 0.01` sketch holding `5.0` returns `Err`, while merging two `alpha = 0.01` sketches holding `3.0` and `7.0` returns `Ok` and leaves `get_count()` at `2`. |
| `untrackable_extreme_is_dropped` | A finite value outside the indexable range is not recorded, so the dense store never spans the gap. | For an `alpha = 0.01` sketch over `1..=2000`, adds `max_indexable * 10.0` and `min_indexable / 10.0` from `ddsketch_indexable_bounds(0.01)` and verifies both `get_count()` and the store's bucket span are unchanged, then that `max_indexable / 2.0` is still recorded and raises the count by `1`. |
| `serde_round_trip_keeps_the_running_scalars` | The derived serde form carries every scalar the buckets do not determine. | Round-trips an `alpha = 0.01` sketch over `[0.25, 1, 2, 3, 10, 50, 100, 1000]` through `rmp-serde` and verifies the decoded sketch matches on `get_count`, `sum`, `min`, `max`, `alpha`, `store_counts`, and `store_offset`, and on quantiles at `{0, 0.25, 0.5, 0.9, 1}`. |
| `serde_round_trip_leaves_the_sketch_usable` | A decoded sketch keeps ingesting on top of the state it came back with. | Adds `5.0` to the decode of an `alpha = 0.01` sketch over `[0.25, 1, 2, 3, 10, 50, 100, 1000]` and verifies `get_count` rises by `1`, `sum` by `5.0`, and that the bucket counts still sum to `get_count`. |
| `serde_refuses_scalars_that_disagree_with_the_store` | Serde checks the scalars against the store the way the ASAPv1 decoder does. | Encodes a crafted state at `alpha = 0.01` whose store holds `[1, 2]` at offset `-3` while `sum` is `0.0` with the empty-store sentinels `+inf`/`-inf` for `min`/`max`, and verifies the decode fails with a complaint naming "DDSketch scalars". |
| `serde_refuses_an_out_of_range_alpha` | An `alpha` outside `(0, 1)` is refused on the way in, not at the first query. | Encodes a crafted state at `alpha = 1.5` with an empty store at offset `0` and the empty-store scalars, and verifies the decode fails with a complaint naming "alpha". |
### CMSHeap
Test file: [`src/sketches/countminsketch_topk.rs`](../src/sketches/countminsketch_topk.rs)
Wire tests: [`src/sketches/countminsketch_topk/wire.rs`](../src/sketches/countminsketch_topk/wire.rs)
Shared heap wire tests: [`src/sketches/countminsketch_topk/heap_wire.rs`](../src/sketches/countminsketch_topk/heap_wire.rs)
| test_name | test_description | what_is_tested |
| --- | --- | --- |
| `insert_and_estimate` | Repeated inserts increment Count-Min estimate for one key. | Inserts `"hello"` 5 times into `CMSHeap::new(3,64,10)` and verifies `estimate("hello") == 5`. |
| `heap_tracks_top_k` | Heap keeps highest-frequency keys within top-k capacity. | Inserts keys `1..5` with frequencies `10,20,30,40,50` into `top_k=3` sketch and verifies heap counts are exactly `[30,40,50]`. |
| `merge_reconciles_heaps` | Merge combines counters and refreshes heap counts from merged sketch. | Merges two sketches containing `"merge_key"` counts `10` and `20`, then verifies merged estimate and heap count are both `30`. |
| `insert_many_updates_estimate_and_heap` | `insert_many` updates estimate and heap entry consistently. | Calls `insert_many("many", 11)` and verifies `estimate == 11` plus heap entry count `11`. |
| `bulk_insert_updates_multiple_keys` | `bulk_insert` updates multiple keys and heavy-hitter counts correctly. | Inserts stream `[7,8,7,9,7]` and verifies estimates `7->3`, `8->1`, `9->1`, with heap count for key `7` equal to `3`. |
| `clear_heap_keeps_cms_counters` | Clearing heap does not clear CMS counters. | After `insert_many("persist",5)`, calls `clear_heap()`, verifies estimate remains `5`, then one more insert rebuilds heap entry to `6`. |
| `from_storage_uses_storage_dimensions` | `from_storage` preserves backend dimensions and requested heap capacity. | Builds from `Vector2D::init(4,128)` with `top_k=9` and verifies `rows=4`, `cols=128`, `heap.capacity=9`. |
| `merge_refreshes_existing_self_heap_entries` | Merge refreshes pre-existing self heap keys to merged estimates. | After merging sketches with `a-key` counts `10` and `5`, verifies merged `a-key` estimate `15` and heap entry count `15`. |
| `fast_path_insert_and_estimate` | Fast path repeated inserts keep estimate exact for single key. | Inserts `"fast"` 7 times into fast-path sketch and verifies estimate `7`. |
| `fast_path_insert_many_and_bulk_insert` | Fast path batched APIs keep heap and estimate in sync. | Applies `insert_many("fast-many",6)` plus bulk inserts adding 2 more hits, then verifies estimate and heap count are `8`. |
| `fast_path_heap_tracks_top_k` | Fast path heap still preserves top-k ordering under weighted updates. | Inserts keys `1..5` with counts `10,20,30,40,50` via `insert_many` and verifies heap counts `[30,40,50]`. |
| `fast_path_merge_refreshes_existing_self_heap_entries` | Fast path merge refreshes self heap entries using merged totals. | Merges sketches where `"a-fast"` contributes `10` and `5` across sides, then verifies estimate and heap count are `15`. |
| `default_construction` | Default CMSHeap constructor uses expected dimensions and heap capacity. | Verifies `CMSHeap::<Vector2D<i64>, RegularPath>::default()` has `rows=3`, `cols=4096`, and `heap.capacity=DEFAULT_TOP_K`. |
| `default_construction_fixed_backends_parity` | Default constructors across storage backends keep intended size/capacity contracts. | Verifies defaults for Fixed/Quick backends are `5x2048`, DefaultMatrix backends are `3x4096`, and all regular/fast variants use `DEFAULT_TOP_K`. |
| `merge_requires_matching_dimensions_panics` | Merge panics on incompatible sketch dimensions. | Verifies merging `CMSHeap::new(3,256,4)` with `CMSHeap::new(4,256,4)` panics with dimension-mismatch message. |
| `heap_entries_match_cms_estimates_after_mutations` | Every heap entry count matches current CMS estimate after updates and merge. | Checks heap-entry equality to `estimate(key)` both before and after merging another mutated sketch. |
| `bulk_insert_equivalent_to_repeated_insert` | Bulk insert is equivalent to repeated single inserts. | Compares bulk vs repeated insertion on same stream and verifies identical per-key estimates and heap counts for keys `1..5`. |
| `regular_vs_fast_equivalence_on_same_stream` | Regular and fast wrappers agree on identical deterministic stream. | Feeds same 10-item string stream to both paths and verifies per-key estimates and heap counts match for `{alpha,beta,gamma,delta,epsilon}`. |
| `merge_with_empty_other_and_empty_self` | Merge behavior is stable when one side is empty. | Verifies merging non-empty with empty leaves counts unchanged and merging empty-self with non-empty copies counts/heap visibility correctly. |
| `duplicate_candidate_keys_during_merge_do_not_corrupt_heap` | Duplicate merge candidates do not duplicate heap entries. | Merges sketches both containing `"dup"`; verifies merged count `19`, heap size within capacity, and exactly one heap entry for `"dup"`. |
| `zipf_stream_top_k_recall_regular_fast_budget` | Regular path heap achieves high top-k recall on Zipf stream. | On Zipf stream (`rows=3`, `cols=4096`, `top_k=16`, `domain=1024`, `exponent=1.1`, `N=20_000`), verifies heap size bound, entry-count consistency, and recall hits `>= 15` vs truth top-16. |
| `zipf_stream_top_k_recall_fast_path_fast_budget` | Fast path heap achieves high top-k recall on Zipf stream. | Runs same Zipf setup in fast mode and verifies heap size bound, entry-count consistency, and recall hits `>= 15`. |
| `zipf_stream_regular_fast_heap_overlap` | Regular and fast heaps substantially overlap on Zipf heavy hitters. | On shared Zipf stream (`top_k=16`), verifies key overlap ratio between regular and fast top-k heaps is at least `0.8`. |
| `cms_heap_round_trip_serialization` | The envelope frames a sketch under kind_id `0x03 0x00`, and the bytes are stable across a round trip. | For a `3x8` regular-path `i64` sketch with a heap of `4` holding three weighted `u64` keys, verifies the bytes open with the ASAPv1 magic, a `kind_id_len` of `2`, and `0x03 0x00`, that the metadata carries `3x8`, `counter_type` `i64`, `mode` `regular`, `k` `4`, and `key_type` `u64`, that dimensions, counters, heap length and capacity, and per-key estimates and heap counts all match, and that re-serializing reproduces the bytes. |
| `cms_heap_byte_keys_round_trip` | A raw byte-array heap key reaches the wire as msgpack `bin`. | For a `2x4` `i64` sketch whose heap holds `[0xff, 0x00, 0xfe]` at `11`, verifies the metadata names `key_type` `bytes`, the decoded heap still finds the key by its own `DataInput::Bytes` at that count, and the bytes re-serialize identically. |
| `cms_heap_f64_counters_round_trip` | The `f64` base counter reaches the wire beside a string-keyed heap. | For a `2x4` `Vector2D<f64>` sketch holding one `Str` heap key, verifies the metadata names `counter_type` `f64` and `key_type` `string`, that the counters and the heap key survive the decode, and that the bytes re-serialize identically. |
| `cms_heap_counter_type_is_pinned_by_the_target` | The base counter type separates two otherwise equal sketches. | For `2x4` sketches holding numerically equal `i64` and `f64` cells, verifies the bytes differ, that `i64` bytes fail to decode as `f64`, and that `f64` bytes fail to decode as `i64`. |
| `cms_heap_mode_in_metadata_round_trips` | The metadata `mode` pins which column derivation built the sketch. | Round-trips a `4x16` fast-path sketch, verifies the metadata names `mode` `fast` and the counters are preserved, then that the same bytes fail to decode as a `RegularPath` sketch. |
| `cms_heap_rejects_foreign_kind_ids` | The neighbouring sketches' kind_ids are refused. | Verifies `CSHeap`, `CountMin`, and `Count` envelopes at `3x8` each fail to decode as a `CMSHeap`. |
| `cms_heap_rejects_zero_dimension_payload` | A zero dimension is a decode error, not a `Vector2D::from_fn` panic. | Verifies a crafted `4x0` envelope fails with a "must be non-zero" complaint. |
| `cms_heap_rejects_dimension_length_mismatch` | The length check fires from the declared dimensions, before any allocation is sized from them. | Verifies a crafted envelope declaring `MATRIX_MAX_ROWS x 2^24` while carrying three counters fails with a "!= rows*cols" complaint. |
| `cms_heap_rejects_serializing_an_unfilled_matrix` | The encode side refuses a matrix its own decoder would reject. | Verifies `Vector2D::<i64>::init(2, 4)`, which reserves eight cells without filling them, fails to serialize. |
| `cms_heap_metadata_rejects_unknown_keys` | An unexpected metadata key fails closed. | Encodes the thirteen `TopKMetadata` fields plus a `bogus_field` as a named map and verifies it does not decode as `TopKMetadata`. |
| `cms_heap_metadata_rejects_a_missing_k_key` | `k` is required, so the heap capacity can never be silently defaulted. | Encodes the other twelve `TopKMetadata` fields as a named map with `k` omitted and verifies it does not decode as `TopKMetadata`. |
| `cms_heap_rejects_a_foreign_counter_type_name` | `counter_type` is pinned by the target, not merely checked for naming a wire counter. | Wraps metadata naming `counter_type: "i32"` — one of Count-Min's three wire counters, alongside `i64` and `f64` — around a valid `2x4` payload, so the envelope is well-formed and still names a counter this sketch does not hold, and verifies an `i64` `CMSHeap` rejects it. |
| `cms_heap_custom_hasher_profile_round_trips_and_is_self_describing` | The metadata describes the hasher that built the sketch rather than a hardcoded profile. | For a `3x8` sketch with a heap of `4` over a hasher declaring its own `HashProfile`, verifies the counters and both heap entries round-trip, the bytes differ from the standard-profile sketch's over the same keys, and a standard-profile decode rejects them. |
| `cms_heap_refuses_a_k_the_metadata_cannot_carry` | A `k` past the metadata's `u32` field fails the encode rather than truncating. | Verifies a `2x4` sketch built at a heap capacity of `1 << 40` fails to serialize with a message naming the "exceeds the u32 metadata field" rule. |
| `heap_every_key_type_round_trips_and_keeps_its_variant` | The `key_type` names the exact `HeapItem` variant and is never widened. | Across all 13 wire key types - `i8`, `i16`, `i32`, `i64`, `isize`, `u8`, `u16`, `u32`, `u64`, `usize`, `f32`, `f64`, and `string` - verifies the metadata carries the expected name, the bytes re-serialize identically, and every decoded key is still found by its original `DataInput` at the weight it was given. |
| `heap_refuses_mixed_and_128_bit_keys` | Keys the wire cannot carry refuse to serialize rather than being coerced. | Verifies a heap holding both an `I32` and an `I64` key fails with a "keys mix variants" complaint naming `key_type is i32`, that a lone `I128` or `U128` key fails with a "128-bit" complaint, and that a 128-bit key seated behind a `U64` one fails too. |
| `heap_empty_emits_the_pinned_key_type_and_round_trips` | A heap monitoring nothing has one encoding. | For an empty `2x8` sketch with a heap of `8`, verifies the metadata carries the pinned `EMPTY_KEY_TYPE` and a `k` of `8`, and that the decode holds no entries at capacity `8` with identical re-serialized bytes. |
| `heap_emitted_order_is_independent_of_seat_order` | The emitted order is descending count with ties broken by the key, not the sift path. | Seats four entries carrying two count ties in one order and in reverse, verifies both serialize to the same bytes, that the payload reads `heap_counts` `[9, 9, 5, 5]` and `keys` `[1, 4, 2, 3]`, and that a decoded heap re-serializes identically. |
| `heap_rejects_a_key_type_the_payload_does_not_carry` | A payload relabelled with another `key_type` is refused. | Re-frames a string-keyed payload under a `u64` `key_type` and a `u64`-keyed payload under `string`, and verifies neither decodes. |
| `heap_index_is_rebuilt_so_updates_still_move_entries` | `slots` and `positions` are rebuilt on decode, so later updates land the same way. | Round-trips a four-entry heap, applies the same rescore and new-key update to the source and to the decoded copy, and verifies both serialize to the same bytes and agree on every key's count. |
| `heap_does_not_allocate_a_declared_k` | A declared `k` is metadata: it bounds the entry count and is reported as the capacity, while the rebuild reserves from the entries it actually has. | Verifies an envelope declaring `k` `u32::MAX` with two entries decodes, reports that capacity, and holds two entries. `rebuild_heap` checks the entry count against `k` first, then seats the entries into `HHHeap::with_expected_len(k, entries.len())`, whose array and index each reserve `entries.len().min(k).min(PREALLOCATED_SLOTS)` — so the declared `k` sizes no allocation on its own. |
| `heap_rejects_crafted_entry_sets` | Entry sets the heap could not have reached are refused. | Verifies three crafted envelopes each fail with their own complaint: two entries over a `k` of `1`, the same key twice, and two keys against one count. |
| `cms_heap_rejects_too_many_rows` | The base matrix carries the seed list's row bound. | Verifies a sketch past `MATRIX_MAX_ROWS` fails to serialize, that a crafted envelope of that geometry fails to decode with a message naming `MATRIX_MAX_ROWS`, and that the boundary row count still serializes. |
### CSHeap
Test file: [`src/sketches/countsketch_topk.rs`](../src/sketches/countsketch_topk.rs)
Wire tests: [`src/sketches/countsketch_topk/wire.rs`](../src/sketches/countsketch_topk/wire.rs)
| test_name | test_description | what_is_tested |
| --- | --- | --- |
| `insert_and_estimate` | Repeated inserts increment `Count` estimate for one key. | Inserts `"hello"` 5 times into `CSHeap::new(5,256,10)` and verifies estimate is `5.0` within `1e-9`. |
| `heap_tracks_top_k` | Heap keeps highest-frequency keys within top-k capacity. | Inserts keys `1..5` with frequencies `100,200,300,400,500` into `top_k=3` sketch and verifies heap counts are exactly `[300,400,500]`. |
| `merge_reconciles_heaps` | Merge combines counters and refreshes heap counts from merged sketch. | Merges two sketches containing `"merge_key"` counts `10` and `20`, then verifies estimate is `30.0` and heap count is `30`. |
| `insert_many_updates_estimate_and_heap` | `insert_many` updates estimate and heap entry consistently. | Calls `insert_many("many", 17)` and verifies estimate `17.0` plus heap entry count equals estimated count. |
| `bulk_insert_updates_multiple_keys` | `bulk_insert` updates multiple keys and heavy-hitter counts correctly. | Inserts stream `[7,8,7,9,7]`, verifies estimate for key `7` is `3.0`, and heap count for key `7` matches estimate cast to integer. |
| `clear_heap_keeps_cs_counters` | Clearing heap does not clear `Count` counters. | After `insert_many("persist",5)`, calls `clear_heap()`, verifies estimate remains `5.0`, then one more insert repopulates heap with updated estimate count. |
| `from_storage_uses_storage_dimensions` | `from_storage` preserves backend dimensions and requested heap capacity. | Builds from `Vector2D::init(4,128)` with `top_k=9` and verifies `rows=4`, `cols=128`, `heap.capacity=9`. |
| `merge_refreshes_existing_self_heap_entries` | Merge refreshes pre-existing self heap keys to merged estimates. | Merges sketches where `"a-key"` is updated on both sides (`120` and `40`), then verifies heap count for `"a-key"` equals merged estimate. |
| `fast_path_insert_and_estimate` | Fast path repeated inserts keep estimate exact for single key. | Inserts `"fast"` 7 times into fast-path sketch and verifies estimate is `7.0` within `1e-9`. |
| `fast_path_insert_many_and_bulk_insert` | Fast path batched APIs keep heap and estimate in sync. | Applies `insert_many("fast-many",6)` plus bulk inserts adding 2 hits, then verifies estimate is `8.0` and heap count matches it. |
| `fast_path_heap_tracks_top_k` | Fast path heap preserves top-k ordering under weighted updates. | Inserts keys `1..5` with counts `100,200,300,400,500` via `insert_many` and verifies heap counts `[300,400,500]`. |
| `fast_path_merge_refreshes_existing_self_heap_entries` | Fast path merge refreshes self heap entries using merged totals. | Merges fast sketches where `"a-fast"` is updated on both sides (`120` and `40`) and verifies heap count equals merged estimate. |
| `default_construction` | Default CSHeap constructor uses expected dimensions and heap capacity. | Verifies `CSHeap::<Vector2D<i64>, RegularPath>::default()` has `rows=3`, `cols=4096`, and `heap.capacity=DEFAULT_TOP_K`. |
| `default_construction_fixed_backends_parity` | Default constructors across storage backends keep intended size/capacity contracts. | Verifies defaults for Fixed/Quick backends are `5x2048`, DefaultMatrix backends are `3x4096`, and all regular/fast variants use `DEFAULT_TOP_K`. |
| `merge_requires_matching_dimensions_panics` | Merge panics on incompatible sketch dimensions. | Verifies merging `CSHeap::new(5,256,4)` with `CSHeap::new(6,256,4)` panics with dimension-mismatch message. |
| `heap_entries_match_cs_estimates_after_mutations` | Every heap entry count matches current sketch estimate after updates and merge. | Checks heap-entry equality to `estimate(key)` both before and after merging another mutated sketch. |
| `bulk_insert_equivalent_to_repeated_insert` | Bulk insert is equivalent to repeated single inserts. | Compares bulk vs repeated insertion on same stream and verifies per-key estimates match within `1e-9` plus identical heap counts for keys `1..5`. |
| `regular_vs_fast_equivalence_on_same_stream` | Regular and fast wrappers agree on identical deterministic stream. | Feeds same 10-item string stream to both paths and verifies per-key estimates match within `1e-9` and heap counts match for `{alpha,beta,gamma,delta,epsilon}`. |
| `merge_with_empty_other_and_empty_self` | Merge behavior is stable when one side is empty. | Verifies merging non-empty with empty leaves estimates/heap size unchanged and merging empty-self with non-empty reproduces estimates and heap visibility. |
| `duplicate_candidate_keys_during_merge_do_not_corrupt_heap` | Duplicate merge candidates do not duplicate heap entries. | Merges sketches both containing `"dup"`; verifies heap count equals merged estimate, heap size stays within capacity, and only one heap entry exists for `"dup"`. |
| `zipf_stream_top_k_recall_regular_fast_budget` | Regular path heap achieves high top-k recall on Zipf stream. | On Zipf stream (`rows=5`, `cols=4096`, `top_k=16`, `domain=1024`, `exponent=1.1`, `N=20_000`), verifies heap size bound, entry-count consistency, and recall hits `>= 15` vs truth top-16. |
| `zipf_stream_top_k_recall_fast_path_fast_budget` | Fast path heap achieves high top-k recall on Zipf stream. | Runs same Zipf setup in fast mode and verifies heap size bound, entry-count consistency, and recall hits `>= 15`. |
| `zipf_stream_regular_fast_heap_overlap` | Regular and fast heaps substantially overlap on Zipf heavy hitters. | On shared Zipf stream (`top_k=16`), verifies key overlap ratio between regular and fast top-k heaps is at least `0.8`. |
| `cs_heap_round_trip_serialization` | The envelope frames a sketch under kind_id `0x0a 0x00`, and the bytes are stable across a round trip. | For a `3x8` regular-path `i64` sketch with a heap of `4` holding three weighted `u64` keys, verifies the bytes open with the ASAPv1 magic, a `kind_id_len` of `2`, and `0x0a 0x00`, that the metadata carries `3x8`, `counter_type` `i64`, `mode` `regular`, `k` `4`, and `key_type` `u64`, that dimensions, counters, heap length and capacity, and per-key estimates and heap counts all match, and that re-serializing reproduces the bytes. |
| `cs_heap_negative_counters_round_trip` | Signed cells reach the wire and come back unchanged. | Round-trips a `2x4` matrix of alternating positive and negative counters beside a `Str` heap key, and verifies the decoded slice equals the source, still holds a negative cell, keeps the heap key, and re-serializes identically. |
| `cs_heap_i32_round_trips_and_is_pinned_by_counter_type` | The `i32` wire config round-trips and its width is identity, not a detail. | Round-trips a `2x4` `Vector2D<i32>` sketch, verifies the metadata names `counter_type` `i32`, then that its bytes differ from the numerically equal `i64` sketch's, that `i32` bytes fail to decode as `i64`, and that `i64` bytes fail to decode as `i32`. |
| `cs_heap_mode_in_metadata_round_trips` | The metadata `mode` pins which column derivation built the sketch. | Round-trips a `4x16` fast-path sketch, verifies the metadata names `mode` `fast` and the counters are preserved, then that the same bytes fail to decode as a `RegularPath` sketch. |
| `cs_heap_rejects_foreign_kind_ids` | The neighbouring sketches' kind_ids are refused. | Verifies `CMSHeap`, `CountMin`, and `Count` envelopes at `3x8` each fail to decode as a `CSHeap`. |
| `cs_heap_rejects_zero_dimension_payload` | A zero dimension is a decode error, not a `Vector2D::from_fn` panic. | Verifies a crafted `4x0` envelope fails with a "must be non-zero" complaint. |
| `cs_heap_rejects_dimension_length_mismatch` | The length check fires from the declared dimensions, before any allocation is sized from them. | Verifies a crafted envelope declaring `MATRIX_MAX_ROWS x 2^24` while carrying three counters fails with a "!= rows*cols" complaint. |
| `cs_heap_rejects_serializing_an_unfilled_matrix` | The encode side refuses a matrix its own decoder would reject. | Verifies `Vector2D::<i64>::init(2, 4)`, which reserves eight cells without filling them, fails to serialize. |
| `cs_heap_metadata_rejects_unknown_keys` | An unexpected metadata key fails closed. | Encodes the thirteen `TopKMetadata` fields plus a `bogus_field` as a named map and verifies it does not decode as `TopKMetadata`. |
| `cs_heap_metadata_rejects_a_missing_key_type_key` | `key_type` is required, so the heap's key variant can never be silently defaulted. | Encodes the other twelve `TopKMetadata` fields as a named map with `key_type` omitted and verifies it does not decode as `TopKMetadata`. |
| `cs_heap_rejects_a_foreign_counter_type_name` | A Count-Min-only counter type name is not a Count Sketch one. | Wraps metadata naming `counter_type: "f64"` around a valid `2x4` payload and verifies both the `i64` and the `i32` sketch reject it. |
| `cs_heap_custom_hasher_profile_round_trips_and_is_self_describing` | The metadata describes the hasher that built the sketch rather than a hardcoded profile. | For a `3x8` sketch with a heap of `4` over a hasher declaring its own `HashProfile`, verifies the counters and both heap entries round-trip, the bytes differ from the standard-profile sketch's over the same keys, and a standard-profile decode rejects them. |
| `cs_heap_refuses_a_k_the_metadata_cannot_carry` | A `k` past the metadata's `u32` field fails the encode rather than truncating. | Verifies a `2x4` sketch built at a heap capacity of `1 << 40` fails to serialize with a message naming the "exceeds the u32 metadata field" rule. |
| `cs_heap_rejects_too_many_rows` | The base matrix carries the seed list's row bound. | Verifies a sketch past `MATRIX_MAX_ROWS` fails to serialize, that a crafted envelope of that geometry fails to decode with a message naming `MATRIX_MAX_ROWS`, and that the boundary row count still serializes. |
### CountL2HH
Test file: [`src/sketches/countsketch_topk.rs`](../src/sketches/countsketch_topk.rs)
Wire tests: [`src/sketches/countsketch_topk/l2hh_wire.rs`](../src/sketches/countsketch_topk/l2hh_wire.rs)
| test_name | test_description | what_is_tested |
| --- | --- | --- |
| `countl2hh_estimates_and_l2_are_consistent` | CountL2HH updates keep estimate and L2 consistent. | For `CountL2HH(3x32)`, applies `+5` then `-2` to one key, verifies estimates `5.0` then `3.0`, and asserts non-trivial L2 (`>= 3.0`). |
| `countl2hh_merge_combines_frequency_vectors` | CountL2HH merge combines per-key frequencies. | Merges two `CountL2HH(3x32)` sketches with same key counts `4` and `9`, then verifies merged estimate `== 13.0`. |
| `countl2hh_round_trip_serialization` | CountL2HH serialization round trip preserves estimate and L2. | Serializes/deserializes `CountL2HH::with_dimensions_and_seed(3,32,7)` after updates, verifying rows/cols and that both estimate and L2 remain unchanged (within `f64::EPSILON`). |
| `count_l2hh_round_trip_serialization` | The envelope frames a sketch under kind_id `0x19 0x00`, and the state survives a round trip. | For a `3x32` sketch seeded at `7` over three signed weighted inserts, verifies the bytes open with the ASAPv1 magic, a `kind_id_len` of `2`, and `0x19 0x00`, that the metadata carries `seed_index` `7` and `3x32`, and that the decode matches on dimensions, seed index, the counter array, the `l2` accumulators, and `get_l2`. |
| `count_l2hh_decoded_re_serializes_identically` | A decoded sketch re-serializes byte for byte. | Verifies the populated `3x32` sketch's decode re-encodes to the bytes it came from. |
| `count_l2hh_negative_counters_round_trip` | Signed cells reach the wire and come back unchanged. | Round-trips a `2x8` sketch fed two negative weights and verifies the decoded slice equals the source, still holds a negative cell, and re-serializes identically. |
| `count_l2hh_seed_index_travels_with_the_sketch` | The seed index is state, not a profile constant. | Verifies `2x8` sketches seeded at `0` and at `9` do not share bytes, and that the decoded seed-`9` sketch reports a `seed_idx` of `9`. |
| `count_l2hh_custom_hasher_profile_round_trips_and_is_self_describing` | The metadata describes the hasher that built the sketch rather than a hardcoded profile. | For a `3x32` sketch over a hasher declaring its own `HashProfile`, verifies the counter array round-trips, the bytes differ from the standard-profile sketch's over the same insert, and a standard-profile decode rejects them. |
| `count_l2hh_rejects_foreign_kind_ids` | The neighbouring universal-sketch kind_ids are refused. | Verifies `Count`, `UnivMon`, `UnivMonPyramid`, and `UnivMonQ` envelopes each fail to decode as a `CountL2HH`. |
| `count_l2hh_rejects_crafted_geometry` | Every geometry rule fires before an allocation is sized from it. | Verifies crafted envelopes carrying a zero `cols`, a `MATRIX_MAX_ROWS x 2^24` declaration against three counters, a five-entry `l2` array against two rows, and a negative `l2` accumulator each fail to decode. |
| `count_l2hh_rejects_serializing_an_unfilled_matrix` | The encode side refuses a matrix its own decoder would reject. | Verifies a `2x4` sketch whose counts are replaced by `Vector2D::init(2, 4)`, which reserves eight cells without filling them, fails to serialize. |
| `l2hh_metadata_rejects_unknown_and_missing_keys` | An unexpected metadata key and a missing required one both fail closed. | Encodes the nine `L2hhMetadata` fields plus a `bogus_field`, and the same fields with `cols` omitted, and verifies neither decodes as `L2hhMetadata`. |
| `count_l2hh_empty_has_one_encoding` | A sketch holding nothing has exactly one encoding. | Verifies a fresh `3x32` sketch and one cleared after an insert serialize to identical bytes. |
| `countl2hh_rejects_too_many_rows` | CountL2HH carries the seed list's row bound on both sides. | Verifies a sketch past `MATRIX_MAX_ROWS` fails to serialize, that a crafted envelope of that geometry fails to decode with a message naming `MATRIX_MAX_ROWS`, and that the boundary row count still serializes. |
### FoldCMS
Test file: [`src/sketches/fold_cms.rs`](../src/sketches/fold_cms.rs)
Conformance: [`tests/conformance_kit.rs`](../tests/conformance_kit.rs) runs `folded_frequency_sketches_pass_frequency_and_merge_conformance`, which drives a `FoldCMS::new(4, 8_192, 1, 64)` through the shared one-sided `frequency_battery` and `merge_equivalence_battery` over a 60,000-draw Zipf stream across a 2,048-key domain.
The `FoldCell` and `FoldEntry` tests live here because both types are declared in this file; `FoldCS` reuses them without re-testing them.
| test_name | test_description | what_is_tested |
| --- | --- | --- |
| `cell_starts_empty` | A `FoldCell::Empty` answers every query without holding anything. | Verifies `entry_count()` is `0`, `is_empty()` is true, and `query(42)` is `0`. |
| `cell_single_insert` | The first insert seats one entry inline. | After `insert(10, 5)` into an `Empty` cell, verifies `entry_count()` is `1`, `query(10)` is `5`, `query(11)` is `0`, and the cell matches `FoldCell::Single`. |
| `cell_single_accumulates` | A repeat of the same `full_col` adds in place rather than upgrading. | After `insert(10, 5)` then `insert(10, 3)`, verifies `entry_count()` is still `1`, `query(10)` is `8`, and the cell still matches `FoldCell::Single`. |
| `cell_collision_upgrades_to_collided` | A second distinct `full_col` is what upgrades the cell. | After `insert(10, 5)` then `insert(42, 3)`, verifies `entry_count()` is `2`, the cell matches `FoldCell::Collided`, and `query(10)` and `query(42)` read `5` and `3`. |
| `cell_collided_accumulates` | A collided cell adds into the matching entry, not a new one. | Inserts `(10, 5)`, `(42, 3)`, `(10, 2)`, `(42, 7)` and verifies `query(10)` is `7`, `query(42)` is `10`, and `entry_count()` is still `2`. |
| `cell_collided_third_entry` | A third distinct `full_col` is appended to the collided vector. | Inserts `(10, 1)`, `(42, 2)`, `(99, 3)` and verifies `entry_count()` is `3` and each column reads back its own `1`, `2`, and `3`. |
| `cell_merge_from_empty` | Merging an empty cell leaves the target alone. | Merges an `Empty` cell into one holding `10` at `5` and verifies `query(10)` is still `5`; nothing else is asserted, so the target's variant is not checked. |
| `cell_merge_from_single` | Merging a matching `full_col` adds without upgrading. | Merges a cell holding `10` at `3` into one holding `10` at `5` and verifies `query(10)` is `8` and the target still matches `FoldCell::Single`. |
| `cell_merge_from_collision` | Merging a different `full_col` upgrades the target. | Merges a cell holding `42` at `3` into one holding `10` at `5` and verifies `query(10)` is `5`, `query(42)` is `3`, and the target matches `FoldCell::Collided`. |
| `cell_iter_empty` | An empty cell iterates nothing. | Verifies `FoldCell::Empty.iter().count()` is `0`; that single assertion is the whole test. |
| `cell_iter_single` | An inline entry iterates as one pair. | For a cell holding `7` at `99`, verifies the collected items are exactly `[(7, 99)]`. |
| `cell_iter_collided` | A collided cell iterates every pair it holds. | For a cell holding `7` at `10` and `15` at `20`, verifies the collected items, once sorted, are exactly `[(7, 10), (15, 20)]`. |
| `fold_cms_dimensions` | The fold level fixes the physical column count. | For `FoldCMS::new(3, 4096, 4, 10)`, verifies `rows()` is `3`, `full_cols()` is `4096`, `fold_cols()` is `256` (`4096 / 2^4`), and `fold_level()` is `4`. |
| `fold_cms_level_zero_is_full` | `new_full` builds a level-zero, full-width sketch. | For `FoldCMS::new_full(3, 1024, 10)`, verifies `fold_cols()` is `1024` and `fold_level()` is `0`. |
| `fold_cms_rejects_non_power_of_two` | A `full_cols` that is not a power of two is refused at construction. | Verifies `FoldCMS::new(3, 1000, 0, 10)` panics with "full_cols must be a power of two". |
| `fold_cms_rejects_excessive_fold_level` | A fold level past the column width is refused at construction. | Verifies `FoldCMS::new(3, 256, 9, 10)` panics with a message naming `fold_level`, `256` being `2^8` so `9` is one level too many. |
| `fold_cms_insert_query_single_key` | A weighted insert reads back at its weight. | Inserts `Str("hello")` at `7` into a `3x1024` level-4 sketch and verifies `query` is `7`. |
| `fold_cms_insert_accumulates` | Two weighted inserts of one key sum. | Inserts `Str("hello")` at `3` then `4` into a `3x1024` level-4 sketch and verifies `query` is `7`. |
| `fold_cms_absent_key_returns_zero` | An unseen key reads zero. | After inserting `Str("present")` at `10` into a `3x1024` level-4 sketch, verifies `query(Str("absent"))` is `0`. |
| `fold_cms_multiple_keys` | Estimates stay one-sided across a hundred weighted keys. | Inserts `U64(i)` at weight `i` for `i` in `0..100` into a `3x4096` level-4 sketch and verifies each estimate is at or above its true count; no upper bound is asserted. |
| `fold_cms_matches_standard_cms_exact` | A folded sketch answers exactly as the full-width CMS it targets. | For `rows=3`, `cols=256`, `fold_level=3` (32 physical columns) over `I32(0..50)` inserted once each, verifies every `query` equals the `CountMin<Vector2D<i64>, RegularPath>::with_dimensions(3, 256)` estimate, and that `to_flat_counters()` has the same length as the standard sketch's storage slice and equals it cell for cell. |
| `fold_cms_matches_standard_cms_insert_many` | Weighted inserts match the full-width CMS's `insert_many`. | For `rows=3`, `cols=512`, `fold_level=4` over `U64(0..30)` at weight `i + 1`, verifies every `query` equals the standard sketch's estimate after the same `insert_many` calls. |
| `same_level_merge_adds_counts` | A same-level merge sums the two sides' counts. | Inserts `Str("user_001")` at `100` into one `3x1024` level-3 sketch and at `200` into another, then verifies `merge_same_level` leaves `query` at `300`. |
| `same_level_merge_matches_standard_cms_merge` | A same-level merge answers as the merged full-width CMS. | For `rows=3`, `cols=512`, `fold_level=4` with `U64(0..20)` on the left and `U64(10..30)` on the right inserted once each, verifies every `query` after `merge_same_level` equals the estimate after `CountMin::merge` for keys `0..30`. |
| `unfold_merge_reduces_level` | `unfold_merge` drops the fold level by one. | For two empty `3x1024` level-3 sketches, verifies the result reports `fold_level()` `2` and `fold_cols()` `cols >> 2`; nothing is inserted, so only the geometry is checked. |
| `unfold_merge_preserves_counts` | An unfolding merge keeps both sides' counts. | Inserts `Str("alpha")` at `10` into one `3x256` level-2 sketch and `Str("beta")` at `20` into another, then verifies the merged sketch is level `1` and queries `10` and `20`. |
| `unfold_merge_matches_standard_cms_merge` | An unfolding merge answers as the merged full-width CMS. | For `rows=3`, `cols=512`, `fold_level=2` with `U64(0..40)` on the left and `U64(20..60)` on the right at weight `i + 1`, verifies every `unfold_merge` query equals the merged standard sketch's estimate for keys `0..60`. |
| `hierarchical_merge_four_sketches` | Four epochs merge down to full width and stay exact. | Builds four `3x1024` level-2 sketches (256 physical columns) over `U64` ranges `0..10`, `10..20`, `20..30`, and `30..40` inserted once each, then verifies `hierarchical_merge` reports `fold_level()` `0` and matches the standard `3x1024` CMS estimate for all 40 keys. |
| `unfold_full_matches_flat_counters` | `unfold_full` changes the geometry, not the counters. | For a `3x256` level-4 sketch over `I32(0..30)` inserted once each, verifies `unfold_full()` reports `fold_level()` `0` and `fold_cols()` `256`, and that `to_flat_counters()` is unchanged. |
| `to_flat_counters_matches_standard_cms` | The flat counter view is the full-width matrix. | For `rows=3`, `cols=128`, `fold_level=3` over `I32(0..20)` inserted once each, verifies `to_flat_counters()` has the same length as the standard sketch's storage slice, then zips the two and verifies equality cell by cell. |
| `serde_round_trip_keeps_the_cells_the_geometry_and_the_heap` | The derived serde form carries the cells, the geometry and the heap. | For `rows=3`, `full_cols=4096`, `fold_level=4`, `top_k=16` fed a seeded (`0x5EED_C45C`) Zipf(`domain = 2_000`, `exponent = 1.2`) stream of `20_000` samples - first checking the fixture actually produced collided cells - round-trips through `rmp_serde` and verifies `rows`, `fold_cols`, `full_cols`, `fold_level`, `total_entries`, `collided_cells` and `to_flat_counters()` are unchanged, that all `2_000` keys estimate identically, that the heap holds the same `16` residents in the same order with the same counts, and that the rebuilt (`#[serde(skip)]`) key index finds its own resident. |
| `sparse_subwindow_has_few_collisions` | A sparse sub-window keeps its cells mostly uncollided. | Inserts 50 distinct `U64` keys into a `3x4096` level-4 sketch (256 physical columns) and verifies `total_entries()` is at most `rows * 50` and at least `rows * 45`, and that `collided_cells()` is under `30`. |
| `heap_tracks_heavy_hitters` | The top-k heap carries the heaviest key at its estimate. | Inserts `Str("heavy")` 100 times, `Str("medium")` 10 times, and `Str("light")` once into a `3x1024` level-3 sketch with `top_k=5`, then verifies the heap is not empty and its `"heavy"` entry reads `100`; the other two keys' entries are not checked. |
| `heap_survives_same_level_merge` | A same-level merge refreshes the heap to the merged estimate. | Inserts `Str("user_x")` 50 times into one `3x1024` level-3 `top_k=5` sketch and 70 times into another, then verifies the heap entry after `merge_same_level` reads `120`. |
| `heap_survives_unfold_merge` | An unfolding merge carries the heap forward at the merged estimate. | Inserts `Str("endpoint_a")` 40 times into one `3x512` level-2 `top_k=5` sketch and 60 times into another, then verifies the merged sketch's heap entry reads `100`. |
| `fold_cms_error_bound_zipf` | Folding does not widen the CMS error bound on a Zipf stream. | For a `3x4096` level-4 sketch with `top_k=20` fed 200,000 draws over an 8,192-key domain at exponent `1.1` and seed `0x5eed_c0de`, counts the keys whose absolute error is under `(e / 4096) * 200_000` and requires that count to exceed `truth.len() * (1 - e^-3)`. |
| `scenario_rate_limiting` | Per-user counts merge exactly across two epochs. | Merges two `3x4096` level-4 epoch sketches holding `user_001` at `350` and `350`, `user_002` at `10` and `5`, and `user_003` at `600` and `700`, and verifies `merge_same_level` leaves queries of exactly `700`, `15`, and `1300`. |
| `scenario_error_frequency` | Per-endpoint error counts merge exactly across two epochs. | Merges two `3x4096` level-4 epoch sketches over four endpoint strings and verifies queries of exactly `350` for `/api/v1/search`, `210` for `/api/v1/login`, `101` for `/api/v2/recommend`, and `10` for `/api/v1/checkout`. |
| `scenario_ddos_detection` | Three epochs — not a power of two — merge and still separate the threshold. | `hierarchical_merge` over three `3x4096` level-4 epoch sketches of four IP strings is verified to leave `10.0.0.42` at exactly `37_000`, above the `15_000` threshold, and `172.16.5.99` at exactly `9_055` and `10.0.0.43` at exactly `8_300`, both below it. |
| `scatter_merge_matches_standard_cms_n1_to_n8` | The N-way scatter merge is exact for every N from 1 to 8. | For each `n` in `1..=8`, builds `n` `3x1024` level-3 epoch sketches over ten consecutive `U64` keys each, and verifies `hierarchical_merge` reports `fold_level()` `0` and matches the standard `3x1024` CMS estimate for all `10 * n` keys. |
| `unfold_to_single_pass_preserves_flat_counters` | A single-pass `unfold_to` is exact at every target level. | For a `3x256` level-4 sketch over `U64(0..40)` at weight `i + 1`, verifies that for target levels `3`, `2`, `1`, and `0` the result reports that level, `fold_cols()` of `cols >> target`, and `to_flat_counters()` identical to the source's. |
| `unfold_to_same_level_returns_clone` | `unfold_to` at the current level is a no-op. | For a `3x256` level-3 sketch holding `Str("x")` at `42`, verifies `unfold_to(3)` reports `fold_level()` `3` and queries `42`. |
| `hierarchical_merge_mixed_fold_levels` | Sketches at different fold levels merge to the same answer as scattering each one first. | Merges a `3x1024` level-4 sketch over `U64(0..20)` with a `3x1024` level-2 sketch over `U64(10..30)`, verifies `hierarchical_merge` reaches `fold_level()` `0`, and compares every key in `0..30` against a reference built by `unfold_to(0)` on each side followed by `merge_same_level`. |
### FoldCS
Test file: [`src/sketches/fold_cs.rs`](../src/sketches/fold_cs.rs)
Conformance: [`tests/conformance_kit.rs`](../tests/conformance_kit.rs) runs `folded_frequency_sketches_pass_frequency_and_merge_conformance`, which drives a `FoldCS::new(5, 8_192, 1, 64)` through the shared two-sided `frequency_battery`, the `turnstile_battery`, and the `merge_equivalence_battery` over a 60,000-draw Zipf stream across a 2,048-key domain.
The shared `FoldCell` and `FoldEntry` behaviour is covered by the cell tests in the [FoldCMS](#foldcms) section.
| test_name | test_description | what_is_tested |
| --- | --- | --- |
| `fold_cs_dimensions` | The fold level fixes the physical column count. | For `FoldCS::new(3, 4096, 4, 10)`, verifies `rows()` is `3`, `full_cols()` is `4096`, `fold_cols()` is `256` (`4096 / 2^4`), and `fold_level()` is `4`. |
| `fold_cs_level_zero_is_full` | `new_full` builds a level-zero, full-width sketch. | For `FoldCS::new_full(3, 1024, 10)`, verifies `fold_cols()` is `1024` and `fold_level()` is `0`. |
| `fold_cs_rejects_non_power_of_two` | A `full_cols` that is not a power of two is refused at construction. | Verifies `FoldCS::new(3, 1000, 0, 10)` panics with "full_cols must be a power of two". |
| `fold_cs_rejects_excessive_fold_level` | A fold level past the column width is refused at construction. | Verifies `FoldCS::new(3, 256, 9, 10)` panics with a message naming `fold_level`, `256` being `2^8` so `9` is one level too many. |
| `fold_cs_insert_query_single_key` | A weighted insert reads back at its weight through the median. | Inserts `Str("hello")` at `7` into a `3x1024` level-4 sketch and verifies `query` is `7`. |
| `fold_cs_insert_accumulates` | Two weighted inserts of one key sum. | Inserts `Str("hello")` at `3` then `4` into a `3x1024` level-4 sketch and verifies `query` is `7`. |
| `fold_cs_absent_key_returns_zero` | An unseen key reads zero. | After inserting `Str("present")` at `10` into a `3x1024` level-4 sketch, verifies `query(Str("absent"))` is `0`. |
| `fold_cs_multiple_keys` | Estimates stay close on both sides across a hundred weighted keys. | Inserts `U64(i)` at weight `i` for `i` in `0..100` into a `3x4096` level-4 sketch and verifies every estimate's absolute error is at most `10`, the signed estimator being two-sided. |
| `fold_cs_sign_application` | The per-row `±1` sign really reaches the stored counters. | Inserts 50 distinct `U64` keys at weight `1` into a `5x1024` level-4 sketch, walks every cell's entries, and verifies at least one count is positive and at least one is negative; no particular sign or cell is pinned. |
| `fold_cs_matches_standard_cs_exact` | A folded sketch answers exactly as the full-width Count Sketch it targets. | For `rows=3`, `cols=256`, `fold_level=3` (32 physical columns) over `I32(0..50)` inserted once each, verifies every `query` equals the `Count<Vector2D<i64>, RegularPath>::with_dimensions(3, 256)` estimate cast to `i64`. |
| `fold_cs_matches_standard_cs_flat_counters` | The flat counter view is the full-width signed matrix. | For the same `3x256` level-3 sketch over `I32(0..50)`, verifies `to_flat_counters()` has the same length as the standard sketch's storage slice and equals it cell for cell. |
| `fold_cs_matches_standard_cs_insert_many` | Weighted inserts match the full-width Count Sketch's `insert_many`. | For `rows=3`, `cols=512`, `fold_level=4` over `U64(0..30)` at weight `i + 1`, verifies every `query` equals the standard sketch's estimate cast to `i64` after the same `insert_many` calls. |
| `same_level_merge_adds_counts` | A same-level merge sums the two sides' counts. | Inserts `Str("user_001")` at `100` into one `3x1024` level-3 sketch and at `200` into another, then verifies `merge_same_level` leaves `query` at `300`. |
| `same_level_merge_matches_standard_cs_merge` | A same-level merge answers as the merged full-width Count Sketch. | For `rows=3`, `cols=512`, `fold_level=4` with `U64(0..20)` on the left and `U64(10..30)` on the right inserted once each, verifies every `query` after `merge_same_level` equals the estimate after `Count::merge` for keys `0..30`. |
| `unfold_merge_reduces_level` | `unfold_merge` drops the fold level by one. | For two empty `3x1024` level-3 sketches, verifies the result reports `fold_level()` `2` and `fold_cols()` `cols >> 2`; nothing is inserted, so only the geometry is checked. |
| `unfold_merge_preserves_counts` | An unfolding merge keeps both sides' counts. | Inserts `Str("alpha")` at `10` into one `3x256` level-2 sketch and `Str("beta")` at `20` into another, then verifies the merged sketch is level `1` and queries `10` and `20`. |
| `unfold_merge_matches_standard_cs_merge` | An unfolding merge answers as the merged full-width Count Sketch. | For `rows=3`, `cols=512`, `fold_level=2` with `U64(0..40)` on the left and `U64(20..60)` on the right at weight `i + 1`, verifies every `unfold_merge` query equals the merged standard sketch's estimate cast to `i64` for keys `0..60`. |
| `hierarchical_merge_four_sketches` | Four epochs merge down to full width and stay exact. | Builds four `3x1024` level-2 sketches (256 physical columns) over `U64` ranges `0..10`, `10..20`, `20..30`, and `30..40` inserted once each, then verifies `hierarchical_merge` reports `fold_level()` `0` and matches the standard `3x1024` Count Sketch estimate for all 40 keys. |
| `unfold_full_matches_flat_counters` | `unfold_full` changes the geometry, not the counters. | For a `3x256` level-4 sketch over `I32(0..30)` inserted once each, verifies `unfold_full()` reports `fold_level()` `0` and `fold_cols()` `256`, and that `to_flat_counters()` is unchanged. |
| `to_flat_counters_matches_standard_cs` | The flat counter view matches the full-width matrix on a second geometry. | For `rows=3`, `cols=128`, `fold_level=3` over `I32(0..20)` inserted once each, verifies `to_flat_counters()` has the same length as the standard sketch's storage slice, then zips the two and verifies equality cell by cell. |
| `serde_round_trip_keeps_the_cells_the_geometry_and_the_heap` | The derived serde form carries the cells, the geometry and the heap. | For `rows=3`, `full_cols=4096`, `fold_level=4`, `top_k=16` fed a seeded (`0x5EED_C55C`) Zipf(`domain = 2_000`, `exponent = 1.2`) stream of `20_000` samples - first checking the fixture actually produced collided cells - round-trips through `rmp_serde` and verifies `rows`, `fold_cols`, `full_cols`, `fold_level`, `total_entries`, `collided_cells` and `to_flat_counters()` are unchanged, that all `2_000` keys estimate identically, that the heap holds the same `16` residents in the same order with the same counts, and that the rebuilt (`#[serde(skip)]`) key index finds its own resident. |
| `sparse_subwindow_has_few_collisions` | A sparse sub-window keeps its cells mostly uncollided. | Inserts 50 distinct `U64` keys into a `3x4096` level-4 sketch (256 physical columns) and verifies `total_entries()` is at most `rows * 50` and at least `rows * 45`, and that `collided_cells()` is under `30`. |
| `heap_tracks_heavy_hitters` | The top-k heap carries the heaviest key at its estimate. | Inserts `Str("heavy")` 100 times, `Str("medium")` 10 times, and `Str("light")` once into a `3x1024` level-3 sketch with `top_k=5`, then verifies the heap is not empty and its `"heavy"` entry reads `100`; the other two keys' entries are not checked. |
| `heap_survives_same_level_merge` | A same-level merge refreshes the heap to the merged estimate. | Inserts `Str("user_x")` 50 times into one `3x1024` level-3 `top_k=5` sketch and 70 times into another, then verifies the heap entry after `merge_same_level` reads `120`. |
| `heap_survives_unfold_merge` | An unfolding merge carries the heap forward at the merged estimate. | Inserts `Str("endpoint_a")` 40 times into one `3x512` level-2 `top_k=5` sketch and 60 times into another, then verifies the merged sketch's heap entry reads `100`. |
| `fold_cs_error_bound_zipf` | Folding does not widen the Count Sketch L2 error bound on a Zipf stream. | For a `3x4096` level-4 sketch with `top_k=20` fed 200,000 draws over an 8,192-key domain at exponent `1.1` and seed `0x5eed_c0de`, counts the keys whose absolute error is under `sqrt(e / 4096)` times the stream's exact L2 norm and requires that count to exceed `truth.len() * (1 - e^-3)`. |
| `scatter_merge_matches_standard_cs_n1_to_n8` | The N-way scatter merge is exact for every N from 1 to 8. | For each `n` in `1..=8`, builds `n` `3x1024` level-3 epoch sketches over ten consecutive `U64` keys each, and verifies `hierarchical_merge` reports `fold_level()` `0` and matches the standard `3x1024` Count Sketch estimate for all `10 * n` keys. |
| `unfold_to_single_pass_preserves_flat_counters` | A single-pass `unfold_to` is exact at every target level. | For a `3x256` level-4 sketch over `U64(0..40)` at weight `i + 1`, verifies that for target levels `3`, `2`, `1`, and `0` the result reports that level, `fold_cols()` of `cols >> target`, and `to_flat_counters()` identical to the source's. |
| `unfold_to_same_level_returns_clone` | `unfold_to` at the current level is a no-op. | For a `3x256` level-3 sketch holding `Str("x")` at `42`, verifies `unfold_to(3)` reports `fold_level()` `3` and queries `42`. |
| `hierarchical_merge_mixed_fold_levels` | Sketches at different fold levels merge to the same answer as scattering each one first. | Merges a `3x1024` level-4 sketch over `U64(0..20)` with a `3x1024` level-2 sketch over `U64(10..30)`, verifies `hierarchical_merge` reaches `fold_level()` `0`, and compares every key in `0..30` against a reference built by `unfold_to(0)` on each side followed by `merge_same_level`. |
### SpaceSaving
Test file: [`tests/e2e_heavy_hitters.rs`](../tests/e2e_heavy_hitters.rs)
Unit tests: [`src/sketches/space_saving.rs`](../src/sketches/space_saving.rs)
Wire tests: [`src/sketches/space_saving/wire.rs`](../src/sketches/space_saving/wire.rs)
Conformance: [`tests/conformance_kit.rs`](../tests/conformance_kit.rs) runs `space_saving_passes_frequency_conformance`, the shared one-sided `frequency_battery` over 1,024 counters.
| test_name | test_description | what_is_tested |
| --- | --- | --- |
| `a_monitored_key_is_sandwiched_by_its_error` | Every monitored key's estimate brackets its true count. | Over a seeded Zipf stream, verifies each monitored key reads at or above its true count and no further above it than that key's own `error`, and that the summary is saturated at its capacity. |
| `an_unmonitored_key_never_exceeds_the_minimum_count` | Dropped keys stay under the `min_count` ceiling. | Verifies every key the summary evicted has a true count at or below `min_count`, and that `upper_bound` and `error` for such a key both report that ceiling. |
| `the_true_heavy_hitters_are_reported_exactly_and_in_order` | `top_k` returns the real heaviest keys in descending order. | Compares `top_k` against exact `FreqTruth` ordering and verifies the reported counts are exact and carry zero error, a true heavy hitter never having been displaced. |
| `a_guaranteed_key_really_outranks_everything_dropped` | `is_guaranteed` is a claim about the real stream. | Verifies every key accepted by `is_guaranteed` has a true count strictly above the largest true count among the keys the summary dropped. |
| `an_arrival_displaces_the_minimum_and_inherits_its_count` | Eviction hands the victim's count to the arrival as its error. | Drives a hand-built sequence through a two-counter summary and verifies the new key takes the minimum slot at `min + 1` with the old minimum as its error allowance, while `total` still counts every arrival. |
| `the_stream_summary_lists_stay_well_formed_under_eviction` | The bucket and counter lists stay traversable under sustained eviction. | Across capacities `1`, `2`, `17`, `256`, and `1_024`, verifies residency equals `min(capacity, distinct)`, the bucket walk reaches every counter exactly once in descending count order, and `entries` agrees with the walk. |
| `a_weighted_arrival_matches_repeating_it` | `insert_many` matches that many single inserts. | Builds two summaries over the same stream, one key-at-a-time and one weighted per key, and verifies equal totals, equal residency, and equal per-key estimates. |
| `a_summary_larger_than_the_domain_is_exact` | A summary with room for the whole domain is exact. | With capacity above the distinct count, verifies every estimate equals the true count, every error is `0`, and `min_count` stays `0`. |
| `a_merge_keeps_the_total_and_never_reads_low` | Merge conserves the inserted mass and stays one-sided. | Partitions the stream into two shards, merges their summaries, and verifies the merged total equals the whole stream length, residency stays within capacity, and no monitored key reads below either side's truth. |
| `a_serde_round_trip_preserves_every_answer` | Serde round trip preserves state and the rebuilt key index. | Round-trips through `rmp-serde` and verifies residency, capacity, total, `min_count`, and per-key estimate/error all match, then confirms the decoded summary still takes inserts against its rebuilt index. |
| `an_empty_summary_answers` | An empty summary answers every query without panicking. | Verifies `len`/`total`/`min_count` are zero, point queries return `0`, `is_guaranteed` is false, and `top_k`/`entries` are empty. |
| `a_weighted_arrival_matches_repeating_it_under_eviction` | A weighted arrival matches repeating it once the summary is evicting. | Feeds the same Zipf stream key by key into two 64-counter summaries, one arrival at a time and one `insert_many` per key, verifies the run saturates all 64 counters, and that `total`, `min_count`, and the whole sorted key/count/error entry list agree. |
| `bulk_insert_matches_repeated_inserts_and_a_zero_weight_is_inert` | `bulk_insert` is the loop it replaces, and a zero weight records nothing. | Verifies a 128-counter summary filled by `bulk_insert` matches one filled one at a time on `total` and on `top_k(usize::MAX)`, then that `insert_many` at weight `0` for a resident key and for an absent one leaves `total`, residency, and `top_k` untouched. |
| `a_zero_capacity_summary_still_answers` | A summary asked for no counters still holds one. | Verifies `with_capacity(0)` reports a capacity of `1`, and that after ten distinct keys residency is `1`, `total` is `10`, and the single held counter reads `10` with an error of `9`. |
| `a_merge_into_an_under_full_summary_keeps_the_ceiling_honest` | A merge carries the peer's ceiling even when there are counters to spare. | Merges a one-counter summary that saw key 7 ten times and key 8 twenty times into an empty 33-counter summary, then verifies residency is `1` and below capacity, `upper_bound` for the dropped key 7 still covers its true `10`, and `is_guaranteed` is false for the key that survived. |
| `a_merge_chain_stays_one_sided_against_the_truth` | A chain of merges over asymmetric capacities stays one-sided. | Shards the stream three ways by position into summaries of capacity 64, 512, and 7, merges them in turn, and verifies the merged `total` equals the stream length, residency stays within capacity, every true key's `upper_bound` covers its true count, every monitored key reads at or above its truth, and every key `is_guaranteed` accepts truly outranks the largest dropped key. |
| `a_merge_picks_the_same_survivors_every_time` | The merge depends on what the summaries hold, not on arrival order. | Merges two 200-counter summaries over keys `0..150` and `100..250`, verifies the union fills the capacity at 200 with exactly the 50 shared keys at count `2`, that five repeats give an identical key/count/error list, and that reversing both arrival orders gives the same list. |
| `a_round_trip_carries_the_merged_ceiling` | The ceiling a merge established survives the wire. | Merges a 4-counter summary of the stream's second half into a 32-counter summary of its first half, round-trips through `rmp-serde`, and verifies `min_count`, `total`, and residency are unchanged, every key's estimate matches, and every true key's decoded `upper_bound` still covers its true count. |
| `crafted_state_fails_closed` | Serialized state no run could have produced is refused. | Verifies hand-built payloads with a zero capacity, entries over the capacity, a counter at `0`, an error above its count, a repeated key, a ceiling of `200` over the lowest count of `3`, and a `total` of `2` under a counter's `9` all fail to decode, while a well-formed two-counter state answers `top_k` and `estimate`. |
| `a_fresh_summary_is_well_formed` | A fresh summary passes the structural check. | For `with_capacity(4)`, verifies `validate()` succeeds, `min_count` is `0`, and `capacity` is `4`. |
| `a_capacity_of_zero_floors_at_one` | A requested capacity of zero floors at one counter. | Verifies `with_capacity(0)` reports a capacity of `1`, and that after two distinct keys `validate()` passes, residency is `1`, and the survivor reads `2`. |
| `a_weighted_arrival_displaces_the_minimum_and_starts_above_it` | A weighted eviction starts the arrival above the count it displaced. | In a two-counter summary holding `1` at 5 and `2` at 2, `insert_many(3, 4)` is verified to evict key 2, leaving key 3 at `6` with error `2`, key 2 at `0`, key 1 at `5`, `min_count` at `5`, `total` at `11`, and `validate()` passing. |
| `a_weighted_raise_passes_every_bucket_below_its_destination` | A multi-hop raise walks the bucket list rather than skipping it. | Over counters at 1, 2, 3, and 4, `insert_many(1, 9)` lifts key 1 from the bottom to the top; verifies the descending walk becomes `[(1,10), (4,4), (3,3), (2,2)]` and `validate()` passes. |
| `counts_saturate_and_keep_the_bucket_order` | Counts saturate at `u64::MAX` instead of wrapping. | Raises a counter seeded at `u64::MAX - 2` twice past the ceiling, verifies `validate()` after each raise, both saturated keys read `u64::MAX`, `total` is `u64::MAX`, and the three-counter walk stays descending, ending at the small counter's `7`. |
| `an_eviction_from_a_saturated_counter_stays_sound` | Evicting a saturated counter keeps the structure sound. | A one-counter summary holding `u64::MAX` is evicted by a new key; verifies `validate()` passes, residency is `1`, the arrival reads `u64::MAX` with an error of `u64::MAX`, and the evicted key's `upper_bound` is `u64::MAX`. |
| `a_merge_saturates_instead_of_wrapping` | Merge saturates rather than wrapping past the ceiling. | Merges a three-counter peer into a two-counter summary already at `u64::MAX` and `u64::MAX - 1`; verifies `validate()` passes, residency stays `2`, `total` is `u64::MAX`, both survivors read `u64::MAX`, and all four keys' `upper_bound` is `u64::MAX`. |
| `a_merge_carries_the_ceiling_into_an_under_full_summary` | A merge into an empty summary still raises its ceiling. | Merging a one-counter peer that saw key 7 ten times and key 8 twenty times into an empty 33-counter summary is verified to leave residency `1` below capacity, `min_count` at or above `10`, `upper_bound(7)` at or above `10`, `is_guaranteed(8)` false, and `validate()` passing. |
| `a_truncating_merge_keeps_the_keys_the_encoder_emits_first` | A merge that must truncate a count tie cuts it by key order alone. | Merges a 3-counter peer holding keys 40, 50, and 60 at 2 into a 4-counter summary holding key 1 at 9 and keys 10, 20, and 30 at 3; verifies `validate()` passes, the six tied keys each reach an `upper_bound` of `5`, the survivors are keys 1, 10, 20, and 30 while the swapped merge keeps 1, 10, and 20, and that the encoder emits those survivors in the same order. |
| `a_chain_of_merges_keeps_the_ceiling_above_everything_dropped` | Two merges compound their ceilings. | Merges two one-counter peers (7 at 10 against 8 at 20, then 9 at 5 against 10 at 7) into a 5-counter summary; verifies `validate()` after each merge, residency below capacity, `upper_bound` covering keys 7 and 9 at their true 10 and 5, and `min_count` at or above `15`. |
| `a_key_that_re_enters_after_a_merge_never_reads_low` | A key re-entering a merged summary comes back above the ceiling. | After a merge drops key 7 at its true 12, one further insert is verified to seat it at `min_count + 1` with `min_count` as its error, at or above its true `13`, with `validate()` passing. |
| `randomized_operations_keep_the_structure_sound` | Randomized weighted inserts keep the structure sound at every step. | Drives 4,000 `insert_many` calls of weight 1, 3, 11, or 97 over a 96-key domain at capacities 1, 2, 7, 64, and 257, calling `validate()` after every step, then checks residency equals `min(capacity, distinct)`, `total` equals the inserted mass, the walk is the right length and descending, and every truth is bracketed by its counter's estimate and error. |
| `randomized_merges_keep_the_structure_sound` | Randomized merges keep the structure sound and one-sided. | For five capacity/domain pairs, merges two independently fuzzed summaries into a fuzzed one and then inserts 200 more keys, calling `validate()` after each merge and after the inserts, and checks the error sandwich against the combined truth, `total` equal to the combined mass, and residency within capacity. |
| `a_decoded_summary_rebuilds_both_link_directions` | Decoding rebuilds the bucket and counter links, not just the counts. | Round-trips a fuzzed 48-counter summary through `rmp-serde` and verifies the decoded summary passes `validate()`, matches residency, `min_count`, and `total`, still brackets every truth, and walks the same key/count set. |
| `a_crafted_state_fails_closed` | `rebuild` refuses state the algorithm could not have produced. | Verifies a zero capacity, entries over the capacity, a counter at `0`, an error above its count, a repeated key, a `discarded_max` of `u64::MAX` over the lowest count of `3`, and a `total` of `0` under a counter's `9` are each rejected with the matching complaint. |
| `a_declared_capacity_is_not_allocated_on_decode` | A huge declared capacity is not allocated on decode. | A state declaring a capacity of `1 << 40` with a single entry is verified to rebuild, pass `validate()`, report that capacity, and hold one counter. |
| `a_non_utf8_byte_key_is_monitored_and_queried` | A byte array that is not UTF-8 is a key like any other. | Inserts `[0xff, 0x00, 0xfe]` three times and `[0x00, 0x80]` at weight 2 into a 4-counter summary, and verifies `validate()` passes, the repeats share one counter, both keys are held as their raw bytes, each estimates its weight, and an unseen byte key reads `0`. |
| `a_byte_key_and_a_string_key_are_separate_counters` | `Bytes(b"abc")` and `Str("abc")` are two keys, not one. | Seats both in a 4-counter summary at weights 5 and 2 and verifies residency is `2`, the byte key reads `5`, and the string key reads `2` through `Str` and `String` alike. |
| `an_evicted_byte_key_keeps_its_bound` | An evicted byte key still reads under the ceiling. | In a 2-counter summary holding a byte key at 3 and another at 2, a third byte key is verified to displace the smallest, leaving the evicted key at `estimate` `0` with an `upper_bound` at or above its true `2`, a `min_count` of `3`, and the newcomer at `3` carrying an error of `2`. |
| `a_merge_pairs_byte_keys_by_their_bytes` | A merge pairs byte keys by their bytes. | Merges a peer holding the shared byte key at 2 and its own at 7 into a summary holding the shared key at 5 and its own at 3, and verifies `validate()` passes, all three byte keys survive as their raw bytes, and the shared key reads `7`. |
| `a_serde_round_trip_keeps_a_byte_key` | A serde round trip carries raw bytes and re-hashes them to the digest a query reaches. | Round-trips a summary holding `[0xff, 0x00, 0xfe]` at 9 and five `0x00` bytes at 4 through `rmp-serde`, and verifies the decoded summary passes `validate()`, holds the same raw byte keys, answers both `DataInput::Bytes` queries at their weights, and reports the same `total`. |
| `space_saving_envelope_structure_and_round_trip` | The envelope frames a summary under kind_id `0x18 0x00`, and the bytes are stable across a round trip. | For a 48-counter summary saturated by 30,000 weighted draws over 400 distinct keys, verifies the bytes open with the ASAPv1 magic, `envelope::VERSION`, a `kind_id_len` of `2`, and `0x18 0x00`, that re-serializing the decoded summary reproduces them exactly, and that residency, capacity, `total`, `min_count`, and `estimate`/`error`/`upper_bound`/`is_guaranteed` agree across all 400 keys. |
| `space_saving_merged_ceiling_survives_the_wire` | The ceiling a merge leaves behind travels in `floor`, which the triples do not determine. | Merges a one-counter summary that saw key 7 ten times and key 8 twenty times into an empty 33-counter summary, then verifies the decoded `min_count` and the `upper_bound` on the dropped key 7 both match the source and still cover its true `10`, with identical re-serialized bytes; a payload carrying only the triples decodes to a `min_count` of `0` here. |
| `space_saving_empty_round_trip` | A summary monitoring nothing has one encoding. | Verifies an empty 16-counter summary reports the pinned `EMPTY_KEY_TYPE` of `u64` in its metadata and decodes back to residency `0`, capacity `16`, `min_count` `0`, `total` `0`, and identical re-serialized bytes. |
| `space_saving_every_key_type_round_trips_and_keeps_its_variant` | The `key_type` names the exact `HeapItem` variant and is never widened. | Across all 14 wire key types - `i8`, `i16`, `i32`, `i64`, `isize`, `u8`, `u16`, `u32`, `u64`, `usize`, `f32`, `f64`, `string` reached from `Str` and `String` alike, and `bytes` - verifies the metadata carries the expected name, the bytes re-serialize identically, and every decoded key still answers its original `DataInput` with the weight it was given; a decoder widening `i32` to `i64` keeps the digest but stops comparing equal, so `estimate` would read zero. |
| `space_saving_emitted_order_is_independent_of_seat_order` | The emitted order is descending count with ties broken by `key_order`, not the arena's seat order. | Rebuilds the same four triples - carrying two count ties that only the key separates - in one order and in reverse, and verifies both serialize to the same bytes. |
| `space_saving_refuses_mixed_and_128_bit_keys` | Keys the wire cannot carry refuse to serialize rather than being coerced. | Verifies a summary holding both an `I32` and an `I64` key fails to serialize, that a lone `I128` or `U128` key fails, and that a 128-bit key seated behind a wire-eligible one is caught on the way into the payload rather than by the first-key check. |
| `space_saving_rejects_a_key_type_the_payload_does_not_carry` | A payload relabelled with another `key_type` is refused. | Re-frames a string-keyed payload under `u64` and under `bytes`, a `u64`-keyed payload under `string` and under `bytes`, and a byte-keyed payload under `u64` and under `string`, and verifies none of them decodes. |
| `space_saving_byte_keys_round_trip_arbitrary_bytes` | A byte-array key reaches the wire as msgpack `bin`, so any byte string survives. | For an 8-counter summary holding `[0xff, 0x00, 0xfe]`, forty `0x80` bytes, and the empty byte string at weights 3, 6, and 9, verifies the metadata names `key_type` `bytes`, the emitted `keys` carry exactly those bytes, every decoded key still answers its original `DataInput::Bytes` at its weight, and the bytes re-serialize identically. |
| `space_saving_refuses_byte_keys_mixed_with_string_keys` | A `Bytes` key and a `String` key are different key types, so a summary holding both has no `key_type`. | Seats `Bytes(b"abc")` and `Str("abc")` in one summary, verifies they take two counters, and that serializing fails with a "mix variants" complaint. |
| `space_saving_custom_hasher_profile_round_trips_and_is_self_describing` | The metadata describes the hasher that built the summary rather than a hardcoded profile. | For a four-counter summary over a hasher declaring its own `HashProfile`, verifies the bytes round-trip with `estimate` intact and re-serialize identically, differ from the standard-profile summary's bytes over the same keys, and are rejected by a standard-profile decode. |
| `space_saving_metadata_rejects_unknown_keys` | An unexpected metadata key fails closed. | Encodes the eight `SpaceSavingMetadata` fields plus a `bogus_field` as a named map and verifies it does not decode as `SpaceSavingMetadata`. |
| `space_saving_rejects_a_crafted_envelope` | Every structural rule is pinned by the complaint it fails with. | Verifies eleven crafted envelopes are each refused for their own reason: a zero capacity, entries over the capacity, `keys` longer than `counts`, `counts` longer than `errors`, a counter at zero, an error of `4` against a count of `3`, the same key twice, an unknown `key_type` of `u256`, a `discarded_max` of `u64::MAX` over the lowest count of `3`, a `total` of `0` under a counter's `9`, and a foreign kind_id. |
| `space_saving_refuses_a_capacity_the_metadata_cannot_carry` | A capacity past the metadata's `u32` field fails the encode rather than truncating. | Rebuilds a one-counter summary declaring a capacity of `1 << 40`, verifies it reports that capacity, and that serializing fails with a message naming the "exceeds the u32 metadata field" rule. |
| `space_saving_does_not_allocate_a_declared_capacity` | A declared capacity is metadata, never an allocation size. | Verifies an envelope declaring `u32::MAX` counters with two entries decodes, reports that capacity, holds two counters with key 7 reading `9`, a `min_count` of `0`, and a two-entry `top_k`. |
| `the_default_summary_holds_the_default_capacity` | `SpaceSaving::default()` carries the documented counter budget and fills it. | Verifies `SPACE_SAVING_DEFAULT_CAPACITY` is `1_024`, that a `SpaceSaving::default()` reports that capacity and is empty, and that after 60,000 `zipf(1.1)` draws over a 2,048-key domain at seed `9_001` residency is `1_024`, `total()` is `60_000`, and `top_k(usize::MAX)` returns `1_024` entries. |
| `a_seat_above_the_ceiling_saturates` | A key seated above an enormous ceiling stops at `u64::MAX` rather than wrapping. | In a 4-counter summary whose ceiling is `u64::MAX - 3` (merged in from a one-counter peer where key 9 reached `u64::MAX - 4` before key 8 displaced it), `insert_many(5, 10)` is verified to leave `validate()` passing, key 5 at `u64::MAX` with an error of `u64::MAX - 3`, and key 8 still at `u64::MAX - 3`. |
| `a_merge_saturates_a_shared_keys_count` | A shared key's paired counts saturate instead of wrapping. | Merges a one-counter peer holding key 2 at `6` into a one-counter summary holding it at `u64::MAX`, and verifies `validate()` passes, residency is `1`, and key 2 reads `u64::MAX`. |
| `a_merge_saturates_a_shared_keys_error` | A shared key's paired errors saturate, so the merge never claims a count it cannot support. | For the same saturated overlap, verifies `validate()` passes, key 2's `error` is `u64::MAX`, and its `estimate` less its `error` is at most `2` - the number of times key 2 truly arrived. |
| `a_merge_saturates_a_key_only_the_other_side_holds` | A key arriving only from the peer inherits this side's ceiling and saturates. | Merges a 4-counter peer holding key 3 at `7` into the `u64::MAX - 3`-ceilinged 4-counter summary, and verifies `validate()` passes, key 3 reads `u64::MAX` with an error of `u64::MAX - 3`, and key 8 still reads `u64::MAX - 3`. |
| `a_merge_saturates_a_key_only_this_side_holds` | A key only this side holds inherits the peer's ceiling and saturates. | Merges the `u64::MAX - 3`-ceilinged summary into a 4-counter summary holding key 3 at `7`, and verifies `validate()` passes, key 3 reads `u64::MAX` with an error of `u64::MAX - 3`, and key 8 reads `u64::MAX - 3`. |
| `a_merge_saturates_the_ceiling` | The ceiling a merge leaves behind saturates rather than wrapping to a tiny bound. | Merges a 4-counter summary ceilinged at `10` (key 6 dropped, key 5 held) into one ceilinged at `u64::MAX - 3`, and verifies `validate()` passes, `min_count` is `u64::MAX`, and `upper_bound` for the dropped key 9 is at least the `u64::MAX - 4` it truly reached. |
| `a_serde_round_trip_carries_a_ceiling_no_counter_holds` | An under-full summary's ceiling lives only in `discarded_max`, and serde carries it. | Merges a one-counter peer that saw key 7 ten times and key 8 twenty times into an empty 33-counter summary, checks residency is below capacity with `min_count` at `30`, then round-trips through `rmp-serde` and verifies the decoded summary passes `validate()`, still reports `min_count` `30`, and covers key 7's true `10` in its `upper_bound`. |
| `a_key_that_only_ties_the_ceiling_is_not_guaranteed` | `is_guaranteed` is strict: tying the ceiling is not outranking it. | In a 2-counter summary holding keys 1 and 2 at 3 each, the arrival of key 3 is verified to leave `validate()` passing, key 1 at `3` with error `0`, `min_count` at `3`, and `is_guaranteed` false for both key 1 and key 3; two further key-1 inserts then take it to `5` against a `min_count` of `4`, at which point `is_guaranteed` accepts it. |
| `clear_resets_every_answer` | `clear` leaves a summary that answers like a fresh one, ceiling and total included. | Clears a 2-counter summary that held key 1 at 5 and key 2 at 3 with key 3 evicting, and verifies `validate()` passes, `is_empty` holds, `len` is `0`, `capacity` is still `2`, `total`, `min_count`, `upper_bound`, and `error` are all `0`, `top_k(4)` and `entries` are empty, and that one further insert seats key 4 at `1` with a `total` of `1`. |
| `colliding_keys_stay_distinct` | Keys sharing a digest are separate counters, each answering for itself. | Under a `OneDigest` hasher that files every key under one digest, inserts keys 10, 20, and 30 at weights 3, 5, and 1 into a 4-counter summary and verifies `validate()` passes, residency is `3`, the held keys are exactly `[10, 20, 30]`, each estimates its own weight, and an unseen key 40 reads `0`. |
| `an_eviction_under_collision_keeps_the_index_straight` | An eviction drops the victim's key from the index before it seats the arrival under the same digest. | Under the `OneDigest` hasher, a 2-counter summary holding key 10 at 3 and key 20 at 2 takes key 30; verifies `validate()` passes, residency is `2`, the held keys are `[10, 30]`, key 30 reads `3` with an error of `2`, key 10 still reads `3`, and the evicted key 20 reads `0`. |
| `a_merge_under_collision_pairs_by_key` | A merge pairs the two sides by key, not by the digest slot they share. | Under the `OneDigest` hasher, merges a 4-counter peer holding key 10 at 2 and key 30 at 7 into one holding key 20 at 3 and key 10 at 5, and verifies `validate()` passes, all three keys survive, the shared key 10 reads `7`, and keys 20 and 30 read `3` and `7`. |
| `a_merge_under_collision_breaks_ties_by_key` | With one digest for everything, key order is the only tie-break left and it still fixes the survivors. | Under the `OneDigest` hasher, merges two 2-counter summaries holding keys 30 and 40 against keys 10 and 20, all at count 1, and verifies the survivors are `[10, 20]` and that swapping which side is merged into gives the same list. |
| `a_decoded_summary_under_collision_keeps_its_keys` | A decode compares keys rather than digests, so it seats all of them and still catches a repeat. | Under the `OneDigest` hasher, round-trips a 4-counter summary holding keys 10, 20, and 30 at weights 5, 3, and 9 through `rmp-serde` and verifies the decoded summary passes `validate()`, holds all three keys, and estimates each at its weight; then that a `SpaceSavingState` listing key 10 twice fails `rebuild` with a "same key twice" complaint. |
### Bloom
Test file: [`tests/e2e_membership.rs`](../tests/e2e_membership.rs)
Unit tests: [`src/sketches/bloom.rs`](../src/sketches/bloom.rs)
Wire tests: [`src/sketches/bloom/wire.rs`](../src/sketches/bloom/wire.rs)
Conformance: [`tests/conformance_kit.rs`](../tests/conformance_kit.rs) runs the shared `membership_battery` on both hash paths against a filter sized for 20,000 keys at a 1% target: `bloom_passes_membership_conformance` over `Bloom<FastPath>` and `bloom_regular_path_passes_membership_conformance` over `Bloom<RegularPath>`. The battery also checks a `predicted-false-positive-rate` band, holding the measured rate to within a quarter either side of the filter's own `predicted_fpp`.
| test_name | test_description | what_is_tested |
| --- | --- | --- |
| `an_inserted_key_is_never_reported_absent` | No false negative, on either hash path. | Fills a filter sized for 20,000 keys at a 1% target and verifies every inserted key reports present on both the `RegularPath` and `FastPath` filters, which decode columns differently. |
| `an_empty_filter_rejects_every_probe` | A fresh filter reports nothing present. | Verifies `is_empty` and a zero insert count, and that probes disjoint from the member set are rejected on both hash paths. |
| `the_measured_false_positive_rate_matches_what_the_sizing_predicts` | The delivered rate honours the target and matches `predicted_fpp`. | Across targets `0.1`, `0.01`, and `0.001`, measures the rate over 200,000 disjoint probes and verifies predicted and measured both stay at or under the target and agree within five binomial standard errors. |
| `the_fill_based_estimate_tracks_the_measured_rate` | `estimated_fpp` reads the bits set, not the insert count. | Inserts the member set three times and verifies `estimated_fpp` still tracks the measured rate within a quarter either way although the insert count has tripled. |
| `repeated_inserts_leave_the_bits_unchanged` | Fill is a function of the distinct keys alone. | Builds one filter with single inserts and one with duplicated inserts over the same keys and verifies identical `count_ones` and `fill_ratio`. |
| `a_union_equals_the_filter_of_the_concatenated_stream` | Merge is an exact union, which is what makes the filter shardable. | Splits a stream across two same-geometry filters, merges them, and verifies the same set bits and insert count as a single-pass filter, plus identical answers on members and non-members alike. |
| `sizing_meets_the_target_and_is_one_power_of_two_from_missing_it` | `dimensions_for` is pinned to its contract rather than to its own expression. | For `(n, p)` pairs from `(1, 0.5)` through `(10_000, 1e-12)`, verifies every slice is a power of two and the row count stays within `BLOOM_MAX_SLICES`, that the chosen geometry's `predicted_fpp(n)` meets the target, and that halving `cols` misses it. |
| `degenerate_geometries_still_answer` | Degenerate geometries answer rather than panic. | Verifies a one-bit filter answers and reports an `estimated_fpp` of `1.0` once set, and that a single-row filter still holds every member it was given. |
| `clearing_restores_an_empty_filter` | `clear` restores the constructed state and keeps the dimensions. | After clearing a filled filter, verifies it is empty with a zero insert count, unchanged rows and columns, and no member reported present. |
| `a_serde_round_trip_preserves_every_answer` | Serde round trip preserves every answer. | Round-trips through `rmp-serde` and verifies matching dimensions, insert count, and set bits, plus identical answers on members and non-members. |
| `storage_is_one_bit_per_cell` | Packed storage is one bit per cell, not one byte. | For an `8x4096` filter, verifies `bit_capacity` equals `rows * cols` and `size_in_bytes` is one eighth of it. |
| `sizing_never_asks_for_more_slices_than_the_seed_list_has` | The slice count stops at the number of seeds the hasher has. | For 10,000 keys at targets `1e-7`, `1e-9`, and `1e-12`, verifies the row count stays within `BLOOM_MAX_SLICES` and that no two rows of the filled filter hold identical bits. |
| `sizing_stays_inside_the_allocation_ceiling` | A target the seed list cannot reach yields the widest geometry that fits. | For `expected_items` up to `usize::MAX` and targets `f64::MIN_POSITIVE`, `0.0`, and `2.0`, verifies `cols` is at least one and a power of two, rows fall in `1..=BLOOM_MAX_SLICES`, and `rows * cols` stays within `BLOOM_MAX_BITS`. |
| `a_nan_target_rate_is_rejected` | A NaN target rate panics. | Verifies `with_capacity(1_000, f64::NAN)` panics with "target false-positive rate must be finite". |
| `an_infinite_target_rate_is_rejected` | An infinite target rate panics. | Verifies `with_capacity(1_000, f64::INFINITY)` panics with "target false-positive rate must be finite". |
| `a_negative_infinite_target_rate_is_rejected` | A negative infinite target rate panics. | Verifies `with_capacity(1_000, f64::NEG_INFINITY)` panics with "target false-positive rate must be finite". |
| `the_two_hash_paths_agree_only_where_the_geometry_gives_each_row_its_own_hash` | Whether the paths land on the same bits is a property of the geometry. | Verifies `8 x 65_536` needs 136 hash bits, so both paths fall back to one seeded hash per row and set identical bits, while `7 x 65_536` fits a packed hash and the paths differ; also verifies that second shape is `BLOOM_DEFAULT_ROWS` by `BLOOM_DEFAULT_COLS`. |
| `a_filter_cannot_be_decoded_into_the_other_hash_path` | The serialized form carries which path built the filter. | Verifies regular-path bytes fail to decode as `Bloom<FastPath>` with an error naming both paths, fast-path bytes fail as `Bloom<RegularPath>` and as the unannotated `Bloom`, and fast-path bytes decoded back into `Bloom<FastPath>` still report every member present. |
| `a_fast_path_serde_round_trip_preserves_every_answer` | The fast path round-trips like the regular one, tag and all. | Round-trips a fast-path filter sized for 20,000 keys at a 1% target and verifies matching dimensions, insert count, and set bits, plus identical answers on 20,000 non-member probes. |
| `a_fast_path_union_equals_the_filter_of_the_concatenated_stream` | Merge is an exact union on the fast path too. | Splits 10,000 keys by parity across two `7 x 2^14` fast-path filters, merges them, and verifies the same set bits and insert count as a single-pass filter, with every key reported present. |
| `merging_filters_of_different_widths_panics` | A merge across slice widths panics. | Verifies merging a `7 x 2^14` filter with a `7 x 2^13` one panics with "bit matrices must have the same dimensions". |
| `merging_filters_of_different_slice_counts_panics` | A merge across slice counts panics. | Verifies merging a `7 x 2^14` filter with an `8 x 2^14` one panics with "bit matrices must have the same dimensions". |
| `bulk_insert_matches_inserting_one_at_a_time` | `bulk_insert` is the loop, not a different filter. | On both hash paths, verifies a filter filled by `bulk_insert` over 20,000 keys has the same set bits and insert count as one filled key by key. |
| `with_capacity_builds_exactly_the_geometry_dimensions_for_reports` | The sizing helper describes the filter `with_capacity` actually builds. | Over `expected_items` `0`, `1`, `17`, `1_000` and `250_000` against targets `0.5`, `0.1`, `0.01`, `1e-4` and `1e-6`, verifies the built filter's rows and columns equal the pair `dimensions_for` reported for the same arguments. |
| `the_slice_count_comes_from_the_bit_budget_not_the_target_alone` | The slice count tracks `expected_items` as well as the target rate. | Verifies `dimensions_for` chooses `5` slices at `(1, 0.05)`, `8` at `(1, 1/128)` and `14` at `(2, 1e-4)`, each exactly one over `round(log2(1/p))`; that the two agree for `expected_items` `1_000`, `100_000` and `10_000_000` across six targets; and that `(1_000_000, 1e-12)` saturates at `BLOOM_MAX_SLICES`. |
| `a_target_outside_the_open_unit_interval_is_clamped_to_the_endpoints` | A target outside `(0, 1)` clamps onto the interval's own endpoints. | Verifies `0.0`, `-0.0`, `-1.0` and `f64::MIN` all size as `f64::MIN_POSITIVE` does, that `1.0`, `1.5` and `f64::MAX` all size as `1.0 - f64::EPSILON` does, and that both endpoint geometries are non-zero with a power-of-two width. |
| `a_target_that_is_not_a_number_panics_instead_of_sizing_a_degenerate_filter` | A NaN target panics rather than clamping into a degenerate filter. | Verifies `dimensions_for(1_000, f64::NAN)` panics naming the finite-rate requirement. |
| `an_infinite_target_panics_instead_of_sizing_a_degenerate_filter` | The same panic reaches through `with_capacity`, not only the helper it delegates to. | Verifies `with_capacity(1_000, f64::INFINITY)` panics naming the finite-rate requirement. |
| `sizing_for_zero_expected_items_still_yields_a_filter_that_answers` | Sizing for no items still yields a filter that holds a key. | Verifies `dimensions_for(0, 0.01)` has both dimensions at least one and equals `dimensions_for(1, 0.01)`, and that the filter built from it reports its only member present. |
| `the_default_geometry_is_the_documented_pair` | `Default` is the two public constants, and they name a filter the hash family can serve. | Verifies a default filter is `BLOOM_DEFAULT_ROWS x BLOOM_DEFAULT_COLS`, that its rows are within `BLOOM_MAX_SLICES`, its width a power of two, its bit capacity under `BLOOM_MAX_BITS`, and that it starts empty. |
| `more_slices_than_the_seed_list_has_is_rejected_at_construction` | More slices than the seed list has is refused at construction, not at serialization. | Verifies `with_dimensions(BLOOM_MAX_SLICES + 1, 1024)` panics with a message naming `BLOOM_MAX_SLICES`. |
| `the_seed_list_length_itself_is_a_legal_slice_count` | The bound is inclusive: the assert fires past it, not at it. | Verifies `with_dimensions(BLOOM_MAX_SLICES, 1024)` builds and reports that many rows. |
| `a_serde_payload_past_the_slice_cap_is_rejected` | The plain serde form is a second door into the filter and fails closed on the same bound. | Encodes the serialized form over a `BLOOM_MAX_SLICES + 1` row grid and verifies the `rmp-serde` decode returns an error naming `BLOOM_MAX_SLICES` rather than panicking inside the decoder. |
| `both_rate_reporters_raise_the_per_slice_rate_to_the_slice_count` | Both rate reporters use the slice count as the exponent. | For a `BLOOM_MAX_SLICES x 1024` filter holding 400 keys at a fill strictly inside `(0, 1)`, verifies `estimated_fpp` equals `fill_ratio^rows` and `predicted_fpp(400)` equals `(1 - e^(-400/cols))^rows`. |
| `an_empty_filter_predicts_nothing_and_a_saturated_one_predicts_everything` | The two ends of the rate scale are reported exactly. | Verifies an empty filter reports a zero fill ratio, a zero `estimated_fpp` and `predicted_fpp(0) == 0`, then fills a `3x8` filter until its fill ratio is `1.0` and verifies `estimated_fpp` is exactly `1.0`. |
| `a_single_insert_sets_exactly_one_bit_in_every_slice` | Partitioning: one key touches exactly one bit per slice, whatever the width. | Across widths `1`, `2`, `7`, `64`, `100` and `1024` by row counts `1`, `5` and `BLOOM_MAX_SLICES`, verifies one insert sets exactly `rows` bits on both hash paths, that `fill_ratio` equals `rows / (rows * cols)`, and that the key reads present. |
| `the_insert_counter_counts_calls_and_clear_returns_it_to_zero` | `inserted` counts calls rather than distinct keys, and `clear` resets it with the bits. | Verifies five inserts of one key count `5`, a `bulk_insert` of three more leaves `8`, and that `clear` returns the count, the bits and the fill ratio to zero. |
| `merging_identical_geometries_sums_the_insert_counts` | A merge adds the counts and keeps both streams' members. | Merges two `5x512` filters holding 30 and 40 distinct keys and verifies the merged count is the sum, all 70 members read present, and the geometry is unchanged. |
| `merging_mismatched_geometries_panics_instead_of_unioning_a_prefix` | A cross-geometry union panics rather than answering no about its own members. | Verifies merging a `5x512` filter with a `5x256` one panics in `BitMatrix::union_from`. |
| `a_zero_slice_width_is_rejected_at_construction` | A zero dimension is refused at construction. | Verifies `with_dimensions(4, 0)` panics rather than handing back a filter every query would panic on. |
| `bit_capacity_and_packed_size_describe_the_same_grid` | The addressable grid and the packed storage behind it describe one filter. | Across `1x1`, `3x7`, `5x64`, `7x65` and `BLOOM_MAX_SLICES x 1024`, verifies `bit_capacity` is `rows * cols`, `size_in_bytes` is `rows * ceil(cols / 64) * 8`, and that the bytes cover the addressable bits. |
| `bloom_envelope_structure_and_round_trip` | The envelope frames a filter under kind_id `0x17 0x00`, and the bytes are stable across a round trip. | For a `7 x 2^14` regular-path filter holding 5,000 members, verifies the bytes open with the ASAPv1 magic, `envelope::VERSION`, a `kind_id_len` of `2`, and `0x17 0x00`, then that re-serializing the decoded filter reproduces them exactly and that `inserted`, `fill_ratio`, every member, and 20,000 disjoint probes all answer as the source does. |
| `bloom_fast_path_round_trip` | The fast path round-trips byte for byte. | For a `7 x 2^14` fast-path filter holding 5,000 members, verifies the decoded filter re-serializes to the same bytes, keeps `inserted`, and answers identically on the members and on 20,000 disjoint probes. |
| `bloom_empty_round_trip` | A filter with no inserts round-trips. | Verifies `Bloom::<RegularPath>::default()` decodes back empty with a zero insert count, unchanged rows and columns, and identical re-serialized bytes. |
| `bloom_cross_mode_rejection` | The metadata `mode` turns a cross-mode decode into an error rather than a filter that denies its own members. | For `7 x 2^12` filters on both paths over the same 5,000 members, verifies the two byte strings differ, regular-path bytes fail to decode as `Bloom<FastPath>`, and fast-path bytes fail as `Bloom<RegularPath>`. |
| `bloom_custom_hasher_profile_round_trips_and_is_self_describing` | The metadata describes the hasher that built the filter rather than a hardcoded profile. | For a `7 x 2^12` filter over a hasher declaring its own `HashProfile`, verifies the bytes round-trip and preserve every answer, differ from the standard-profile filter's bytes over the same members, and are rejected by a standard-profile decode. |
| `bloom_metadata_rejects_unknown_keys` | An unexpected metadata key fails closed. | Encodes the ten `BloomMetadata` fields plus a `bogus_field` as a named map and verifies it does not decode as `BloomMetadata`. |
| `bloom_rejects_foreign_kind_id` | Another sketch's kind_id is refused even when the rest parses cleanly. | Wraps well-formed Bloom metadata and payload in an envelope carrying kind_id `0x02 0x00` and verifies the decode fails. |
| `bloom_rejects_zero_dimension` | A zero dimension is a decode error, not a `BitMatrix::new` panic. | For crafted `0 x 64` and `4 x 0` envelopes, verifies the decode fails with a message naming the "dimensions must be non-zero" rule. |
| `bloom_rejects_non_power_of_two_cols` | A modulo-folded width is outside the wire-eligible subset. | Verifies a crafted `2 x 96` envelope fails with "not a power of two", while the same four-word payload at `2 x 128` decodes, so the geometry rule is what rejects it and not the word count. |
| `bloom_rejects_too_many_rows` | More slices than the seed list has entries is outside the wire-eligible subset. | Verifies a crafted `BLOOM_MAX_SLICES + 1` envelope fails with a message naming `BLOOM_MAX_SLICES`, and that the boundary row count itself decodes. |
| `bloom_rejects_oversized_bit_capacity` | The capacity rule fires from the declared dimensions, before any allocation is sized from them. | Verifies a crafted envelope declaring `4 x (BLOOM_MAX_BITS / 2)` while carrying two words fails with a message naming `BLOOM_MAX_BITS`. |
| `bloom_rejects_word_count_mismatch` | The word stride is derived from `cols`, so a payload that disagrees is refused in either direction. | Verifies 5-word and 7-word payloads for a `3x128` grid both fail with a "words length" complaint, while the correct 6 words decode. |
| `bloom_rejects_padding_bits_set` | Bits parked in a row's trailing slack are rejected. | For a `2x8` grid whose bits `8..64` are padding, verifies payloads setting the first padding bit, the last, and one mid-row are each refused with a "row padding" complaint - such bits are unreachable by `get` but counted by `count_ones`, so they would skew `fill_ratio` and `estimated_fpp` while every membership answer looked fine - and that the same words with the padding clear decode to a `fill_ratio` of `0.5`. |
| `bloom_with_capacity_round_trip_meets_predicted_fpp` | A filter sized for a realistic target still delivers it after a round trip. | For 50,000 keys at a `0.001` target, verifies the decoded filter keeps the source's dimensions, reports every member present, and delivers a measured rate over 200,000 disjoint probes within five binomial standard errors of its own `predicted_fpp`. |
| `a_packed_64_geometry_gives_each_row_its_own_window` | In the packed 64-bit layout each row reads its own hash window. | Verifies `hash_mode_for_matrix(5, 1024)` is `MatrixHashMode::Packed64`, that a `5x1024` `Bloom<FastPath>` holding keys `0..300` reports every one present, and that the rate measured over the 200,000 probes from `10_000_000` is within five binomial standard errors of `predicted_fpp(300)` and at or under `0.01`, which one shared window across the five slices would exceed. |
| `degenerate_sizing_inputs_give_a_usable_geometry` | A degenerate sizing input yields a real geometry rather than one bit per slice. | Verifies `Bloom::<RegularPath>::dimensions_for` returns `(7, 2)` for `(0, 0.01)`, `(20, 1 << 26)` for `(1_000, 0.0)`, and `(1, 32)` for `(1_000, 2.0)`. |
| `non_power_of_two_widths_answer_membership_on_both_paths` | A width that is not a power of two folds the same bits on insert and on lookup. | For the geometries `1x1`, `3x65`, `7x100`, `5x127`, `9x129` and `5x1_000`, inserts keys `0..200` into a `Bloom<RegularPath>` and a `Bloom<FastPath>` built by `with_dimensions` and verifies neither path loses a single member. |
| `the_allocation_ceiling_is_the_documented_number` | The allocation ceiling is a documented number, and a target past it settles on the widest geometry that fits. | Verifies `BLOOM_MAX_BITS` is `1 << 31` and that `Bloom::<RegularPath>::dimensions_for(1 << 40, 1e-9)` is `(20, 1 << 26)`, the ceiling divided by the slice count and rounded down to a power of two. |
| `the_default_filter_has_the_documented_dimensions` | The default filter is the documented geometry. | Verifies `Bloom::<RegularPath>::default()` reports rows and columns equal to `BLOOM_DEFAULT_ROWS` and `BLOOM_DEFAULT_COLS`, and that it is `is_empty`. |
### Elastic
Test file: [`src/sketches/elastic.rs`](../src/sketches/elastic.rs)
Wire tests: [`src/sketches/elastic/wire.rs`](../src/sketches/elastic/wire.rs)
| test_name | test_description | what_is_tested |
| --- | --- | --- |
| `init_with_dimensions_sizes_both_parts` | Both parts take the requested dimensions. | `init_with_dimensions(12, 2, 256)` is verified to yield 12 heavy buckets and a 2x256 light layer. |
| `init_with_length_keeps_the_default_light_layer` | `init_with_length` sizes the heavy table alone and leaves the light layer at its defaults. | `init_with_length(8)` is verified to yield 8 heavy buckets over `DEFAULT_LIGHT_ROWS` x `DEFAULT_LIGHT_COLS`. |
| `an_empty_heavy_table_is_rejected` | A zero bucket count panics. | `init_with_length(0)` is verified to panic with "at least one heavy bucket" rather than divide by zero in the bucket index. |
| `a_negative_heavy_table_is_rejected` | A negative bucket count panics. | `init_with_length(-1)` is verified to panic rather than widen to a huge `usize`. |
| `an_empty_light_layer_is_rejected` | A zero-row light layer panics. | `init_with_dimensions(8, 0, 4096)` is verified to panic with "non-empty light layer". |
| `a_zero_width_light_layer_is_rejected` | A zero-column light layer panics. | `init_with_dimensions(8, 3, 0)` is verified to panic with "non-empty light layer". |
| `heavy_bucket_tracks_repeated_flow_exactly` | Heavy bucket tracks repeated flow exactly. | Top-K/heavy-hitter tracking and updates behave as expected. |
| `light_sketch_counts_colliding_flows` | Light sketch counts colliding flows. | Core functional behavior for this component path is validated. |
| `eviction_moves_the_resident_flow_into_the_light_layer` | Takeover evicts the resident flow, not the arriving one. | After 10 inserts of a resident and `LAMBDA * 10` inserts of a colliding flow, verifies the bucket holds the arrival with `(vote_pos, vote_neg, eviction) = (1, 1, true)`, `query(resident) == 10`, and `query(arrival) == 80`. |
| `expansion_doubles_the_heavy_table` | Copy operation doubles bucket count. | After `expand_heavy()` on an 8-bucket table, verifies `bktlen` and `heavy.len()` are both `16`. |
| `expansion_preserves_every_existing_estimate` | Lemma 3.2 keeps estimates put across a doubling. | Records `query` for 24 flows over 8 buckets, doubles, and verifies every estimate is unchanged. |
| `repeated_expansion_keeps_estimates_intact` | Two doublings in a row stay correct. | Same 24 flows through two `expand_heavy()` calls to `bktlen = 32`, all estimates unchanged. |
| `an_insert_onto_a_stale_copy_replaces_it` | Incremental cleanup drops stale copies. | Finds a stale bucket after a doubling, inserts a key that hashes to it, and verifies the arrival takes the slot at `vote_pos = 1` while the displaced flow keeps its mass elsewhere. |
| `merge_after_expansion_does_not_double_count` | Flushing an expanded table spills each flow once. | Doubles a 24-flow table, merges an empty peer, and verifies every estimate equals its true count rather than twice it. |
| `merge_does_not_double_count_an_expanded_peer` | The peer's stale copies are skipped too. | Merges an expanded 24-flow peer into an unexpanded sketch and verifies no estimate doubles. |
| `maximum_merging_does_not_double_count_an_expanded_peer` | Same for max merging. | As above through `merge_max`. |
| `full_bucket_count_counts_residents_above_the_threshold` | Full-bucket count matches the threshold. | With 6 flows at 10 votes each, verifies `full_bucket_count(9) == 6` and `full_bucket_count(10) == 0`. |
| `compression_shrinks_the_heavy_table` | Active compression divides the bucket count. | After `compress_heavy(4)` on a 16-bucket table, verifies `bktlen` and `heavy.len()` are both `4`. |
| `compression_keeps_the_larger_flow_and_spills_the_smaller` | The bigger resident wins its group. | Puts a 30-vote flow in bucket 0 and a 3-vote flow in bucket 4, halves the table, and verifies the big flow still reads `30` from the heavy part while the small one has left it and reads back at least `3` from the light layer. |
| `compression_neither_loses_nor_doubles_mass` | Compression only ever adds error. | Compresses 40 flows over 16 buckets by 4 and verifies no flow underestimates and the summed estimate rises without doubling. |
| `a_ratio_that_does_not_divide_the_table_is_rejected` | Lemma 3.2 needs `w' \| w`. | `compress_heavy(3)` on an 8-bucket table panics with "must divide the bucket count". |
| `compression_after_expansion_does_not_double_count` | Stale copies are dropped before grouping. | Expands 12 buckets to 24 — putting each twin 12 apart — compresses by 3 so twins land in different groups, verifies no flow is resident twice, then merges an empty peer and verifies every estimate equals its true count. |
| `expand_then_compress_returns_to_the_original_size` | Doubling and halving round-trips. | `expand_heavy()` then `compress_heavy(2)` returns an 8-bucket table to 8 buckets with no flow underestimated. |
| `heavy_only_insert_never_touches_the_light_layer` | Overload mode leaves every light counter alone. | Seeds the light layer through `insert`, snapshots all `2x64` counters, then runs `insert_heavy_only` across a vacant seat, a match, discarded arrivals, and a takeover, and verifies the snapshot is unchanged. |
| `heavy_only_takeover_inherits_the_evicted_flow_size` | Takeover carries the evicted flow's size to the arrival. | After 10 resident votes and `LAMBDA * 10` colliding arrivals, verifies the bucket becomes `(arrival, vote_pos=10, vote_neg=0)` rather than starting at `1`. |
| `heavy_only_takeover_inherits_the_eviction_flag` | Takeover carries the bucket's flag to the arrival. | Seeds a resident bucket's `eviction` to `false` and to `true` in turn, drives a takeover through `insert_heavy_only`, and verifies the arrival reads back the seeded value rather than a forced `true`. |
| `heavy_only_takeover_discards_the_evicted_flow_as_designed` | The evicted flow's size is dropped, not spilled. | In the same scenario, verifies `query` on the evicted flow returns `0` against a true count of `10`. |
| `heavy_only_matches_insert_while_buckets_seat_and_match` | Seating and matching agree with the normal path. | Feeds 6 flows into a 16-bucket table through both paths and verifies every bucket field and every `query` result matches. |
| `merge_keeps_uncontested_flows_in_the_heavy_part` | Merge leaves elephants in the heavy part. | Verifies post-merge `query` returns exactly `30` and `18`, that both flows are still resident with those vote counts, and that every bucket carries the eviction flag. |
| `merge_keeps_the_larger_flow_on_a_contested_bucket` | A contested bucket goes to the larger flow. | With a 20-count and a 9-count flow on one bucket, verifies the 20 keeps the bucket and the loser reads back at `>= 9` from the light layer. |
| `merge_keeps_the_peers_flow_when_it_is_the_larger` | Each side is sized against its own sketch. | A 3-count local flow loses its bucket to the peer's 50-count flow; querying the peer's flow against the local sketch would read near 0 and flip the outcome. |
| `merge_sums_the_votes_of_a_flow_both_sides_held` | A shared elephant is summed, not replaced. | A flow with 30 left and 20 right comes back resident with `vote_pos == 50`. |
| `merge_never_underestimates_across_a_large_flow_set` | Merging preserves the one-sided guarantee. | 60 flows, half of them shared, through a `2x64` light layer; every flow reads back at or above its true count. |
| `merge_does_not_leave_a_stale_copy_as_a_resident` | Expansion copies do not survive a merge. | After a doubling and a merge, `heavy_hitters` reports each flow exactly once; the merge clears the stale flag, so a kept copy would look live. |
| `merge_preserves_colliding_flow_mass` | Merge preserves mass for bucket-colliding flows. | Merges two sketches whose flows share a heavy bucket and verifies both estimates stay at or above their true counts. |
| `a_bucket_reoccupied_after_merge_still_reads_the_light_layer` | A post-merge resident keeps its flushed mass. | After merging a 30-count flow away and re-inserting it once, verifies `query` returns `31` rather than `1`. |
| `maximum_merging_never_underestimates_disjoint_flows` | Maximum merging keeps Elastic's one-sided guarantee. | Merges two sketches over 80 disjoint flows through a `2x64` light layer and verifies every per-flow estimate is at or above its true count. |
| `maximum_merging_is_tighter_than_sum_merging` | Maximum merging beats sum merging on disjoint flows. | Runs the same 80-flow disjoint input through `merge` and `merge_max` and verifies no flow is looser under max and at least one is strictly tighter; measured totals are 434 against 359 for a truth of 275. |
| `maximum_merging_underestimates_a_mouse_flow_both_sides_saw` | Maximum merging's precondition, pinned as behavior. | A mouse flow kept out of the heavy part by a hot flow, inserted 30 times left and 20 times right, reads back as `30` after `merge_max` and `50` after `merge`. |
| `maximum_merging_sums_a_flow_both_heavy_parts_held` | The restriction is on the light half only. | A shared flow resident on both sides comes back with `vote_pos == 50` under `merge_max`, since the heavy parts are combined bucket by bucket either way. |
| `maximum_merging_keeps_the_larger_flow_on_a_contested_bucket` | Maximum merging contests buckets the same way. | The 20-count flow keeps the bucket against a 9-count peer, and the loser reads back at `>= 9`. |
| `heavy_hitters_reports_every_resident_above_the_threshold` | Heavy hitter detection reports the right set. | Over four residents of a 256-bucket table (50/30/12/3), verifies `heavy_hitters(20)` is exactly the 50 and 30 flows, `heavy_hitters(100)` is empty, and `heavy_hitters(1)` has all four. |
| `heavy_hitters_includes_a_flow_sitting_exactly_on_the_threshold` | The threshold is inclusive. | A flow of exactly 20 is reported at `threshold = 20` and one of 19 is not, matching the reference's `val >= threshold`. |
| `heavy_hitters_does_not_report_a_flow_twice_after_expansion` | Expansion does not duplicate hitters. | After `expand_heavy()` leaves every resident a stale copy, verifies three flows come back once each rather than twice. |
| `heavy_changes_reports_only_moves_past_the_threshold` | Heavy change detection filters by size of move. | Over rising (10->55), falling (60->8), and steady (40->42) flows, verifies only the first two are reported at `threshold = 20`. |
| `heavy_changes_covers_a_flow_present_in_only_one_window` | A flow in one window only is a change. | Verifies a flow of 40 that vanishes reports `(40, 0)` and one of 45 that appears reports `(0, 45)`. |
| `heavy_changes_reports_each_flow_once` | Each flow appears once in the change list. | A flow resident in both windows, each expanded so it also has a stale copy, reaches the id list four times and is reported once. |
| `elastic_round_trip_serialization` | The envelope frames a sketch under kind_id `0x0b 0x00`, and the state survives a round trip. | For an 8-bucket heavy table over a `2x256` light layer fed 12 hits of one flow and one of another, verifies the bytes open with the ASAPv1 magic, a `kind_id_len` of `2`, and `0x0b 0x00`, and that the decode keeps `bktlen`, the light dimensions, every heavy bucket, every light counter, and a `query` of `12`. |
| `elastic_rejects_foreign_kind_id` | The inlined Count-Min's own envelope is not an Elastic one. | Verifies a stand-alone `2x256` `CountMin<Vector2D<i32>, RegularPath>` envelope fails to decode as an `Elastic`. |
| `elastic_metadata_rejects_unknown_keys` | An unexpected metadata key fails closed. | Encodes the twelve `ElasticMetadata` fields plus a `bogus_field` as a named map and verifies it does not decode as `ElasticMetadata`. |
| `elastic_metadata_rejects_a_missing_light_cols_key` | `light_cols` is required and can never be silently defaulted. | Encodes the other eleven `ElasticMetadata` fields as a named map with `light_cols` omitted and verifies it does not decode as `ElasticMetadata`. |
| `elastic_rejects_zero_dimension_payload` | A zero dimension in either part is a decode error, not a panic. | Verifies crafted envelopes declaring `0` heavy buckets, `0` light rows, and `0` light columns each fail rather than panicking in the `cols.ilog2()` mask derivation. |
| `elastic_rejects_dimension_length_mismatch` | Both length checks run before the heavy table and the light matrix are built. | Verifies a crafted envelope declaring `1024` buckets over `MATRIX_MAX_ROWS x 2^24` while carrying two buckets and three light counters fails, and that a payload whose heavy arrays agree with each other but whose `light_counts` holds eight entries against a declared `2x256` fails too. |
| `elastic_rejects_a_flow_and_vote_that_disagree_on_occupancy` | A free bucket is `nil` with no vote, and a payload where the two disagree is refused. | Verifies a crafted payload naming a flow whose `vote_pos` is `0`, and one carrying a vote under a `nil` flow, both fail to decode. |
| `elastic_rejects_serializing_an_inconsistent_sketch` | The encode side refuses states its own decoder would reject. | Verifies an 8-bucket sketch whose `bktlen` is set to `16` fails to serialize, and that one whose free bucket names a flow fails too. |
| `elastic_free_buckets_are_nil_and_never_collide_with_an_empty_flow_id` | A free bucket is `nil`, not an empty string. | For an all-free 4-bucket table, verifies the payload holds one `0xc0` per bucket and no `0xa0` and that the decode matches bucket for bucket; then that a table holding an inserted empty flow id emits an `0xa0`, decodes identically, and answers that flow's `query` with `1`. |
| `elastic_mixed_occupancy_round_trips` | A table mixing free, occupied and evicted buckets round-trips bucket for bucket. | For a 16-bucket table over `3x512` fed a resident, a colliding flow past the `LAMBDA` threshold, and six more flows, verifies the fixture holds both vacant and flagged buckets and that the decode matches on every bucket, every light counter, and both flows' `query` results. |
| `elastic_negative_votes_and_light_counters_round_trip` | Votes and light counters are signed on the wire. | Sets a bucket's `vote_neg` to `-300` and `vote_pos` to `-7` and inserts a light weight of `-9` into a 4-bucket `2x8` sketch, then verifies the decode matches on every bucket and every light counter. |
| `elastic_stale_copies_round_trips_in_both_states` | `stale_copies` is carried, since the buckets do not determine it. | Verifies an 8-bucket sketch decodes with the flag `false`, then that after `expand_heavy()` it decodes with the flag `true`, a `bktlen` of `16`, matching buckets, `heavy_hitters` agreeing with the source, and exactly twice as many occupied buckets as reported flows. |
| `elastic_decoded_sketch_reserializes_byte_identically` | The emitted order is bucket index order for the heavy table and row-major for the light layer. | For a 16-bucket `3x512` sketch fed 40 flows and then expanded, verifies the decoded sketch re-serializes to the bytes it came from. |
| `elastic_custom_hasher_profile_round_trips_and_is_self_describing` | The metadata describes the hasher that built the sketch rather than a hardcoded profile. | For an 8-bucket `2x256` sketch over a hasher declaring its own `HashProfile`, verifies the buckets and light counters round-trip, the bytes differ from the standard-profile sketch's over the same flows, and a standard-profile decode rejects them. |
| `elastic_rejects_too_many_light_rows` | The light Count-Min layer carries the seed list's row bound. | Verifies a sketch past `MATRIX_MAX_ROWS` fails to serialize, that a crafted envelope of that geometry fails to decode with a message naming `MATRIX_MAX_ROWS`, and that the boundary row count still serializes. |
| `heavy_hitters_size_a_flagged_resident_through_the_light_layer` | A flagged resident is sized by `query`, not by `vote_pos`. | After 10 inserts of a resident and `LAMBDA * 10` (`80`) inserts of a bucket-colliding flow into an `init_with_length(8)` sketch, verifies the bucket reads `vote_pos == 1` with `eviction` set, and that `heavy_hitters(50)` is exactly `[(arrival, 80)]` rather than empty. |
### Coco
Test file: [`src/sketches/coco.rs`](../src/sketches/coco.rs)
Wire tests: [`src/sketches/coco/wire.rs`](../src/sketches/coco/wire.rs)
| test_name | test_description | what_is_tested |
| --- | --- | --- |
| `insert_then_estimate_matches_full_value_for_partial_key` | Insert then estimate matches full value for partial key. | Core behavior for insert/query/update and deterministic semantics is validated; the substring query and `estimate_key` both return `5`. |
| `estimate_with_udf_allows_custom_partial_matching` | Estimate with udf allows custom partial matching. | Core behavior for insert/query/update and deterministic semantics is validated. |
| `tied_minimum_buckets_are_chosen_uniformly_at_random` | Buckets tied at the smallest value are picked uniformly. | Inserts one key into 2,000 fresh `32x4` tables, where all four mapped buckets tie at `0`, and verifies each row takes between 200 and 800 of the landings rather than row 0 taking all of them. |
| `the_three_queries_disagree_on_a_key_that_prefixes_another` | The three query shapes are distinguished on prefixing keys. | With `k1=7` and `k10=5` inserted, verifies `estimate_substring("k1")` returns `12` while `estimate_key` and `estimate_projected` both return `7`. |
| `estimate_projected_aggregates_full_keys_sharing_a_partial_key` | Projection aggregates full keys onto one partial key. | Reproduces the paper's figure 7: two full keys on srcip `19.98.10.26` sum to `1041`, and the lone `34.52.73.17` key returns `856`. |
| `recorded_flows_yields_each_occupied_bucket_once` | The query front-end lists every recorded flow exactly once. | After 20 weighted inserts into a `32x4` table, verifies the iterator yields one entry per occupied bucket and that no key appears twice. |
| `group_by_agrees_with_per_key_projected_queries` | One-pass grouping matches the per-key scan. | Over 60 inserts across 5 families, verifies every `group_by` entry equals `estimate_projected` for the same partial key. |
| `group_by_preserves_the_inserted_mass` | Grouping conserves the inserted mass under eviction. | Drives 400 inserts of weight 3 through an `8x2` table and verifies the grouped totals still sum to `1200`. |
| `group_by_reproduces_the_papers_figure_seven` | Grouping reproduces the paper's worked example. | Groups `19.98.10.26\|80=521`, `19.98.10.26\|443=520`, and `34.52.73.17\|118=856` by srcip and verifies exactly two entries, `1041` and `856`. |
| `a_key_occupies_at_most_one_bucket_per_row` | A key never gains a second home in the table. | After 64 inserts of one key into a `32x4` table, verifies exactly one bucket holds it and `estimate_key` returns `64`. |
| `estimate_key_never_exceeds_the_inserted_mass` | Point queries stay inside the table mass. | Over 500 weighted inserts across 40 keys in an `8x2` table, verifies the table mass equals the inserted mass and no per-key estimate exceeds it. |
| `merge_combines_tables_without_losing_counts` | Merge combines tables without losing counts. | Merge behavior preserves expected aggregate semantics and internal invariants. |
| `coco_round_trip_serialization` | The envelope frames a sketch under kind_id `0x0c 0x00`, and the state survives a round trip. | For an `init_with_size(8, 4)` table holding two weighted keys, verifies the bytes open with the ASAPv1 magic, a `kind_id_len` of `2`, and `0x0c 0x00`, and that the decode keeps `w` `8`, `d` `4`, every bucket's key and value, and an `estimate_key` of `521`. |
| `coco_rejects_foreign_kind_id` | Another sketch carrying `rows`/`cols` metadata is refused on its kind_id. | Verifies a `4x8` Count-Min envelope fails to decode as a `Coco`. |
| `coco_metadata_rejects_unknown_keys` | An unexpected metadata key fails closed. | Encodes the eight `CocoMetadata` fields plus a `bogus_field` as a named map and verifies it does not decode as `CocoMetadata`. |
| `coco_metadata_rejects_a_missing_cols_key` | `cols` is required and can never be silently defaulted. | Encodes the other seven `CocoMetadata` fields as a named map with `cols` omitted and verifies it does not decode as `CocoMetadata`. |
| `coco_rejects_zero_dimension_payload` | A zero dimension is a decode error, not a `Vector2D` panic. | Verifies a crafted `4x0` envelope with an empty payload fails rather than panicking in the `cols.ilog2()` mask derivation. |
| `coco_rejects_dimension_length_mismatch` | The length check fires from the declared dimensions, before any allocation is sized from them. | Verifies a crafted envelope declaring `MATRIX_MAX_ROWS x 2^24` while carrying three buckets fails. |
| `coco_rejects_mass_under_an_unoccupied_bucket` | An unoccupied bucket holds no mass. | Verifies a crafted `1x2` payload pairing a `nil` key with a value of `9` fails to decode. |
| `coco_rejects_serializing_a_geometry_mismatch` | The encode side refuses geometries its own decoder would reject. | Verifies a sketch whose `w` is set to `16` against an 8-wide table fails to serialize, and that an `init_with_size(8, 0)` sketch fails too. |
| `coco_empty_buckets_are_nil_and_never_collide_with_an_empty_key` | An unoccupied bucket is `nil`, not an empty string. | For an all-empty `init_with_size(4, 2)` table, verifies the payload holds eight `0xc0` and no `0xa0`, the decode matches cell for cell, and `recorded_flows` is empty; then that a table holding an inserted empty key emits an `0xa0`, decodes identically, lists one flow, and answers that key's `estimate_key` with `5`. |
| `coco_mixed_occupancy_round_trips` | A table mixing occupied and free buckets round-trips bucket for bucket. | For an `init_with_size(16, 3)` table fed ten weighted keys, verifies the fixture leaves both bucket states present and that the decode matches on every cell and on `estimate_key` for all ten keys. |
| `coco_decoded_sketch_reserializes_byte_identically` | The emitted order is the table's own index order, so a decode re-encodes exactly. | For an `init_with_size(16, 3)` table fed twelve weighted keys, verifies the decoded sketch re-serializes to the bytes it came from. |
| `coco_custom_hasher_profile_round_trips_and_is_self_describing` | The metadata describes the hasher that built the sketch rather than a hardcoded profile. | For an `init_with_size(8, 4)` table over a hasher declaring its own `HashProfile`, verifies every cell round-trips, the bytes differ from the standard-profile sketch's over the same keys, and a standard-profile decode rejects them. |
| `coco_rejects_too_many_rows` | Row `i` hashes at seed index `i`, so the table carries the seed list's row bound. | Verifies a sketch past `MATRIX_MAX_ROWS` fails to serialize, that a crafted envelope of that geometry fails to decode with a message naming `MATRIX_MAX_ROWS`, and that the boundary row count still serializes. |
### KMV
Test file: [`src/sketches/kmv.rs`](../src/sketches/kmv.rs)
Wire tests: [`src/sketches/kmv/wire.rs`](../src/sketches/kmv/wire.rs)
| test_name | test_description | what_is_tested |
| --- | --- | --- |
| `assert_serialization_round_trip` | Assert serialization round trip. | Serialization/deserialization preserves component state and behavior after round trip. |
| `kmv_round_trip_serialization` | The envelope frames a sketch under kind_id `0x0e 0x00`, and the bytes are stable across a round trip. | For `k = 64` filled by 5,000 distinct keys, verifies the bytes open with the ASAPv1 magic, a `kind_id_len` of `2`, and `0x0e 0x00`, that the metadata carries `k` `64` and the canonical seed index, that the 64 emitted hashes are strictly ascending, and that the decode matches on `k`, capacity, retained hashes, heap root, and `estimate`, re-serializing identically. |
| `kmv_emitted_order_is_independent_of_insertion_order` | The emitted order follows the hash value, not the arrival order. | Fills two `k = 32` sketches with the same 2,000 keys forward and backward, verifies their heap arrays differ, and that both serialize to the same bytes, which a decode re-encodes exactly. |
| `kmv_empty_round_trip` | A sketch that retains nothing has exactly one encoding. | Verifies a fresh `k = 16` sketch emits `k` `16` beside an empty `hashes` array and decodes back to length `0` at capacity `16` with an `estimate` of `0.0` and identical re-serialized bytes. |
| `kmv_carries_hashes_at_full_u64_width` | The retained digests travel at 64 bits. | Inserts `0`, `1`, `u64::MAX / 2`, and `u64::MAX` by hash into a `k = 4` sketch and verifies the payload and the decoded sketch both carry those four values, re-serializing identically. |
| `kmv_rejects_foreign_kind_id` | Another sketch's kind_id is refused. | Verifies a `3x8` Count-Min envelope fails to decode as a `KMV` with a "kind_id mismatch" complaint. |
| `kmv_metadata_rejects_unknown_keys` | An unexpected metadata key fails closed. | Encodes the eight `KmvMetadata` fields plus a `bogus_field` as a named map and verifies it does not decode as `KmvMetadata`. |
| `kmv_metadata_rejects_a_missing_k_key` | `k` is required and can never be silently defaulted. | Encodes the other seven `KmvMetadata` fields as a named map with `k` omitted and verifies it does not decode as `KmvMetadata`. |
| `kmv_rejects_a_crafted_envelope` | Every structural rule is pinned by the complaint it fails with. | Verifies four crafted envelopes are each refused for their own reason: a `k` of `0`, three hashes over a `k` of `2`, an unsorted hash array, and one holding a duplicate. |
| `kmv_rejects_a_payload_declaring_more_hashes_than_it_carries` | An over-declared array header is refused on the read. | Verifies a payload whose `array32` header declares `2^30` elements while carrying two of them fails rather than being allocated. |
| `kmv_does_not_allocate_a_declared_k` | A declared `k` is metadata, never an allocation size. | Verifies an envelope declaring `k` `u32::MAX` with two hashes decodes, reports that bound and an `estimate` of `2.0`, and that a further hash is appended rather than evicting one. |
| `kmv_refuses_a_k_the_metadata_cannot_carry` | A `k` past the metadata's `u32` field fails the encode rather than truncating. | Verifies a sketch built at `k = 1 << 40` fails to serialize with a message naming the "exceeds the u32 metadata field" rule. |
| `kmv_refuses_to_serialize_a_state_decode_would_reject` | The encode side refuses the states decode refuses. | Verifies a `k = 0` sketch fails to serialize, and that one retaining two hashes at `k = 1` fails with a "2 hashes over a k of 1" complaint. |
| `kmv_custom_hasher_profile_round_trips_and_is_self_describing` | The metadata describes the hasher that built the sketch rather than a hardcoded profile. | For a `k = 16` sketch over 500 keys through a hasher declaring its own `HashProfile`, verifies the retained hashes round-trip and re-serialize identically, that the two profiles retain the same hashes yet emit different bytes, and that a standard-profile decode rejects them. |
### UniformSampling
Test file: [`src/sketches/uniform.rs`](../src/sketches/uniform.rs)
Wire tests: [`src/sketches/uniform/wire.rs`](../src/sketches/uniform/wire.rs)
| test_name | test_description | what_is_tested |
| --- | --- | --- |
| `sample_count_tracks_rate` | Sample count tracks rate. | Core behavior for insert/query/update and deterministic semantics is validated. |
| `samples_are_drawn_from_input_stream` | Samples are drawn from input stream. | Core behavior for insert/query/update and deterministic semantics is validated. |
| `merge_combines_samples_using_rate_based_target` | Merge combines samples using rate based target. | Merge behavior preserves expected aggregate semantics and internal invariants. |
| `merge_rejects_different_rates` | Merge rejects different rates. | Merge behavior preserves expected aggregate semantics and internal invariants. |
| `sample_access_is_stable` | Sample access is stable. | Core behavior for insert/query/update and deterministic semantics is validated. |
| `uniform_sampling_round_trip_serialization` | The envelope frames a sampler under kind_id `0x0d 0x00`, and the state survives a round trip. | For a sampler at rate `0.25` seeded at `0xBEEF_FACE` over 40 updates, verifies the bytes open with the ASAPv1 magic, a `kind_id_len` of `2`, and `0x0d 0x00`, and that the decode matches on `sample_rate`, `total_seen`, `len`, and the retained samples. |
| `uniform_sampling_re_encodes_byte_identically` | The priorities are payload state, not derived. | For a sampler at rate `0.5` seeded at `0xFACE_FACE` over 33 updates, verifies the decoded sampler re-serializes to the bytes it came from. |
| `uniform_sampling_rng_state_resumes_the_same_sequence` | The payload carries the RNG position, so a decode resumes the same draws. | Feeds the same 40 further updates to a rate-`0.3` sampler and to its decoded copy, and verifies they agree on the samples, on `total_seen`, and on their re-serialized bytes. |
| `uniform_sampling_empty_round_trip_has_exactly_one_encoding` | An empty sampler has one encoding for a given rate and RNG position. | Verifies a rate-`0.1` sampler seeded at `0xABC1` decodes back empty with `total_seen` `0` and its rate intact, and that its bytes equal both a fresh twin's and the decoded sampler's re-serialization. |
| `uniform_sampling_rejects_foreign_kind_id` | Another sketch's kind_id is refused. | Verifies a `3x8` Count-Min envelope fails to decode as a `UniformSampling`. |
| `us_metadata_rejects_unknown_keys` | An unexpected metadata key fails closed. | Encodes the three `UsMetadata` fields plus a `bogus_field` as a named map and verifies it does not decode as `UsMetadata`. |
| `us_metadata_rejects_a_missing_item_type_key` | `item_type` is required and can never be silently defaulted. | Encodes a named map holding only `metadata_version` and `sample_rate` and verifies it does not decode as `UsMetadata`. |
| `us_metadata_rejects_a_foreign_item_type_name` | Samples are `f64`, and no other `item_type` name decodes. | Wraps an `i64`-labelled metadata around a one-sample payload and verifies it does not decode. |
| `uniform_sampling_rejects_an_out_of_range_sample_rate` | A rate outside `(0, 1]` is refused before it reaches `target_size`. | Verifies crafted envelopes at rates `0.0`, `-0.5`, `1.5`, `NaN`, and infinity each fail rather than panic. |
| `uniform_sampling_huge_declared_stream_costs_two_samples` | The declared stream length never sizes an allocation. | Verifies a payload declaring `total_seen` `u64::MAX` beside two samples decodes to a sampler holding exactly those two. |
| `uniform_sampling_rejects_more_samples_than_the_rate_allows` | Retaining more than the rate allows is not a state the algorithm reaches. | Verifies a payload of three samples at `total_seen` `2` and rate `0.5` fails to decode. |
| `uniform_sampling_rejects_parallel_array_length_mismatch` | The two payload arrays are parallel. | Verifies a payload of three priorities against two values fails to decode. |
| `uniform_sampling_rejects_unordered_priorities` | Entries are held in ascending priority, with ties broken by the value. | Verifies a payload of priorities `[9, 2, 5]` fails to decode, and that one with equal priorities whose values run `[8.0, 1.0]` fails too. |
| `uniform_sampling_rejects_crafted_bytes_without_panicking` | Truncated, foreign and garbage bytes are errors, never panics. | Verifies six truncations of a valid envelope, 64 bytes of `0xff`, and a valid envelope carrying a garbage payload all fail to decode. |
| `uniform_sampling_rejects_serializing_an_over_full_sampler` | The encode side refuses a sampler its own decoder would reject. | Verifies a sampler holding two samples whose `total_seen` is set to `1` fails to serialize. |
## Sketch Frameworks
### Hydra
Test file: [`src/sketch_framework/hydra.rs`](../src/sketch_framework/hydra.rs)
Wire tests: [`src/sketch_framework/hydra/wire.rs`](../src/sketch_framework/hydra/wire.rs)
| test_name | test_description | what_is_tested |
| --- | --- | --- |
| `hydra_updates_countmin_frequency` | Hydra updates countmin frequency. | Updates `"user;session"` with value `"event"` 5 times and verifies combined query `>= 5` while an unrelated key query is exactly `0.0`. |
| `hydra_updates_countmin_frequency_multiple_values` | Hydra updates countmin frequency multiple values. | Inserts values `I64(0..4)` with multiplicity `i` under one key, verifies per-value fan-out query `>= i`, and checks unrelated-key query returns `0.0`. |
| `hydra_round_trip_serialization` | Hydra round trip serialization. | After mixed inserts, verifies MessagePack round trip keeps non-empty payload, preserves dimensions/template type, and keeps queried frequencies exactly unchanged. |
| `hydra_subpopulation_frequency_test` | Hydra subpopulation frequency test. | On a fixed labeled dataset, asserts exact subpopulation frequencies for single-label, multi-label, full-key, and disjoint cross-population queries (including zero-result case). |
| `hydra_subpopulation_cardinality_test` | Hydra subpopulation cardinality test. | Using HLL-backed counters, checks single/multi/full-key cardinalities are approximately `3.0` (within `EPSILON`) and disjoint/unknown keys return `0.0`. |
| `hydra_tracks_kll_quantiles` | Hydra tracks KLL quantiles. | For inserted samples `[10,20,30,40,50]`, verifies CDF query at `30.0` is `0.6` (within `1e-9`) and empty-bucket query returns `0.0`. |
| `hydra_kll_single_label_cdfs` | Hydra KLL single label cdfs. | For each label group, verifies exact expected CDF levels `{1/3, 2/3, 1}` at chosen thresholds using `EPSILON` tolerance. |
| `hydra_kll_multi_label_cdfs` | Hydra KLL multi label cdfs. | Verifies exact CDF values for multi-label combinations and confirms a non-overlapping key pair returns CDF `0.0`. |
| `hydra_kll_extreme_queries` | Hydra KLL extreme queries. | Confirms CDF boundary behavior (`0` below range, `1` above range) for known keys and `0` for unknown keys. |
| `test_count_min_frequency_query` | Test count min frequency query. | Inserts one key three times into `HydraCounter::CM`, then verifies `Frequency` query succeeds and returns exactly `3.0`. |
| `test_count_min_invalid_query_types` | Test count min invalid query types. | Verifies unsupported CM queries return errors, including exact message for `Quantile` (`"Count-Min Sketch Counter does not support Quantile Query"`). |
| `test_hll_cardinality_query` | Test HLL cardinality query. | Inserts `100` unique items plus one duplicate and verifies `Cardinality` query succeeds with estimate constrained to `(90.0, 110.0)`. |
| `test_kll_quantile_query` | Test KLL quantile query. | Inserts values `1..=100` and verifies median query succeeds with estimate within `+/-5` of `50.0`. |
| `test_univmon_universal_queries` | Test univmon universal queries. | Inserts `A` 10 times and `B` 20 times, then checks `L1=30.0`, cardinality is approximately `2.0` (`abs err < 0.5`), and entropy is positive. |
| `test_merge_counters` | Test merge counters. | Merges two CM counters and verifies frequency sum (`2.0`) for shared key, then confirms merging with mismatched counter type (`HLL`) returns error. |
| `test_count_frequency_query` | Test count frequency query. | Inserts one `Count` key four times and verifies `Frequency` query succeeds with exact result `4.0`. |
| `test_count_invalid_query_types` | Test count invalid query types. | Verifies unsupported `Count` queries fail, including exact `Quantile` error message and error on `Cardinality`. |
| `hydra_count_min_round_trip_serialization` | A Count-Min grid round-trips under kind_id `0x07 0x01`. | For a `3x8` grid of `2x16` fast-path Count-Min counters over a two-column schema fed 30 records, verifies the envelope names that kind_id, that the grid and counter dimensions and the schema survive, that three frequency probes answer identically, and that the decode re-serializes to the same bytes. |
| `hydra_count_sketch_round_trip_serialization` | A Count Sketch grid round-trips under kind_id `0x07 0x02`. | Runs the same round trip over `2x16` fast-path Count Sketch counters and the same three frequency probes. |
| `hydra_hyperloglog_round_trip_serialization` | An HLL grid round-trips under kind_id `0x07 0x03`. | Runs the same round trip over `HyperLogLog<ErtlMLE>` counters fed 300 records, probing two cardinality queries. |
| `hydra_kll_round_trip_serialization` | A KLL grid round-trips under kind_id `0x07 0x00`. | Runs the same round trip over default `KLL` counters fed 300 records, probing two quantiles and a CDF. |
| `hydra_univmon_round_trip_serialization` | A UnivMon grid round-trips under kind_id `0x07 0x04`. | Runs the same round trip over `UnivMon::init_univmon(4, 2, 16, 3)` counters fed 120 records, probing L1, L2, entropy, and cardinality. |
| `hydra_count_sketch_negative_cells_round_trip` | Signed cells reach the wire and come back unchanged. | Verifies the Count Sketch grid holds a negative counter and that every cell of every counter matches after a decode. |
| `hydra_schema_round_trips_exactly` | The key columns round-trip exactly, escaping included. | For a grid whose two labels carry a semicolon, a colon, and a backslash and whose subkeys carry a semicolon, verifies the round trip preserves both frequency probes' answers and that the decoded schema equals the labels. |
| `hydra_variants_reject_each_others_envelopes` | Each variant's decoder owns exactly one kind_id. | Runs all five per-variant decoders against all five variants' envelopes and verifies each succeeds only on its own, and that a plain `2x16` Count-Min envelope is refused by every decoder and by `deserialize_from_bytes`. |
| `hydra_rejects_a_mixed_variant_grid` | A grid mixing counter variants has no encoding. | Replaces one cell of a Count-Min grid with an HLL counter and verifies serialization fails with a complaint naming `cell (1, 1)` and both counter types. |
| `hydra_rejects_serializing_an_inconsistent_grid` | The encode side refuses states its own decoder would reject. | Verifies four Count-Min grids each fail to serialize: one whose `row_num` is `4` against its storage, one whose grid is an unfilled `Vector2D::init(3, 8)`, one holding a `2x8` cell against a `2x16` prototype, and one whose `type_to_clone` holds data. |
| `hydra_univmon_rejects_cells_mixing_key_variants` | A UnivMon grid whose cells hold different `HeapItem` variants has no single `counter_key_type`. | Seats a string-keyed UnivMon in a `u64`-keyed grid and verifies serialization fails with a "mix key variants" complaint. |
| `hydra_rejects_crafted_geometry` | Every declared count is measured against the payload before anything is sized from it. | Verifies nine crafted Count-Min metadata shapes each fail with their own complaint - a `MATRIX_MAX_ROWS x 2^20` grid, an overflowing product, a grid and a counter each one row past `MATRIX_MAX_ROWS`, a zero grid row or column, a zero counter row or column, and a `4x16` counter against the payload - and that an empty schema fails too. |
| `hydra_rejects_crafted_geometry_for_the_variable_counters` | The variable-length counters are cut by the same rule. | Verifies a `MATRIX_MAX_ROWS x 4096` KLL grid declaration fails, and that a `MATRIX_MAX_ROWS x 4096` UnivMon declaration and shapes carrying a zero `sketch_col`, `layer_size`, or `heap_size` each fail too. |
| `hydra_metadata_rejects_unknown_and_missing_keys` | An unexpected metadata key and a missing required one both fail closed. | Encodes the fourteen `HydraMatrixMetadata` fields plus a `bogus_field`, and the same fields with `schema` omitted, and verifies neither decodes as `HydraMatrixMetadata`. |
| `hydra_cell_envelopes_mirror_the_counters_own_bytes` | A cell's inlined state is exactly that counter's own payload. | Verifies the HLL, KLL, and UnivMon cell envelopes built from a cell's state equal the bytes those counters serialize to on their own. |
| `hydra_pins_its_hash_profile` | Hydra hashes its subkeys through the crate default, so it has one truthful profile. | Verifies a Count-Min grid emits `DefaultXxHasher`'s profile id and seed list, and that the same payload re-framed under a custom profile is different bytes that fail to decode. |
| `hydra_rejects_too_many_rows` | The grid and the matrix counters each carry the seed list's row bound. | Verifies a grid past `MATRIX_MAX_ROWS` and a counter past it both fail to serialize with a message naming `MATRIX_MAX_ROWS`, and that the boundary row count still serializes. |
| `key_schema_encoding_names_its_columns` | `encode_subkey_into` names every column it includes and escapes the separators. | For schemas `["a","b","c"]` and `["x","y"]`, verifies masks `0b001`, `0b010`, and `0b101` over `["p","q","r"]` give `"a:p"`, `"b:q"`, and `"a:p;c:r"`, that the `{a,c}` projection differs from the two-column full key over the same values, that `["x;y","z"]` and `["x","y;z"]` give `"x:x\;y;y:z"` and `"x:x;y:y\;z"`, that a colon gives `"x:a\:b;y:c"` and a backslash `"x:a\\b;y:c"`, that labels `["a;b","c:d"]` give `"a\;b:p;c\:d:q"`, and that an empty value gives `"x:;y:c"` against `"y:c"` for the same column left unconstrained. |
| `key_schema_rejects_invalid_column_lists` | An empty, duplicated, or over-long column list is refused. | Verifies `KeySchema::try_from` fails for an empty `Vec<String>`, for `["a","a"]`, and for `MAX_KEY_COLUMNS + 1` (`17`) distinct labels. |
| `hydra_subkeys_are_labelled_by_column` | A subkey carries its column, so the same value in two columns never shares a cell. | On `3x512` grids of `2x64` fast-path Count-Min counters: after 10 updates of `["alice","bob"]`, verifies `[Some("alice"), None]` and `[None, Some("bob")]` read `10.0` while `[None, Some("alice")]` and `[Some("bob"), None]` read `0.0`; that `["x;y","z"]` and `["x","y;z"]` stay four separate `1.0` answers; that a three-column grid fed `["p","q","r"]` and `["p","other","r"]` answers `[Some("p"), None, Some("r")]` with `2.0`, the full key with `1.0`, and `[None, Some("q"), None]` with `1.0`; and that a two-value update, a one-column query, an all-`None` query, a `Cardinality` query against a Count-Min counter, a duplicate label list, and an empty label list each return an error rather than panicking. |
| `hydra_merge_rejects_schema_mismatch` | Merge requires the same column labels in the same declaration order. | For `3x64` grids of `2x64` fast-path Count-Min counters, verifies merging `["src","dst"]` with `["dst","src"]`, with `["src","port"]`, and with `["src"]` each return an error, while merging an identical `["src","dst"]` grid succeeds and leaves `query_frequency(&[Some("alice"), None], &Str("pkt"))` at exactly `2.0`. |
| `median_failure_probability_matches_binomial_tail` | The median failure probability is the binomial tail `P[Bin(rows, p) >= ceil(rows/2)]`. | Verifies `median_failure_probability(5, 0.25)` is `0.103_515_625`, `(3, 0.25)` is `0.156_25`, `(5, 0.0)` is `0.0`, and `(5, 1.0)` is `1.0`, each within `1e-12`. |
### HashSketchEnsemble
Test file: [`src/sketch_framework/hashlayer.rs`](../src/sketch_framework/hashlayer.rs)
| test_name | test_description | what_is_tested |
| --- | --- | --- |
| `test_insert_and_estimate` | Insert and frequency estimate accuracy on Zipf stream. | On Zipf stream (`N=10_000`, `domain=1000`, `exp=1.5`), builds default 2-sketch ensemble (CMS + Count, `3x4096`) and verifies average relative error for both CMS (index `0`) and Count (index `1`) frequency estimates over sampled keys is below `0.1`. |
| `test_insert_at` | Targeted insert updates only specified indices. | Inserts only at index `[0]` via `insert_at`, then verifies CMS at index `0` has a positive estimate while Count at index `1` returns `0.0`. |
| `test_insert_with_hash_matches_insert` | Pre-computed hash insert matches regular insert. | Builds two identical ensembles; one uses `insert()`, the other uses `hash_input()` + `insert_with_hash()`. Verifies CMS estimates at index `0` are identical for a probe key. |
| `test_hll_cardinality` | HLL-only ensemble cardinality accuracy. | Builds HLL-only ensemble (`HyperLogLog<ErtlMLE>`), inserts Zipf stream, and verifies cardinality relative error vs true distinct count is `< 0.02`. |
| `test_estimate_on_hll_returns_error` | Frequency query on HLL sketch returns error. | Calls `estimate()` on an HLL-only ensemble and verifies it returns `Err`. |
| `test_cardinality_on_cms_returns_error` | Cardinality query on CMS sketch returns error. | Calls `cardinality()` on a CMS+Count ensemble and verifies it returns `Err`. |
| `test_direct_access` | Index-based get/get_mut and sketch type reporting. | Verifies `get(0)` and `get(1)` return `Some`, `get(2)` returns `None`, and `get_mut(0)` reports `sketch_type() == "CountMin"`. |
| `test_bounds_checking` | Out-of-bounds queries return errors. | Confirms `estimate(999, ...)`, `cardinality(999)`, and `estimate_with_hash(999, ...)` all return `Err`. |
| `test_custom_dimensions` | Custom-dimension ensemble insert and estimate. | Builds 2-sketch ensemble (CMS + Count, `5x2048`), verifies `len=2`/non-empty, inserts Zipf stream, and confirms both indices return positive estimates. |
| `test_mixed_matrix_and_hll` | Mixed CMS + HLL ensemble queries. | Builds ensemble with one CMS and one `HyperLogLog<ErtlMLE>`, inserts Zipf stream, verifies CMS estimate at index `0` is positive and HLL cardinality error at index `1` is `< 0.05`. |
| `test_push_compatible` | Push compatible sketch succeeds. | Creates single-CMS ensemble (`3x4096`), pushes a Count sketch with matching dimensions, verifies `push` returns `Ok` and `len=2`. |
| `test_push_incompatible_rejected` | Push incompatible sketch is rejected. | Creates single-CMS ensemble (`3x4096`), pushes a Count sketch with different dimensions (`5x2048`), verifies `push` returns `Err`. |
### UnivMon
Test file: [`src/sketch_framework/univmon.rs`](../src/sketch_framework/univmon.rs)
Wire tests: [`src/sketch_framework/univmon/wire.rs`](../src/sketch_framework/univmon/wire.rs)
| test_name | test_description | what_is_tested |
| --- | --- | --- |
| `univmon_round_trip_serialization` | Univmon round trip serialization. | After weighted inserts, verifies non-empty serialization and round-trip preservation of configuration fields, `bucket_size`, `L1/L2/entropy` (`<1e-6` drift), and cardinality (`< EPSILON` drift). |
| `update_populates_bucket_size_and_heavy_hitters` | Update populates bucket size and heavy hitters. | Inserting one hot key `40` times sets `bucket_size=40`, tracks key in heavy-hitter heap with count `>=20`, and yields exact `L1=40` and `cardinality=1`. |
| `merge_with_combines_heavy_hitters` | Merge with combines heavy hitters. | Merging sketches with disjoint heavy keys verifies merged left heap contains both contributions (`left=25`, `right=30`) while right heap retains `right=30`. |
| `univmon_layers_use_different_seeds` | Univmon layers use different seeds. | Verifies hash outputs for the same key with seed indices `0..3` are all pairwise different. |
| `univmon_cardinality_is_positive` | Univmon cardinality is positive. | After inserting `20` distinct flow keys, cardinality estimate is exactly `20.0`. |
| `univmon_bucket_size_tracked_correctly` | Univmon bucket size tracked correctly. | Inserts counts `100`, `200`, `150` for three flows and verifies `bucket_size` equals total `450`. |
| `univmon_basic_operation` | Univmon basic operation. | On fixed mixed workload, verifies exact aggregate metrics `cardinality=10.0` and `L1=131.0`. |
| `test_statistical_accuracy` | Test statistical accuracy. | On heavy/medium/noise synthetic distribution, verifies relative error for both `L2` and `entropy` is below `0.15`. |
| `univmon_random_data_matches_ground_truth_within_configured_tolerance` | Random weighted updates keep every metric inside its own tolerance. | Over `10_000` seeded random weighted updates across 5,000 keys into `init_univmon(256, 6, 8192, 16)`, requires relative error against the exact truth map at or under `0.07` for cardinality and at or under `0.05` for `L1`, `L2`, and entropy. |
| `univmon_layers_with_different_heap_loads_round_trip` | Each layer's heap contents and emitted order survive the round trip. | For an `init_univmon(8, 2, 16, 4)` pyramid fed 40 weighted keys, verifies the layers carry different heap loads, that every layer's length, capacity of `8`, and per-key counts match after a decode, and that the bytes re-serialize identically. |
| `univmon_carries_update_mode_and_candidate_flags` | `update_mode` and `candidate_complete` are state, not derived. | For a terminal-only `init_univmon(2, 2, 8, 3)` pyramid fed 20 keys through `fast_insert`, verifies the payload carries `update_mode` `2`, that the decode preserves the candidate flags, cardinality, and entropy and re-serializes identically, and that forcing every flag true changes what the pyramid reports. |
| `univmon_empty_has_one_encoding` | An empty pyramid has exactly one encoding. | Verifies a fresh `init_univmon(4, 2, 16, 3)` pyramid and one freed after an insert serialize to identical bytes carrying the pinned `EMPTY_KEY_TYPE`, and that the decode holds empty heaps and re-serializes identically. |
| `univmon_pins_its_hash_profile` | UnivMon hashes through the crate default, so it has one truthful profile. | Verifies a populated pyramid emits `DefaultXxHasher`'s profile id and seed list, and that the same payload re-framed under a custom profile is different bytes that fail to decode. |
| `univmon_rejects_foreign_kind_ids` | The neighbouring universal-sketch kind_ids are refused. | Verifies `Count`, `CountL2HH`, `UnivMonPyramid`, and `UnivMonQ` envelopes each fail to decode as a `UnivMon`. |
| `univmon_rejects_crafted_shapes` | Every shape rule fires before an allocation is sized from it. | Verifies six crafted metadata shapes fail - a `layer_size` of `u32::MAX` or `0`, a zero `sketch_col` or `heap_size`, a `MATRIX_MAX_ROWS x 4096` sketch, and a `heap_size` of `1` - and that a short `heap_counts`, a short `candidate_complete`, and an `update_mode` of `7` each fail too. |
| `univmon_rejects_serializing_an_inconsistent_pyramid` | The encode side refuses states its own decoder would reject. | Verifies a layer resized to `2x32` and a layer hashing at another layer's seed index each fail to serialize while the matching `2x16` layer at its own index serializes, and that a pyramid whose heap mixes key variants fails with a "keys mix variants" complaint while a 128-bit key fails outright. |
| `univmon_metadata_rejects_unknown_and_missing_keys` | An unexpected metadata key and a missing required one both fail closed. | Encodes the eleven `UnivMonMetadata` fields plus a `bogus_field`, and the same fields with `key_type` omitted, and verifies neither decodes as `UnivMonMetadata`. |
| `univmon_rejects_too_many_layer_rows` | Every layer is a CountL2HH matrix, so `sketch_row` carries the seed list's row bound. | Verifies a sketch past `MATRIX_MAX_ROWS` fails to serialize, that a crafted envelope of that geometry fails to decode with a message naming `MATRIX_MAX_ROWS`, and that the boundary row count still serializes. |
| `standard_updates_l2_for_every_sampled_layer` | `insert` writes the weight into every layer the key is sampled into. | For `init_univmon(16, 3, 128, 6)`, finds the first `U64` key whose `find_bottom_layer_num` is at least `2`, inserts it at weight `3`, and verifies `get_l2()` is exactly `3.0` on every layer from `0` through that bottom layer. |
| `terminal_update_touches_one_physical_layer_and_reconstructs_queries` | `fast_insert` writes one layer and the queries reconstruct the rest. | For the same `init_univmon(16, 3, 128, 6)` and key, `fast_insert` at weight `3` is verified to leave `get_l2()` at `3.0` on the bottom layer and `0.0` on each of the other five, while `calc_l1`, `calc_l2`, `calc_card`, and `calc_entropy` read exactly `3.0`, `3.0`, `1.0`, and `0.0`. |
| `merge_combines_weight_l2_and_evicted_candidate_counts` | Merge sums the weights and folds both sides' candidate counts into the layer. | For two `init_univmon(1, 3, 1024, 1)` sketches fed `Str("x")` at `100` on the left and `Str("x")` at `5` plus `Str("y")` at `10` on the right, verifies the merged `bucket_size` is `115`, layer 0's `get_l2()` is `sqrt(105^2 + 10^2)` within `1e-9`, the single heap slot holds `x` at count `105`, and `calc_entropy()` is finite and at or above `0.0`. |
| `standard_and_terminal_merges_match_one_pass_with_complete_candidates` | A merge of two halves matches one pass over the whole stream on both update paths. | For `init_univmon(128, 5, 2048, 10)`, splits 2,000 updates over the 64 keys `U64(i % 64)` by parity into two sketches, merges them, and verifies `bucket_size` equals the one-pass sketch's exactly and `calc_l1`, `calc_l2`, `calc_card`, and `calc_entropy` all agree within `1e-9`, run once through `insert` and once through `fast_insert`. |
### UnivMon Optimized
Test file: [`src/sketch_framework/univmon_optimized.rs`](../src/sketch_framework/univmon_optimized.rs)
Wire tests: [`src/sketch_framework/univmon_optimized/wire.rs`](../src/sketch_framework/univmon_optimized/wire.rs)
| test_name | test_description | what_is_tested |
| --- | --- | --- |
| `pool_basic_take_put` | Pool basic take put. | Validates pool accounting: initial preallocation (`available=2`, `allocated=2`), on-demand allocation when empty (`allocated=3`), and reuse on put/take without further allocation. |
| `pool_free_resets_sketch` | Pool free resets sketch. | Confirms returning a used sketch to pool resets state so retaken sketch has `bucket_size=0` and near-zero `L2` in layer `0`. |
| `pyramid_basic_insert_and_query` | Pyramid basic insert and query. | For simple inserts, verifies exact aggregate state with `bucket_size=65`, `L1` approximately `65` (`<1e-6`), and `cardinality=3`. |
| `pyramid_fast_insert_matches_standard` | Pyramid fast insert matches standard. | On identical 500-item stream, verifies standard vs fast paths keep identical `bucket_size`, with `L1` deviation `<10%` and cardinality deviation `<15%`. |
| `pyramid_two_tier_dimensions` | Pyramid two tier dimensions. | Verifies two-tier layout metadata for configured pyramid (`layer_size=8`, `elephant_layers=4`). |
| `pyramid_free_resets_state` | Pyramid free resets state. | After bulk inserts, `free()` resets sketch to empty baseline (`bucket_size=0`, layer-0 `L2` approximately `0`). |
| `pyramid_merge_combines_data` | Pyramid merge combines data. | Merging disjoint halves verifies merged `L1` stays within `10%` of the sum of pre-merge `L1` values. |
| `pyramid_accuracy_zipf` | Pyramid accuracy Zipf. | On heavy/medium/light Zipf-like workload, requires relative error `<15%` for `L1`, `L2`, cardinality, and entropy. |
| `pyramid_fast_insert_accuracy` | Pyramid fast insert accuracy. | Using `fast_insert` only, requires relative error `<15%` for `L1`, `L2`, cardinality, and entropy versus exact frequency map. |
| `pyramid_memory_savings_vs_uniform` | Pyramid memory savings vs uniform. | Verifies pyramid column budget is smaller than uniform baseline and computed memory savings exceed `30%`. |
| `pyramid_round_trip_serialization` | The envelope frames a pyramid under kind_id `0x11 0x00`, and the bytes are stable across a round trip. | For `UnivMonPyramid::new(4, 2, 3, 16, 2, 8, 4)` fed four weighted string keys, verifies the bytes open with the ASAPv1 magic, a `kind_id_len` of `2`, and `0x11 0x00`, that the metadata carries that layout and `key_type` `string`, and that the decode matches on `bucket_size`, L1, L2, cardinality, entropy, and the candidate flags, re-serializing identically. |
| `pyramid_two_tier_geometry_survives` | The two tiers are derived from the layer's position. | Verifies every decoded layer keeps its tier's dimensions - `3x16` for the two elephant layers and `2x8` for the mouse layers - its own seed index, and its counter array. |
| `pyramid_layers_with_different_heap_loads_round_trip` | Each layer's heap contents survive the round trip. | For `UnivMonPyramid::new(8, 2, 3, 32, 2, 16, 4)` fed 40 weighted keys, verifies the layers carry different heap loads, that every layer's length and per-key counts match after a decode, and that the bytes re-serialize identically. |
| `pyramid_without_mouse_layers_round_trips` | The one-tier case still round-trips. | For a pyramid whose four layers are all elephants, verifies the decoded layers all read `2x16` and the bytes re-serialize identically. |
| `pyramid_empty_has_one_encoding` | An empty pyramid has exactly one encoding. | Verifies a fresh pyramid and one freed after an insert serialize to identical bytes carrying a `key_type` of `u64`, and that the decode re-serializes identically. |
| `pyramid_carries_update_mode_and_candidate_flags` | `update_mode` and `candidate_complete` are state, not derived. | For a terminal-only `UnivMonPyramid::new(2, 1, 2, 8, 2, 8, 3)` fed 20 keys through `fast_insert`, verifies the payload carries `update_mode` `2` and that the decode preserves the candidate flags and cardinality and re-serializes identically. |
| `pyramid_pins_its_hash_profile` | The pyramid hashes through the crate default, so it has one truthful profile. | Verifies a populated pyramid emits `DefaultXxHasher`'s profile id and seed list, and that the same payload re-framed under a custom profile is different bytes that fail to decode. |
| `pyramid_rejects_foreign_kind_ids` | The neighbouring universal-sketch kind_ids are refused. | Verifies `Count`, `CountL2HH`, `UnivMon`, and `UnivMonQ` envelopes each fail to decode as a `UnivMonPyramid`. |
| `pyramid_rejects_crafted_shapes` | Every layout rule fires before an allocation is sized from it. | Verifies six crafted metadata layouts fail - a `layer_size` of `u32::MAX` or `0`, a `heap_size` of `0` or `1`, a zero `elephant_col`, and a `MATRIX_MAX_ROWS x 4096` mouse tier - and that a short `heap_lens` and an `update_mode` of `9` each fail too. |
| `pyramid_rejects_serializing_an_inconsistent_layout` | The encode side refuses states its own decoder would reject. | Verifies a mouse layer holding the elephant tier's `3x16` dimensions fails to serialize, and that a layer hashing at another layer's seed index fails too. |
| `pyramid_metadata_rejects_unknown_and_missing_keys` | An unexpected metadata key and a missing required one both fail closed. | Encodes the fourteen `PyramidMetadata` fields plus a `bogus_field`, and the same fields with `mouse_col` omitted, and verifies neither decodes as `PyramidMetadata`. |
### UnivMon-Q
Test file: [`src/sketch_framework/univmon_q.rs`](../src/sketch_framework/univmon_q.rs)
Wire tests: [`src/sketch_framework/univmon_q/wire.rs`](../src/sketch_framework/univmon_q/wire.rs)
| test_name | test_description | what_is_tested |
| --- | --- | --- |
| `univmon_q_round_trip_serialization` | The envelope frames a sketch under kind_id `0x1a 0x00`, and the bytes are stable across a round trip. | For a 4-level, 64-wide, depth-3 sketch seeded at `5` with source id `7` over 200 updates, verifies the bytes open with the ASAPv1 magic, a `kind_id_len` of `2`, and `0x1a 0x00`, that the metadata carries that shape, `counter_type` `i64`, and `seed_index` `5`, and that the decode matches on config, source id, `count`, `min`, `max`, `cdf`, and `estimate_f2`, re-serializing identically. |
| `univmon_q_ordering_state_continues_after_a_round_trip` | The ordering state survives, so a decoded sketch draws the same occurrence priorities. | Feeds the same 400 further updates to a sketch built over 300 updates and to its decoded copy, and verifies they agree on `next_sequence`, on the sorted ordered heap, on `cdf`, and on their serialized bytes. |
| `univmon_q_empty_has_one_encoding` | An empty sketch has exactly one encoding, and `min` and `max` travel as msgpack nil. | Verifies two fresh sketches at the same config and source id serialize identically with a payload `count` of `0` and no extrema, that a cleared sketch is deliberately different bytes since it keeps its occurrence sequence, and that the decode is empty and re-serializes identically. |
| `univmon_q_counter_type_is_pinned` | The counter width is pinned by `counter_type`. | Verifies a 32-bit-counter sketch emits `counter_type` `i32` and decodes with its `estimate_f2` intact, that its bytes differ from the 64-bit sketch's over the same 50 updates, and that relabelling the metadata `f64` makes the decode fail. |
| `univmon_q_custom_hasher_profile_round_trips_and_is_self_describing` | The metadata describes the hasher that built the sketch rather than a hardcoded profile. | For a sketch over a hasher declaring its own `HashProfile`, verifies `estimate_f2` round-trips, the bytes differ from the standard-profile sketch's over the same 100 updates, and a standard-profile decode rejects them. |
| `univmon_q_rejects_foreign_kind_ids` | The neighbouring universal-sketch kind_ids are refused. | Verifies `Count`, `CountL2HH`, `UnivMon`, and `UnivMonPyramid` envelopes each fail to decode as a `UnivMonQ`. |
| `univmon_q_rejects_crafted_shapes` | Every shape rule fires before an allocation is sized from it. | Verifies seven crafted configs fail - `levels` of `63` or `1`, a `width` of `u32::MAX`, a `depth` of `4`, zero `candidates` or `ordered_samples`, and another `hash_seed` - and that a short `candidate_scores`, a short `ever_evicted`, a missing `min`, swapped extrema, a short `occurrence_keys`, and reversed `candidate_keys` each fail too. |
| `univmon_q_rejects_serializing_an_inconsistent_state` | The encode side refuses states its own decoder would reject. | Verifies a level whose `PackedCountSketch` is not the config's size, a `count`/`min`/`max` triple the algorithm cannot reach, and a candidate table over its declared capacity each fail to serialize. |
| `univmon_q_metadata_rejects_unknown_and_missing_keys` | An unexpected metadata key and a missing required one both fail closed. | Encodes the fourteen `UnivMonQMetadata` fields plus a `bogus_field`, and the same fields with `counter_type` omitted, and verifies neither decodes as `UnivMonQMetadata`. |
| `exact_l1_and_occurrence_entropy_for_known_distribution` | A two-value distribution's L1 and entropy come back exactly. | For a 8-level, 4096-wide, depth-5 sketch with 1 candidate, 100 ordered samples and `hash_seed` `17` over 80 copies of `0.0` and 20 of `1.0`, verifies `estimate_l1` is `100.0`, that `estimate_entropy_occurrence` and `estimate_entropy` both land within `1e-12` of the exact `-(0.8 ln 0.8 + 0.2 ln 0.2)`, and that `prepare_queries` reports the same L1 and entropy. |
| `candidate_eviction_history_distinguishes_full_from_truncated` | A candidate table that is merely full has not evicted anything. | On a `Level::new(32, 1, 64, 2)` - width 32, depth 1, 64-bit counters, 2 candidates - verifies `ever_evicted` stays false after the two updates that fill the table, flips on the third key, and is reset by `clear`. |
| `candidate_merge_uses_zero_error_for_full_complete_summary` | A merge re-scores the union from the merged sketch and keeps the heaviest. | Merges a 2-candidate `Level` holding key 3 at 2 into one holding key 1 at 100 and key 2 at 1, and verifies the merge sets `ever_evicted` because the 3-key union exceeds the capacity, and that `candidate_scores` reads exactly `100` for key 1 and `2` for key 3 with key 2 dropped; no `error` field is inspected. |
| `asapv1_envelope_preserves_candidate_eviction_history` | The per-level eviction flag travels on the wire. | For a 2-level, 1-candidate sketch over `[1.0, 2.0, 3.0]` that has evicted on some level, verifies the decoded sketch's per-level `ever_evicted` vector equals the source's. |
| `l2_heavy_candidate_survives_a_diffuse_tail` | An item above twice the L2 threshold stays recoverable under 50,000 distinct competitors. | In a 2-level, 4096-wide, depth-5 sketch with 32 candidates and no ordered samples, searches for a value that samples to the terminal level, adds it 200 times, then adds 50,000 further distinct values that also sample there; verifies `200` exceeds twice `sqrt(F2/32)` for the exact `200^2 + 50_000`, that the level has evicted, that `candidate_scores` still holds the target key, and that `logical_heavy_sets_from(&recover_candidates())` lists it. |
| `exact_for_tiny_frequency_vector` | A seven-element stream is answered exactly by every query. | For the 8-level, 128-wide, depth-5, 32-candidate, 32-sample config over `[5, 1, 2, 2, 9, 5, 5]`, verifies `rank(2.0)` and `estimate_rank_universal(2.0)` are `Some(3)`, `rank(5.0)` is `Some(6)`, quantiles `0.0`/`0.5`/`1.0` are `1.0`/`5.0`/`9.0`, `estimate_frequency(5.0)` is `3`, `estimate_distinct` is `4.0`, `estimate_f2` is `15.0`, the linear `estimate_g_sum` is `7.0`, `heavy_hitters(1)` is `[(5.0, 3)]`, and that `prepare_queries` reproduces all of those plus `count`, `quantiles`, and `cdf`. |
| `ordered_queries_match_the_exact_oracle_when_every_occurrence_is_retained` | With a sample large enough to keep every occurrence, the ordered queries are the oracle. | For a 512-wide, 64-candidate sketch with `ordered_samples` equal to the stream length and source id `0xfeed`, over the 11 values `-inf`, `-100`, `-0.0`, `0.0`, `0.0`, `1.0` three times, `50.0`, `inf`, and `NaN`, verifies all 101 quantiles at `i/100` match the `total_cmp`-sorted truth bit-for-bit, `rank` returns the exact upper rank of every distinct value, and the maximum CDF error is exactly `0.0`. |
| `data_input_api_rejects_non_numeric_values` | The `DataInput` path takes numbers and refuses strings. | Verifies `update_data_input` accepts `I64(-10)` and `F32(2.5)`, returns an error for `Str("no")`, and leaves `count` at `2`. |
| `float_encoding_matches_total_order` | The `u64` key encoding is order-preserving and lossless over the whole `f64` range. | Verifies `float_to_ordered` is strictly increasing across `-inf`, `-10.0`, `-0.0`, `0.0`, `10.0`, `inf`, and `NaN`, and that `ordered_to_float` returns each value with identical bits. |
| `merge_matches_one_pass_for_complete_candidates` | A merge of two shards equals the one-pass sketch when nothing was truncated. | Splits the nine values `[5, 1, 9, 5, 2, 100, 2, 5, -7]` `4`/`5` across two sketches at the 32-candidate config, merges, and verifies `count`, `cdf`, and `estimate_f2` all equal the one-pass sketch's. |
| `prepared_queries_match_direct_queries_after_candidate_eviction` | A prepared query answers identically to the direct one even once candidates have been evicted. | For an 8-candidate, 64-sample sketch over 5,000 updates where every fifth value is `42.0` and the rest are a multiplicative hash mod `997`, verifies `prepare_queries` agrees exactly with the sketch on `estimate_distinct`, `estimate_f2`, `estimate_l1`, the linear `estimate_g_sum`, `estimate_entropy`, `estimate_entropy_universal`, `heavy_hitters(5)`, `rank(500.0)`, `estimate_rank_universal(500.0)`, `quantiles` at `{0.1, 0.5, 0.9, 0.99}`, and `cdf`. |
| `approximate_ordered_queries_remain_monotone_and_dual_after_eviction` | The CDF and quantile answers stay monotone and mutually consistent after eviction. | For an 8-candidate, 64-sample sketch with source id `787` over 5,000 updates where every fourth value is `42.0` and the rest are a multiplicative hash mod `2_003`, verifies some level has evicted, the `cdf` points strictly increase in value and never decrease in rank with a final rank of `1.0`, the 101 quantile estimates at `i/100` are non-decreasing, and each estimate's `rank` divided by `count` is within `1/count` of its quantile. |
| `asapv1_round_trip_preserves_queries` | A round trip preserves the configuration, identity, and every answer. | For the 32-candidate config over 1,000 updates of `value % 97`, verifies the decoded sketch matches the source on `config`, `source_id`, `count`, `cdf`, and `estimate_f2`. |
| `asapv1_checkpoint_resume_preserves_occurrence_priorities` | A sketch resumed from a checkpoint draws the same occurrence priorities as one that was never interrupted. | For a 16-candidate, 64-sample sketch with source id `991`, feeds the first 1,337 of 5,000 values to a twin pair, resumes one from its bytes, feeds both the remaining 3,663, and verifies `next_sequence` is `5_000`, the sorted ordered heaps are identical, and `cdf` and `estimate_f2` agree. |
| `clear_does_not_reuse_occurrence_identities` | `clear` keeps the occurrence sequence, so no priority is ever drawn twice. | For a 128-sample sketch with source id `31337`, records the `(priority_high, priority_low)` pairs after 100 updates, verifies `next_sequence` is `100` both before and after `clear`, reaches `200` after 100 more updates, and that no occurrence in the refilled heap carries a first-round priority pair. |
| `occurrence_sample_merge_is_associative` | The occurrence sample does not depend on the merge tree's shape. | Builds three 1,000-update shards at source ids `10`, `20`, and `30` over `(index * 17 + offset) % 991` for offsets `0`, `1`, and `2`, and verifies `(a+b)+c` and `a+(b+c)` hold the same sorted ordered heap and report the same `cdf`. |
| `occurrence_sample_merge_retains_the_exact_global_bottom_k` | A merged sample is the exact global bottom-k, not an approximation of it. | Builds four 500-update shards at source ids `101`, `202`, `303`, and `404` over `(sequence * 37 + source_id) % 251` at 64 ordered samples, collects every occurrence priority the shards drew through `occurrence(key, sequence)`, sorts and truncates it to 64, and verifies the merged sketch's ordered heap equals that list exactly. |
| `bottom_k_sampling_is_uniform_over_stream_positions` | Every stream position is equally likely to be sampled. | Runs a 32-sample sketch over a 256-position stream for each of 256 source ids, and verifies the inclusion counts sum to exactly `8_192` and their chi-squared against the expected `32` per position is under `400`. |
| `synthetic_uniform_quantiles_have_dkw_bounded_rank_error` | A uniform stream's quantiles stay inside a 6% rank band. | For a 10-level, 2048-wide sketch with `width_halving_period` `5`, depth 3, 32-bit counters, 256 candidates, 512 ordered samples, `hash_seed` `5` and the fixed source id `1` over 100,000 updates of `0..100_000`, verifies the normalized rank error at `{0.01, 0.1, 0.5, 0.9, 0.99}` is below `0.06` and the maximum CDF error is too. |
| `ordered_queries_are_accurate_across_sources_and_distributions` | Rank and CDF accuracy hold across source identities and stream shapes. | For the same 10-level, 2048-wide, 512-sample config over three 50,000-value distributions - a unique ramp, two modes at `0` and `100_000` over `index * 17 % 5_000`, and 60% `42.0` against a diffuse `1_000 +` residual mod `20_000` - and 32 source ids each, verifies the worst quantile rank error has a median under `0.035` and a p95 under `0.06`, and the maximum CDF error a median under `0.04` and a p95 under `0.07`. |
| `cdf_error_decreases_at_the_expected_rate_with_sample_memory` | CDF error falls as `Theta(1/sqrt(k))` in the occurrence-sample size. | Over a 20,000-value ramp at a 10-level, 1024-wide, 128-candidate config and 24 source ids per setting, verifies the mean maximum CDF error times `sqrt(k)` stays under `1.5` for `ordered_samples` of `128`, `512`, and `2_048`, and that each mean is below `0.75` times the previous one. |
| `recovered_heavy_item_improves_residual_cdf_accuracy` | Folding the recovered heavy hitter into the CDF beats the raw occurrence sample. | Over 20,000 values that are `42.0` nine times in ten against a diffuse `1_000 +` residual mod `10_000`, at a 10-level, 1024-wide, 128-candidate, 256-sample config across 32 source ids, verifies `heavy_hitters(1)` names `42.0` every time, the mean assisted CDF error is below `0.85` times the raw occurrence-sample error, the mean rank error at the heavy value's `0.9` boundary is below `0.25` times the raw one, and the p95 assisted error is under `0.025`. |
| `eight_way_merge_retains_multi_metric_accuracy` | An eight-way merge keeps quantile, cardinality, F2, and heavy-hitter accuracy together. | Round-robins 100,000 updates - 40% `42.0`, the rest a shifted multiplicative hash mod `20_000` - across eight sketches at a 10-level, 4096-wide, `width_halving_period` `7`, depth-3, 512-candidate, 1024-sample config, merges them pairwise down to one, and verifies the quantile rank error at `{0.01, 0.1, 0.5, 0.9, 0.99}` is under `0.03`, `estimate_distinct` and `estimate_f2` are within 10% of the exact values, and `heavy_hitters(1)` names `42.0`. |
| `clear_retains_configuration` | `clear` empties the sketch without disturbing its configuration. | Verifies a cleared 32-candidate sketch reports `is_empty`, returns the same `config` it was built with, and answers `quantile(0.5)` with `None`. |
### NitroBatch
Test file: [`src/sketch_framework/nitro.rs`](../src/sketch_framework/nitro.rs)
| test_name | test_description | what_is_tested |
| --- | --- | --- |
| `nitro_batch_countmin_error_bound_zipf` | Nitro batch countmin error bound Zipf. | On Zipf stream (`rows=3`, `cols=4096`, `N=200_000`), verifies CountMin estimates satisfy in-bound key count `> (1-delta)*distinct` using `epsilon=e/cols`, `delta=e^-rows`, and bound `epsilon*N`. |
| `nitro_batch_count_error_bound_zipf` | Nitro batch Count Sketch L2 error bound on a Zipf stream. | On the same stream, checks `Count` median estimates against **Count Sketch's own** bound `sqrt(kappa/cols) * \|\|f_-i\|\|_2` (kappa = 3, residual L2 recomputed per key from the exact frequency vector), requiring the in-bound share to exceed `1 - P[Bin(rows, 1/3) >= ceil(rows/2)]`. Count-Min's `epsilon*N` does not apply to this sketch and is far looser on a skewed stream. Sampling RNG is seeded. |
| `the_cached_path_advances_the_cursor_once_per_admission_and_wraps` | The cached path draws a table entry per admission, wraps at the table length, and folds an out-of-range cursor back in. | For `NitroBatch::with_target_and_seed(0.1, CountMin::<Vector2D<i32>, FastPath>::with_dimensions(3, 1024), seed)` fed 10,000 copies of `7i64` through `insert_cached_step`, verifies seed `0` starts at cursor `0` and ends between `500` and `2_000` entries on for roughly `1_000` admissions (the exact one-draw-per-admission ratio is not pinned), that a seed of `SKIP_TABLE_LEN - 8` ends below its start, and that `commit_ctx(usize::MAX, 0)` folds the cursor below `SKIP_TABLE_LEN` (`65_536`) and a further run does not panic. |
### ExponentialHistogram
Test file: [`src/sketch_framework/eh.rs`](../src/sketch_framework/eh.rs)
Wire tests: [`src/sketch_framework/eh/wire.rs`](../src/sketch_framework/eh/wire.rs)
| test_name | test_description | what_is_tested |
| --- | --- | --- |
| `constructor_infers_merge_norm` | Constructor infers merge norm. | Verifies constructor infers `SketchNorm::L1` for CM payload and `SketchNorm::L2` for `COUNTL2HH` payload. |
| `l1_merge_invariant_same_size` | L1 merge invariant same size. | Under repeated updates with `k=2`, verifies L1 merge policy compacts buckets so `bucket_count < 10`. |
| `l2_merge_invariant_sum_l22` | L2 merge invariant sum l22. | With `k=1` and weighted updates, verifies L2 merge rule keeps bucket count bounded (`bucket_count <= 2`). |
| `merge_recomputes_l2_mass` | Merge recomputes L2 mass. | After L2 merges, verifies bounded bucket count (`<=2`) and non-negative recomputed `l2_mass` for every payload bucket. |
| `test_basic_insertion_and_query` | Test basic insertion and query. | After one update at `t=100`, verifies single bucket presence, exact min/max timestamps (`100`), and successful interval merge query for `[100,100]`. |
| `eh_round_trip_serialization` | The envelope frames a histogram under kind_id `0x13 0x00`, and the state survives a round trip. | For `k = 2` over a 1,000-tick window of Count-Min buckets fed six timestamped updates, verifies the bytes open with the ASAPv1 magic, a `kind_id_len` of `2`, and `0x13 0x00`, and that the decode matches on `window`, `k`, `merge_norm`, every bucket's size, time range, and bit-exact `l2_mass`, and the bucket count. |
| `eh_every_variant_round_trips_as_a_bucket` | Every variant this build carries round-trips as a bucket and as the prototype. | For each populated variant, builds a `k = 3` histogram over four timestamped updates and verifies the decoded prototype keeps its `sketch_type`, the bucket ranges match, and the bytes are stable across a re-serialization. |
| `eh_empty_has_one_encoding_and_round_trips` | A histogram with no buckets has exactly one encoding. | Verifies two `k = 2` histograms over the same Count-Min prototype serialize identically and that the decode holds a bucket count of `0` and re-serializes to the same bytes. |
| `eh_carries_a_non_empty_prototype` | A prototype carrying state keeps it, so later buckets start from it. | For a prototype fed seven inserts of one key, verifies the decoded prototype answers that key as the source does and at or above `7.0`. |
| `eh_decoded_re_serializes_byte_identically_and_queries_agree` | A decoded histogram re-encodes exactly and answers the same interval query. | Verifies the populated histogram's decode re-serializes to the bytes it came from and that `query_interval_merge(0, 50)` answers the same key identically on both. |
| `eh_rejects_foreign_kind_ids` | An `EHSketchList` envelope and a Count-Min envelope are not histogram envelopes. | Verifies both fail to decode as an `ExponentialHistogram`. |
| `eh_metadata_rejects_unknown_keys` | An unexpected metadata key fails closed. | Encodes the three `EhMetadata` fields plus a `bogus_field` as a named map and verifies it does not decode as `EhMetadata`. |
| `eh_metadata_rejects_a_missing_key` | `k` is required and can never be silently defaulted. | Encodes a named map holding only `metadata_version` and `window` and verifies it does not decode as `EhMetadata`. |
| `eh_rejects_a_zero_k` | `k` is at least `1` on both sides. | Verifies a histogram whose `k` is set to `0` fails to serialize, and that a valid payload re-framed under metadata declaring `k` `0` fails to decode. |
| `eh_rejects_parallel_arrays_of_unequal_length` | A declared array far longer than the buckets carried is refused before anything is sized from it. | Verifies a payload of one bucket against a `sizes` array of a million entries fails to decode. |
| `eh_rejects_impossible_bucket_state` | A zero size and an inverted time range are states the algorithm never reaches. | Verifies a crafted bucket of size `0` and one spanning `[9, 4]` each fail to decode, and that a histogram whose first bucket's size is set to `0` fails to serialize. |
| `eh_rejects_derived_fields_that_disagree` | A cached field that disagrees with the state it derives from has no encoding. | Verifies a histogram whose first bucket's `l2_mass` is set to `42.0` fails to serialize, and that one whose `merge_norm` is switched to `L2` over Count-Min buckets fails too. |
| `eh_rejects_an_experimental_kind_id_in_a_bucket` | An experimental variant's kind_id in a bucket is refused without the feature. | Verifies crafted buckets relabelled with the `Coco`, `Elastic`, and `UniformSampling` kind_ids each fail to decode, with a message naming the variant and "experimental" in builds without the feature. |
| `eh_rejects_a_custom_hash_profile_bucket` | A bucket naming a custom hash profile is refused, since the variant's decoder pins the profile of the type it rebuilds. | Verifies a bucket whose descriptor comes from a custom-profile Count-Min fails to decode. |
| `eh_rejects_an_unknown_kind_id_in_a_bucket` | An unknown kind_id in a bucket is refused. | Verifies a bucket relabelled `0xff 0xff` fails with a "not a wire variant" complaint. |
### EHSketchList
Test file: [`src/sketch_framework/eh_sketch_list.rs`](../src/sketch_framework/eh_sketch_list.rs)
Wire tests: [`src/sketch_framework/eh_sketch_list/wire.rs`](../src/sketch_framework/eh_sketch_list/wire.rs)
| test_name | test_description | what_is_tested |
| --- | --- | --- |
| `insert_routes_to_countl2hh_and_univmon` | Insert routes to countl2hh and univmon. | Verifies variant routing by checking `COUNTL2HH` estimate `>=9` after 9 inserts and `UNIVMON` `bucket_size=6` after 6 inserts. |
| `count_sketch_insert_and_query_round_trip` | Count insert and query round trip. | Confirms the `Count` variant updates/query path by inserting one key and verifying returned estimate is at least `1.0`. |
| `ddsketch_insert_and_quantile_query_round_trip` | DDSketch insert and quantile query round trip. | Inserts `10,20,30` into DDSketch variant and verifies queried median (`q=0.5`) lies within `[10.0, 30.0]`. |
| `supports_norm_whitelist_is_enforced` | Supports norm whitelist is enforced. | Validates norm capability matrix: `CM/CS/DDS` support `L1` only, while `COUNTL2HH/UNIVMON` support `L2` only. |
| `eh_sketch_list_round_trip_serialization` | The envelope frames a union under kind_id `0x14 0x00`, and the state survives a round trip. | For a `3x8` fast-path Count-Min variant holding one key, verifies the bytes open with the ASAPv1 magic, a `kind_id_len` of `2`, and `0x14 0x00`, and that the decode keeps a `sketch_type` of `CountMin` and answers that key as the source does. |
| `eh_sketch_list_every_variant_round_trips` | Every variant this build carries round-trips and keeps its type. | For each populated variant, verifies the decode reports the same `sketch_type` and re-serializes to the bytes it came from. |
| `eh_sketch_list_kind_ids_are_build_independent` | The ten nested kind_ids and their registry names are the same in every build. | Verifies `variant_name` maps each of the ten ids to its name and `0xff 0xff` to `None`, and that every populated variant emits the id the table gives it. |
| `eh_sketch_list_rejects_an_experimental_kind_id` | An experimental variant's kind_id is refused without the feature. | Verifies crafted triples carrying the `Coco`, `Elastic`, and `UniformSampling` kind_ids each fail to decode, with a message naming the variant and "experimental" in builds without the feature. |
| `eh_sketch_list_rejects_an_unknown_kind_id` | An unknown kind_id is refused. | Verifies a Count-Min triple relabelled `0xff 0xff` fails with a "not a wire variant" complaint. |
| `eh_sketch_list_rejects_sibling_algorithm_kind_ids` | The nested ids are pinned to one algorithm each. | Verifies an HLL triple relabelled `0x01 0x01` or `0x01 0x03` fails to decode, and that a KLL triple relabelled `0x06 0x01` fails too. |
| `eh_sketch_list_rejects_a_mismatched_kind_id_and_descriptor` | A kind_id that does not match the blocks it carries is refused by the variant's own decoder. | Verifies an HLL triple relabelled with the Count-Min kind_id fails to decode. |
| `eh_sketch_list_rejects_foreign_kind_ids` | A Count-Min envelope and an `ExponentialHistogram` envelope are not union envelopes. | Verifies both fail to decode as an `EHSketchList`. |
| `eh_sketch_list_metadata_rejects_unknown_keys` | An unexpected metadata key fails closed. | Encodes `metadata_version` plus a `bogus_field` as a named map and verifies it does not decode as `EhSketchListMetadata`. |
| `eh_sketch_list_metadata_rejects_a_missing_key` | `metadata_version` is required. | Encodes an empty named map and verifies it does not decode as `EhSketchListMetadata`. |
| `eh_sketch_list_rejects_crafted_blocks` | Crafted blocks fail closed with an error, never a panic. | Verifies a Count-Min triple whose descriptor is cut in half, and one whose state is three `0xc1` bytes, each fail to decode. |
| `eh_sketch_list_rejects_a_custom_hash_profile_descriptor` | A descriptor naming a custom hash profile is refused, since the variant's decoder pins the profile of the type it rebuilds. | Verifies a triple built from a custom-profile Count-Min fails to decode. |
| `eh_sketch_list_query_agrees_after_decode` | A decoded union answers a query the way the original did. | For every populated variant, verifies the source and the decode return the same answer for that variant's sample input. |
| `nested_ddsketch_survives_a_serde_round_trip` | The nested DDSketch keeps its running state through a serde round trip. | Feeds `10.0`, `20.0`, `30.0`, `40.0` into an `EHSketchList::DDS(DDSketch::new(0.01))`, round-trips it through `rmp-serde`, and verifies the decode matches on `get_count`, `sum`, `min`, and `max` and that its `q = 0.5` query lands inside `[10.0, 40.0]`. |
### EHUnivOptimized
Test file: [`src/sketch_framework/eh_univ_optimized.rs`](../src/sketch_framework/eh_univ_optimized.rs)
| test_name | test_description | what_is_tested |
| --- | --- | --- |
| `basic_insertion_and_query` | Basic insertion and query. | For updates `{(1,5),(2,3),(1,2)}` across `[100,102]`, verifies map-tier result with exact counts (`1->7`, `2->3`, `total=10`) plus `L1=10` and `cardinality=2`. |
| `map_merge_bounds_volume` | Map merge bounds volume. | With `k=1` and 50 one-count updates, verifies merge policy bounds growth so `bucket_count < 50`. |
| `promotion_creates_sketch_buckets` | Promotion creates sketch buckets. | Under small promotion thresholds and many distinct updates, verifies at least one map bucket is promoted (`um_buckets` becomes non-empty). |
| `window_expiration` | Window expiration. | With `window=100`, advancing to `t=200` after earlier inserts confirms expiration by forcing oldest surviving `min_time` to recent range (`>=100` or `==200`). |
| `hybrid_query_returns_sketch` | Hybrid query returns sketch. | After forcing both map and sketch tiers to coexist, verifies interval query spanning both returns `EHUnivQueryResult::Sketch` (not map-only). |
| `cover_check` | Cover check. | Verifies coverage logic transitions from false (empty) to true for contained intervals and remains false when query extends outside observed range. |
| `accuracy_known_distribution` | Accuracy known distribution. | On fixed known histogram, verifies query estimates for `L1`, `L2`, cardinality, and entropy each stay within `10%` relative error. |
| `pool_used_during_promotion` | Pool used during promotion. | With bounded preallocated pool, promotion workload verifies sketch-tier creation and confirms pool allocation accounting remains active (`total_allocated >= 2`). |
| `correctness_map_only_exact` | Correctness map only exact. | For map-only regime, verifies `L1/L2/cardinality/entropy` each match exact truth within `1%` tolerance. |
| `correctness_subinterval_query` | Correctness subinterval query. | For two-phase stream, verifies full-interval query recovers `L1` approximately `200` and `cardinality` approximately `2` within `5%` tolerance. |
| `correctness_expired_data_excluded` | Correctness expired data excluded. | After sliding beyond window cutoff, verifies very old segment is excluded by checking earliest retained bucket time is at least `50`. |
| `correctness_volume_bounded_long_stream` | Correctness volume bounded long stream. | Over `20_000` updates with `k=4`, verifies EH volume bound by requiring maximum observed bucket count `< 200`. |
| `correctness_pool_recycling_across_cycles` | Correctness pool recycling across cycles. | Long-run expiration/promotion cycling keeps pool bounded (`total_allocated < 50`) and still returns valid interval query results. |
| `correctness_sketch_merge_preserves_metrics` | Correctness sketch merge preserves metrics. | After repeated promotions/merges, verifies each sketch bucket has positive `L2^2` and stored `l22` stays within `1%` relative difference of recomputed value. |
| `accuracy_zipf_distribution_sketch_tier` | Accuracy Zipf distribution sketch tier. | On heavy/medium/light Zipf-like stream in sketch tier, requires `L1/L2/cardinality/entropy` relative errors each `<= 15%`. |
| `accuracy_uniform_distribution` | Accuracy uniform distribution. | On uniform stream, requires `L1/L2/cardinality/entropy` relative errors each `<= 10%`. |
| `accuracy_sliding_window` | Accuracy sliding window. | Across suffix and periodic sliding-window queries, verifies average relative error for `L1`, `L2`, cardinality, and entropy is each below `15%`. |
| `accuracy_varies_with_k` | Accuracy varies with K. | For `k in {2,8,32}`, verifies per-k average of `L1/L2` relative errors remains under `15%` on same fixed stream/window. |
| `accuracy_suffix_queries` | Accuracy suffix queries. | Across suffix lengths `[1000,2000,5000,8000]`, verifies worst observed `L2` relative error remains below `20%`. |
| `accuracy_distribution_shift` | Accuracy distribution shift. | For two-phase distribution shift stream, verifies full-span `L1/L2/cardinality/entropy` estimates each stay within `15%` relative error. |
### OctoSketch
Test file: [`tests/e2e_octo.rs`](../tests/e2e_octo.rs)
Unit tests: [`src/sketch_framework/octo.rs`](../src/sketch_framework/octo.rs)
Runtime feature: the `runtime_tests` module is `#[cfg(all(test, feature = "octo-runtime"))]`, so the rows from `run_octo_cm_tracks_a_single_threaded_sketch` through `octo_runtime_close_preserves_queued_items` run only under `cargo test --features octo-runtime`.
| test_name | test_description | what_is_tested |
| --- | --- | --- |
| `compact_worker_clears_the_counter_it_promotes` | A worker promotes at the threshold and clears the counter it sent. | Inserts `U64(42)` into a `3x64` `CmWorkerSketch` at a threshold of `CM_PROMASK`, and verifies nothing is emitted over the first `CM_PROMASK - 1` inserts, that the next insert emits exactly `3` deltas - one per row - each carrying a value of `CM_PROMASK`, and that every residual counter is back to `0`. |
| `compact_worker_uses_a_quarter_of_the_counter_memory` | The worker holds one byte per counter against a full sketch's four. | For a `3x4096` `CmWorkerSketch`, verifies `counter_bytes() * 4` equals `rows * cols * size_of::<i32>()`. |
| `compact_worker_honours_a_custom_threshold` | A custom threshold decides how often a counter promotes. | Inserts `U64(7)` 100 times into a `1x16` `CmWorkerSketch` at a threshold of `10` and verifies exactly `10` promotions. |
| `compact_count_worker_promotes_on_magnitude_and_clears` | The signed worker thresholds on `\|counter\|` and clears what it sends. | Inserts `U64(99)` 200 times into a `3x64` `CountWorkerSketch` at `COUNT_PROMASK`, and verifies at least one delta was emitted, that every delta's `value.unsigned_abs()` is `COUNT_PROMASK`, and that every residual counter's magnitude is under `31`. |
| `keyed_deltas_carry_the_key_that_triggered_them` | A keyed delta names the key whose insert produced it. | Drives `CM_PROMASK` inserts of `Str("flow-a")` through `insert_hashes_emit_keyed_delta` on a `2x8` `CmWorkerSketch` and verifies the emitted deltas are non-empty and every one carries `input_to_owned` of that key; the delta count and the delta values are not checked. |
| `dd_worker_promotes_and_clears_a_bucket` | A DDSketch bucket promotes at the threshold and is cleared. | Adds `42.0` `CM_PROMASK` times to a `DdWorkerSketch` at alpha `0.01` under a threshold of `CM_PROMASK`, and verifies exactly one delta carrying a value of `CM_PROMASK` and an empty residual. |
| `dd_worker_drops_what_the_parent_would_drop` | Values `DDSketch::add` would itself drop never promote. | Adds each of `0.0`, `-1.0`, `f64::NAN` and `f64::INFINITY` 1,000 times at a threshold of `1` and verifies zero promotions. |
| `dd_promotion_bounds_the_quantile_rank_error_by_what_it_holds_back` | The held-back mass bounds the parent's quantile rank error. | Feeds 200,000 values `1.0 + (i * 7) % 999` through a `DdWorkerSketch` at alpha `0.01` and a threshold of `DD_PROMASK` into a parent `DDSketch`, and verifies `held_back()` plus the parent's `get_count()` equals `200_000`, that the held-back share is under `0.05`, and that the parent's `0.1`, `0.5`, `0.9` and `0.99` quantiles each fall between the exact value at rank `q - slack` scaled by `1 - alpha` and the exact value at rank `q + slack` scaled by `1 + alpha`. |
| `dd_a_higher_threshold_holds_back_more_of_a_sparse_stream` | Held-back mass grows with the threshold. | Over 20,000 values `1.0 + (i * 7) % 999` at alpha `0.01`, verifies `held_back()` is strictly increasing across thresholds `2`, `8` and `31`. |
| `a_univmon_worker_refuses_a_geometry_that_outruns_the_hash` | A geometry past the 128-bit hash budget panics at construction. | Verifies `L2hhWorkerSketch::new(13, 2048, 0)` - 13 rows at 11 column bits, so 143 bits - panics with a message naming the 128-bit hash budget. |
| `the_widest_accepted_univmon_geometry_still_addresses_distinct_rows` | The widest geometry inside the budget still gives every row its own index. | For `L2hhWorkerSketch::new(11, 2048, 0)` - 121 bits - inserts `U64(7)` at a threshold of `1` and verifies `11` deltas landing on `11` distinct row indices. |
| `every_worker_reads_one_threshold_the_same_way` | The compact worker and the full sketch clamp one threshold identically. | Inserts `U64(9)` 400 times at a threshold of `200` into both a `1x64` `CountWorkerSketch` and a `1x64` regular-path `Count<Vector2D<i32>>`, and verifies both promoted at all, that the two emitted value sequences are equal, and that every emitted value's magnitude is `MAX_PROMASK`. |
| `an_hll_worker_refuses_a_threshold_no_register_can_reach` | A threshold no register gain can reach panics at construction. | Verifies `HllOctoWorker::with_threshold(max_hll_threshold(14))` panics with a message naming the precision. |
| `any_hll_threshold_above_zero_costs_cardinality_accuracy` | Only a threshold of zero leaves the parent's cardinality intact. | Over 50,000 distinct keys into a default `HyperLogLog<Classic>` child and parent, sweeps thresholds `0`, `1`, `2` and `4` and verifies the threshold-`0` parent estimates exactly what a single-threaded reference does, that each higher threshold sends strictly fewer messages and estimates no higher than the threshold below it, that the threshold-`4` estimate is under half of 50,000, and that `max_hll_threshold(14)` is `50`. |
| `a_ddsketch_delta_from_a_finer_mapping_is_dropped_not_allocated` | A delta naming an index outside the parent's store is dropped, not grown into. | Applies `DdDelta` at index `i32::MAX / 2` and at `i32::MIN / 2`, each with a value of `4`, to a `DDSketch` at alpha `0.01` holding one sample of `50.0`, and verifies the store length is unchanged and `get_count()` is still `1`. |
| `a_count_worker_refuses_hashes_built_for_a_different_geometry` | Hashes built for another row count panic rather than partly landing. | Verifies a `4x16` `CountWorkerSketch` fed two-row hashes panics with a "one hash per row" message. |
| `a_worker_refuses_hashes_built_for_a_different_geometry` | The Count-Min worker refuses the same mismatch. | Verifies a `4x16` `CmWorkerSketch` fed two-row hashes panics with a "one hash per row" message. |
| `coco_worker_promotes_the_key_its_bucket_holds_and_clears_it` | A Coco bucket promotes its `<key, counter>` pair and clears. | Inserts `"flow::coco"` into a `CocoWorkerSketch::new(64, 2)` at `COCO_PROMASK`, and verifies nothing promotes over the first `COCO_PROMASK - 1` inserts, that the next insert emits exactly one delta carrying that key and a value of `COCO_PROMASK`, and that every residual counter is `0`. |
| `coco_promotion_conserves_the_inserted_mass` | Promoted mass plus residual is the whole stream, and a flush hands over the rest. | Drives 5,000 inserts over the 200 keys `flow::{i % 200}` through a `CocoWorkerSketch::new(16, 2)` into a `CocoOctoAggregator::new(16, 2)` at `COCO_PROMASK`, verifies the parent's recorded mass plus the worker's residual equals `5_000`, and that after `flush` the parent alone holds `5_000`. |
| `elastic_worker_promotes_each_half_on_its_own_terms` | The heavy half, the light half and the keyed eviction spill all promote. | Alternates `"flow::a"` and `"flow::b"` over 1,000 inserts into an `ElasticWorkerSketch::new(1, 2, 64)` at `ELASTIC_PROMASK` and verifies at least one `Heavy`, at least one `Light` and at least one `Evicted` delta; the counts and the delta contents are not checked. |
| `threshold_for_error_follows_equation_four` | `threshold_for_error` is Equation 4, with a floor of one and a one-byte ceiling. | Verifies `threshold_for_error` returns `100` for (`0.0004`, `1_000_000.0`, `4`) and for (`0.0001`, `1_000_000.0`, `1`), `1` for (`1e-9`, `1_000.0`, `1`), and `MAX_PROMASK` for (`0.001`, `1_000_000.0`, `1`). |
| `shared_threshold_is_visible_to_every_holder` | Every clone of an `OctoThreshold` reads and writes one value, clamped to `1..=MAX_PROMASK`. | For an `OctoThreshold::new(31)` and a clone of it, verifies `increase(4)` reads back as `35` on the clone, `decrease(34)` floors at `1` on the original, and `set(u32::MAX)` reads back as `MAX_PROMASK`. |
| `hll_threshold_zero_promotes_every_improvement` | At threshold zero a register promotes exactly when it improves. | Verifies the first insert of `U64(1)` into a default `HyperLogLog<Classic>` emits one delta and that a second insert of the same key emits none. |
| `hll_threshold_holds_back_small_register_gains` | A positive threshold sends fewer register messages. | Over 20,000 distinct keys into two default `HyperLogLog<Classic>` sketches, verifies only that the threshold-`4` sketch promoted strictly fewer times than the threshold-`0` one; neither estimate is checked. |
| `run_octo_cm_tracks_a_single_threaded_sketch` | A finished Count-Min run trails a single-threaded sketch by under `workers * tau` per key. | Runs 100,000 inputs `U64(i % 1024)` through a `3x4096` `CmOctoPlan` on 4 workers and verifies every one of the 1,024 keys' estimate is at or below the single-threaded reference's and no more than `4 * CM_PROMASK` below it. |
| `run_octo_hll_matches_a_single_threaded_sketch_exactly` | An HLL run at the default threshold is register-identical to one thread. | Runs 50,000 distinct keys through `HllOctoPlan` on 4 workers and verifies the parent's register slice equals a single-threaded `HyperLogLog<Classic>`'s. |
| `hash_partitioning_sends_a_key_to_exactly_one_worker` | `HashByKey` routes one key to one worker. | Inserts `U64(4_242)` 1,000 times across 4 workers whose delta is their own worker id, and verifies exactly one worker's load is non-zero and the loads sum to `1_000`. |
| `round_robin_partitioning_still_spreads_inputs_evenly` | `RoundRobin` deals inputs across the workers in turn. | Inserts `U64(0..10)` across 3 workers and verifies the per-worker loads are exactly `[4, 3, 3]`. |
| `a_shared_threshold_reaches_every_worker` | Every worker reads the threshold the config was built with. | Runs 2,000 inputs through 4 workers that emit the threshold they read, and verifies 2,000 reports, all equal to `37`. |
| `the_threshold_still_decides_how_much_is_promoted` | A lower threshold sends more messages for the same stream. | Over 4,000 inserts of `U64(i % 8)` into a `2x256` `CmWorkerSketch`, verifies a threshold of `4` promotes strictly more often than one of `64`; this drives the worker directly rather than the runtime. |
| `the_controller_raises_tau_when_the_queue_runs_long` | A queue far above target pushes tau up. | Drives `ThresholdController` against one channel held at 500 queued items for 8 rounds of `POLLS_BETWEEN_CLOCK_READS` polls, at `target_queue_len` `10`, `alpha` `0.25`, a zero interval and a band of `1..=MAX_PROMASK`, and verifies tau ends above its starting `31`; how far it moved is not checked. |
| `the_controller_lowers_tau_when_the_queue_runs_short` | An idle queue walks tau down to its floor. | Drives the controller against an empty channel for 64 rounds at `target_queue_len` `10`, `alpha` `0.25`, a zero interval and a band of `4..=MAX_PROMASK`, and verifies tau ends at exactly `4` from a start of `31`. |
| `an_inverted_control_band_is_normalised_rather_than_fatal` | An inverted min/max band collapses onto its floor instead of panicking. | Drives the controller against 500 queued items for 8 rounds with `min_threshold` `32` above `max_threshold` `8`, and verifies tau ends at exactly `32`. |
| `the_controller_holds_tau_inside_the_dead_band` | A queue held at target settles tau after the initial transient. | Holds the channel at 10 items for 8 rounds at `target_queue_len` `10`, `alpha` `0.25` and a band of `1..=200`, and verifies tau ends at `32` - one step above its starting `31`, taken on the first evaluation's prediction of `20`, with every later prediction of `10` inside the `[7.5, 12.5]` dead band. |
| `the_adaptive_controller_moves_tau_during_a_real_run` | A live controller keeps tau in its band and the parent within `workers * tau`. | Runs 200,000 inputs `U64(i % 4096)` through a `3x1024` `CmOctoPlan` on 4 hash-partitioned workers from a starting tau of `60`, at `target_queue_len` `8`, `alpha` `0.25`, a `1us` interval and a band of `4..=120`, and verifies the settled tau is inside `4..=120` and that key `0`'s deficit against a single-threaded reference is between `0` and `4 * MAX_PROMASK`; whether and how far tau actually moved is deliberately not asserted. |
| `the_topk_aggregator_rebuilds_the_heavy_hitter_heap_from_worker_keys` | The aggregator builds a heavy-hitter heap out of keyed deltas alone. | Runs `U64(0..4)` at 4,000 occurrences each plus a light tail of `U64(1_000..6_000)` through a `4x2048` `CmTopKOctoPlan` at a heap of `8` on 4 workers, and verifies the heap is non-empty and finds each of the four hot keys. |
| `a_parent_wider_than_its_workers_estimates_zero` | A parent geometry wider than the workers' reads zero, and `plan.aggregator()` is how not to hit it. | Runs 40,000 inputs `U64(i % 64)` through a `3x1024` `CmOctoPlan` on 4 workers into a `5x1024` parent and verifies key `0` estimates `0`, then that the same run into `plan.aggregator()` estimates at least `600`. |
| `a_key_below_the_threshold_never_reaches_the_topk_aggregator` | A key that never reaches tau is absent from the parent and from the heap entirely. | For the 20 keys `U64(0..20)` over a `3x1024` `CmTopKOctoPlan` at a heap of `32` on 4 workers, first asserts every key's `(worker, row, col)` cells are collision-free, then verifies that at `CM_PROMASK - 1` occurrences each the heap is empty and key `0` estimates `0`, while at `CM_PROMASK` occurrences the heap holds all `20` keys and key `0` estimates at least `CM_PROMASK`. |
| `the_count_topk_aggregator_also_tracks_heavy_hitters` | The Count top-k aggregator keeps a heap too. | Runs `U64(0..3)` at 5,000 occurrences each plus a tail of `U64(500..3_000)` through a `5x2048` `CountTopKOctoPlan` at a heap of `8` on 4 workers, and verifies the heap finds each of the three hot keys. |
| `run_octo_ddsketch_tracks_quantiles_of_the_stream` | A finished DDSketch run answers quantiles within alpha plus the fleet's rank slack. | Runs 200,000 values `1.0 + (i * 7) % 999` through `DdOctoPlan` at alpha `0.01` on 4 workers and verifies the fleet's held-back share is under `0.05` and that the `0.1`, `0.5` and `0.9` quantiles each fall between the exact value at rank `q - slack` scaled by `1 - alpha` and the exact value at rank `q + slack` scaled by `1 + alpha`. |
| `run_octo_univmon_reaches_the_deepest_layer` | The scaled per-layer threshold lets the deepest layer through. | Runs 60,000 inputs `U64(i % 4_096)` through a 12-layer `5x1024` `UnivMonOctoPlan` at a heap of `64` on 1 worker, and verifies layer `11` holds at least one non-zero counter. |
| `run_octo_univmon_tracks_heavy_hitters_and_total_weight` | The reported total weight trails the stream without overshooting it, and layer 0 holds the hot keys. | Runs `U64(0..5)` at 4,000 occurrences each plus a tail of `U64(10_000..15_000)`, 25,000 inputs in all, through a 6-layer `3x256` `UnivMonOctoPlan` at a heap of `32` and a shared tau of `8` on 4 workers, and verifies `bucket_size` is at most 25,000 and above `0.9 * 25_000`, that layer 0's heap finds each of the five hot keys, and that no layer claims a complete candidate set. |
| `octo_runtime_streaming_matches_the_batch_helper` | `OctoRuntime` and `run_octo` end in the same parent state. | Runs 30,000 inputs `U64(i % 1024)` through a `3x4096` `CmOctoPlan` on 4 workers once through `run_octo` and once insert-by-insert through `OctoRuntime`, and verifies keys `0..128` estimate identically on both parents. |
| `finishing_a_ddsketch_run_answers_against_the_whole_stream` | `finish` flushes, so every sample has reached the parent. | Runs 20,000 near-distinct values `1.0 + i * 0.37` through `DdOctoPlan` at alpha `0.01` on 4 workers and verifies the parent's count equals `20_000`, that quantiles `0.0`, `0.1`, `0.5`, `0.9` and `1.0` are each within `2 * alpha` relative error of the exact value, and that `min` and `max` bracket the stream's extremes to within alpha. |
| `a_mid_stream_flush_makes_the_live_parent_answerable` | A mid-stream flush lands everything accepted so far and does not seal the runtime. | Inserts the first 10,000 of 20,000 values `1.0 + i * 0.37` into a `DdOctoPlan` runtime at alpha `0.01` on 4 workers, flushes, and verifies the read handle sees a count of exactly `10_000` and answers a median, then inserts the remaining 10,000 and verifies `finish` reports `20_000`. |
| `a_worker_that_dies_mid_flush_fails_the_flush_rather_than_hanging_it` | A worker that panics during a flush fails the flush instead of hanging it. | With 2 workers whose `flush` panics, verifies that one insert followed by `flush` panics with "worker dropped during flush". |
| `flushing_twice_is_harmless` | A second flush changes nothing. | Inserts 5,000 values into a `DdOctoPlan` runtime at alpha `0.01` on 2 workers, flushes twice, and verifies `finish` reports a count of `5_000`. |
| `a_flushed_count_min_parent_matches_a_single_pass_exactly` | A finished Count-Min parent equals a single-threaded pass cell for cell. | Runs 40,000 inputs `U64(i % 512)` through a `3x1024` `CmOctoPlan` on 4 workers and verifies all 3,072 counters equal a single-threaded reference's. |
| `octo_runtime_close_is_idempotent` | Closing twice is allowed. | Calls `close` twice on a 2-worker `HllOctoPlan` runtime that saw no inserts and verifies `finish` estimates `0`. |
| `octo_runtime_insert_after_close_panics` | An insert after `close` panics. | Verifies inserting `U64(1)` into a closed 2-worker `HllOctoPlan` runtime panics with "cannot insert after runtime has been closed". |
| `octo_runtime_empty_stream_finishes` | A runtime that saw nothing still finishes. | Verifies `finish` on a 4-worker `HllOctoPlan` runtime with no inserts estimates `0`. |
| `octo_runtime_live_read_handle_tracks_the_aggregator` | A read handle reaches the live parent before the run is finished. | Inserts 64 inputs into a 2-worker counting runtime and polls the read handle, verifying it reads `0` before any insert, never goes backwards, never exceeds `64`, reaches exactly `64` inside a 10-second deadline, and that `finish` then reports `64`. |
| `octo_runtime_close_preserves_queued_items` | `close` does not discard what is already queued. | Inserts 257 inputs into a 4-worker counting runtime, calls `close`, and verifies `finish` reports `257`. |
| `a_worker_picks_the_same_layers_as_a_single_threaded_insert` | A worker routes a key to the same layer set a single-threaded insert would. | For keys `U64(0..5_000)` over 6 layers, verifies `bottom_layer_for_hash(hash64_seeded(BOTTOM_LAYER_FINDER, key), 6)` equals `UnivMon::bottom_layer_for` for every key and is under `6`. |
| `one_worker_at_threshold_one_reproduces_a_single_threaded_univmon` | At tau 1 one worker leaves the aggregator in a single-threaded UnivMon's exact state. | Drives a 20,000-input skewed stream through one `UnivMonOctoWorker` at `3x256` over 6 layers, a heap of `32` and a threshold of `1`, and verifies the aggregator matches `UnivMon::init_univmon(32, 3, 256, 6)` on `bucket_size`, on `candidates_complete()`, and per layer on the counter array, `get_l2` and the heavy-hitter heap contents, plus `calc_g_sum`. |
| `promotion_conserves_every_layer_counter` | Promoted plus residual reconstructs every layer counter, and no residual is over tau. | Drives a 30,000-input skewed stream through one worker at a threshold of `31` and verifies, for every cell of all 6 `3x256` layers, that the aggregator's counter plus the worker's residual equals the single-threaded counter, and that the residual's magnitude is under `31`. |
| `completeness_is_withdrawn_exactly_where_the_layer_thresholds` | Completeness is withdrawn on exactly the layers whose scaled threshold is above one. | Drives a 5,000-input skewed stream through one worker at a base threshold of `8` and verifies every layer whose `univmon_layer_threshold(8, layer)` exceeds `1` reports incomplete candidates while every layer at `1` reports complete, and that both groups are non-empty. |
| `raising_tau_mid_run_withdraws_completeness_that_was_already_granted` | Raising tau withdraws a completeness verdict already granted. | Drives a 4,000-input skewed stream through one worker at tau `1` and verifies at least one layer reports complete candidates, then sets tau to `64`, drives the same stream again, and verifies every layer whose `univmon_layer_threshold(64, layer)` exceeds `1` now reports incomplete. |
| `workers_sharing_an_id_are_refused_rather_than_summed_wrongly` | Two workers reporting the same id panic rather than making the fleet total a maximum. | Drives a 200-input stream through two `UnivMonOctoWorker`s both built with id `0` into one aggregator and verifies it panics with "worker ids must be distinct". |
| `the_layer_threshold_tracks_how_little_traffic_a_deep_layer_sees` | `univmon_layer_threshold` halves tau per layer with a floor of one. | Verifies `univmon_layer_threshold(32, ..)` is `32` at layer `0`, `16` at layer `1`, `1` at layer `5` and still `1` at layer `40` without shift overflow, and that a base of `1` stays `1` at layer `0`. |
| `the_worker_holds_one_byte_per_counter_and_no_keys` | A UnivMon worker holds one byte per counter and no key storage. | Verifies a 6-layer `3x256` `UnivMonOctoWorker` reports `counter_bytes()` of `3 * 256 * 6`, an eighth of the `i64` counters a UnivMon layer holds, and that processing 5,000 distinct 40-character string keys leaves `counter_bytes()` unchanged. |
| `cm_promotion_is_lossless_modulo_the_child_residual` | Promoted counts plus the child's residual reconstruct a single pass. | Drives 20,000 keys of a zipf(1.1) stream over domain `512` at seed `9_101` through a `5x2048` `CountMin<Vector2D<i32>, RegularPath>` child via `insert_emit_delta`, replays every `CmDelta` into a parent with `apply_delta`, and verifies for all 10,240 cells that parent plus child residual equals the single-pass reference cell and that every residual is at most `TAU - 1 = 30`. |
| `cm_deltas_are_well_formed_and_carry_exactly_one_promotion` | Every Count-Min delta carries one promotion window and addresses a real cell. | Over 20,000 zipf(1.1) keys, domain `512`, seed `9_102`, on a `5x2048` child, verifies the emitted `CmDelta` list is non-empty and that each delta has `value == CM_PROMASK` (`31`), `row < 5` and `col < 2048`. |
| `cm_parent_holds_every_completed_promotion` | The parent holds every whole multiple of tau and nothing partial. | Over 30,000 zipf(1.1) keys, domain `512`, seed `9_103`, on `5x2048`, verifies every parent cell equals `31 * (reference_cell / 31)`, that the worst cell deficit is at most `30`, and that it is strictly above `0`. |
| `cm_octo_estimate_trails_the_single_thread_estimate_by_under_one_promotion` | An unflushed parent's point estimate is one-sided and lags by under one window. | Over 40,000 zipf(1.1) keys, domain `256`, seed `9_104`, on `5x2048`, verifies for each of the keys `U64(0..256)` that `parent.estimate()` never exceeds the single-threaded `reference.estimate()` and trails it by at most `30`. |
| `cm_fast_path_promotes_on_the_same_schedule_as_the_regular_path` | The fast path promotes exactly the mask value and loses no counts. | Over 20,000 zipf(1.1) keys, domain `512`, seed `9_105`, through a `5x2048` `CountMin<Vector2D<i32>, FastPath>` child into a `FastPath` parent, verifies at least one promotion fired, that every emitted delta's `value` is `CM_PROMASK`, and that parent plus child equals a `FastPath` single-pass reference on all 10,240 cells; the regular path is never run, so the promotion *schedules* of the two paths are not compared despite the name - only the per-cell promotion rule and conservation are asserted. |
| `cm_delta_addressing_survives_columns_past_the_u16_ceiling` | Delta row/col fields address a geometry wider than 65,536 columns. | Drives 60,000 zipf(1.1) keys, domain `4_096`, seed `9_108`, through a `3x100_000` `CountMin<Vector2D<i32>, RegularPath>` child straight into a parent, and verifies parent plus child equals the single-pass reference on all 300,000 cells. |
| `cm_delta_application_is_order_independent` | Delivery order does not change the Count-Min parent. | Captures the deltas of 15,000 zipf(1.1) keys, domain `512`, seed `9_106`, on `5x2048`, applies them in order and again after `shuffle` with `StdRng::seed_from_u64(9_106)`, and verifies the two parents' full 10,240-cell vectors are equal. |
| `cm_sharded_children_conserve_counts_against_a_single_pass` | Sharding preserves every count, with one window of slack per shard. | Deals 40,000 zipf(1.1) keys, domain `512`, seed `9_107`, round-robin across `4` `5x2048` children into one parent, and verifies per cell that the parent plus the sum of the four residuals equals the single-pass reference and that the summed residual is at most `4 * 30 = 120`. |
| `count_deltas_carry_exactly_the_signed_threshold` | A Count-sketch delta is always plus or minus the mask value. | Over 30,000 zipf(1.1) keys, domain `256`, seed `9_201`, through a `5x2048` `Count<Vector2D<i32>, RegularPath>` child, verifies the delta list is non-empty and that every delta has `value.unsigned_abs() == COUNT_PROMASK` (`31`), `row < 5` and `col < 2048`. |
| `count_promotion_is_lossless_modulo_the_child_residual` | Promoted signed counts plus the residual reconstruct a single pass. | Over 30,000 zipf(1.1) keys, domain `256`, seed `9_202`, on `5x2048`, verifies for all 10,240 cells that parent plus child equals the single-pass reference and that each residual's magnitude is at most `30`. |
| `count_octo_estimate_stays_within_one_residual_of_the_single_thread_estimate` | The signed parent's estimate stays within one window either way. | Over 40,000 zipf(1.1) keys, domain `256`, seed `9_203`, on `5x2048`, verifies for each of `U64(0..256)` that the absolute gap between `parent.estimate()` and `reference.estimate()` is at most `30.0`. |
| `count_fast_path_conserves_counts_like_the_regular_path` | The signed fast path promotes the mask magnitude and loses no counts. | Over 20,000 zipf(1.1) keys, domain `256`, seed `9_204`, through a `5x2048` `Count<Vector2D<i32>, FastPath>` child into a `FastPath` parent, verifies every emitted delta's magnitude is `COUNT_PROMASK` and that parent plus child equals a `FastPath` single-pass reference on all 10,240 cells; the regular path is not run, so the two paths are never compared against each other. |
| `count_delta_application_is_order_independent` | Delivery order does not change the Count-sketch parent. | Captures the deltas of 15,000 zipf(1.1) keys, domain `256`, seed `9_205`, on `5x2048`, applies them in order and again after `shuffle` with `StdRng::seed_from_u64(9_205)`, and asserts the two 10,240-cell vectors are equal; that single equality is the whole assertion. |
| `count_sharded_children_conserve_signed_counts` | Sharding the signed sketch preserves every count. | Deals 40,000 zipf(1.1) keys, domain `256`, seed `9_206`, round-robin across `3` `5x2048` children into one parent, and verifies per cell that the parent plus the three residuals equals the single-pass reference; no bound on the residual size is asserted here. |
| `hll_promotion_reproduces_the_single_thread_registers_exactly` | Max-register promotion leaves parent and child identical to one pass. | Feeds the 60,000 distinct keys `U64(0..60_000)` through a default `HyperLogLog<Classic>` (p14) child into a parent, and verifies `HLL_PROMASK == 0`, that the parent's and the child's `registers_as_slice()` both equal a single-pass reference's, and that `parent.estimate()` equals `reference.estimate()`. |
| `hll_promotion_is_exact_for_every_variant_and_precision` | Promotion is register-exact at every precision and estimator. | Feeds 40,000 values `i.wrapping_mul(2_654_435_761)` through an inline `check!` macro that runs one child, one parent and one single-pass reference per type, asserting both the parent's and the child's registers equal the reference's for `HyperLogLogP12<Classic>`, `HyperLogLog<Classic>` (p14), `HyperLogLogP16<Classic>`, `HyperLogLogP12<ErtlMLE>`, `HyperLogLog<ErtlMLE>` and `HyperLogLogP16<ErtlMLE>`. |
| `hll_deltas_are_strictly_increasing_per_register_and_never_repeat` | Each register's delta stream is strictly increasing and replays its final value. | Over the 30,000 distinct keys `U64(0..30_000)` on a default `HyperLogLog<Classic>`, verifies every delta's `pos` is inside the register array, that its `value` is strictly above the best value promoted for that register so far, and that the resulting per-register maxima equal the child's `registers_as_slice()`. |
| `hll_duplicate_keys_promote_nothing_after_the_first_improvement` | Only the first insert of a key can improve a register. | Inserts `U64(7)` 1,000 times into a default `HyperLogLog<Classic>` through `insert_emit_delta` and verifies exactly `1` delta was emitted. |
| `hll_delta_application_is_order_independent` | Max is commutative, so register delivery order is free. | Captures the deltas of `U64(0..30_000)`, applies them in order and again after `shuffle` with `StdRng::seed_from_u64(9_301)`, and verifies the two parents' register slices are equal. |
| `hll_sharded_children_match_a_single_pass_exactly` | Sharded HLL promotion carries no partition penalty. | Deals the 50,000 distinct keys `U64(0..50_000)` round-robin across `4` default `HyperLogLog<Classic>` children into one parent and verifies the parent's `registers_as_slice()` equals a single-pass reference's. |
| `hll_cardinality_survives_the_delta_round_trip_exactly` | Delta-fed registers match a single pass byte for byte, and the estimate stays in band. | Over the 100,000 distinct keys `U64(0..100_000)` through a default `HyperLogLog<Classic>`, verifies the parent's registers equal the reference's, that `parent.estimate()` equals `reference.estimate()`, and that the relative error against the exact `100_000` is under `0.025` (p14's 1.04/sqrt(2^14) is about 0.81%). |
| `run_octo_cm_matches_a_single_threaded_replay_of_the_same_partition` | The Count-Min runtime is cell-identical to a deterministic replay at every worker count. | Under `--features octo-runtime`, runs 40,000 zipf(1.1) keys, domain `512`, seed `9_401`, through `run_octo` with `CmOctoPlan::new(5, 2048)` at `queue_capacity` `4096` and no core pinning, for `1, 2, 3, 4, 7` workers, and verifies all 10,240 parent cells equal those of a `HashByKey` single-threaded replay that flushes its children at end of stream. |
| `run_octo_count_matches_a_single_threaded_replay_of_the_same_partition` | The Count-sketch runtime is cell-identical to a deterministic replay. | Under `--features octo-runtime`, runs 40,000 zipf(1.1) keys, domain `256`, seed `9_402`, through `run_octo` with `CountOctoPlan::new(5, 2048)` at `1, 2, 4` workers, and verifies all 10,240 parent cells equal a flushed `HashByKey` single-threaded replay's. |
| `run_octo_hll_is_bit_exact_and_worker_count_invariant` | The HLL runtime's registers are the single-threaded ones at any worker count. | Under `--features octo-runtime`, runs the 80,000 distinct keys `U64(0..80_000)` through `run_octo` with `HllOctoPlan::new()` at `1, 2, 3, 4, 8` workers and verifies the parent's `registers_as_slice()` equals a single-threaded `HyperLogLog<Classic>`'s at every count. |
| `run_octo_ddsketch_matches_a_single_threaded_replay` | The DDSketch runtime's buckets are a pure function of the partition. | Under `--features octo-runtime`, runs 40,000 values `1.0 + (i * 7) % 999` through `run_octo` with `DdOctoPlan::new(0.01)` on `4` workers and verifies `get_count()` and the list of non-zero `(store_offset + index, count)` pairs equal those of a single-threaded `DdWorkerSketch` replay driven at `DD_PROMASK` (`4`) and then flushed; the raw store offset and length are deliberately not compared. |
| `run_octo_is_deterministic_across_repeated_runs` | Two runs of the same stream give the same parent. | Under `--features octo-runtime`, runs 30,000 zipf(1.1) keys, domain `512`, seed `9_403`, through `CmOctoPlan::new(5, 2048)` on `4` workers twice and verifies the two 10,240-cell vectors are equal. |
| `streaming_runtime_matches_the_batch_helper` | `OctoRuntime` and `run_octo` end in the same parent state. | Under `--features octo-runtime`, runs 30,000 zipf(1.1) keys, domain `512`, seed `9_404`, on `4` workers once through `run_octo` and once insert-by-insert through `OctoRuntime` plus `finish`, both with `CmOctoPlan::new(5, 2048)`, and verifies the 10,240-cell vectors are equal. |
| `insert_batch_matches_element_wise_inserts` | `insert_batch` is element-wise `insert`. | Under `--features octo-runtime`, runs 20,000 zipf(1.1) keys, domain `512`, seed `9_405`, through two `CmOctoPlan::new(5, 2048)` runtimes on `3` workers - one per-input `insert`, one single `insert_batch` - and verifies the finished parents' 10,240-cell vectors are equal. |
| `degenerate_config_is_clamped_rather_than_rejected` | Zero workers and zero queue capacity clamp to one instead of dropping data. | Under `--features octo-runtime`, runs the 5,000 distinct keys `U64(0..5_000)` through `run_octo` with `num_workers: 0` and `queue_capacity: 0` on `HllOctoPlan`, and verifies the parent's registers equal a single-threaded reference's. |
| `a_one_slot_queue_applies_backpressure_without_deadlocking` | A one-slot queue still finishes the whole stream correctly. | Under `--features octo-runtime`, runs the 20,000 distinct keys `U64(0..20_000)` through `run_octo` with `4` workers and `queue_capacity: 1` on `HllOctoPlan`, and asserts the parent's registers equal a single-threaded reference's; the assertion is that the run terminates and is exact - no queue occupancy or blocking is observed, so "applies backpressure" is not itself measured. |
| `a_borrowed_key_may_be_dropped_the_moment_insert_returns` | A borrowed key can be freed the instant `insert` returns. | Under `--features octo-runtime`, inserts 20,000 `DataInput::Str` values `format!("session-{i:020}")` into an `OctoRuntime` over `HllOctoPlan` on `4` workers, dropping each owned `String` immediately after the call, and verifies the finished parent's registers equal a single-threaded reference's over the same 20,000 strings. |
| `a_borrowed_key_reaches_a_keyed_aggregator_by_value` | A key-storing aggregator receives borrowed keys by value. | Under `--features octo-runtime`, inserts `hot-0`, `hot-1`, `hot-2` as borrowed `Str` values 4,000 times each (each `String` dropped right after `insert`) into an `OctoRuntime` over `CmTopKOctoPlan::new(4, 2048)` with a top-`8` `CmTopKOctoAggregator` on `4` workers, and verifies the parent's `heap().find()` returns a hit for all three keys; the heap counts are not checked. |
| `an_empty_stream_finishes_with_a_pristine_parent` | An empty stream leaves every counter at zero. | Under `--features octo-runtime`, calls `run_octo(&[], ...)` with `CmOctoPlan::new(5, 2048)` on `4` workers and verifies all 10,240 parent cells are `0`. |
| `a_user_defined_worker_and_aggregator_round_trip_every_input` | The public `OctoPlan`/`OctoWorker`/`OctoAggregator` traits work from outside the crate. | Under `--features octo-runtime`, defines a `SumWorker`/`SumPlan`/`SumAggregator` whose delta is `(worker_id, 1)`, runs `U64(0..10_001)` through `run_octo` on `3` workers under `OctoPartition::RoundRobin`, and verifies the per-worker loads sum to exactly `10_001` and that each worker `w` received exactly the count of stream indices with `i % 3 == w`. |
| `the_read_handle_observes_a_monotone_prefix_of_the_final_state` | The live read handle is monotone and reaches the live total before `finish`. | Under `--features octo-runtime`, drives `U64(0..4_000)` through an `OctoRuntime` over `SumPlan` on `2` workers, and verifies the handle reads `0` before the first insert, that every reading sampled at each 500th insert is non-decreasing and at most `4_000`, that it then reaches exactly `4_000` inside a 10-second `Instant`-based deadline while the runtime is still open, and that `finish` reports `4_000`. |
| `reading_through_a_stale_handle_panics` | Reading a handle after `finish` panics. | Under `--features octo-runtime`, a `#[should_panic(expected = "Octo runtime has been finished")]` test that takes a `read_handle()` from a 2-worker `SumPlan` runtime, calls `finish()`, then calls `with_parent` on the stale handle. |
| `close_is_idempotent_and_preserves_already_queued_work` | Closing twice is allowed and drains what was queued. | Under `--features octo-runtime`, inserts `U64(0..3_001)` into a 4-worker `SumPlan` runtime, calls `close()` twice, and verifies `finish` reports a per-worker total of exactly `3_001`. |
| `inserting_after_close_panics` | An insert after `close` panics. | Under `--features octo-runtime`, a `#[should_panic(expected = "cannot insert after runtime has been closed")]` test that closes a 2-worker `SumPlan` runtime and then inserts `U64(1)`. |
| `a_finished_run_carries_only_count_mins_own_one_sided_error` | A flushed Count-Min run has only Count-Min's own one-sided error left. | Under `--features octo-runtime`, runs 200,000 zipf(1.1) keys, domain `4_096`, seed `9_501`, through `CmOctoPlan::new(5, 4096)` on `4` workers and verifies for every one of the 4,096 keys that the estimate is at or above the exact `FreqTruth` count and at most `exact + (e / 4096) * N` above it. |
| `run_octo_hll_cardinality_error_stays_within_three_sigma` | The HLL runtime is register-exact and its cardinality is within three sigma. | Under `--features octo-runtime`, runs the 200,000 distinct keys `U64(0..200_000)` through `HllOctoPlan` on `4` workers and verifies the parent's registers equal a single-threaded reference's exactly, then that the relative error of `estimate()` against `200_000` is under `0.025`. |
| `run_octo_count_frequencies_track_a_zipf_stream` | A flushed Count-sketch run holds the Count-sketch L2 bound on the heavy keys. | Under `--features octo-runtime`, runs 200,000 zipf(1.1) keys, domain `2_048`, seed `9_502`, through `CountOctoPlan::new(5, 4096)` on `4` workers, then for the truth's top `64` keys collects any estimate whose absolute error exceeds `3 * \|\|f\|\|_2 / sqrt(4096)` and asserts the violation list is empty. |
| `theorem_1_bounds_the_count_min_error` | The Count-Min estimates satisfy Theorem 1's band under both partitions. | Drives 400,000 zipf(1.1) keys, domain `8_192`, seed `11_001`, through a `4`-worker `5x4096` Count-Min replay under `HashByKey` and `RoundRobin` at `eps = 2/4096` and `delta = 2^-5 = 0.03125`, and per route verifies the precondition `L1 > k'*tau/eps`, that the worst underestimate over every truth key is strictly below the `k*tau = 124` per-counter ceiling, and that the share of keys outside `eps*L1` is below `delta`; finally that `HashByKey`'s worst deficit is at most `RoundRobin`'s. Also prints the measured eps, delta, band, violation rate and worst deficit/excess. |
| `theorem_3_bounds_the_count_sketch_error` | The Count-sketch estimates satisfy Theorem 3's band under both partitions. | Asserts `COUNT_PROMASK == CM_PROMASK`, then drives 400,000 zipf(1.1) keys, domain `8_192`, seed `11_003`, through a `4`-worker `5x4096` Count-sketch replay under both routes at `eps = sqrt(8/4096)` and `delta = 2^-5`, and per route verifies the precondition `L2 > 2*k'*tau/eps`, that the worst gap to a single-core `Count` sketch is strictly below `k*tau = 124`, and that the share of keys outside `eps*L2` is below `delta`; finally that `HashByKey`'s worst gap is at most `RoundRobin`'s. |
| `theorem_4_holds_unconditionally_because_this_implementation_pins_tau_to_zero` | With tau pinned to zero, HLL promotion is exact far below the paper's precondition. | Asserts `HLL_PROMASK == 0`, computes `2 * alpha_m * m^2 * 2^(2-2)` for `m = 2^14` as the precondition at the paper's smallest suggested tau of `2`, then for each `n` in `10, 100, 1_000, 10_000` drives `U64(0..n)` through a `HyperLogLog<Classic>` child into a parent and verifies `n` is below that precondition, that the parent's registers equal an ideal single-pass sketch's, and that the two estimates are equal. |
| `theorem_2_delta_promotion_sends_l_times_fewer_counters_for_the_same_goal` | At the same accuracy goal, delta promotion ships far fewer counters than sketch-merge. | Runs 40,000 zipf(1.1) keys, domain `2_048`, seed `11_005`, through a `4`-worker `3x1024` Octo replay and a sketch-merge replay at a merge period of `TAU = 31`, both `HashByKey`, and verifies both meet the accuracy goal `k*tau = 124` against a single-core sketch over keys `U64(0..2_048)`, that the merge/octo counter ratio exceeds `l/4 = 256`, and that the byte ratio (`size_of::<CmDelta>()` per Octo message against `size_of::<i32>()` per merged counter) exceeds `l/16 = 64`. |
| `delta_promotion_beats_sketch_merge_on_online_accuracy` | Delta promotion's online error beats sketch-merge at parity and at ten times the budget. | Runs 60,000 zipf(1.1) keys, domain `4_096`, seed `11_007`, through a `4`-worker `3x1024` Octo replay, a single-core sketch and two sketch-merge replays sized to spend `1x` and `10x` Octo's counters, querying the truth's top `32` keys at `8` checkpoints offset to `i % (n/8) == (n/8)/3` so they miss merge boundaries, and verifies each baseline actually outspent Octo, that each baseline's MAE exceeds `2x` Octo's, that the parity baseline's exceeds `8x` Octo's, and that Octo's MAE is within `TAU = 31` of the single-core MAE. |
| `sketch_merge_staleness_grows_with_the_merge_period_while_promotion_does_not` | Sketch-merge staleness grows with its period while promotion stays capped at tau. | Runs 40,000 zipf(1.1) keys, domain `2_048`, seed `11_009`, through a `4`-worker `3x1024` Octo replay and four sketch-merge replays at periods `500, 1_000, 2_000, 4_000`, sampling the single hottest key's deficit at `40` off-boundary query points, and verifies Octo's mean deficit is at most `31`, that the mean deficit strictly increases across each consecutive pair of periods, and that the `4_000` period's mean deficit exceeds `3x` Octo's. |
| `count_sketch_online_accuracy_beats_sketch_merge` | The Count sketch's online error is at most half sketch-merge's at parity. | Runs 60,000 zipf(1.1) keys, domain `4_096`, seed `12_001`, through a `4`-worker `5x1024` Octo Count replay, an ideal single-pass `Count`, and merge baselines sized by `merge_periods` to `1x` and `10x` Octo's counters, averaging absolute error over the truth's top `32` keys at `8` off-boundary checkpoints, and verifies both baselines were funded (parity at least Octo's spend, `10x` above parity), that Octo's mean error is below half the parity baseline's, and that it is below the `10x` baseline's. |
| `hyperloglog_online_accuracy_beats_sketch_merge` | HLL delta promotion is exactly ideal online and beats sketch-merge. | Runs the 200,000 distinct keys `U64(0..200_000)` through a `4`-worker Octo HLL replay, an ideal `HyperLogLog<Classic>`, and merge baselines sized to `1x` and `10x` Octo's register messages, taking relative cardinality error at `8` off-boundary checkpoints where the exact answer is `i + 1`, and verifies the baselines were funded, that Octo's mean relative error equals the ideal sketch's *exactly* (`assert_eq!` on the two f64 means), and that it is below both baselines'. |
| `ddsketch_delta_promotion_trades_quantile_accuracy_for_messages` | Raising DDSketch's threshold buys fewer messages and costs quantile accuracy. | Over 200,000 `exponential_f64(n, 0.05, 12_101)` values clamped to at least `1e-3` at alpha `0.01` on `4` workers, sweeps thresholds `1, 2, 4, 8` through the shared online comparison (relative error at quantiles `0.1`, `0.5`, `0.9` over `8` off-boundary checkpoints against merge baselines at `1x` and `10x` budget), and verifies threshold `1` promotes exactly `200_000` counters and lands within `1e-12` of the ideal sketch's error, and that each step up in threshold sends strictly fewer counters and is no more accurate than the step below. |
| `univmon_online_accuracy_beats_sketch_merge` | UnivMon delta promotion tracks the single-core answer far more closely than sketch-merge. | Runs 60,000 zipf(1.1) keys, domain `4_096`, seed `12_201`, through `UnivMonOctoPlan` at `5x1024`, `12` layers, heap `64`, tau `COUNT_PROMASK` on `4` workers, against an ideal `UnivMon` and merge baselines sized to `1x` and `10x` Octo's counters, scoring the mean of the relative cardinality and entropy gaps to the ideal sketch at `8` off-boundary checkpoints, and verifies the baselines were funded, that Octo's gap is below half the parity baseline's, that the `10x` baseline beats the parity one, and that the `10x` spend exceeds `10x` Octo's counters. |
| `univmon_heavy_hitter_recall_beats_sketch_merge` | The UnivMon aggregator's layer-0 heap recalls the hot keys at least as well as sketch-merge. | Runs 60,000 zipf(1.1) keys, domain `4_096`, seed `12_203`, through `UnivMonOctoPlan` at `5x1024`, `12` layers, heap `64`, tau `COUNT_PROMASK` on `4` workers against a merge baseline funded at parity, measuring at `8` off-boundary checkpoints the share of the truth's top `16` keys that `hh_layers[0].find()` returns, and verifies Octo's mean recall is at least the baseline's and above `0.9`. |
| `a_flat_threshold_starves_the_deep_univmon_layers` | One flat threshold empties UnivMon's deep layers while the scaled one keeps them exact. | Over 60,000 zipf(1.1) keys, domain `4_096`, seed `12_201`, drives a `12`-layer `5x1024` heap-`64` pyramid of `L2hhWorkerSketch` workers twice - once at a flat base of `31` for every layer, once at `univmon_layer_threshold(31, layer)` - and verifies the ideal sketch has non-zero cells on layer `11`, the flat run has exactly `0` there, the scaled run has exactly as many as the ideal, and that the flat run's relative cardinality error against the ideal exceeds `0.5` while the scaled run's is below `0.1`. |
| `coco_deltas_carry_exactly_one_promotion_window_and_a_key_the_stream_used` | Every Coco delta carries exactly tau and names a key the stream contained. | Drives 40,000 zipf(1.1) keys, domain `2_048`, seed `21_001`, rendered through `flow_key_string`, into `CocoOctoPlan::new(512, 2).worker(0)`, and verifies the promotion list is non-empty and that every `CocoDelta` has `value == COCO_PROMASK` (`31`) and a `key` present in the set of rendered stream keys. |
| `coco_promotion_conserves_the_stream_mass_exactly` | Promoted plus held-back Coco mass is the stream, and no residual has reached tau. | Runs 60,000 zipf(1.1) keys, domain `2_048`, seed `21_002`, through `4` `CocoOctoWorker`s over a `512x2` table under `HashByKey`, and verifies the parent table's summed `val` plus the workers' one-byte residuals equals `60_000` exactly, that the residual is strictly positive, that every worker bucket holds strictly less than `31`, and that the unflushed parent's mass is strictly below `60_000`. |
| `coco_flush_hands_over_every_residual_bucket` | A Coco flush ships exactly the partial counts and empties the workers. | Runs 60,000 zipf(1.1) keys, domain `2_048`, seed `21_003`, through `4` workers over a `512x2` table, then flushes and verifies the shipped deltas' values sum to exactly the pre-flush residual, that each flushed value is in `1..31`, that the workers' residual is then `0`, and that the parent's mass is exactly `60_000`. |
| `coco_promotes_the_bucket_incumbent_when_the_arrival_loses_the_election` | A promotion may name the bucket's incumbent rather than the arriving key. | Over four 20,000-key zipf(1.1) streams, domain `2_048`, seeds `21_100..21_104`, through a `16x2` `CocoOctoWorker`, counts promotions whose `key` differs from the arriving key and verifies more than `1_000` promotions fired and that the incumbent share exceeds `0.05`; the assertion only rules out a worker that always names the arrival - it does not check that the incumbent is named on every losing election, and the exact share is not pinned. |
| `coco_sharded_workers_conserve_mass_and_partition_the_point_queries` | Sharding leaves the flushed Coco parent holding and partitioning the whole stream. | Runs 60,000 zipf(1.1) keys, domain `2_048`, seed `21_004`, through a `512x2` table at `1, 2, 4, 8` workers under `HashByKey`, flushes, and verifies per worker count that the parent's table mass is exactly `60_000` and that `estimate_key` summed over every distinct rendered key is also exactly `60_000`. |
| `coco_octo_point_estimates_stay_unbiased_across_independent_runs` | The Coco aggregator's weighted replay leaves point estimates unbiased. | Repeats `120` independent single-worker runs of 20,000 zipf(1.1) keys, domain `1_000`, seed `21_005`, through a `64x2` table with a flush, summing `estimate_key` over the truth's top `32` keys each time, and verifies the sample mean is within `5` standard errors of the exact top-32 mass and that `5` standard errors is itself under `2%` of that mass (so the band is narrow enough to mean something). |
| `elastic_deltas_split_into_keyed_heavy_votes_keyed_evictions_and_unkeyed_light_cells` | Elastic promotion emits all three message kinds, each well formed. | Drives 40,000 zipf(1.1) keys, domain `2_048`, seed `22_001`, through `ElasticOctoPlan::new(64, 3, 1024).worker(0)` and verifies every `Heavy` delta has `value == ELASTIC_PROMASK` (`31`) and a key the stream used, every `Evicted` delta has `votes < 31` and a key the stream used, every `Light` delta has `value == 31`, `row < 3` and `col < 1024`, and that heavy, light and evicted counts are all non-zero, that at least one heavy message carries `eviction: true`, and that at least one eviction carries zero votes. |
| `elastic_promotion_conserves_the_stream_mass_row_by_row` | Elastic conserves the stream on every light row at every worker count. | Runs 60,000 zipf(1.1) keys, domain `2_048`, seed `22_002`, through `1, 2, 4, 8` `ElasticOctoWorker`s over `256` buckets and a `3x2048` light layer under `HashByKey`, and verifies for each of the `3` rows that parent heavy votes plus parent light row plus summed worker light rows plus the heavy votes the flush then ships equals exactly `60_000`, and that the flushed-held amount is strictly positive. |
| `elastic_flush_empties_both_halves_of_every_worker` | An Elastic flush empties heavy and light halves and leaves the parent holding the stream. | Runs 60,000 zipf(1.1) keys, domain `2_048`, seed `22_003`, through `4` workers over `256` buckets and a `3x2048` light layer, then flushes and verifies no `Evicted` delta is shipped (a flush panics the test if one is), that every flushed `Heavy`/`Light` value is in `1..31`, that each worker's light residual is all zeros, and that parent heavy plus each of the `3` parent light rows is exactly `60_000`. |
| `elastic_eviction_hands_the_evicted_resident_over_under_its_own_key` | An eviction reaches the parent's light layer under the victim's own key. | With `ElasticOctoPlan::with_threshold(1, 1, 64, OctoThreshold::new(127))` - a tau above anything the workload reaches - sends `flow::resident` `3` times and then `flow::challenger` `LAMBDA * 3 = 24` times (checking first that the two keys land on different light cells), and verifies the worker shipped exactly `[Evicted { key: resident, votes: 3 }]`, that the worker's light residual is `0` on the resident's cell and `23` on the challenger's, and that after applying the delta the parent's light layer holds `3` on the resident's cell and `0` on the challenger's. |
| `elastic_octo_never_underestimates_any_flow_after_a_flush` | A flushed Elastic parent never reads any flow below its true size. | Runs 60,000 zipf(1.1) keys, domain `4_096`, seed `22_004`, through `1, 2, 4, 8` workers over `128` buckets and a `3x2048` light layer under `HashByKey`, flushes, and verifies `query` is at or above the exact count for every one of the distinct rendered keys, and that at least one true flow is absent from the parent's heavy table (so the light-layer read-through path is actually exercised). |
| `a_heavy_flow_that_never_spilled_is_estimated_exactly` | A heavy flow no worker ever evicted reads back exactly, not through the light layer. | Builds a `4`-bucket, `1x1` `ElasticOctoPlan`, picks a `lone` key hashing to bucket `0` and two contenders hashing to bucket `1`, sends `200` lone arrivals and `400` alternating contested ones through one worker into the aggregator, flushes, and verifies the single light cell holds non-zero noise from the contenders, that the lone flow's parent bucket has `eviction == false`, and that `query` returns exactly `200`. |
| `a_resident_that_spilled_at_a_worker_reads_through_to_the_light_layer` | A flow evicted at a worker is flagged at the parent and read through the light layer. | With a `1`-bucket, `1x64` `ElasticOctoPlan`, sends `ELASTIC_PROMASK = 31` arrivals of `flow::resident`, one arrival of a challenger chosen to land on a different light cell, then `LAMBDA - 2 = 6` more resident arrivals, and verifies the worker shipped exactly `[Heavy { resident, 31, eviction: false }, Evicted { resident, votes: 0 }]`, and after the flush that the parent's bucket has `eviction == true` and `vote_pos == 31`, and that `query` returns exactly `31 + 6 = 37`. |
| `run_octo_coco_conserves_the_stream_mass_at_every_worker_count` | The threaded Coco pipeline conserves and partitions the stream at any worker count. | Under `--features octo-runtime`, runs 60,000 zipf(1.1) keys, domain `2_048`, seed `23_001`, through `run_octo` with `CocoOctoPlan::new(512, 2)` at `1, 2, 3, 4, 8` workers and verifies per count that the parent table's mass is exactly `60_000` and that `estimate_key` summed over every distinct rendered key is exactly `60_000`. |
| `run_octo_elastic_conserves_the_stream_mass_whatever_the_interleaving` | The threaded Elastic pipeline conserves per row and stays one-sided. | Under `--features octo-runtime`, runs 60,000 zipf(1.1) keys, domain `4_096`, seed `23_002`, through `run_octo` with `ElasticOctoPlan::new(128, 3, 2048)` at `1, 2, 3, 4, 8` workers and verifies per count that parent heavy votes plus each of the `3` light rows is exactly `60_000` and that `query` is at or above the exact count for every distinct rendered key. |
| `run_octo_elastic_matches_a_single_threaded_replay_at_one_worker` | At one worker the Elastic runtime is bit-exact against a sequential replay. | Under `--features octo-runtime`, runs 40,000 zipf(1.1) keys, domain `2_048`, seed `23_003`, through `run_octo` with `ElasticOctoPlan::new(128, 3, 1024)` on `1` worker, repeated `3` times, and verifies every heavy bucket's `(flow_id, vote_pos, vote_neg, eviction)` and all `3 * 1024` light counters equal those of a flushed single-threaded `HashByKey` replay. |
| `coco_online_accuracy_beats_sketch_merge` | Coco's online relative error and heavy-hitter F1 both favour delta promotion. | Over `3` streams of 200,000 zipf(1.1) keys, domain `5_000`, seeds `24_001..24_004`, drives a `4`-worker `512x2` Octo Coco replay, an ideal single-pass `Coco` and a sketch-merge baseline sized to Octo's counter spend, scoring at `8` off-boundary checkpoints the mean relative error over the truth's top `32` keys and the F1 of the reported set against the `HH_ALPHA = 0.0002` heavy-hitter threshold, and verifies the baseline was not starved, that Octo's relative error is below half the baseline's, that Octo's F1 is above the baseline's, that the ideal pass leads Octo, and that Octo's relative error is below `0.10`. |
| `elastic_online_accuracy_beats_sketch_merge` | Elastic's online relative error and F1 both favour delta promotion. | Over 300,000 zipf(1.1) keys, domain `5_000`, seed `24_101`, drives a `4`-worker Octo Elastic replay at `1_024` buckets and a `3x4096` light layer, an ideal single-pass `Elastic`, and a sketch-merge baseline sized to Octo's spend, scoring at `8` off-boundary checkpoints the mean relative error over the truth's top `32` keys and F1 at the `0.0002` heavy-hitter threshold, and verifies the baseline was funded, that Octo's relative error is below half the baseline's, that Octo's F1 exceeds `1.2x` the baseline's, that the ideal pass leads Octo, and that Octo's relative error is below `0.06`. |
| `cm_top_k_point_estimates_trail_the_single_thread_reference_by_at_most_k_tau` | The Count-Min top-k aggregator trails a single thread by at most `k*tau` and keeps Count-Min's own bound. | Drives 200,000 zipf(1.1) keys, domain `8_192`, seed `0x0C70_1101`, through `CmTopKOctoPlan::new(5, 2048)` on `4` workers with a top-`32` aggregator under both `HashByKey` and `RoundRobin`, and per route tallies over every truth key that the estimate is at or below a `CMSHeap` reference's and no more than `k*tau = 124` under it, that it is at or above `truth - 124`, that it is under `CountMinSpec::new(5, 2048).simultaneous_bound(..., SIMULTANEOUS_LEVEL = 1e-3)` with zero violations tolerated, and that violations of the marginal `e*(N-f)/w` bound occur at a rate no worse than `e^-5`. |
| `count_top_k_point_estimates_satisfy_the_l2_bound_within_the_promotion_residual` | The Count top-k aggregator holds the L2 bound widened by exactly `k*tau`. | Drives the same 200,000-key stream through `CountTopKOctoPlan::new(5, 2048)` on `4` workers with a top-`32` aggregator under both routes, and per route tallies over every truth key that the absolute gap to a `CSHeap` reference is at most `k*tau = 124`, that the absolute error against truth is within `CountSketchSpec::new(5, 2048).scale_at(simultaneous_kappa(distinct, 1e-3), \|\|f_-i\|\|_2) + 124` with zero violations, and that violations of `sqrt(3/w)*\|\|f_-i\|\|_2 + 124` occur at a rate no worse than the spec's marginal failure probability. |
| `top_k_plans_recover_the_heavy_hitters_their_promotion_floor_guarantees` | Both top-k plans recover every heavy hitter above the promotion floor, with a consistent heap. | Over the same 200,000-key stream and both routes, drives `CmTopKOctoPlan` and `CountTopKOctoPlan` at `5x2048` on `4` workers with a top-`32` aggregator and verifies per plan and route that the heap holds at most `32` entries with no duplicate key, that at least `16` of the true top `32` clear the `k*tau = 124` floor (a premise check), that *every* true top-32 key above that floor is present, that no heap key's true count is below the true 32nd count minus `124`, and that each heap entry's stored count equals the aggregator sketch's own estimate for that key. |
| `a_key_below_the_promotion_threshold_never_reaches_the_top_k_aggregator` | A flow below tau is absent from the top-k aggregator entirely, and the first crossing ships exactly tau. | On `CmTopKOctoPlan::new(5, 2048)` with one worker and a top-`32` aggregator, sends `U64(0xC01D)` `TAU - 1 = 30` times and verifies zero deltas shipped, that the aggregator estimates `0` for it, and that the heap is empty; then sends one more arrival and verifies at least one delta was promoted, that every delta's `key` is `input_to_owned` of that key, that the aggregator then estimates exactly `TAU = 31`, and that the heap holds exactly `1` entry. |
| `hll_octo_plan_is_register_exact_and_in_band_under_both_partitions` | `HllOctoPlan` is register-exact and in cardinality band under either partition. | Drives 60,000 zipf(1.1) keys, domain `1_024`, seed `0x0C70_ACC0`, through `HllOctoPlan` on `4` workers under `HashByKey` and `RoundRobin`, flushes each worker, and per route verifies the parent's `registers_as_slice()` equals a single-threaded `HyperLogLog<Classic>`'s exactly and that `estimate()` passes `CardinalityConfidenceSpec::hll(14, 4.0)` against the exact distinct count. |
| `dd_octo_plan_is_bucket_exact_after_flush_and_holds_alpha_under_both_partitions` | `DdOctoPlan` is bucket-exact after a flush and holds alpha under either partition. | Turns the same 60,000-key stream into values `1.0 + key`, drives them through `DdOctoPlan::new(0.01)` on `4` workers under both routes, flushes, and per route verifies `get_count()` equals a single-pass `DDSketch`'s, that every bucket over the union of both stores' index ranges matches the reference (offset differences allowed for), and that the quantiles `0.0, 0.01, 0.1, 0.5, 0.9, 0.99, 1.0` all satisfy `RelativeQuantileSpec::core(0.01)` against the exact order statistics, with zero violations tolerated. |
| `univmon_octo_plan_reports_the_delivered_l1_and_holds_its_f2_bound_under_both_partitions` | The UnivMon parent's L1 is exactly the delivered weight, and its F2 holds the AMS bound. | Drives the same 60,000-key stream through `UnivMonOctoPlan::new(5, 4096, 8)` with heap `64` on `4` workers under both routes, recording the largest `weight_total` each worker stamped on a delta, and per route verifies the delivered sum never exceeds `N`, that `parent.calc_l1()` equals that sum *exactly* (`UnivMonOctoWorker` has no flush, so mass after a worker's last delta stays in flight and the printed context names how much), and that `calc_l2().powi(2)` passes `SecondMomentSpec::new(5, 4096)`'s `sqrt(2*kappa/w)` relative band against the exact F2. |
| `coco_and_elastic_octo_plans_stay_one_sided_on_heavy_keys_under_both_partitions` | Coco and Elastic Octo plans stay one-sided on heavy keys and inside the stream mass under either partition. | Drives the same 60,000-key stream through `CocoOctoPlan::new(4096, 2)` and `ElasticOctoPlan::new(512, 3, 4096)` on `4` workers under both routes with a per-worker flush, and per route verifies for the truth's top `32` keys that Coco's `estimate_key` is never below the exact count and never above the whole stream mass, that Elastic's `query` stays inside `[0, stream mass]`, and that a single-threaded reference of each family satisfies the same rules (so a failure separates the partition from the sketch itself). |
### TumblingWindow
Test file: [`src/sketch_framework/tumbling.rs`](../src/sketch_framework/tumbling.rs)
| test_name | test_description | what_is_tested |
| --- | --- | --- |
| `pool_take_returns_preallocated` | A take off a pre-allocated pool hands back a sketch without allocating. | For a `SketchPool<FoldCMS>` of `4` over `FoldCMSConfig { rows: 3, full_cols: 1024, fold_level: 3, top_k: 10 }`, verifies `available` and `total_allocated` both start at `4`, and that one `take` leaves `available` at `3` with `total_allocated` still `4`. |
| `pool_take_allocates_when_empty` | An empty pool allocates rather than failing. | For a `SketchPool<FoldCMS>` of `0` over the `3x1024` fold-3 config, verifies `available` and `total_allocated` both start at `0`, and that one `take` raises `total_allocated` to `1`. |
| `pool_put_recycles` | A returned sketch goes back on the free list instead of being dropped. | For a `SketchPool<FoldCMS>` of `1` over the `3x1024` fold-3 config, verifies `available` is `0` after a `take` and back to `1` after the `put`, with `total_allocated` still `1`. |
| `fold_cms_clear_resets_to_empty` | `FoldCMS::clear` empties both the counters and the heap. | Inserts keys `U64(0..50)` at weight `1` into a `FoldCMS::new(3, 1024, 3, 10)` built directly, verifies key `0` reads above `0`, then after `clear` verifies all fifty keys read `0` and `heap()` is empty. |
| `fold_cs_clear_resets_to_empty` | `FoldCS::clear` empties both the counters and the heap. | Inserts keys `U64(0..50)` at weight `1` into a `FoldCS::new(3, 1024, 3, 10)` built directly, verifies key `0` reads non-zero, then after `clear` verifies all fifty keys read `0` and `heap()` is empty. |
| `kll_clear_resets_to_empty` | `KLL::clear` resets the count and the CDF. | Feeds `F64(0..1000)` into a `KLL::init(200, 8)` built directly, verifies `count()` is above `0`, then after `clear` verifies `count()` is `0` and `cdf().query(0.5)` is `0.0`. |
| `univmon_q_tumbling_merges_quantiles_and_universal_metrics` | A `TumblingWindow<UnivMonQ>` merge carries the quantile and the distinct count exactly. | For `TumblingWindow::new(100, 4, cfg, 2)` over `UnivMonQConfig { levels: 8, width: 256, width_halving_period: 0, depth: 5, counter_bits: 64, candidates: 64, ordered_samples: 64, hash_seed: 5 }` fed `F64(value % 50)` at timestamps `0..300`, verifies `query_all` reports `count` `300`, `quantile(0.5)` of `Some(24.0)`, and `estimate_distinct` of `50.0`. |
| `zero_window_size_panics` | A `window_size` of zero is refused at construction. | Verifies `TumblingWindow::<FoldCMS>::new(0, 5, cfg, 4)` over the `3x1024` fold-3 config panics with `"window_size must be > 0"`. |
| `window_closes_on_time_advance` | A timestamp past the boundary closes the active window. | For `TumblingWindow::new(100, 10, cfg, 4)` over the `3x1024` fold-3 config, verifies `closed_count` is `0` after inserts at `t = 0` and `t = 50`, `1` after an insert at `t = 100`, and `2` after one at `t = 200`. |
| `window_evicts_oldest_beyond_max` | Eviction drops the oldest window's data and retains exactly `max_windows`. | For `TumblingWindow::new(100, 3, cfg, 4)` over the `3x1024` fold-3 config fed keys `U64(0..5)` at timestamps `w * 100`, verifies `closed_count()` is exactly `3`, that `query_all()` estimates `1` for each of the keys `U64(1..5)` held by the three retained windows and the active one, and that the evicted window's key `U64(0)` estimates `0`. |
| `window_pool_recycles_on_eviction` | Eviction returns sketches to the pool, cleared, and the pool allocates nothing after priming. | For `TumblingWindow::new(100, 2, cfg, 4)` over the `3x1024` fold-3 config fed keys `U64(0..6)` at timestamps `w * 100` - six windows opened, five closed, three evicted - verifies `closed_count()` is `2`, `pool_available()` is exactly `1`, and `pool_total_allocated()` is still the initial `4`, then verifies the active window (running on the sketch window 2 handed back) estimates `1` for its own key `U64(5)` and `0` for window 2's key `U64(2)`. |
| `query_all_matches_manual_merge` | `query_all` answers exactly as one sketch fed the same stream. | For `TumblingWindow::new(100, 10, cfg, 4)` over the `3x1024` fold-3 config fed keys `U64(0..20)` at timestamps `i * 30`, and a `FoldCMS::new(3, 1024, 3, 10)` fed the same twenty keys, verifies `query_all` and the manual sketch return equal estimates for every key. |
| `query_recent_selects_subset` | `query_recent(n)` covers the `n` newest closed windows plus the active one, and nothing older. | For `TumblingWindow::new(100, 10, cfg, 4)` over the `3x1024` fold-3 config holding `Str("old")` at weight `5` in window 0, `Str("new")` at `10` in window 1, and `Str("active")` at `7` in the active window 2, verifies `query_recent(1)` reads `new` as `10`, `active` as `7`, and `old` as `0`. |
| `fold_cms_tumbling_hierarchical_merge` | `query_all_hierarchical` on `FoldCMS` keeps most estimates inside the Count-Min bound. | For `TumblingWindow::new(10_000, 8, cfg, 10)` over `FoldCMSConfig { rows: 3, full_cols: 4096, fold_level: 4, top_k: 20 }` fed a seeded (`0xCAFE_BABE`) Zipf(`domain = 5000`, `exponent = 1.1`) stream of `80_000` samples at timestamps `i`, verifies over `90%` of distinct keys have `\|est - truth\|` under `(e / 4096) * L1`. |
| `kll_tumbling_quantile_accuracy` | A merged `TumblingWindow<KLL>` puts the median inside a 2% rank band. | For `TumblingWindow::new(5_000, 4, cfg, 6)` over `KLLConfig { k: 200, m: 8, seed: None }` fed `20_000` seeded (`0xDEAD_BEEF`) uniform values in `[0.0, 1_000_000.0)` at timestamps `i`, verifies `query_all().cdf().query(0.5)` falls between the sorted values at ranks `ceil(0.48n)` and `ceil(0.52n)`. |
| `flush_closes_active_window` | `flush` closes the active window even mid-window, and the data stays queryable. | For `TumblingWindow::new(100, 10, cfg, 4)` over the `3x1024` fold-3 config holding `Str("x")` at weight `5` from `t = 10`, verifies `closed_count` goes from `0` to `1` across `flush(50)`, that `active_sketch()` then reads `x` as `0`, and that `query_all` still reads it as `5`. |
| `fold_cs_tumbling_basic` | A `TumblingWindow<FoldCS>` merge sums one key's weight across windows. | For `TumblingWindow::new(100, 10, cfg, 4)` over `FoldCSConfig { rows: 3, full_cols: 1024, fold_level: 3, top_k: 10 }` fed `Str("hello")` at weights `5`, `3`, and `2` at timestamps `0`, `100`, and `200`, verifies `query_all` reads the key as exactly `10`. |
| `fold_cs_tumbling_hierarchical_merge` | `query_all_hierarchical` on `FoldCS` unfolds to level `0` and answers every key exactly. | For `TumblingWindow::new(100, 10, cfg, 6)` over `FoldCSConfig { rows: 5, full_cols: 4096, fold_level: 2, top_k: 10 }` fed keys `U64(0..40)` once each across four windows, verifies the merged sketch reports `fold_level()` of `0` and that no key of the forty is off its true `1` by more than `1`. |
| `fold_cms_tumbling_accuracy_zipf` | A flat `query_all` on `FoldCMS` meets the Count-Min bound at its own confidence. | For `TumblingWindow::new(31_250, 16, cfg, 18)` over `FoldCMSConfig { rows: 3, full_cols: 4096, fold_level: 4, top_k: 20 }` fed a seeded (`0xACC0_BAC1`) Zipf(`domain = 10_000`, `exponent = 1.1`) stream of `500_000` samples, verifies the share of keys within `(e / 4096) * L1` is at or above `(1 - e^-3) * 100`, and reports mean and max absolute error. |
| `fold_cms_hierarchical_vs_flat_merge` | A hierarchical merge and an unfolded flat merge are the same answer, key for key. | Feeds a seeded (`0xF1A7_CAFE`) Zipf(`domain = 5000`, `exponent = 1.1`) stream of `100_000` samples into two identical `TumblingWindow::new(12_500, 8, cfg, 10)` managers over `FoldCMSConfig { rows: 3, full_cols: 4096, fold_level: 3, top_k: 20 }`, and verifies `query_all_hierarchical` reaches `fold_level` `0` and returns estimates exactly equal to `query_all().unfold_full()` for every key in the truth map. |
| `fold_cs_tumbling_accuracy_zipf` | A flat `query_all` on `FoldCS` meets the Count Sketch L2 bound at its own confidence. | For `TumblingWindow::new(31_250, 16, cfg, 18)` over `FoldCSConfig { rows: 5, full_cols: 4096, fold_level: 4, top_k: 20 }` fed a seeded (`0xC5_ACCA`) Zipf(`domain = 10_000`, `exponent = 1.1`) stream of `500_000` samples, verifies the share of keys within `sqrt(e / 4096) * L2` is at or above `(1 - e^-5) * 100`, and reports mean and max absolute error. |
| `kll_tumbling_multi_quantile_accuracy` | Five quantiles of a merged `TumblingWindow<KLL>` each land in a 2% rank band. | For `TumblingWindow::new(12_500, 8, cfg, 10)` over `KLLConfig { k: 200, m: 8, seed: None }` fed `100_000` seeded (`0x411_00171`) uniform values in `[0.0, 10_000_000.0)`, verifies `query_all().cdf().query(q)` for `q` in `0.10`, `0.25`, `0.50`, `0.75`, `0.90` sits between the sorted values at ranks `q - 0.02` and `q + 0.02`. |
| `kll_tumbling_distribution_shift` | Across a mid-stream distribution change the merged CDF keeps the shape of both halves. | For `TumblingWindow::new(12_500, 8, cfg, 10)` over `KLLConfig { k: 400, m: 8, seed: None }` fed `50_000` seeded (`0xFA_ACE1`) `normal(100, 10)` values then `50_000` seeded (`0xFA_ACE2`) `normal(500, 50)` values, verifies `query_all().cdf()` puts `p10` below `200.0`, `p50` between `50.0` and `600.0`, `p90` above `350.0`, and `p10 < p50 < p90`. |
| `kll_tumbling_seeded_is_byte_identical_across_instances` | A `KLLConfig` seed makes the whole tumbling pipeline reproducible, and a different seed does not alias onto it. | Feeds `20_000` seeded (`0x5EED_0001`) uniform values in `[0.0, 1_000_000.0)` at timestamps `i` through two independent `TumblingWindow::new(1000, 4, KLLConfig { k: 200, m: 8, seed: Some(0x5EED_CAFE) }, 6)` managers - twenty windows, so the run rotates and evicts - and verifies `query_all().serialize_to_bytes()` is identical; a third manager at seed `0x5EED_CAFE + 1` is verified to produce different bytes. |
| `tumbling_eviction_correctness` | After eviction the merge answers the retained windows, and evicted-only keys stay inside the bound. | For `TumblingWindow::new(10_000, 4, cfg, 6)` over `FoldCMSConfig { rows: 3, full_cols: 4096, fold_level: 4, top_k: 20 }` fed a seeded (`0xE01C_0100`) Zipf(`domain = 5000`, `exponent = 1.1`) stream of `80_000` samples over eight windows, verifies over `90%` of the retained truth - windows `3..8`, the four newest closed plus the active - is within `(e / 4096) * retained_L1`, and that every key appearing only in windows `0..3` reads at or under that same bound rather than exactly `0`. |
| `tumbling_query_recent_accuracy` | `query_recent` answers its own subset's truth, and excluded keys stay inside the bound. | For `TumblingWindow::new(10_000, 6, cfg, 8)` over `FoldCMSConfig { rows: 3, full_cols: 4096, fold_level: 4, top_k: 20 }` retaining all six windows of a seeded (`0xBEC3_0A00`) Zipf(`domain = 5000`, `exponent = 1.1`) stream of `60_000` samples, verifies over `90%` of the truth for windows `2..6` is within `(e / 4096) * recent_L1` under `query_recent(3)`, and that every key appearing only in windows `0` and `1` reads at or under that bound. |
| `fold_cms_tumbling_heap_correctness` | The merged `FoldCMS` heap recovers most of the true heavy hitters, with counts and root ordering intact. | For `TumblingWindow::new(25_000, 8, cfg, 10)` over `FoldCMSConfig { rows: 3, full_cols: 4096, fold_level: 4, top_k: 20 }` fed a seeded (`0xBEAF_C0DE`) Zipf(`domain = 10_000`, `exponent = 1.3`) stream of `200_000` samples, verifies `query_all().heap().heap()` holds exactly `20` residents and holds at least `80%` of the exact top-`20` keys as `HeapItem::U64` entries, that every resident's count is positive and no greater than the merged estimate for its key, that the merged estimate is at or above the exact count (Count-Min's one-sided error), and that the min-heap's root is the smallest resident. |
| `fold_cs_tumbling_query_recent_accuracy` | `query_recent` on `FoldCS` meets the L2 bound over its own subset. | For `TumblingWindow::new(10_000, 6, cfg, 8)` over `FoldCSConfig { rows: 5, full_cols: 4096, fold_level: 4, top_k: 20 }` retaining all six windows of a seeded (`0xC5_0A01`) Zipf(`domain = 5000`, `exponent = 1.1`) stream of `60_000` samples, verifies over `90%` of the truth for windows `2..6` is within `sqrt(e / 4096) * recent_L2` under `query_recent(3)`, and that every key appearing only in windows `0` and `1` has `\|est\|` at or under that bound. |
| `kll_tumbling_query_recent_accuracy` | `query_recent` on `KLL` answers the quantiles of its own subset. | For `TumblingWindow::new(12_500, 8, cfg, 10)` over `KLLConfig { k: 200, m: 8, seed: None }` fed `100_000` seeded (`0xA11_0072`) uniform values in `[0.0, 10_000_000.0)`, verifies `query_recent(3).cdf().query(q)` for `q` in `0.10`, `0.25`, `0.50`, `0.75`, `0.90` sits inside a `0.03` rank band of the `50_000` values in windows `4..8`. |
| `fold_cs_tumbling_heap_correctness` | The merged `FoldCS` heap recovers most of the true heavy hitters, with counts and root ordering intact. | For `TumblingWindow::new(25_000, 8, cfg, 10)` over `FoldCSConfig { rows: 5, full_cols: 4096, fold_level: 4, top_k: 20 }` fed a seeded (`0xC5_4EA9`) Zipf(`domain = 10_000`, `exponent = 1.3`) stream of `200_000` samples, verifies `query_all().heap().heap()` holds exactly `20` residents and holds at least `80%` of the exact top-`20` keys as `HeapItem::U64` entries, that every resident's count is positive, that each resident's merged estimate is within `2%` of its exact count (Count Sketch's error is two-sided), and that the min-heap's root is the smallest resident. |
| `fold_cms_tumbling_vs_monolithic` | Splitting a `FoldCMS` stream into windows costs at most half again the error. | For `TumblingWindow::new(25_000, 8, cfg, 10)` over `FoldCMSConfig { rows: 3, full_cols: 4096, fold_level: 4, top_k: 20 }` and a `FoldCMS::new(3, 4096, 4, 20)` both fed a seeded (`0xDE_AD01`) Zipf(`domain = 10_000`, `exponent = 1.1`) stream of `200_000` samples, verifies the merged window's mean absolute error is at most `1.5` times the single sketch's, and reports both. |
| `fold_cs_tumbling_vs_monolithic` | Splitting a `FoldCS` stream into windows costs at most half again the error. | For `TumblingWindow::new(25_000, 8, cfg, 10)` over `FoldCSConfig { rows: 5, full_cols: 4096, fold_level: 4, top_k: 20 }` and a `FoldCS::new(5, 4096, 4, 20)` both fed a seeded (`0xDE_AD02`) Zipf(`domain = 10_000`, `exponent = 1.1`) stream of `200_000` samples, verifies the merged window's mean absolute error is at most `1.5` times the single sketch's, and reports both. |
| `kll_tumbling_vs_monolithic` | Splitting a `KLL` stream into windows costs at most `0.02` of rank. | For `TumblingWindow::new(12_500, 8, cfg, 10)` over `KLLConfig { k: 200, m: 8, seed: None }` and a `KLL::init(200, 8)` both fed `100_000` seeded (`0xDE_AD03`) uniform values in `[0.0, 10_000_000.0)`, verifies the merged window's worst rank error over `q` in `0.10`, `0.25`, `0.50`, `0.75`, `0.90` is at most the single sketch's plus `0.02`, and reports both. |
| `tumbling_single_window_accuracy` | With `window_size` past the stream length nothing closes and every payload still answers. | Over `50_000` samples with `window_size` set to `50_001` and `max_windows` `10`, pool cap `4`, verifies `closed_count()` is `0` in three subsections and that `query_all` holds: a `3x4096` fold-4 `FoldCMS` on a seeded (`0x51_0001`) Zipf(`5000`, `1.1`) stream over `90%` within `(e / 4096) * L1`; a `5x4096` fold-4 `FoldCS` on a seeded (`0x51_0002`) stream over `90%` within `sqrt(e / 4096) * L2`; and a `KLL { k: 200, m: 8 }` on seeded (`0x51_0003`) uniform values in `[0.0, 1_000_000.0)` with `q` `0.25`, `0.50`, `0.75` inside a `0.02` rank band. |
| `tumbling_very_small_windows` | Five hundred rotations under a fifty-window cap still answer the retained tail. | For `TumblingWindow::new(10, 50, cfg, 52)` over `FoldCMSConfig { rows: 3, full_cols: 1024, fold_level: 3, top_k: 10 }` fed a seeded (`0x77_1100`) Zipf(`domain = 500`, `exponent = 1.2`) stream of `5000` samples at timestamps `i` - `500` windows, of which only the newest `50` closed plus the active survive - verifies over `85%` of the truth built from samples `4500..5000` is within `(e / 1024) * L1` under `query_all`. |
| `tumbling_skewed_load` | A window carrying most of the stream does not break the Count-Min bound. | For `TumblingWindow::new(10_000, 5, cfg, 7)` over `FoldCMSConfig { rows: 3, full_cols: 4096, fold_level: 4, top_k: 20 }` fed five seeded (`0xBE_EF00 + w`) Zipf(`domain = 5000`, `exponent = 1.1`) phases - `1_000` samples each except `36_000` for phase `2`, each phase followed by a jump to the next window boundary - verifies over `90%` of keys are within `(e / 4096) * L1`, the truth covering all `40_000` samples including the two light windows the `max_windows` cap has already evicted. |
## MessagePack Portable Wire Types
### Portable CountMinSketch
Test file: [`src/message_pack_format/portable/countminsketch.rs`](../src/message_pack_format/portable/countminsketch.rs)
| test_name | test_description | what_is_tested |
| --- | --- | --- |
| `msgpack_delta_against_empty_round_trips` | A msgpack delta against an empty snapshot carries the window. | For a `5x1024` sketch fed 200 updates of `"hot"` at weight `1.0`, verifies the msgpack delta computed against a fresh `5x1024` sketch at threshold `1.0`, applied to another fresh sketch, reproduces the `"hot"` estimate to within 10%. |
| `msgpack_delta_wire_layout_is_parallel_arrays` | The delta is a five-element array of scalars plus parallel index arrays. | For a `3x8` sketch fed `"x"` at weight `5.0`, verifies the delta bytes equal `rmp_serde::to_vec(&(rows as u64, cols as u64, row_idx: Vec<u32>, col_idx: Vec<u32>, d_count: Vec<i64>))` recomputed from the non-zero cells of `sketch()`, and that decoding reports `rows` `3` and `cols` `8`. |
| `test_count_min_sketch_creation` | A fresh sketch has the requested shape and zeroed cells. | For `CountMinSketch::new(4, 1000)`, verifies `rows` is `4`, `cols` is `1000`, `sketch()` is 4 rows of 1,000, and every cell is `0.0`. |
| `test_count_min_sketch_update` | An insert never reads below its weight. | For a `2x10` sketch fed `"key1"` at weight `1.0`, verifies `estimate("key1")` is at or above `1.0`. |
| `test_count_min_sketch_query_empty` | An empty sketch answers zero. | Verifies a `2x10` sketch reports `estimate("anything")` of exactly `0.0`. |
| `test_count_min_sketch_merge` | Merge sums cells element-wise. | Merges two `2x3` legacy matrices, the left holding `5.0` at `(0,0)` and `10.0` at `(1,2)` and the right `3.0` at `(0,0)` and `7.0` at `(0,1)`, and verifies the merged cells read `8.0`, `7.0`, and `10.0`. |
| `test_count_min_sketch_merge_dimension_mismatch` | Mismatched row counts are refused. | Verifies merging a `3x3` sketch into a `2x3` one fails. |
| `test_count_min_sketch_msgpack_round_trip` | The msgpack round trip preserves shape and estimates. | Round-trips a `4x256` sketch fed `"apple"` at `5.0` then `2.0` and `"banana"` at `3.0`, and verifies the decode reports `rows` `4`, `cols` `256`, and estimates at or above `7.0` for `"apple"` and `3.0` for `"banana"`. |
| `test_aggregate_count` | `aggregate_count` builds a decodable sketch from parallel key and weight arrays. | For `aggregate_count(4, 100, ["a", "b", "a"], [1.0, 2.0, 3.0])`, verifies the returned bytes decode and report estimates at or above `4.0` for `"a"` and `2.0` for `"b"`. |
| `test_aggregate_count_empty` | An empty stream produces nothing. | Verifies `aggregate_count(4, 100, &[], &[])` returns `None`. |
| `test_apply_delta_additive` | Delta cells add into the matrix. | For a `2x3` sketch holding `[[1, 2, 3], [4, 5, 6]]`, applies cells `(0,0,10)` and `(1,2,100)` and verifies the matrix becomes `[[11, 2, 3], [4, 5, 106]]`. |
| `test_apply_delta_matches_full_merge` | Applying a delta lands where merging the same addition lands. | For a `2x2` base `[[1, 2], [3, 4]]`, verifies merging the addition `[[10, 0], [0, 20]]` and applying the delta cells `(0,0,10)` and `(1,1,20)` give the same matrix. |
| `test_apply_delta_out_of_range` | A cell outside the declared geometry is refused. | Verifies a delta carrying cell `(5, 0, 1)` against a `2x3` sketch fails to apply. |
| `test_update_then_envelope_matches_sketchlib_go_bytes` | The proto envelope for a populated matrix is byte-identical to the checked-in golden. | For a `4x2048` sketch fed 50 updates of `flow-{i % 10}` at weight `1.0`, builds a `CountMinState` with `counter_type` `INT64`, row-major `counts_int`, and per-row `l1`/`l2`, wraps it in a `SketchEnvelope` with `format_version` `1` and `sample_p` `0.0`, and verifies the prost encoding matches the 8,275-byte [`cms_envelope_golden.hex`](../src/sketches/testdata/cms_envelope_golden.hex) on both length and content. |
| `test_hh_keys_matches_go_golden_bytes` | Heavy-hitter keys at tag 6 reach the wire in the golden's shape. | For the same `4x2048` and 50-update `flow-{i % 10}` stream, decodes the packed delta as a proto `CountMinDelta`, sets `hh_keys` to `["flow-0", "flow-3", "flow-7"]`, and verifies the re-encoding equals a 263-byte inline golden, then that those bytes apply to a fresh `4x2048` sketch. |
| `test_compute_delta_against_empty_round_trips` | A proto delta against an empty snapshot carries the whole matrix. | For a `4x2048` sketch fed 200 updates of `flow-{i % 37}` at weight `1.0`, verifies the delta computed against an empty sketch at threshold `1.0`, applied to a fresh `4x2048` sketch, reproduces `sketch()` cell for cell. |
| `test_compute_delta_then_apply_matches_current` | A delta between two non-empty snapshots reconstructs the later one. | For a `2x64` base fed 40 updates of `k{i % 8}` and a current fed 30 more, verifies the delta applied to the base reproduces the current matrix. |
| `test_compute_delta_matches_go_golden_bytes` | The packed delta bytes are pinned by a golden. | For a `4x2048` sketch fed 50 updates of `flow-{i % 10}` at weight `1.0`, verifies the delta against an empty sketch at threshold `1.0` equals a 239-byte inline golden. |
### Portable CountMinSketchWithHeap
Test file: [`src/message_pack_format/portable/countminsketch_topk.rs`](../src/message_pack_format/portable/countminsketch_topk.rs)
| test_name | test_description | what_is_tested |
| --- | --- | --- |
| `test_creation` | A fresh composite has the requested matrix and an empty heap. | For `CountMinSketchWithHeap::new(4, 1000, 20)`, verifies `rows` `4`, `cols` `1000`, `heap_size` `20`, a `sketch_matrix()` of 4 rows of 1,000, and no heap items. |
| `test_query_empty` | An empty composite answers zero. | Verifies a `2x10` composite with a 5-slot heap reports `estimate("anything")` of `0.0`. |
| `test_merge` | Merge sums the matrices and adopts the peer's heap bound. | Merges a `2x10` composite holding `5.0` at `(0,0)`, `15.0` at `(1,1)`, heap `{key3: 75.0, key1: 80.0}` and `heap_size` `3` into one holding `10.0` at `(0,0)`, `20.0` at `(1,1)`, heap `{key1: 100.0, key2: 50.0}` and `heap_size` `5`, and verifies the merged cells read `15.0` and `35.0`, `heap_size` becomes `3`, and the heap holds at most 3 items. |
| `test_merge_dimension_mismatch` | Mismatched row counts are refused. | Verifies merging a `3x10` composite into a `2x10` one fails. |
| `test_msgpack_round_trip` | The round trip carries the matrix, the heap bound, and the heap itself. | Round-trips a `4x128` composite with a 3-slot heap fed `"hot"` at `100.0` and `"cold"` at `1.0`, and verifies the decode reports `rows` `4`, `cols` `128`, `heap_size` `3`, a non-empty heap holding `"hot"` at or above `100.0`, and estimates at or above `100.0` and `1.0`. |
| `test_aggregate_topk` | `aggregate_topk` builds a decodable composite honouring its heap bound. | For `aggregate_topk(4, 100, 2, ["a", "b", "a", "c"], [1.0, 2.0, 3.0, 0.5])`, verifies the decode reports `heap_size` `2` and at most 2 heap items; the heap contents themselves are not checked. |
| `test_aggregate_topk_empty` | An empty stream produces nothing. | Verifies `aggregate_topk(4, 100, 10, &[], &[])` returns `None`. |
### Portable CountSketch
Test file: [`src/message_pack_format/portable/countsketch.rs`](../src/message_pack_format/portable/countsketch.rs)
| test_name | test_description | what_is_tested |
| --- | --- | --- |
| `msgpack_delta_against_empty_round_trips` | A msgpack delta against an empty snapshot carries the signed cells exactly. | For a `5x1024` sketch fed 200 updates of `"hot"` at weight `1.0`, verifies the delta against a fresh sketch at threshold `1.0`, applied to another fresh sketch, reproduces `sketch()` cell for cell. |
| `msgpack_delta_wire_layout_is_parallel_arrays` | The delta is a five-element array of scalars plus parallel index arrays. | For a `3x8` sketch fed `"x"` at weight `5.0`, verifies the delta bytes equal `rmp_serde::to_vec(&(rows as u64, cols as u64, row_idx: Vec<u32>, col_idx: Vec<u32>, d_count: Vec<i64>))` recomputed from the non-zero cells, and that decoding reports `rows` `3` and `cols` `8`. |
| `test_new_empty` | A fresh sketch has the requested shape and zeroed cells. | For `CountSketch::new(2, 3)`, verifies `rows` is `2`, `cols` is `3`, and `sketch()` is `[[0.0, 0.0, 0.0], [0.0, 0.0, 0.0]]`. |
| `test_from_legacy_matrix` | A legacy matrix is adopted unchanged, signs included. | Verifies `from_legacy_matrix([[1.0, -2.0, 3.0], [-4.0, 5.0, -6.0]], 2, 3)` reports exactly that matrix from `sketch()`. |
| `test_merge_element_wise` | Merge sums signed cells element-wise. | Merges the `2x2` matrix `[[-1.0, -2.0], [-3.0, -4.0]]` into `[[1.0, 2.0], [3.0, 4.0]]` and verifies every merged cell is `0.0`. |
| `test_merge_dimension_mismatch` | Mismatched row counts are refused. | Verifies merging a `3x3` sketch into a `2x3` one fails. |
| `test_merge_refs` | `merge_refs` sums every input. | Merges three `1x2` sketches holding `[1.0, 2.0]`, `[3.0, 4.0]`, and `[5.0, 6.0]` and verifies the result is `[[9.0, 12.0]]`. |
| `test_apply_delta_additive` | Delta cells add into the matrix, negative weights included. | For a `2x3` sketch holding `[[1.0, -2.0, 3.0], [-4.0, 5.0, -6.0]]`, applies cells `(0,0,10)`, `(0,2,-3)`, and `(1,1,-15)` and verifies the matrix becomes `[[11.0, -2.0, 0.0], [-4.0, -10.0, -6.0]]`. |
| `test_apply_delta_matches_full_merge` | Applying a delta lands where merging the same addition lands. | For a `2x2` base `[[1.0, 2.0], [3.0, 4.0]]`, verifies merging the addition `[[10.0, 0.0], [0.0, 20.0]]` and applying the delta cells `(0,0,10)` and `(1,1,20)` give the same matrix. |
| `test_apply_delta_out_of_range` | A cell outside the declared geometry is refused. | Verifies a delta carrying cell `(2, 0, 1)` against a two-row `2x3` sketch fails to apply. |
| `test_apply_delta_rebuilds_topk_from_hh_keys` | The `hh_keys` channel rebuilds Top-K by re-querying the merged matrix. | For a `3x16` sketch fed `"alpha"` at `5.0` and `"beta"` at `3.0`, applies a delta with no cells and `hh_keys` `["alpha", "beta"]` and verifies `topk` holds both keys and that `"alpha"` reads above `"beta"`. |
| `test_apply_delta_hh_keys_topk_capacity` | The rebuilt Top-K is bounded by `COUNT_SKETCH_TOPK_CAPACITY`. | For a `3x1024` sketch fed 105 keys `k0000`..`k0104` at weights `1.0`..`105.0`, applies a delta whose `hh_keys` carries all 105 and verifies `topk` holds exactly `COUNT_SKETCH_TOPK_CAPACITY` (`100`) entries; which entries survive is not checked. |
| `test_msgpack_round_trip` | The msgpack round trip preserves the signed matrix and its shape. | Round-trips a `2x2` sketch holding `[[1.5, -2.5], [3.5, -4.5]]` and verifies the matrix, `rows`, and `cols` are unchanged. |
| `test_update_then_envelope_matches_sketchlib_go_bytes` | The proto envelope for a populated matrix is byte-identical to the golden. | For a `3x512` sketch fed 25 updates over the five keys `k-a`..`k-e` (each five times) at weight `1.0`, builds a `CountSketchState` with `counter_type` `INT64`, row-major `counts_int`, per-row `l2` of `125.0`, and no `topk`, wraps it in a `SketchEnvelope` with `format_version` `1`, and verifies the prost encoding equals a 1,577-byte inline golden. |
| `test_hh_keys_matches_go_golden_bytes` | Heavy-hitter keys at tag 6 reach the wire in the golden's shape. | For the same `3x512` sketch over `k-a`..`k-e`, decodes the packed delta against an empty sketch as a proto `CountSketchDelta`, sets `hh_keys` to `["flow-0", "flow-3", "flow-7"]`, and verifies the re-encoding equals a 117-byte inline golden. |
| `test_compute_delta_against_empty_round_trips` | A proto delta against an empty snapshot carries the whole signed matrix. | For a `3x512` sketch fed 200 updates of `k-{i % 23}` at weight `1.0`, verifies the delta against an empty sketch at threshold `1.0`, applied to a fresh `3x512` sketch, reproduces `sketch()` cell for cell. |
| `test_compute_delta_then_apply_matches_current` | A delta between two non-empty snapshots reconstructs the later one. | For a `3x64` base fed 40 updates of `x{i % 8}` and a current fed 30 more, verifies the delta applied to the base reproduces the current matrix. |
| `test_compute_delta_matches_go_golden_bytes` | The packed delta bytes and per-row L2 are pinned by a golden. | For a `3x512` sketch fed the 25 `k-a`..`k-e` updates, verifies the delta against an empty sketch at threshold `1.0` equals a 93-byte inline golden carrying the packed cell arrays and a per-row L2 of `125.0`. |
### Portable CountSketchWithHeap
Test file: [`src/message_pack_format/portable/countsketch_topk.rs`](../src/message_pack_format/portable/countsketch_topk.rs)
| test_name | test_description | what_is_tested |
| --- | --- | --- |
| `test_creation` | A fresh composite has the requested matrix and an empty heap. | For `CountSketchWithHeap::new(4, 1000, 20)`, verifies `rows` `4`, `cols` `1000`, `heap_size` `20`, a `sketch_matrix()` of 4 rows of 1,000, and no heap items. |
| `test_query_empty` | An empty composite answers zero. | Verifies a `2x10` composite with a 5-slot heap reports `estimate("anything")` of `0.0`. |
| `test_merge` | Merge sums the matrices and adopts the peer's heap bound. | Merges a `2x10` composite holding `5.0` at `(0,0)`, `15.0` at `(1,1)`, heap `{key3: 75.0, key1: 80.0}` and `heap_size` `3` into one holding `10.0` at `(0,0)`, `20.0` at `(1,1)`, heap `{key1: 100.0, key2: 50.0}` and `heap_size` `5`, and verifies the merged cells read `15.0` and `35.0`, `heap_size` becomes `3`, and the heap holds at most 3 items. |
| `test_merge_dimension_mismatch` | Mismatched row counts are refused. | Verifies merging a `3x10` composite into a `2x10` one fails. |
| `test_msgpack_round_trip` | The round trip carries the matrix, the heap bound, and the heap itself. | Round-trips a `4x128` composite with a 3-slot heap fed `"hot"` at `100.0` and `"cold"` at `1.0`, and verifies the decode reports `rows` `4`, `cols` `128`, `heap_size` `3`, a non-empty heap holding `"hot"` at or above `100.0`, and estimates at or above `100.0` and `1.0`. |
| `test_aggregate_topk` | `aggregate_topk` builds a decodable composite honouring its heap bound. | For `aggregate_topk(4, 100, 2, ["a", "b", "a", "c"], [1.0, 2.0, 3.0, 0.5])`, verifies the decode reports `heap_size` `2` and at most 2 heap items; the heap contents themselves are not checked. |
| `test_aggregate_topk_empty` | An empty stream produces nothing. | Verifies `aggregate_topk(4, 100, 10, &[], &[])` returns `None`. |
| `test_median_estimator_differs_from_cms_style_min` | The median-over-rows estimator tracks the true count rather than inflating. | For a `5x64` composite with a 10-slot heap fed `"heavy"` 50 times at weight `1.0` and 20 keys `light-0`..`light-19` once each, verifies `estimate("heavy")` falls in `40.0..=60.0`. |
### Portable DdSketch
Test file: [`src/message_pack_format/portable/ddsketch.rs`](../src/message_pack_format/portable/ddsketch.rs)
| test_name | test_description | what_is_tested |
| --- | --- | --- |
| `msgpack_delta_against_empty_round_trips` | A msgpack delta against an empty snapshot carries the bucket store. | For an `alpha` `0.01` sketch fed `1.0..=200.0`, verifies the delta against an empty sketch at threshold `1` applied to a fresh sketch gives the same `total_count` and quantiles at `0.5`, `0.9`, and `0.99` within 1%. |
| `msgpack_delta_wire_layout_is_parallel_arrays` | The delta is a two-element array of parallel index and count arrays. | For an `alpha` `0.01` sketch fed `1.0`, `1.0`, and `1000.0`, verifies the delta bytes equal `rmp_serde::to_vec(&(idx: Vec<i32>, d_count: Vec<u64>))` recomputed from the non-zero store cells at absolute index, and that decoding reports two buckets. |
| `test_new_empty` | A fresh sketch holds nothing. | For `DdSketch::new(0.01)`, verifies `total_count` is `0` and `store_counts` is empty. |
| `test_merge_aligned_same_offset` | Aligned stores add cell by cell. | Merges `[10, 20, 30]` at offset `-1` into `[1, 2, 3]` at offset `-1` and verifies the store becomes `[11, 22, 33]`, the offset stays `-1`, and `total_count` is `66`. |
| `test_merge_overlapping_offsets` | Merge widens the window across overlapping stores. | Merges `[10, 10, 10]` at offset `0` into `[1, 1, 1]` at offset `-1` and verifies the store becomes `[1, 11, 11, 10]` at offset `-1` with `total_count` `33`. |
| `test_merge_disjoint_offsets` | Merge zero-fills the gap between disjoint stores. | Merges `[3, 4]` at offset `5` into `[1, 2]` at offset `0` and verifies the store becomes `[1, 2, 0, 0, 0, 3, 4]` at offset `0`. |
| `test_apply_delta_additive_inside_store` | Delta buckets inside the store add to their cells. | For a base `[1, 2, 3]` at offset `-1`, applies a delta with buckets `(-1,4)`, `(0,8)`, `(1,12)`, `d_count` `24`, `d_sum` `120.0`, and `new_max` `9.0`, and verifies the store becomes `[5, 10, 15]` with `total_count` `30`. |
| `test_apply_delta_expands_store_on_new_bucket` | A delta bucket past the store grows it. | For a base `[1, 2]` at offset `0`, applies a delta with the single bucket `(4, 7)`, `d_count` `7`, and `d_sum` `35.0`, and verifies the store becomes `[1, 2, 0, 0, 7]` at offset `0` with `total_count` `10`. |
| `test_apply_delta_matches_full_merge` | Applying a delta lands where merging the same addition lands. | For a base `[1, 2, 3]` at offset `0`, verifies merging `[10, 0, 20]` at offset `0` and applying the delta buckets `(0,10)` and `(2,20)` give the same store and `total_count`. |
| `test_merge_alpha_mismatch` | Sketches of different relative accuracy are not mergeable. | Verifies merging an `alpha` `0.02` sketch into an `alpha` `0.01` one fails. |
| `test_msgpack_round_trip` | The msgpack round trip preserves alpha, store, and offset. | Round-trips `from_raw(0.01, [1, 2, 3], -2)` and verifies `alpha`, `store_counts`, `store_offset`, and `total_count` are unchanged. |
| `test_msgpack_is_three_element_array` | The wire form is a three-element array, not a map. | For `from_raw(0.01, [1, 2, 3], -2)`, verifies the first byte of `to_msgpack` is `0x93`, the msgpack fixarray marker for length `3`. |
| `test_insert_and_quantile_lognormal` | Quantiles track a known log-normal distribution. | Feeds 100,000 xorshift64\*/Box-Muller log-normal samples with `mu` `3` and `sigma` `0.7` into an `alpha` `0.01` sketch and verifies `\|ln(P50 / 20.09)\|` and `\|ln(P99 / 102.4)\|` are each below `0.05`; P90 is not asserted. |
| `test_delta_chain_preserves_quantile_accuracy` | A chain of applied deltas stays inside the alpha bound of the direct path. | Over five batches of 10,000 log-normal samples at `alpha` `0.01`, seeds one sketch from the first batch and applies four deltas built by the test's own `compute_dd_delta` helper, then verifies its `total_count` equals the directly fed sketch's exactly and that quantiles at `0.5`, `0.9`, and `0.99` agree within `alpha`; the shipped `compute_delta` is not the path exercised here. |
| `test_compute_delta_against_empty_round_trips` | A delta against an empty snapshot carries the whole store. | For an `alpha` `0.01` sketch fed `1.0..=200.0`, verifies the delta against empty at threshold `1`, applied to a fresh sketch, gives the exact `total_count`, the same count for every non-zero bucket compared at absolute index, and quantiles at `0.5`, `0.9`, and `0.99` within 1%. |
| `test_consecutive_windows_emit_own_state` | Each window emits its own state rather than a cross-window difference. | Builds `win1` from `1.0..=50.0` inserted twice (count `2` per bucket) and `win2` from `1.0..=50.0` once, and verifies `win2`'s delta against empty reconstructs `win2`'s `total_count` and that those bytes differ from `win2`'s delta against `win1`. |
| `test_update_then_envelope_matches_go_golden_bytes` | The proto envelope for a populated store is byte-identical to the golden. | For an `alpha` `0.01` sketch fed `1.0..=50.0`, builds a `DdSketchState` from `wire_alpha()`, `store_counts`, and `store_offset`, wraps it in a `SketchEnvelope` with `format_version` `1`, and verifies the prost encoding equals a 403-byte inline golden carrying a 384-entry store and a `store_offset` of `-64` (sint32 zigzag `0x7f`); the golden constant records that it is the Rust-produced value and still to be reconciled against the Go reference. |
### Portable DeltaResult
Test file: [`src/message_pack_format/portable/delta_set_aggregator.rs`](../src/message_pack_format/portable/delta_set_aggregator.rs)
| test_name | test_description | what_is_tested |
| --- | --- | --- |
| `test_msgpack_round_trip` | Both key sets survive the round trip. | Round-trips a `DeltaResult` with `added` `{"web", "api"}` and `removed` `{"db"}` and verifies the decode holds 2 added keys including both names and 1 removed key. |
| `test_empty_sets` | A `DeltaResult` holding nothing round-trips. | Verifies a `DeltaResult` with both sets empty encodes and decodes back with both sets still empty. |
### Portable HllSketch
Test file: [`src/message_pack_format/portable/hll.rs`](../src/message_pack_format/portable/hll.rs)
| test_name | test_description | what_is_tested |
| --- | --- | --- |
| `estimate_holds_past_the_32_bit_range` | The estimator follows the HyperLogLog formula rather than saturating. | For each rank in `12`, `16`, `18`, and `20` filled across all 16,384 registers of a precision-14 sketch, verifies `estimate()` is within a relative `1e-9` of `alpha_m * m * 2^rank` with `alpha_m = 0.7213 / (1 + 1.079 / m)` and `m = 16384`. |
| `msgpack_delta_against_empty_round_trips` | A msgpack register delta against an empty snapshot carries every register. | For a precision-12 sketch fed the little-endian bytes of `0..2000u64`, verifies the delta against an empty sketch at threshold `1`, applied to a fresh sketch, reproduces the register array exactly and the estimate to within 0.1%. |
| `msgpack_delta_wire_layout_is_parallel_arrays` | The register delta is two parallel arrays of index and value. | For a precision-4 sketch fed `b"a"` and `b"b"`, verifies the delta bytes equal `rmp_serde::to_vec(&(reg_idx: Vec<u32>, reg_val: Vec<u8>))` recomputed from the non-zero registers, and that decoding yields one update per non-zero register. |
| `test_new_empty` | A fresh sketch is `2^precision` zeroed registers. | For `HllSketch::new(Regular, 4)`, verifies the register array is 16 long and every register is `0`. |
| `test_merge_register_wise_max` | Merge takes the register-wise maximum. | Merges the precision-2 registers `[4, 2, 6, 0]` into `[1, 5, 3, 7]` and verifies the result is `[4, 5, 6, 7]`. |
| `test_apply_delta_max_semantics` | A delta raises registers to the maximum, never lowers them. | Applies the updates `(0,4)`, `(1,2)`, `(2,6)`, `(3,0)` to the precision-2 registers `[1, 5, 3, 7]` and verifies the result is `[4, 5, 6, 7]`. |
| `test_apply_delta_out_of_range` | A register index past the array is refused. | Verifies a delta carrying update `(7, 3)` against a precision-2 (four-register) sketch fails to apply. |
| `test_apply_delta_matches_full_merge` | Applying a delta lands where merging the same addition lands. | For the precision-2 base `[1, 5, 3, 7]`, verifies merging the addition `[4, 0, 6, 0]` and applying the delta updates `(0,4)` and `(2,6)` give the same register array. |
| `test_merge_variant_mismatch` | Two estimator variants are not mergeable. | Verifies merging a `Datafusion` precision-4 sketch into a `Regular` precision-4 one fails. |
| `test_merge_precision_mismatch` | Two precisions are not mergeable. | Verifies merging a precision-5 `Regular` sketch into a precision-4 one fails. |
| `test_merge_refs` | `merge_refs` takes the maximum across every input. | Merges three precision-1 sketches holding `[1, 0]`, `[0, 3]`, and `[2, 2]` and verifies the result is `[2, 3]`. |
| `test_update_then_estimate_within_2pct` | The estimate lands within 2% on a 50,000-key stream. | Feeds `key-0`..`key-49999` into a precision-12 `Regular` sketch and verifies the relative error of `estimate()` against `50_000` is below `0.02`. |
| `test_estimate_empty_is_zero` | An empty sketch estimates zero. | Verifies a precision-4 `Regular` sketch reports an `estimate()` of exactly `0.0`. |
| `test_msgpack_round_trip` | The encoding is an ASAPv1 envelope and the HIP state survives it. | Round-trips a `Hip` precision-3 sketch holding registers `[0, 1, 2, 3, 4, 5, 6, 7]` with `hip_kxq0` `1.0`, `hip_kxq1` `2.0`, and `hip_est` `3.0`, and verifies the bytes open with the `ASAPv1` magic and that the decode matches on registers, precision, and a `hip_kxq0` of `1.0`. |
| `test_update_then_envelope_matches_sketchlib_go_bytes` | The proto envelope for a populated register array is byte-identical to the checked-in golden. | For a `Datafusion` precision-14 sketch fed the little-endian `f64` bytes of `1..=50`, builds a `HyperLogLogState` from `wire_proto_variant()`, the precision, and the registers with `registers_sparse` unset, wraps it in a `SketchEnvelope` with `format_version` `1` and `sample_p` `0.0`, and verifies the prost encoding matches the 16,398-byte [`hll_envelope_golden.hex`](../src/sketches/testdata/hll_envelope_golden.hex) on both length and content. |
| `sparse_round_trip_exact` | The sparse register encoding is exact. | For a 16,384-register array holding `1` at index `0`, `7` at `1`, `51` at `300`, `12` at `8191`, and `3` at `16383`, verifies `encode_sparse_registers` reports `num_registers` `16384` and that the decode returns the array unchanged. |
| `registers_from_state_reads_both` | `registers_from_state` reads the sparse and the dense form alike. | For the same 16,384-register array at `variant` `2` and `precision` `14`, verifies the registers come back identical whether the state carries `registers_sparse` with `registers` empty or `registers` with `registers_sparse` unset. |
| `sparse_empty_is_all_zero` | An all-zero register array encodes to nothing. | For 16,384 zeroed registers, verifies the sparse `packed` field is empty and the decode returns the zeros. |
| `sparse_rejects_out_of_range_index` | A sparse index past `num_registers` is refused. | Verifies `HllSparseRegisters { num_registers: 4, packed: [5, 3] }`, whose first uvarint delta of `5` lands outside a four-register array, fails to decode. |
| `test_compute_delta_against_empty_round_trips` | A proto register delta against an empty snapshot carries every register. | For a `Datafusion` precision-14 sketch fed the little-endian bytes of `0..5000u64`, verifies the delta against an empty sketch at threshold `0`, applied to a fresh sketch, reproduces the register array. |
| `test_compute_delta_then_apply_matches_current` | A delta between two non-empty snapshots reconstructs the later one. | For a `Datafusion` precision-12 base fed `0..2000u64` and a current fed `2000..5000u64` on top, verifies the delta applied to the base reproduces the current register array. |
| `test_compute_delta_matches_go_golden_bytes` | The packed register delta bytes are pinned by a golden. | For a `Datafusion` precision-14 sketch fed the little-endian `f64` bytes of `1..=50`, verifies the delta against an empty sketch at threshold `0` equals a 132-byte inline golden in the packed `(index_delta, value)` form. |
| `test_compute_subwindow_delta_matches_go_golden_bytes` | A sub-window delta's bytes are pinned by a golden and still reconstruct the window. | For a `Datafusion` precision-14 base fed `0..2000` as `f64` little-endian bytes and a current fed `2000..5000` on top, verifies the delta carries only the registers that grew and equals a 5,097-byte inline golden, then that applying it to the base reproduces the current register array. |
### Portable HydraKllSketch
Test file: [`src/message_pack_format/portable/hydra_kll.rs`](../src/message_pack_format/portable/hydra_kll.rs)
| test_name | test_description | what_is_tested |
| --- | --- | --- |
| `test_creation` | A fresh matrix-of-KLL has the requested shape. | For `HydraKllSketch::new(2, 3, 200)`, verifies `rows` is `2`, `cols` is `3`, and the cell matrix is 2 rows of 3. |
| `test_update_and_query` | A per-key quantile query answers after inserts. | For a `2x10` matrix at `k` `200` fed `"key1"` at `5.0` and `10.0`, verifies `quantile("key1", 0.5)` is at or above `0.0`; the returned value itself is not pinned. |
| `test_merge` | Merge keeps the matrix geometry. | Merges a `2x5` matrix at `k` `200` fed `"key1"` with `6.0..=10.0` into one fed `1.0..=5.0` and verifies only that `rows` stays `2` and `cols` stays `5`; no quantile is checked. |
| `test_merge_dimension_mismatch` | Mismatched row counts are refused. | Verifies merging a `3x5` matrix into a `2x5` one fails. |
| `test_msgpack_round_trip` | The round trip preserves the matrix geometry. | Round-trips a `2x3` matrix at `k` `200` fed `"key1"` at `5.0` and `"key2"` at `10.0` and verifies the decode reports `rows` `2` and `cols` `3`; the per-cell KLL state is not checked. |
| `test_aggregate_hydrakll` | `aggregate_hydrakll` builds a decodable matrix from parallel key and value arrays. | For `aggregate_hydrakll(2, 5, 200, ["a", "b", "a"], [1.0, 2.0, 3.0])`, verifies the returned bytes decode and report `rows` `2` and `cols` `5`; no quantile is checked. |
| `test_aggregate_hydrakll_empty` | An empty stream produces nothing. | Verifies `aggregate_hydrakll(2, 5, 200, &[], &[])` returns `None`. |
### Portable KllSketch
Test file: [`src/message_pack_format/portable/kll.rs`](../src/message_pack_format/portable/kll.rs)
| test_name | test_description | what_is_tested |
| --- | --- | --- |
| `kll_data_msgpack_matches_kll_sketch` | The DTO codec is byte-identical to the facade's. | For a `k` `200` sketch fed the 500 values `0.0..=499.0`, verifies `KllSketch::to_msgpack` equals `KllSketchData { k, sketch_bytes }::to_msgpack` and that the DTO round-trips with `k` and `sketch_bytes` unchanged. |
| `test_kll_creation` | A fresh sketch is empty and keeps its `k`. | For `KllSketch::new(200)`, verifies `count()` is `0` and `k` is `200`. |
| `test_kll_update` | Every insert is counted. | Feeds `10.0`, `20.0`, and `15.0` into a `k` `200` sketch and verifies `count()` is `3`. |
| `test_kll_quantile` | The extremes are exact and the median brackets the true one. | For a `k` `200` sketch fed `1.0..=10.0`, verifies `quantile(0.0)` is `1.0`, `quantile(1.0)` is `10.0`, and the median falls in `5.0..=6.0`. |
| `test_kll_merge` | Merge conserves the count and the extremes. | Merges a `k` `200` sketch fed `6.0..=10.0` into one fed `1.0..=5.0` and verifies `count()` is `10`, `quantile(0.0)` is `1.0`, and `quantile(1.0)` is `10.0`. |
| `test_msgpack_round_trip` | The round trip preserves `k`, the count, and the extremes. | Round-trips a `k` `200` sketch fed `1.0..=5.0` and verifies the decode reports `k` `200`, `count()` `5`, `quantile(0.0)` `1.0`, and `quantile(1.0)` `5.0`. |
| `test_aggregate_kll` | `aggregate_kll` builds a decodable sketch from a value array. | For `aggregate_kll(200, [1.0, 2.0, 3.0, 4.0, 5.0])`, verifies the returned bytes decode to a sketch with `count()` `5`, `quantile(0.0)` `1.0`, and `quantile(1.0)` `5.0`. |
| `test_aggregate_kll_empty` | An empty value array produces nothing. | Verifies `aggregate_kll(200, &[])` returns `None`. |
| `test_update_then_envelope_matches_sketchlib_go_bytes` | The raw-`f64` proto envelope is byte-identical to the golden. | For `KLL::init_kll_with_seed(200, 42)` fed `1.0..=50.0`, builds a `KllState` from the `wire_k`/`wire_m`/`wire_num_levels`/`wire_levels`/`wire_items` accessors plus the `CoinState` from `wire_coin()`, leaving `offset` `0.0`, `value_scale` `0`, and `residuals` empty, wraps it in a `SketchEnvelope` with `format_version` `1`, and verifies the prost encoding equals a 423-byte inline golden. |
| `value_offset_round_trip_exact_fixed_point` | The fixed-point form round-trips integer and fixed-decimal series bit-exactly. | Verifies the 200 values `1_000_000 + 7i` encode at `value_scale` `0` and decode back equal, and that the 128 values `100.0 + 0.001i` encode at a scale in `-3..=0` and decode back equal. |
| `value_offset_guard_rejects_irrational` | A value with no exact decimal scale falls back to raw `f64`. | Verifies `encode_value_offset` returns `None` for `[0.0, 1.0, PI, 3.0]`, for the empty slice, for `[1.0, NAN]`, and for `[1.0, INFINITY]`. |
| `proto_dual_read_round_trip_both_forms` | The decoder reads the raw-`f64` and the value-offset form to the same answer. | For `KLL::init_kll_with_seed(200, 7)` fed `1.0..=5000.0`, builds one `KllState` carrying `wire_items()` and one carrying the `encode_value_offset` triple with `items` empty, and verifies `KllProtoItems::from_state` yields identical items and identical quantiles at `0.0`, `0.1`, `0.25`, `0.5`, `0.75`, `0.9`, and `1.0`. |
| `proto_rejects_both_forms_populated` | A state carrying both forms at once is refused. | Verifies a `KllState` with `k` `200`, `m` `8`, `num_levels` `1`, `levels` `[0, 2]`, `items` `[1.0, 2.0]`, and `residuals` `[1, 2]` fails to decode. |
| `golden_value_offset_envelope_from_go` | The value-offset envelope the Go side emits decodes to the right samples. | Decodes an 80-byte golden and verifies the `KllState` leaves `items` empty, carries `value_scale` `0`, `offset` `1.0`, and 50 residuals, and that the dual-read recovers `1.0..=50.0` with `quantile(0.0)` `1.0` and `quantile(1.0)` `50.0`. |
| `golden_value_offset_envelope_for_go` | The value-offset envelope this encoder emits is pinned byte for byte. | For `1.0..=50.0`, verifies `encode_value_offset` gives `offset` `1.0` and `value_scale` `0`, that the `SketchEnvelope` around a `KllState` with `k` `200`, `m` `8`, `num_levels` `1`, `levels` `[0, 50]`, and no coin encodes to the 76-byte `RUST_GOLDEN_HEX`, and that the dual-read recovers `1.0..=50.0`. |
### Portable Sampling Rescale
Test file: [`src/message_pack_format/portable/sampling.rs`](../src/message_pack_format/portable/sampling.rs)
| test_name | test_description | what_is_tested |
| --- | --- | --- |
| `dual_read_zero_means_one` | An unset `sample_p` reads as no sampling. | Verifies both `effective_sample_p` over an envelope carrying `sample_p` `0.0` and `sample_p_or_default(0.0)` return `1.0`. |
| `out_of_range_falls_back_to_one` | A malformed probability falls back to no sampling. | Verifies `sample_p_or_default` returns `1.0` for `-0.5`, for `1.5`, and for `f64::NAN`. |
| `valid_p_passes_through` | A probability inside `(0, 1]` is used as given. | Verifies `effective_sample_p` over an envelope carrying `sample_p` `0.1` returns `0.1`, and that `sample_p_or_default(1.0)` returns `1.0`. |
| `rescale_count_inverts_probability` | A count-like estimate is rescaled by `1/p`. | Verifies `rescale_count(10_000.0, 0.1)` is `100_000.0` within `1e-6`, that `rescale_count(123.0, 1.0)` is `123.0`, and that a `p` of `0.0` returns `123.0` rather than dividing by zero. |
| `rescale_with_env` | The envelope's own `sample_p` drives the rescale. | Verifies `rescale_count_with_env(5_000.0, env)` at `sample_p` `0.05` is `100_000.0` within `1e-6`, and that at `sample_p` `0.0` an input of `42.0` comes back unchanged. |
| `quantiles_are_scale_invariant` | The quantile family is declared to need no rescale. | Asserts `is_quantile_scale_invariant()`, a `const fn` returning `true`; nothing about a quantile estimate is computed. |
### Portable SetAggregator
Test file: [`src/message_pack_format/portable/set_aggregator.rs`](../src/message_pack_format/portable/set_aggregator.rs)
| test_name | test_description | what_is_tested |
| --- | --- | --- |
| `test_creation` | A fresh aggregator holds nothing. | Verifies `SetAggregator::new()` has an empty `values` set. |
| `test_insert` | A repeated key is inserted once. | Feeds `"web"`, `"api"`, and `"web"` again and verifies `values` holds 2 keys, both `"web"` and `"api"`. |
| `test_merge` | Merge is set union. | Merges an aggregator holding `{"api", "db"}` into one holding `{"web", "api"}` and verifies the result holds exactly `"web"`, `"api"`, and `"db"`. |
| `test_msgpack_round_trip` | The set survives the round trip. | Round-trips an aggregator holding `{"web", "api"}` and verifies the decode holds 2 keys, both names present. |
| `test_msgpack_matches_wire_format` | The bytes are a named map under a `values` key. | For an aggregator holding `{"a"}`, verifies the bytes decode into a locally declared `StringSet { values: HashSet<String> }` that still contains `"a"`. |
## Common
### Common Hash Utilities
Test file: [`src/common/hash.rs`](../src/common/hash.rs)
| test_name | test_description | what_is_tested |
| --- | --- | --- |
| `hash128_seeded_preserves_cardinality` | Hash128 seeded preserves cardinality. | With `SEED_IDX=0` and `SAMPLE_SIZE=5000`, verifies uniform and Zipf sample unique-input counts exactly match unique-hash counts (no observed collisions). |
| `hash128_seeded_is_deterministic_for_repeated_inputs` | Hash128 seeded is deterministic for repeated inputs. | For fixed key `"deterministic-key"` and seed `3`, verifies 100 repeated `hash128_seeded` calls always equal the first hash value. |
| `digest_hasher_spreads_digests_that_share_their_low_bits` | `DigestHasher` mixes rather than passing a digest through. | Hashes `0..1024` shifted left by 16, so every digest shares its ten low bits, and verifies more than 550 of the 1,024 low-bit buckets are occupied rather than the single bucket a pass-through hash would fill; the unshifted range is held to the same bound. |
| `owned_byte_keys_hash_like_the_borrowed_input` | A `HeapItem::Bytes` key hashes exactly like the `DataInput::Bytes` a caller queries with. | Across the empty byte string, `b"projectasap"`, `[0xff, 0x00, 0xfe]`, and 64 `0x80` bytes, at seed indices `0`, `1`, `CANONICAL_HASH_SEED`, and one past the seed list, verifies `hash64_seeded` equals `hash_item64_seeded` and `hash128_seeded` equals `hash_item128_seeded`. |
| `xxh3_regression_vectors_match_go` | The seeded digests of one fixed byte key are pinned values. | Verifies `hash64_seeded(0, &DataInput::Bytes(b"projectasap"))` is `887548862923853302`, `hash64_seeded(CANONICAL_HASH_SEED, ..)` is `8535098769003547387`, and `hash128_seeded(CANONICAL_HASH_SEED, ..)` is `199634325175509853918794253804029959851`. |
| `hash_seed_index_wraps_like_go` | A seed index past the end of the seed list wraps back into it. | Verifies `hash64_seeded` and `hash128_seeded` over `DataInput::Bytes(b"projectasap")` return the same digest at `SEEDLIST.len() + CANONICAL_HASH_SEED` as at `CANONICAL_HASH_SEED`. |
| `packed64_hasher_accepts_compatible_dimensions` | A `u64` matrix hash accepts a geometry whose row slices fit in 64 bits. | For a `SketchHasher` whose `HashType` is `u64`, verifies `hash_for_matrix_seeded(0, 3, 4096, &U64(7))` passes `<u64 as MatrixFastHash>::assert_compatible(3, 4096)` and returns `DefaultXxHasher::hash64_seeded(0, ..)`. |
| `packed128_hasher_accepts_larger_dimensions` | A `u128` matrix hash accepts a geometry a `u64` one cannot carry. | For a `SketchHasher` whose `HashType` is `u128`, verifies `hash_for_matrix_seeded(0, 8, 4096, &U64(11))` passes `<u128 as MatrixFastHash>::assert_compatible(8, 4096)` and returns `DefaultXxHasher::hash128_seeded(0, ..)`. |
| `packed64_hasher_rejects_oversized_dimensions` | A `u64` matrix hash panics on a geometry whose row slices overrun it. | Verifies `hash_for_matrix_seeded(0, 8, 4096, &U64(19))` on a `HashType = u64` hasher panics with "SketchHasher hash type u64 cannot represent fast-path hash for rows=8, cols=4096; use u128 or MatrixHashType". |
| `digest_hasher_avalanche_flips_about_half_the_output_bits` | Flipping one input bit flips each output bit about half the time. | For each of the 64 input bits, hashes `0..4096` through `DigestHasher::write_u64` with and without that bit flipped and verifies the mean number of flipped output bits is inside `31.0..=33.0` and that each of the 64 output bits flips at a rate inside `0.42..=0.58`. |
| `digest_hasher_keeps_distinct_digests_distinct` | The mix is injective, so distinct digests keep distinct hashes. | Verifies `DigestBuildHasher::default().hash_one` gives 4,096 pairwise distinct hashes over `0..4096u64`, and that `hash_one(0u64)` and `hash_one(1u64)` differ. |
| `digest_hasher_write_separates_short_byte_slices` | The byte path separates eight-byte keys, depends on byte order, and carries no seed. | Verifies the 1,024 eight-byte keys `(i * 0x0001_0001_0001_0001).to_be_bytes()` hash pairwise distinctly through `DigestHasher::write`, that `b"ab"` differs from `b"ba"` and from `b"abc"`, that one `write(b"ab")` equals `write(b"a")` then `write(b"b")`, and that two independently built `DigestBuildHasher::default()` agree on `"seed-free"`. |
### Common Input Types
Test file: [`src/common/input.rs`](../src/common/input.rs)
| test_name | test_description | what_is_tested |
| --- | --- | --- |
| `a_byte_array_owns_and_borrows_back_unchanged` | A borrowed byte array owns as a byte array, not as a string. | Verifies `input_to_owned(&DataInput::Bytes([0xff, 0x00, 0xfe]))` is `HeapItem::Bytes` of those bytes, that `heap_item_to_sketch_input` borrows the same bytes back, and that the owned key compares equal to the original input. |
| `a_byte_key_is_not_the_string_of_the_same_bytes` | `Bytes` and `Str` are different keys even where the bytes are valid UTF-8. | Verifies the owned forms of `Bytes(b"abc")` and `Str("abc")` are unequal, that the byte key matches only `DataInput::Bytes`, and that the string key matches `Str` and `String` but not `Bytes`. |
### Common Heap Utilities
Test file: [`src/common/heap.rs`](../src/common/heap.rs)
| test_name | test_description | what_is_tested |
| --- | --- | --- |
| `heap_retains_top_k_items_by_count` | Heap retains top K items by count. | For `HHHeap::new(3)` updated with counts `1..5`, verifies heap size is `3` and retained counts are exactly `[3,4,5]`. |
| `update_count_increments_existing_entry` | Update count increments existing entry. | Repeatedly updates key `alpha` with counts `1,2,3` and verifies stored heap entry count is `3` (incremental update, not replacement). |
| `clean_resets_heap_state` | Clean resets heap state. | After inserting two items into `HHHeap::new(2)`, `clear()` is verified to leave the heap empty. |
| `test_min_heap_basic` | Test min heap basic. | For `CommonHeap::<i32, KeepSmallest>::new_min(5)`, verifies `peek=1` and pop order `1,3,5,7`, then `None`. |
| `test_max_heap_basic` | Test max heap basic. | For `CommonHeap::<i32, KeepLargest>::new_max(5)`, verifies `peek=7` and pop order `7,5,3,1`, then `None`. |
| `test_bounded_heap_capacity` | Test bounded heap capacity. | With min-heap capacity `3`, verifies length never exceeds 3 and final retained values are `[5,7,10]` after pushing `5,3,7,1,10`. |
| `test_update_at` | Test update at. | After mutating an internal element (`heap[1]=3`) and calling `update_at(1)`, verifies heap root updates so `peek()` becomes `3`. |
| `test_custom_struct_with_ord` | Test custom struct with ord. | Uses `HHItem` values with counts `5,3,7` and verifies min-heap ordering by checking root count is `3`. |
| `test_topk_use_case` | Test topk use case. | Simulated top-k flow keeps only counts `[3,4,5]` at capacity 3 and verifies lookup for `key-4` succeeds with count `4`. |
| `test_heap_size` | Test heap size. | Verifies both `CommonHeap<u64, KeepSmallest>` and `CommonHeap<u64, KeepLargest>` sizes equal `size_of::<Vec<u64>>() + size_of::<usize>()`. |
| `test_topk_with_custom_comparator` | Test topk with custom comparator. | With custom comparator and capacity 3, verifies low-count insert is rejected/replaced as expected so heap size is 3 and root count is `5`. |
| `test_exact_topk_heap_replacement` | Test exact topk heap replacement. | Reproduces TopK-style find/update flow for keys `1..5`, verifies retained counts `[3,4,5]`, finds `key-4` with count `4`, then verifies `clear()` makes heap empty. |
| `the_index_survives_a_long_churning_stream` | The index stays exact through eviction, promotion, and re-entry. | At capacities 1, 2, 7, 64, and 512, streams 20,000 skewed draws over a 2,048-key domain and every 97 steps verifies `slots` carries each resident's digest, every position is listed in its own bucket, `find_heap_item` returns that position, and the index holds no entry beyond the residents; residency ends at `min(capacity, distinct)`. |
| `the_residents_are_the_k_largest_counts` | The residents are exactly the `k` largest counts. | Over 20,000 skewed draws across a 512-key domain into a 32-slot heap, verifies against a brute-force ranking that every resident's count is current and at or above the 32nd largest count, and that the heap is full. |
| `re_scoring_a_resident_never_duplicates_it` | A resident is re-scored in place rather than seated twice. | Updates `hot` and `warm` 50 rounds each into a 4-slot heap and verifies the index stays consistent, residency is `2`, `find` locates `hot`, and its count reads `50`. |
| `a_zero_capacity_heap_turns_everything_away` | A zero-capacity heap accepts nothing and stays consistent. | Verifies 32 updates into `HHHeap::new(0)` all return `false`, the heap stays empty, `find` returns `None`, and the index is consistent. |
| `clearing_drops_the_index_with_the_heap` | `clear` drops the index along with the entries. | After filling an 8-slot heap from 32 keys, verifies `clear()` leaves it empty with `find` returning `None` and a consistent index, then refills from 40 fresh keys and verifies the index is consistent again at residency `8`. |
| `a_decoded_heap_rebuilds_its_index` | The index is derived, so decoding rebuilds it rather than carrying it. | Round-trips a 16-slot heap fed 5,000 skewed draws through `rmp-serde` and verifies the decoded index is consistent, residency and capacity match, every resident is still found, and a further update re-scores a resident to `1_000_000` with the index still consistent. |
| `the_indexed_heap_matches_the_rebuild_implementation` | Retention does not depend on how the index is maintained. | At capacities 0, 1, 2, 3, 7, 8, 64, and 257, runs 30,000 skewed draws over a 4,096-key domain through both the shipped heap and a reference that rebuilds its key index in full after every accepted update, and verifies at every step that the completeness flag agrees and that both arrays hold the same key and count at every position. |
| `the_indexed_heap_matches_the_rebuild_implementation_on_string_keys` | The same agreement on the owned-key path and its different hash. | Runs 20,000 `flow::<n>` string keys over a 2,048-key domain into a 32-slot heap and verifies the shipped and rebuild implementations agree on the completeness flag and on every position's key and count at every step. |
| `the_two_agree_when_counts_move_in_both_directions` | Falling counts sink a resident back down and the two still agree. | Feeds a 16-slot heap 10,000 updates whose counts oscillate over `-30..=30` rather than only climbing, and verifies the shipped and rebuild implementations agree on the completeness flag and on every position at every step. |
| `the_heap_is_reproducible_across_runs` | The same stream gives the same heap, array position included. | Runs 20,000 skewed draws over a 1,024-key domain into a 64-slot heap five times over and verifies all five key/count snapshots are identical, so neither the index nor the map's iteration order reaches the output. |
| `a_bucket_holding_both_sides_of_a_swap_is_unchanged` | Swapping two entries of one bucket leaves the bucket alone. | With heap positions `0` and `1` both carrying digest `7`, `swap_entry(0, 1)` is verified to leave the slots as `[7, 7]` and the bucket listing positions `[0, 1]`. |
| `a_swap_moves_only_its_own_entry_out_of_a_shared_bucket` | A swap patches the matching entry, not the bucket head. | With digest `7` listed at positions `[2, 0]` and digest `9` at `[1]`, `swap_entry(0, 1)` is verified to leave slots `[9, 7, 7]`, digest `7` listing `[1, 2]`, and digest `9` listing `[0]`; patching the head instead would corrupt position 2. |
| `dropping_one_entry_keeps_the_rest_of_its_bucket` | Dropping one position leaves the bucket's other positions. | With digest `7` listed at `[0, 3, 5]`, `drop_entry(7, 3)` is verified to leave `[0, 5]`. |
| `dropping_the_last_entry_removes_the_bucket` | The bucket goes when its last position does. | With digest `7` listed at `[4]`, `drop_entry(7, 4)` is verified to remove the key from the index entirely. |
| `two_shared_buckets_follow_the_sift` | The index tracks the slots through a long run of sifts. | Seeds a 16-item `HHHeap` so residents alternate between two digests, then runs 200 `rescore` calls and verifies after each that every position is listed under the digest its slot names and that the buckets together name every heap position exactly once. |
| `a_value_tying_the_root_does_not_displace_it` | The bounded push replaces the root only on a strict improvement. | For a 3-capacity `CommonHeap<HHItem, KeepSmallest>` holding counts `5`, `7`, `9`, verifies a push tying the root at `5` leaves `a` resident and the arrival out, while a push of `6` evicts `a`; for a 3-capacity `KeepLargest` heap holding `9`, `7`, `5`, verifies a tie at `9` is turned away while `8` evicts `a`. |
| `push_back_with_reports_every_swap_of_its_sift` | `push_back_with` seats the value at `len()` and reports each swap as `(destination, source)`. | Pushing `50, 40, 30, 20, 10` into an 8-capacity `CommonHeap<i32, KeepSmallest>` is verified to report `[]`, `[(0,1)]`, `[(0,2)]`, `[(1,3),(0,1)]`, `[(1,4),(0,1)]`, to leave the array `[10, 20, 40, 50, 30]`, and to start every non-empty sift at the index the value was appended at. |
| `replace_root_with_returns_the_displaced_root` | `replace_root_with` hands back the displaced root and reports the new value's sift. | On the heap holding `[10, 20, 40, 50, 30]`, verifies `replace_root_with(60, ..)` returns `10`, reports `[(0,1),(1,4)]` with the first swap leaving index `0`, and leaves `[20, 30, 40, 50, 60]`. |
| `update_at_with_reports_the_sift_in_both_directions` | `update_at_with` reports the sift in whichever direction it runs and reports nothing for an index it refuses. | On the heap holding `[20, 30, 40, 50, 60]`, verifies setting index `4` to `5` reports `[(1,4),(0,1)]` and leaves `[5, 20, 40, 50, 30]`, setting index `0` to `100` reports `[(0,1),(1,4)]` and leaves `[20, 30, 40, 50, 100]`, and that `update_at_with(5, ..)` returns `false`, reports no swap, and leaves the array alone. |
| `a_parallel_array_follows_the_reported_swaps` | A caller that applies each reported swap keeps its own array aligned to the heap. | Pushes `50, 40, 30, 20, 10` tagged `a` through `e` into an 8-capacity `CommonHeap<i32, KeepSmallest>` through `push_back_with`, swapping a `Vec<char>` on every report, and verifies the heap reads `[10, 20, 40, 50, 30]` against tags `['e','d','b','a','c']`; then sets index `0` to `100`, runs `update_at_with(0, ..)` and verifies `[20, 30, 40, 50, 100]` against tags `['d','c','b','a','e']`. |
| `a_decoded_heap_takes_string_keyed_updates` | A decoded heap's rebuilt index is readable from the `DataInput` update path. | Fills an 8-slot `HHHeap` with `flow-0`..`flow-7` at counts `1..=8`, round-trips it through `rmp-serde`, verifies `find` locates every key at its count, then updates `flow-7` to `999` and verifies residency stays `8`, that key is seated exactly once, its count reads `999`, and the index is consistent. |
| `retention_matches_a_heapless_oracle` | Which keys survive matches a scan of a plain vector. | At capacities 0, 1, 2, 3, 5, 8, 11, and 16, streams 4,000 skewed draws over a 64-key domain (seed `0x2f2f`) at the distinct counts `((step * 7_919) % 1_000_003) + 1` and verifies at every step that the completeness flag matches the oracle's, that the heap is ordered under `KeepSmallest`, and that both hold the same sorted key/count set. |
| `a_lookup_reads_the_key_at_every_position_in_a_bucket` | A bucket naming two positions is answered by the key at each, not by the first position listed. | Seats `U64(11)` at `10` and `U64(22)` at `20` in a 4-slot `HHHeap`, rewrites `slots` so both positions carry `11`'s digest and lists that bucket as `[other, wanted]`, then verifies `find(&U64(11))` and `find_heap_item(&HeapItem::U64(11))` both return `11`'s own position and its count still reads `10`. |
### Common Structure Utilities
Test file: [`src/common/structure_utils.rs`](../src/common/structure_utils.rs)
| test_name | test_description | what_is_tested |
| --- | --- | --- |
| `median_test` | Median test. | For 1,000 seeded random arrays of lengths 3, 4, and 5, verifies `compute_median_inline_f64` exactly matches sort-based median for every case. |
| `the_skip_cursor_advances_by_one_per_draw_and_wraps_at_the_table_length` | The cursor advances one entry per draw, wraps at the table length, and folds an out-of-range value back in. | Verifies `Nitro::init_nitro(0.5)` draws once and leaves `cursor()` at `1`, that 4,096 `draw_geometric()` calls touch 4,096 distinct entries, that `PRECOMPUTED_SAMPLE_LEN - 1` further draws bring the cursor back to `0`, that `commit_ctx(usize::MAX, 0)` folds the cursor below `PRECOMPUTED_SAMPLE_LEN` (`65_536`) and a further draw does not panic, and that `init_nitro(1.0)` keeps `to_skip` at `0` and the cursor at `0` across 64 draws. |
| `the_geometric_skip_mean_matches_the_configured_rate` | The skip distances average `(1-p)/p` at the configured rate. | At rates `0.5`, `0.3`, `0.1`, `0.07`, and `0.01`, sums 20,000 successive `to_skip` values from `init_nitro(rate)` and verifies the mean is within `4 * sqrt((1-p)/p^2 / 20_000)` of `(1-p)/p`. |
| `stochastic_rounding_only_draws_where_the_reciprocal_is_not_an_integer` | An integer `1/p` emits a fixed weight without advancing the rounding stream; a fractional one dithers around `1/p`. | At rates `1.0`, `0.5`, `0.1`, and `0.01`, verifies 64 `admitted_delta()` calls all return `round(1/p)` and leave `rounding_state` unchanged; at `0.3` and `0.07`, verifies 50,000 draws contain both `floor(1/p)` and `floor(1/p) + 1` and that their mean is within `4 * sqrt(frac * (1 - frac) / 50_000)` of `1/p`. |
| `the_first_row_slot_is_admitted_with_probability_p` | The first row slot a sampler ever sees is admitted with probability `p`, not unconditionally. | At rates `0.5`, `0.3`, `0.1`, `0.07`, and `0.01`, runs 4,000 one-row `admit_rows(1, ..)` calls from independent seeds `1 + trial * 16`, verifies no call admits twice and any admission is row `0`, and that the mean admitted weight is within `4 * sqrt(((1-p)/p + p*r*(1-r)) / 4_000)` of `1` for `r = frac(1/p)`; a sampler admitting every first slot would read `1/p`. |
| `admit_rows_carries_the_skip_across_updates_and_admits_every_landing` | The skip carries across update boundaries, one update can admit several rows, and the cursor wraps mid-run. | For `(rate, start cursor)` pairs `(0.5, 0)`, `(0.25, 0)`, and `(0.5, PRECOMPUTED_SAMPLE_LEN - 4)`, verifies `init_nitro_seeded` leaves `cursor()` at `start + 1`, that each of 4,000 `admit_rows(8, ..)` calls reports exactly the `(row, weight)` list a hand replay of `PRECOMPUTED_SAMPLE` gives, that at least one update admits more than one row and at least one admits none, and that the third case's cursor has wrapped below its start. |
| `full_sampling_admits_every_row_at_unit_weight` | At `p = 1` every row is admitted at weight `1` and nothing carries between updates. | Verifies 16 successive `admit_rows(5, ..)` calls on `Nitro::init_nitro(1.0)` each report `[(0,1),(1,1),(2,1),(3,1),(4,1)]` and leave `to_skip` at `0`. |
| `the_admission_buffer_never_reaches_the_heap_within_the_supported_row_count` | The admission buffer stays inline at the largest supported row count. | At rates `1.0`, `0.9`, `0.5`, `0.3`, `0.07`, and `0.01` from seed `0x0117_0042`, runs 2,000 `admit_rows(MATRIX_MAX_ROWS, ..)` calls per rate and verifies `SmallVec::spilled()` is false after every one. |
| `an_oversized_skip_counter_does_not_overflow_the_admission_walk` | A skip counter near `usize::MAX` is absorbed rather than overflowing the walk. | After `commit_ctx(0, usize::MAX)` on a `p = 0.5` sampler, verifies `admit_rows(5, ..)` admits nothing and leaves `to_skip` at exactly `usize::MAX - 5`, then runs 64 `admit_rows(20, ..)` calls at rates `1e-12`, `1e-15`, and `f64::MIN_POSITIVE`, which assert nothing beyond not panicking. |
| `the_context_restores_the_rounding_stream_and_the_legacy_pair_does_not` | The full context continues the run; the legacy pair carries no rounding state. | At rates `0.3` and `0.07` from seed `0x0117_5EED`, runs 37 `admit_rows(5, ..)` calls and then verifies a fresh sampler under `restore_context(source.context())` emits exactly the admissions the uninterrupted clone emits over the next 64 updates, while one under `commit_ctx(legacy.0, legacy.2)` from `get_ctx()` emits a different sequence. |
### Vector2D (Common Structure)
Test file: [`src/common/structures/vector2d.rs`](../src/common/structures/vector2d.rs)
| test_name | test_description | what_is_tested |
| --- | --- | --- |
| `required_bits_match_expected_thresholds` | Required bits match expected thresholds. | Verifies `Vector2D::get_required_bits()` returns `64` for `(3,4096)`, `32` for `(3,64)`, and `128` for `(5,1_048_576)`. |
| `fast_insert_non_pow2_and_degenerate_cols_match_reference` | The cached-field fast insert lands where a shift-mask-modulo reference says, non-power-of-two and degenerate widths included. | For `3 x cols` `Vector2D<i64>` grids at `cols` of `1`, `17`, `100`, and `1000`, feeds 500 xorshift hashes (seeded `0x9E37_79B9_7F4A_7C15`) through `fast_insert` as `MatrixHashType::Packed64` and verifies `as_slice()` equals a reference array incremented at `((h >> (mask_bits * row)) & mask) % cols` for all three rows. |
### BitMatrix (Common Structure)
Test file: [`src/common/structures/bit_matrix.rs`](../src/common/structures/bit_matrix.rs)
| test_name | test_description | what_is_tested |
| --- | --- | --- |
| `every_cell_owns_exactly_one_bit` | Each cell owns one bit and no other cell's. | Across 33 geometries (`1`, `2`, and `5` rows by columns `1`, `2`, `7`, `63`, `64`, `65`, `100`, `127`, `128`, `129`, and `255`), sets every cell in turn and verifies it read clear beforehand, reads set afterwards, and that `count_ones` rises by exactly one each time, ending at `rows * cols` with a `fill_ratio` of `1.0`. |
| `row_padding_is_never_reachable_or_counted` | Rows are padded out to whole words and the padding never counts. | Over the same 33 geometries, fills every addressable cell and verifies `size_in_bytes` is `rows * cols.div_ceil(64) * 8` while `count_ones` is exactly `rows * cols`. |
| `put_and_clear_reset_individual_bits` | `put(.., false)` and `clear` both return the matrix to empty. | Over the same 33 geometries, sets every cell through `put(.., true)`, clears them one at a time through `put(.., false)` and verifies `count_ones` is `0` and `fill_ratio` is `0.0`, then sets the last cell and verifies `clear()` empties it again. |
| `a_column_past_the_last_one_panics_rather_than_aliasing` | A column past `cols` panics instead of landing in row padding. | Verifies `set(0, 100)` on a `3x100` matrix panics with "(0, 100) is outside a 3x100 bit matrix". |
| `a_column_reaching_the_next_row_panics` | A column that reaches the next row's words panics. | Verifies `set(0, 128)` on a `3x100` matrix panics with "(0, 128) is outside a 3x100 bit matrix" rather than aliasing row 1. |
| `a_row_past_the_last_one_panics` | A row past the last one panics. | Verifies `get(3, 0)` on a `3x100` matrix panics with "(3, 0) is outside a 3x100 bit matrix". |
| `put_checks_bounds_too` | `put` is bounds-checked like `set` and `get`. | Verifies `put(0, 120, true)` on a `2x100` matrix panics with "(0, 120) is outside a 2x100 bit matrix". |
| `union_takes_the_bitwise_or` | `union_from` is the bitwise or of the two grids. | Unions a `3x100` matrix holding `(0,5)` and `(1,99)` with one holding `(1,99)` and `(2,0)`, then verifies `count_ones` is `3` and all three cells read set. |
| `union_across_geometries_panics` | A union across geometries panics. | Verifies `union_from` between a `3x100` and a `3x101` matrix panics with "bit matrices must have the same dimensions". |
| `a_zero_dimension_is_rejected` | A zero dimension panics at construction. | Verifies `BitMatrix::new(0, 64)` panics with "a bit matrix needs both dimensions". |
| `a_round_trip_recomputes_the_derived_fields` | A decoded matrix folds hashes exactly as the original does. | Over the same 33 geometries, round-trips through `rmp-serde` and verifies the dimensions and every cell match, then drives one `hash_for_matrix` digest through `fast_insert` on both the original and the decoded matrix and verifies they set the same cells. |
| `a_payload_that_does_not_fit_its_dimensions_is_rejected` | A word count that disagrees with the dimensions fails at decode. | Verifies a `3x100` payload carrying 2 words is refused with "needs 6 words, got 2", one carrying 9 words is refused, and a zero-row payload is refused with "needs both dimensions". |
| `the_wire_form_carries_only_the_stored_fields` | The wire carries `words`, `rows`, and `cols` and nothing derived from them. | Verifies a fresh `3x100` matrix encodes byte for byte identically to a struct of just those three fields. |
| `a_packed_64_grid_decodes_a_distinct_window_per_row` | Each row of a packed-64 grid reads its own window of the hash. | For a `5x1024` `BitMatrix`, verifies `hash_mode_for_matrix(5, 1024)` is `MatrixHashMode::Packed64`, then `fast_insert`s 300 `U64` keys and verifies every pair of rows differs at some column; the per-row bit windows themselves are not compared. |
| `dimensions_whose_word_count_overflows_are_rejected` | Dimensions whose word count overflows fail at decode. | Verifies a crafted payload declaring `usize::MAX` rows by `128` columns with an empty `words` array is refused with an error containing "dimensions overflow". |
### Common Hash Spec
Test file: [`src/common/hashspec.rs`](../src/common/hashspec.rs)
| test_name | test_description | what_is_tested |
| --- | --- | --- |
| `seed_table_matches_sketchlib_go` | The seed table and the canonical seed index are pinned values. | Verifies `CANONICAL_HASH_SEED_TABLE` equals the twenty listed seeds (`0xcafe3553`, `0xade3415118`, through `0xdb0c2e0d`) in order, and that `CANONICAL_HASH_SEED` is `5`. |
| `hash_with_spec_matches_sketchlib_go` | The byte-key hash of one fixed key is a pinned value. | Verifies `hash_with_spec(&HashSpec::default(), b"projectasap")` is `887548862923853302`. |
| `derive_index_matches_go_bit_slicing` | `derive_index` slices the row's own window out of one hash. | For the `HashSpec::default()` hash of `b"projectasap"`, verifies `derive_index(&spec, row, h, 512)` is `(h >> (row * 9)) & 0x1ff` and `derive_index(&spec, row, h, 1024)` is `(h >> (row * 10)) & 0x3ff`, for rows `0..3` of each width. |
| `derive_sign_matches_go_high_bit` | `derive_sign` reads bit `63 - row` of the hash. | For the same hash, verifies `derive_sign(&spec, row, h)` is `1` where bit `63 - row` is set and `-1` where it is clear, for rows `0..5`. |
| `mask_bits_for_width_matches_go` | The mask width is the column count's bit length. | Verifies `mask_bits_for_width` returns `1` for `1` and for `2`, `2` for `4`, `9` for `512`, `10` for `1024`, and `12` for `4096`. |
| `default_hashspec_has_packed_derivation` | The default spec names packed derivation, the canonical index, and the full seed table. | Verifies `HashSpec::default()` carries `seed_derivation == SeedDerivation::Packed`, `canonical_seed_index == CANONICAL_HASH_SEED`, and a `seed_list` as long as `CANONICAL_HASH_SEED_TABLE`. |
### MatrixHashType (Common Structure)
Test file: [`src/common/structures/matrix_storage.rs`](../src/common/structures/matrix_storage.rs)
| test_name | test_description | what_is_tested |
| --- | --- | --- |
| `col_decode_matches_reference_for_all_dim_classes` | The column decode agrees with a shift-mask-modulo reference for every dimension class. | For columns `1, 2, 3, 5, 7, 8, 10, 100, 1000, 2048, 4096, 5003`, verifies `col_for_row(row, cols)` on `MatrixHashType::Packed64(0x0123_4567_89AB_CDEF)`, on a bare `u64` of the same value, on `MatrixHashType::Packed128(0x0011_2233_4455_6677_8899_AABB_CCDD_EEFF)`, and on a bare `u128` of that value each equal `((hash >> (mask_bits * row)) & mask) % cols`, over as many rows as the hash width admits (`64 / mask_bits` and `128 / mask_bits`, each clamped to `1..=6`). |
### ASAPv1 Envelope (MessagePack)
Test file: [`src/message_pack_format/envelope.rs`](../src/message_pack_format/envelope.rs)
| test_name | test_description | what_is_tested |
| --- | --- | --- |
| `round_trip_frames_metadata_and_payload` | `encode` frames the two blocks and `split` hands them back unchanged. | Verifies `encode(&[0x01, 0x03], b"meta-block", b"payload-bytes")` opens with `MAGIC`, carries `VERSION` at byte `6` and a `kind_id_len` of `2` at byte `7`, and that `split` returns the kind_id, metadata, and payload byte for byte. |
| `rejects_bad_magic_and_version` | A wrong magic byte and an unknown version both fail. | Verifies `split` accepts `encode(&[0x01, 0x01], b"m", b"p")`, then rejects the same bytes with byte `0` set to `b'X'`, and rejects them with the version byte `6` set to `0xFF`. |
| `rejects_truncation` | A truncated envelope fails rather than indexing past its slices. | Verifies `split` rejects `encode(&[0x01, 0x01], b"metadata", b"payload")` cut by its last byte, and rejects it cut to its first three bytes. |
## Integration Suites
One subsection per integration test binary under [`tests/`](../tests/); the component sections above cover the unit tests inside `src/`. A suite that spans several sketches is split by the concern each part drives, following the source file's own structure.
### Frequency: Count-Min and Count Sketch
Test file: [`tests/e2e_frequency.rs`](../tests/e2e_frequency.rs)
| test_name | test_description | what_is_tested |
| --- | --- | --- |
| `countmin_fast_path_zipf_conforms_to_the_count_min_model_and_merges_shards_exactly` | A single-pass sketch and a three-way shard merge both hold the Count-Min contract, and the merge is exact on every key. | Feeds `zipf_u64(100_000, 8192, 1.1, 1001)` into one `CountMin<Vector2D<i64>, FastPath>` at `4x4096` and, round-robin on the arrival index, into three shards of the same shape, then merges shard C into B and B into A. Runs `CountMinSpec::new(4, 4096).assert_contract` over `estimate` for both the single-pass and the merged sketch: one-sidedness `est >= f` and the simultaneous `b*(N-f)/w` bound at `delta = 1e-3` tolerate zero violations, and the marginal `e*(N-f)/w` bound is pinned as a violation rate at `e^-4`. Then verifies `single.estimate` equals `shard_a.estimate` exactly on every one of `FreqTruth`'s distinct keys. |
| `countmin_vecbased_error_bound` | Count-Min's contract holds on both insert paths across the growable-storage geometry sweep. | For each of the 15 shapes in rows `{3,5,7}` by cols `{2048, 4096, 8192, 16384, 32768}`, inserts `zipf_u64(20_000, 512, 1.2, 1002)` into `CountMin<Vector2D<i64>, RegularPath>` and `CountMin<Vector2D<i64>, FastPath>` built by `with_dimensions`, and runs `CountMinSpec::assert_contract` at that shape on each of the two (30 contract runs): one-sidedness and the simultaneous `b*(N-f)/w` bound at `delta = 1e-3` with zero violations, and the marginal `e*(N-f)/w` bound as a rate pin at `e^-d`. |
| `count_vecbased_error_bound` | Count Sketch's L2 contract holds on both insert paths across the growable-storage geometry sweep. | The same 15 shapes in rows `{3,5,7}` by cols `{2048, 4096, 8192, 16384, 32768}` and the same `zipf_u64(20_000, 512, 1.2, 1002)` stream, into `Count<Vector2D<i64>, RegularPath>` and `Count<Vector2D<i64>, FastPath>`, checked with `CountSketchSpec::assert_contract` (30 runs): the simultaneous `sqrt(kappa/w)` residual-L2 band at the kappa union-bounded to `delta = 1e-3` over the probed keys tolerates zero violations, and the marginal band at `kappa = 3` is pinned as a rate at `P[Bin(d, 1/3) >= ceil(d/2)]`. |
| `countmin_matbased_error_bound` | Count-Min's contract holds on the compile-time matrices at every documented shape. | Builds `CountMin::from_storage` over `FixMat1`..`FixMat15` on both `RegularPath` and `FastPath` (30 contract runs), feeds each `zipf_u64(20_000, 512, 1.2, 1002)`, and runs `CountMinSpec::assert_contract` with the spec dimensions matched to the matrix: `FixMat1..3` at `(3,2048)`/`(5,2048)`/`(7,2048)`, `FixMat4..6` at 4096, `FixMat7..9` at 8192, `FixMat10..12` at 16384, `FixMat13..15` at 32768. |
| `count_matbased_error_bound` | Count Sketch's L2 contract holds on the compile-time matrices at every documented shape. | Builds `Count::from_storage` over `FixMat1`..`FixMat15` on both `RegularPath` and `FastPath` (30 contract runs) with the same `zipf_u64(20_000, 512, 1.2, 1002)` stream, and runs `CountSketchSpec::assert_contract` at the matrix's own `(rows, cols)` - `FixMat1..3` at 2048 columns, then 4096, 8192, 16384 and 32768 columns for each of 3, 5 and 7 rows. |
| `countmin_regular_path_satisfies_the_count_min_theorem` | Count-Min's theorem holds on the `RegularPath` over independent key populations and both hashing domains. | Over 3 trials, each supplying the two `bound_streams` shapes at `n = 120_000` - zipf(1.1) over a 8192-key domain seeded `1005 + trial*977` and offset by `trial*100_000`, presented as `DataInput::U64`, and uniform over 4096 values seeded `1006 + trial*977` mapped to distinct `f64` in `[100, 1000)` and presented as `DataInput::F64` - inserts into a fresh `CountMin<Vector2D<i32>, RegularPath>` at `3x4096` and runs `CountMinSpec::new(3, 4096).assert_contract` per trial and shape (6 runs): one-sidedness and the simultaneous bound with zero violations, marginal `e*(N-f)/w` as a rate pin at `e^-3`. |
| `countmin_fast_path_conforms_to_the_count_min_model` | The `FastPath`, whose row indices are sliced from one 128-bit hash, conforms to the same Count-Min arithmetic. | The same 3 trials by 2 `bound_streams` shapes at `n = 120_000` and the same `3x4096` geometry, into `CountMin<Vector2D<i32>, FastPath>`, with `CountMinSpec::new(3, 4096).assert_contract` run per trial and shape (6 runs) at unwidened bounds: zero violations for one-sidedness and the simultaneous `b*(N-f)/w` bound at `delta = 1e-3`, and the marginal rate at `e^-3`. |
| `countsketch_both_paths_meet_the_l2_median_bound` | Count Sketch's L2 median bound holds on both insert paths and both hash domains, pooled over independent key populations. | Inserts each of the 3 trials by 2 `bound_streams` shapes (`n = 120_000`) into `Count<Vector2D<i32>, RegularPath>` and `Count<Vector2D<i32>, FastPath>` at `3x4096`, accumulating through `CountSketchSpec::tally_into` into one simultaneous and one marginal `Tally` per `shape/path` label, so all three trials pool into a single acceptance decision for each of the four labels. Per label, asserts zero violations of the simultaneous `sqrt(kappa/w)` residual-L2 band at the kappa union-bounded to `delta = 1e-3`, and a marginal violation rate at `kappa = 3` no greater than `P[Bin(3, 1/3) >= 2]`. |
| `countsketch_error_stays_rank_independent_within_the_documented_empirical_band` | Count Sketch's mean absolute error stays within a 3x spread across frequency deciles. | Inserts `zipf_u64(200_000, 8192, 1.1, 1007)` into `Count<Vector2D<i64>, RegularPath>` at `5x4096`, sorts the exact `FreqTruth` pairs by count, cuts them into 10 equal deciles of `distinct/10` keys each (the remainder is dropped), and takes the mean of `abs(estimate - true)` per decile. The only assertion is `hi <= lo * 3.0` on those ten means; the individual decile means are not pinned, and no per-key bound is checked here. |
### Frequency: CountL2HH
Test file: [`tests/e2e_frequency.rs`](../tests/e2e_frequency.rs)
| test_name | test_description | what_is_tested |
| --- | --- | --- |
| `countl2hh_weighted_turnstile_satisfies_the_l2_median_bound` | CountL2HH's point estimates obey the Count Sketch L2 bound and its `get_l2_sqr` tracks F2 within the AMS bound under a weighted turnstile stream. | Builds `CountL2HH::<DefaultXxHasher>::with_dimensions_and_seed(4, 2048, 11)`, feeds `zipf_u64(30_000, 512, 1.3, 1005)` through `fast_insert_with_count` at weights `1 + (i % 5)`, then applies a `-10` decrement to the hottest key from `truth.top_k(1)`. Asserts `CountSketchSpec::new(4, 2048).assert_contract` over `fast_get_est` (zero violations of the simultaneous `sqrt(kappa/w)` residual-L2 band at `delta = 1e-3`, marginal rate at `kappa = 3` no greater than `P[Bin(4, 1/3) >= 2]`), and that `SecondMomentSpec::new(4, 2048).check(get_l2_sqr(), truth.f2())` holds, i.e. the F2 relative error is at most `sqrt(2*3/2048)` (about `0.0541`). |
### Frequency: FoldCMS and FoldCS
Test file: [`tests/e2e_frequency.rs`](../tests/e2e_frequency.rs)
| test_name | test_description | what_is_tested |
| --- | --- | --- |
| `fold_cms_foldcs_counts_and_hierarchical_merge` | Weighted counts are exact on sparse dimensions and survive a same-level merge, a signed update, and a hierarchical merge. | On `FoldCMS::<DefaultXxHasher>::new(3, 2048, 0, 32)` sketches: 100 inserts of `Str("alpha")` at weight 2 into each of two sketches plus 100 of `Str("beta")` at weight 1 into the second, verifying `query` reads `200`, `200` and `100`; after `merge_same_level`, `400` for alpha and `100` for beta. On `FoldCS::<DefaultXxHasher>::new(3, 2048, 0, 32)`, `Str("gamma")` at `+60` then `-20` is verified to query `40`. Finally `FoldCMS::hierarchical_merge` of two sketches built by `build_fold_cms` (30 and 45 inserts at weight 3) is verified to query `90` and `135`. |
| `folded_sketches_keep_their_own_bounds_through_a_sixteen_way_merge` | Folded sketches keep their own theorems, evaluated at the folded width, through a sixteen-way hierarchical merge. | Splits `zipf_u64(240_000, 10_000, 1.1, 1009)` into 16 windows of 15,000, giving each window a `FoldCMS` and a `FoldCS` of `3x4096` at `fold_level = 4` and `top_k = 20`, then `hierarchical_merge`s each family. Asserts `CountMinSpec::new(3, 256)` over `FoldCMS::query` and `CountSketchSpec::new(3, 256)` over `FoldCS::query` - the bounds are evaluated at the folded width `4096 >> 4 = 256`, not the unfolded 4096 - with the specs' usual rules: zero violations for one-sidedness and both simultaneous bounds at `delta = 1e-3`, and the marginal bounds as rate pins at `e^-3` and `P[Bin(3, 1/3) >= 2]`. |
### Frequency: Portable Count-Min and Count Sketch
Test file: [`tests/e2e_frequency.rs`](../tests/e2e_frequency.rs)
| test_name | test_description | what_is_tested |
| --- | --- | --- |
| `portable_cms_and_cs_string_keys_satisfy_their_own_bounds` | The portable wire twins satisfy their own theorems over string keys with no extra slack. | Feeds `zipf_u64(50_000, 2048, 1.1, 1006)` as string keys `"k{k}"` through `update(&key, 1.0)` into `portable::countminsketch::CountMinSketch::new(3, 4096)` and `portable::countsketch::CountSketch::new(5, 4096)`, then asserts `CountMinSpec::new(3, 4096).assert_contract` over the portable Count-Min's `estimate` and `CountSketchSpec::new(5, 4096).assert_contract` over the portable Count Sketch's `estimate`, against a `FreqTruth` keyed on the underlying `i64` identities. |
### Frequency: Documented Input Matrix
Test file: [`tests/e2e_frequency.rs`](../tests/e2e_frequency.rs)
| test_name | test_description | what_is_tested |
| --- | --- | --- |
| `countmin_input_{1..12}_grid_satisfies_the_count_min_model` | Each documented input holds Count-Min's contract over the whole documented `(row, column)` grid on both storage backends and both hash paths. | One test per documented input id, each calling `countmin_documented_matrix(id)`: `common::inputs::key_input(id)` supplies the stream and its exact `FreqTruth`, then `countmin_documented_vector_grid` sweeps rows `{3,5,7}` by cols `{2_048, 4_096, 8_192, 16_384, 32_768}` on `CountMin<Vector2D<i64>, RegularPath>` and `CountMin<Vector2D<i64>, FastPath>`, and `countmin_documented_fixed_grid` sweeps the same 15 shapes as the compile-time matrices `FixMat1`..`FixMat15` via `from_storage` on both paths - 60 `CountMinSpec::assert_contract` runs per test, each at its own cell's `(rows, cols)`, so every run checks zero violations of one-sidedness and of the simultaneous `b*(N-f)/w` bound at `delta = 1e-3` plus a marginal `e*(N-f)/w` rate pin at `e^-d`. Generated names and their input ids: `countmin_input_1_grid_satisfies_the_count_min_model` (1, 100K uniform `i64` over `[0, 10M)`), `countmin_input_2_grid_satisfies_the_count_min_model` (2, 1M uniform `i64`), `countmin_input_3_grid_satisfies_the_count_min_model` (3, 100K zipf(1.1) `i64` over 4,096 keys), `countmin_input_4_grid_satisfies_the_count_min_model` (4, 1M zipf(1.1) over 4,096 keys), `countmin_input_5_grid_satisfies_the_count_min_model` (5, 100K zipf(1.1) `i64` over 20,000 keys), `countmin_input_6_grid_satisfies_the_count_min_model` (6, 1M zipf(1.1) over 20,000 keys), `countmin_input_7_grid_satisfies_the_count_min_model` (7), `countmin_input_8_grid_satisfies_the_count_min_model` (8), `countmin_input_9_grid_satisfies_the_count_min_model` (9), `countmin_input_10_grid_satisfies_the_count_min_model` (10), `countmin_input_11_grid_satisfies_the_count_min_model` (11) and `countmin_input_12_grid_satisfies_the_count_min_model` (12) - ids 7 to 12 being the same six shapes drawn identically and presented as `DataInput::F64` bit patterns. Every stream is seeded `0x1_0000_0000 + id * 0x9E37_79B9`. |
| `countsketch_input_{1..12}_grid_satisfies_the_l2_bound` | Each documented input holds Count Sketch's L2 bound over the whole documented `(row, column)` grid on both storage backends and both hash paths. | One test per documented input id, each calling `countsketch_documented_matrix(id)`: the same `common::inputs::key_input(id)` stream and truth, then `countsketch_documented_vector_grid` over rows `{3,5,7}` by cols `{2_048, 4_096, 8_192, 16_384, 32_768}` on `Count<Vector2D<i64>, RegularPath>` and `Count<Vector2D<i64>, FastPath>`, and `countsketch_documented_fixed_grid` over `FixMat1`..`FixMat15` via `from_storage` on both paths - 60 `CountSketchSpec::assert_contract` runs per test at each cell's own `(rows, cols)`, every run requiring zero violations of the simultaneous `sqrt(kappa/w)` residual-L2 band at the kappa union-bounded to `delta = 1e-3` and a marginal violation rate at `kappa = 3` no greater than `P[Bin(d, 1/3) >= ceil(d/2)]`. Generated names and their input ids: `countsketch_input_1_grid_satisfies_the_l2_bound` (1, 100K uniform `i64` over `[0, 10M)`), `countsketch_input_2_grid_satisfies_the_l2_bound` (2, 1M uniform `i64`), `countsketch_input_3_grid_satisfies_the_l2_bound` (3, 100K zipf(1.1) over 4,096 keys), `countsketch_input_4_grid_satisfies_the_l2_bound` (4, 1M zipf(1.1) over 4,096 keys), `countsketch_input_5_grid_satisfies_the_l2_bound` (5, 100K zipf(1.1) over 20,000 keys), `countsketch_input_6_grid_satisfies_the_l2_bound` (6, 1M zipf(1.1) over 20,000 keys), `countsketch_input_7_grid_satisfies_the_l2_bound` (7), `countsketch_input_8_grid_satisfies_the_l2_bound` (8), `countsketch_input_9_grid_satisfies_the_l2_bound` (9), `countsketch_input_10_grid_satisfies_the_l2_bound` (10), `countsketch_input_11_grid_satisfies_the_l2_bound` (11) and `countsketch_input_12_grid_satisfies_the_l2_bound` (12) - ids 7 to 12 carrying the same six shapes as `DataInput::F64` keys, each stream seeded `0x1_0000_0000 + id * 0x9E37_79B9`. |
| `countl2hh_input_{3,4,5,6,9,10,11,12}_weighted_turnstile_holds_its_bounds` | Each skewed documented input holds CountL2HH's point-estimate bound, the documented 2% on the hottest key after its decrement, and the documented 10% on F2. | One test per skewed documented input id, each calling `countl2hh_documented_input(id)`: builds `CountL2HH::<DefaultXxHasher>::with_dimensions_and_seed(4, 2_048, 11)`, feeds the input's keys through `fast_insert_with_count` at weights `1 + (i % 5)`, then applies a decrement of `-(truth.get(hot) / 10)` to the hottest key. Four assertions follow: `CountSketchSpec::new(4, 2048).assert_contract` over `fast_get_est` (zero violations of the simultaneous residual-L2 band at `delta = 1e-3`, marginal rate at `kappa = 3` no greater than `P[Bin(4, 1/3) >= 2]`); the hottest key's relative error at most `0.02`; `get_l2_sqr`'s relative error against `truth.f2()` at most `0.10`; and `SecondMomentSpec::new(4, 2048).check`, i.e. that same F2 relative error also within `sqrt(2*3/2048)` (about `0.0541`). Generated names and their input ids: `countl2hh_input_3_weighted_turnstile_holds_its_bounds` (3, 100K zipf(1.1) `i64` over 4,096 keys), `countl2hh_input_4_weighted_turnstile_holds_its_bounds` (4, 1M zipf(1.1) over 4,096 keys), `countl2hh_input_5_weighted_turnstile_holds_its_bounds` (5, 100K zipf(1.1) `i64` over 20,000 keys), `countl2hh_input_6_weighted_turnstile_holds_its_bounds` (6, 1M zipf(1.1) over 20,000 keys), `countl2hh_input_9_weighted_turnstile_holds_its_bounds` (9), `countl2hh_input_10_weighted_turnstile_holds_its_bounds` (10), `countl2hh_input_11_weighted_turnstile_holds_its_bounds` (11) and `countl2hh_input_12_weighted_turnstile_holds_its_bounds` (12) - ids 9 to 12 being the `f64`-keyed twins of 3 to 6. The four uniform inputs (1, 2, 7, 8) are not in this family. |
### Cardinality: Batteries
Test file: [`tests/e2e_cardinality.rs`](../tests/e2e_cardinality.rs)
| test_name | test_description | what_is_tested |
| --- | --- | --- |
| `hll_{classic,ertl_mle,hip}_p{12,14,16}_satisfies_..._error_model` | Each core HLL alias tracks the true cardinality inside its own estimator's `z = 4` band, ignores replayed identities, and reproduces a single pass from disjoint shards. | One `hll_battery!` body per invocation, over `CHECKPOINTS = [10, 100, 1_000, 10_000, 100_000, 1_000_000, 10_000_000]`. A fresh sketch per checkpoint is fed `DataInput::U64(base + k)` from its own namespace `base = (1 << 40) * (i + 1)`, and each `estimate()` goes through `CardinalityConfidenceSpec::check` at `z = 4.0`: relative band `4 * 1.04/sqrt(m)` for the `hll` model, `4 * sqrt(ln 2 / m)` for `hll_hip`. Then re-inserting the first `min(target, 200_000)` already-seen identities must leave `estimate()` bit-identical (`assert_eq!`). Then over a fresh `200_000`-identity namespace, an even/odd shard merge must give `registers_as_slice()` and `estimate()` equal to the single pass. Invocations: `hll_classic_p12_satisfies_its_register_error_model` (`HyperLogLogP12<Classic>`, `hll`, mergeable), `hll_classic_p14_satisfies_its_register_error_model` (`HyperLogLogP14<Classic>`), `hll_classic_p16_satisfies_its_register_error_model` (`HyperLogLogP16<Classic>`), `hll_ertl_mle_p12_satisfies_the_cramer_rao_error_model` (`HyperLogLogP12<ErtlMLE>`), `hll_ertl_mle_p14_satisfies_the_cramer_rao_error_model` (`HyperLogLogP14<ErtlMLE>`), `hll_ertl_mle_p16_satisfies_the_cramer_rao_error_model` (`HyperLogLogP16<ErtlMLE>`), `hll_hip_p12_satisfies_the_hip_error_model` (`HyperLogLogHIPP12`, `hll_hip`, not_mergeable), `hll_hip_p14_satisfies_the_hip_error_model` (`HyperLogLogHIPP14`), `hll_hip_p16_satisfies_the_hip_error_model` (`HyperLogLogHIPP16`). The three `not_mergeable` HIP invocations still build and fill the three `200_000`-identity shard sketches but assert nothing about them. |
| `hll_{classic,ertl_mle,hip}_custom_p{10..18}_satisfies_..._error_model` | Every custom register geometry from p10 to p18 holds its estimator's `z = 4` band over its own checkpoint grid, is unmoved by a replay, and merges shard-for-shard. | The same `hll_battery!` body as the core aliases (fresh sketch per checkpoint on namespace `(1 << 40) * (i + 1)`, `CardinalityConfidenceSpec::check` at `z = 4.0`, replay of `min(target, 200_000)` identities asserted bit-identical, `200_000`-identity even/odd merge asserted equal to the single pass register for register), but over `HyperLogLogImpl<Classic, HllRegP{n}>` (`hll`, mergeable), `HyperLogLogImpl<ErtlMLE, HllRegP{n}>` (`hll`, mergeable) and `HyperLogLogHIPImpl<HllRegP{n}>` (`hll_hip`, not_mergeable, so its merge block asserts nothing), each with the precision's own checkpoints: p10 `[100, 1_000, 20_000, 200_000]` for `hll_classic_custom_p10_satisfies_its_register_error_model`, `hll_ertl_mle_custom_p10_satisfies_the_cramer_rao_error_model`, `hll_hip_custom_p10_satisfies_the_hip_error_model`; p11 `[200, 2_000, 40_000, 200_000]` for `hll_classic_custom_p11_satisfies_its_register_error_model`, `hll_ertl_mle_custom_p11_satisfies_the_cramer_rao_error_model`, `hll_hip_custom_p11_satisfies_the_hip_error_model`; p12 `[400, 4_000, 50_000, 300_000]` for `hll_classic_custom_p12_satisfies_its_register_error_model`, `hll_ertl_mle_custom_p12_satisfies_the_cramer_rao_error_model`, `hll_hip_custom_p12_satisfies_the_hip_error_model`; p13 `[1_000, 10_000, 100_000, 500_000]` for `hll_classic_custom_p13_satisfies_its_register_error_model`, `hll_ertl_mle_custom_p13_satisfies_the_cramer_rao_error_model`, `hll_hip_custom_p13_satisfies_the_hip_error_model`; p14 `[2_000, 16_000, 200_000, 800_000]` for `hll_classic_custom_p14_satisfies_its_register_error_model`, `hll_ertl_mle_custom_p14_satisfies_the_cramer_rao_error_model`, `hll_hip_custom_p14_satisfies_the_hip_error_model`; p15 `[4_000, 32_000, 300_000, 1_000_000]` for `hll_classic_custom_p15_satisfies_its_register_error_model`, `hll_ertl_mle_custom_p15_satisfies_the_cramer_rao_error_model`, `hll_hip_custom_p15_satisfies_the_hip_error_model`; p16 `[5_000, 60_000, 500_000, 1_200_000]` for `hll_classic_custom_p16_satisfies_its_register_error_model`, `hll_ertl_mle_custom_p16_satisfies_the_cramer_rao_error_model`, `hll_hip_custom_p16_satisfies_the_hip_error_model`; p17 `[10_000, 100_000, 800_000, 1_500_000]` for `hll_classic_custom_p17_satisfies_its_register_error_model`, `hll_ertl_mle_custom_p17_satisfies_the_cramer_rao_error_model`, `hll_hip_custom_p17_satisfies_the_hip_error_model`; p18 `[10_000, 100_000, 1_500_000]` for `hll_classic_custom_p18_satisfies_its_register_error_model`, `hll_ertl_mle_custom_p18_satisfies_the_cramer_rao_error_model`, `hll_hip_custom_p18_satisfies_the_hip_error_model`. |
| `portable_hll_variants_and_precisions_satisfy_the_register_error_model` | Every portable wire variant and precision holds the register error model and merges by register-wise maximum. | For each of `HllVariant::Regular`, `HllVariant::Datafusion`, `HllVariant::Hip` crossed with precisions `12`, `14`, `16`, draws its own stream `uniform_u64(200_000, u64::MAX / 4, seed)` with `seed = 2001 + (v * 3 + p)`, feeds `HllSketch::update` with `to_be_bytes()`, and checks `HllSketch::estimate()` against the `HashSet` distinct count via `CardinalityConfidenceSpec::hll(precision, 4.0)` — all three tags are held to `4 * 1.04/sqrt(m)`, since `estimate()` runs the same register formula for each. Then `merge` of a second sketch built over the same distinct identities must leave `estimate()` unchanged, and an even/odd shard merge of the same stream must give exactly that same `estimate()`. |
| `hll_accuracy_improves_with_precision_as_the_error_model_predicts` | A larger precision actually buys accuracy, and the measured RSE stays near the predicted `1.04/sqrt(m)`. | Measures the RMS relative error of `HyperLogLogP12<Classic>`, `HyperLogLogP14<Classic>` and `HyperLogLogP16<Classic>` over `BLOCKS = 6` disjoint blocks of `N = 1_000_000` identities (`DataInput::U64(b * N + i)`), asserts each measured RSE is `<= 2.0 *` `CardinalityConfidenceSpec::hll(p, 4.0).sigma_rel()`, and asserts the p12 RSE is at least `2.0x` the p16 RSE; the model's predicted 4x improvement is not asserted, only 2x. |
| `hll_classic_switchover_band_stays_within_the_documented_empirical_band` | The Classic estimator's error at the linear-counting switchover stays inside a 1.5x-to-10x empirical band around the asymptotic RSE. | For `HyperLogLogP12/P14/P16<Classic>` at `n = 2.5m` (`10_240`, `40_960`, `163_840`), computes the RMS relative error over `BLOCKS = 6` disjoint blocks (identities `b * 20_000_000 + i`) and forms `ratio = rse / (1.04/sqrt(m))` from `CardinalityConfidenceSpec::hll(p, 4.0).sigma_rel()`; asserts `ratio <= 10.0` and `ratio >= 1.5`, so both a widened cliff and a vanished one fail. |
| `set_aggregator_union_is_exact` | A `SetAggregator` union keeps every member exactly. | Feeds `uniform_u64(20_000, 500, 2002)` as `member-{k}` strings into `SetAggregator::update`, merges a second aggregator holding `extra-a` and `extra-b`, then asserts `agg.values.len()` equals the length of a parallel `HashSet` of the same members and that `agg.values` contains every one of them; the distinct count is compared against the in-test truth set rather than a pinned number. |
| `custom_precision_accuracy_improves_with_precision_as_the_error_model_predicts` | A higher custom precision does not lose to a lower one on the same stream. | Feeds the same `N = 200_000` identities from `BASE = (1 << 40) * 41` into `HyperLogLogImpl<Classic, HllRegP10>`, `<Classic, HllRegP13>` and `<Classic, HllRegP18>` and asserts only the two orderings `e18 <= e10` and `e18 <= e13` on absolute relative error; no error band is asserted, p10 against p13 is not compared, and with one trial per precision no error ratio is pinned. |
| `a_custom_precision_merge_reproduces_the_single_pass_registers_for_every_estimator` | A shard merge at a custom precision reproduces the single pass exactly, for both register estimators. | Over `N = 120_000` identities from `BASE = (1 << 40) * 42` split even/odd by `k % 2`, builds single/even/odd `HyperLogLogImpl<Classic, HllRegP13>` and `HyperLogLogImpl<ErtlMLE, HllRegP13>`, calls `merge`, and asserts for each estimator that the merged `registers_as_slice()` equals the single pass's and that `estimate()` is equal too. |
| `a_set_aggregator_delta_describes_the_change_and_survives_the_wire` | A `DeltaResult` over two set snapshots survives the MessagePack wire and replays into the later snapshot. | Builds `SetAggregator`s over `["web", "api", "db", "cache"]` and `["web", "api", "queue"]`, forms a `DeltaResult` from the two `HashSet::difference` results, and asserts `added == {"queue"}` and `removed == {"db", "cache"}` (these two pin the test's own set arithmetic, not a library call); then `to_msgpack` / `DeltaResult::from_msgpack` must return both sets unchanged, applying the decoded delta to the earlier aggregator must reproduce `after.values`, and an all-empty `DeltaResult` must round-trip still empty. |
### Cardinality: Duplicate-Heavy Zipf Streams
Test file: [`tests/e2e_cardinality.rs`](../tests/e2e_cardinality.rs)
| test_name | test_description | what_is_tested |
| --- | --- | --- |
| `hll_{classic,ertl_mle,hip}_zipf_p{10..18}_satisfies_..._error_model` | On skewed streams every HLL precision estimates the distinct count rather than the arrival count, and duplicates change nothing. | One `hll_zipf_battery!` body per invocation, run over two shared `OnceLock` streams from `build_zipf`: `small` = `zipf_u64(60_000 draws, 1_500 domain, 1.05, seed 4001)` offset by `(1 << 40) * 51` (1,495 distinct, 40x duplication) and `large` = `zipf_u64(5_000_000 draws, 1_800_000 domain, 0.6, seed 4002)` offset by `(1 << 40) * 52` (1,491,155 distinct, 3.4x). Per stream it first guards that the distinct count `n` satisfies `n < 2m` or `n > 4m` so the register model applies, then checks `estimate()` against `n` via `CardinalityConfidenceSpec::check` at `z = 4.0` (`4 * 1.04/sqrt(m)` for `hll`, `4 * sqrt(ln 2 / m)` for `hll_hip`), then asserts `estimate()` over the full arrival stream equals `estimate()` over the first-appearance-only stream exactly, and finally that replaying every draw again leaves `estimate()` unchanged. Invocations: p10 over `HyperLogLogImpl<Classic, HllRegP10>` / `<ErtlMLE, HllRegP10>` / `HyperLogLogHIPImpl<HllRegP10>` for `hll_classic_zipf_p10_satisfies_its_register_error_model`, `hll_ertl_mle_zipf_p10_satisfies_the_cramer_rao_error_model`, `hll_hip_zipf_p10_satisfies_the_hip_error_model`; and the same three types per precision for p11 (`hll_classic_zipf_p11_satisfies_its_register_error_model`, `hll_ertl_mle_zipf_p11_satisfies_the_cramer_rao_error_model`, `hll_hip_zipf_p11_satisfies_the_hip_error_model`), p12 (`hll_classic_zipf_p12_satisfies_its_register_error_model`, `hll_ertl_mle_zipf_p12_satisfies_the_cramer_rao_error_model`, `hll_hip_zipf_p12_satisfies_the_hip_error_model`), p13 (`hll_classic_zipf_p13_satisfies_its_register_error_model`, `hll_ertl_mle_zipf_p13_satisfies_the_cramer_rao_error_model`, `hll_hip_zipf_p13_satisfies_the_hip_error_model`), p14 (`hll_classic_zipf_p14_satisfies_its_register_error_model`, `hll_ertl_mle_zipf_p14_satisfies_the_cramer_rao_error_model`, `hll_hip_zipf_p14_satisfies_the_hip_error_model`), p15 (`hll_classic_zipf_p15_satisfies_its_register_error_model`, `hll_ertl_mle_zipf_p15_satisfies_the_cramer_rao_error_model`, `hll_hip_zipf_p15_satisfies_the_hip_error_model`), p16 (`hll_classic_zipf_p16_satisfies_its_register_error_model`, `hll_ertl_mle_zipf_p16_satisfies_the_cramer_rao_error_model`, `hll_hip_zipf_p16_satisfies_the_hip_error_model`), p17 (`hll_classic_zipf_p17_satisfies_its_register_error_model`, `hll_ertl_mle_zipf_p17_satisfies_the_cramer_rao_error_model`, `hll_hip_zipf_p17_satisfies_the_hip_error_model`) and p18 (`hll_classic_zipf_p18_satisfies_its_register_error_model`, `hll_ertl_mle_zipf_p18_satisfies_the_cramer_rao_error_model`, `hll_hip_zipf_p18_satisfies_the_hip_error_model`). |
### Cardinality: Documented Input Matrix
Test file: [`tests/e2e_cardinality.rs`](../tests/e2e_cardinality.rs)
| test_name | test_description | what_is_tested |
| --- | --- | --- |
| `hll_p{10..18}_over_the_documented_inputs_holds_its_error_model` | Every estimator at every precision holds both the flat documented band and its own `z = 4` band over all twelve documented inputs, and merges by register-wise maximum. | One `documented_hll_matrix!` body per precision, looping over `KEY_INPUT_IDS` `1..=12` from `common::inputs::key_input` (100K and 1M draws, uniform `[0, 10M)` and Zipf(1.1) over 4096- and 20000-key domains, `I64` for ids 1-6 and the mirrored `F64` twins for 7-12). For each input it builds `HyperLogLogImpl<Classic, HllRegP{n}>`, `HyperLogLogImpl<ErtlMLE, HllRegP{n}>` and `HyperLogLogHIPImpl<HllRegP{n}>` over every key, then checks each `estimate()` against the input's exact distinct count twice: through `CardinalityConfidenceSpec::hll(p, 4.0)` for Classic and ErtlMLE and `::hll_hip(p, 4.0)` for HIP, and against the flat `documented_band(p)` of `0.13` at p10-p12, `0.046` at p13-p14 and `0.023` at p15-p18. It then replays every key into the Classic sketch and asserts `estimate()` does not move, and asserts an even/odd shard merge of Classic reproduces the single pass's `registers_as_slice()`. Invocations: `hll_p10_over_the_documented_inputs_holds_its_error_model` (`HllRegP10`), `hll_p11_over_the_documented_inputs_holds_its_error_model` (`HllRegP11`), `hll_p12_over_the_documented_inputs_holds_its_error_model` (`HllRegP12`), `hll_p13_over_the_documented_inputs_holds_its_error_model` (`HllRegP13`), `hll_p14_over_the_documented_inputs_holds_its_error_model` (`HllRegP14`), `hll_p15_over_the_documented_inputs_holds_its_error_model` (`HllRegP15`), `hll_p16_over_the_documented_inputs_holds_its_error_model` (`HllRegP16`), `hll_p17_over_the_documented_inputs_holds_its_error_model` (`HllRegP17`), `hll_p18_over_the_documented_inputs_holds_its_error_model` (`HllRegP18`). |
| `set_aggregator_input_{1..12}_is_exact` | `SetAggregator` is exact on distinct count, membership, replay and shard merge for every documented input. | One test per input id, each calling `set_aggregator_documented_input(id)`, which inserts every key of `key_input(id)` as `m{key}` and asserts `agg.values.len()` equals the `HashSet` distinct count of the input's keys, that every `m{key}` is present, that the never-streamed member `m-1` is absent, that replaying the whole stream leaves the length unchanged, and that an even/odd shard `merge` yields both the same length and a set equal to the single pass's. Generated names and their input ids: `set_aggregator_input_1_is_exact` (1), `set_aggregator_input_2_is_exact` (2), `set_aggregator_input_3_is_exact` (3), `set_aggregator_input_4_is_exact` (4), `set_aggregator_input_5_is_exact` (5), `set_aggregator_input_6_is_exact` (6), `set_aggregator_input_7_is_exact` (7), `set_aggregator_input_8_is_exact` (8), `set_aggregator_input_9_is_exact` (9), `set_aggregator_input_10_is_exact` (10), `set_aggregator_input_11_is_exact` (11), `set_aggregator_input_12_is_exact` (12). |
| `univmon_input_{1..12}_recovers_its_cardinality` | UnivMon reports an exact L1 and a cardinality within 30% for every documented input. | One test per input id, each calling `univmon_documented_cardinality(id)`, which builds `UnivMon::init_univmon(32, 5, 2_048, 16)` (heap 32, `5x2048` counters, 16 layers), inserts every key of `key_input(id)` with weight `1`, asserts `calc_l1()` equals `input.keys.len() as f64` exactly, and asserts `calc_card()` is within `CARDINALITY_BAND = 0.30` relative of the input's exact distinct count. Generated names and their input ids: `univmon_input_1_recovers_its_cardinality` (1), `univmon_input_2_recovers_its_cardinality` (2), `univmon_input_3_recovers_its_cardinality` (3), `univmon_input_4_recovers_its_cardinality` (4), `univmon_input_5_recovers_its_cardinality` (5), `univmon_input_6_recovers_its_cardinality` (6), `univmon_input_7_recovers_its_cardinality` (7), `univmon_input_8_recovers_its_cardinality` (8), `univmon_input_9_recovers_its_cardinality` (9), `univmon_input_10_recovers_its_cardinality` (10), `univmon_input_11_recovers_its_cardinality` (11), `univmon_input_12_recovers_its_cardinality` (12). |
| `a_pyramid_too_shallow_for_the_stream_cannot_recover_its_cardinality` | An eight-layer UnivMon pyramid cannot recover the distinct count of the 100K uniform input. | Builds `UnivMon::init_univmon(32, 5, 2_048, 8)`, inserts every key of documented input `(1)` (100K uniform `i64` draws over `[0, 10M)`, 99,515 distinct) with weight `1`, and asserts `calc_card() < distinct * 0.5`; only that upper bound is pinned, not how far below it the estimate lands. |
### Quantiles: KLL Rank Contract
Test file: [`tests/e2e_quantiles.rs`](../tests/e2e_quantiles.rs)
| test_name | test_description | what_is_tested |
| --- | --- | --- |
| `kll_family_stays_within_the_datasketches_maximum_rank_error_characterization` | Both KLL implementations stay inside the DataSketches maximum-rank-error characterization across the whole `(k, shape, feed)` grid. | Crosses `n=30_000` streams over 4 repeats x 6 `rank_streams` shapes (`uniform` over `[0, 100M)`, `normal(1000, 250)`, `zipf(1.1)` over 8192 keys in `[1e6, 1e7]`, `duplicate-heavy` with 50 distinct values, `monotonic`, `outside-in`) x `k in {64, 200, 800}` x 4 feed modes (`SinglePass`, `bulk_update`, a 4-shard round-robin merged pairwise into a tree, and a `TumblingWindow<KLL>` with window `n/8`, 32 retained, `m=8`, read through `query_all`). Every sketch gets its own compaction seed from `kll_trial_seed`, is reduced by `KllRankSpec::datasketches(k)` to its worst normalized rank error over the q grid `[0.0, 0.01, 0.1, 0.5, 0.9, 0.99, 1.0]`, and is tallied under a `KLL/{feed}` or `KLLDynamic/{feed}` label (72 trials each; `KLLDynamic` has no `TumblingMerge` mode, so 7 labels in all). Each label is then accepted by `Tally::assert_independent_binomial` at a per-trial failure probability of `0.01` against `eps(k) = 2.446 / k^0.9433`. |
| `kll_rank_error_shrinks_with_k_as_the_characterization_predicts` | Raising `k` really tightens the rank error, so `k` is wired through to the compactor capacities. | Feeds `n=100_000` uniform values over `[0, 100M)` (stream seed `0xC0FF_EE01`) into `KLL::init_kll_with_seed(k, seed)` for `k in {64, 256, 1024}` at the four fixed seeds `0x5EED_0001..0x5EED_0004`, and takes each `k`'s worst rank error over the 19-point grid `i/20, i in 1..20`. Asserts each worst-of-four is at most `eps(k)` (`~0.0484`, `~0.0132`, `~0.00354`) and that `worst(k=64) >= 4 * worst(k=1024)`; the message quotes the characterization's predicted `16^0.9433 = 13.4x`. |
### Quantiles: KLL Bulk Ingestion
Test file: [`tests/e2e_quantiles.rs`](../tests/e2e_quantiles.rs)
| test_name | test_description | what_is_tested |
| --- | --- | --- |
| `kll_bulk_update_is_byte_identical_to_the_update_loop` | `KLL::bulk_update` produces the same sketch as a loop of `update`, not merely one in the same rank band. | Over the 9 `bulk_cases(0, 20_000)` streams (the six `rank_streams` shapes plus `exponential(1e-3)` seed `3007`, `log-uniform` on `gamma = 1.01/0.99` bucket edges seed `3005`, and a 10-element `sequential-10`), builds two `KLL<f64>` at `k=200` sharing the seed `kll_bulk_seed(case)` and asserts equal `count()`, equal `serialize_to_bytes()` output, and bit-identical `quantile(q)` (`to_bits()`) at every `q` in `[0.0, 0.01, 0.1, 0.5, 0.9, 0.99, 1.0]`. |
| `kll_dynamic_bulk_update_is_byte_identical_to_the_update_loop` | `KLLDynamic::bulk_update` holds the same byte-level equality on its own wire form. | Same equality on `KLLDynamic<f64>` at `k=200`, `n=10_000`, over the 9 `bulk_cases(1, n)` streams with seed `kll_bulk_seed(0x0100 + case)`: asserts equal `count()`, equal `serialize_to_bytes()`, and equal `quantile(q).to_bits()` over the same 7-point q grid. |
| `kll_bulk_update_on_a_degenerate_slice_matches_the_loop` | The two degenerate slice lengths behave as a no-op and as a single `update`. | Feeds `1.0, 2.0, 3.0` into a `k=200` sketch at `kll_bulk_seed(0x0200)`, then asserts `bulk_update(&[])` leaves `count()`, `quantile(0.5).to_bits()` and `serialize_to_bytes()` unchanged; and that a fresh sketch given `bulk_update(&[42.0])` serializes byte-identically to one given `update(&42.0)`. |
| `kll_bulk_update_data_input_matches_the_loop_and_stops_at_the_first_non_numeric` | The `DataInput` batch path equals the loop and aborts at the first non-numeric element with the prefix applied. | Wraps 5_000 `normal_f64(100, 20)` values (seed `8001`) as `DataInput::F64` and asserts `bulk_update_data_input` and a loop of `update_data_input` serialize identically at `k=200`, seed `kll_bulk_seed(0x0300)`. Then feeds `[F64(1.0), String("x"), F64(2.0)]` and asserts the call returns `Err` while `count() == 1`, and that `bulk_update_data_input(&[])` returns `Ok` leaving `count() == 0`. |
### Quantiles: KLL Geometry Axes
Test file: [`tests/e2e_quantiles.rs`](../tests/e2e_quantiles.rs)
| test_name | test_description | what_is_tested |
| --- | --- | --- |
| `kll_minimum_compactor_capacity_axis_keeps_the_count_exact_and_reports_its_own_geometry` | Every supported `m` leaves `k` alone, reports its own geometry on the wire, and keeps its answers inside the observed range. | For `m in {2, 4, 8, 16, 64}` builds `KLL::init_with_seed(200, m, kll_axis_seed(m))` over 20_000 uniform values (seed `0x4B11_0001`) and asserts `k() == 200`, `wire_m() == m` and `wire_k() == 200`. Despite the name the count is not pinned exactly: `count()` is only asserted between `0.95x` and `1.05x` of 20_000. The quantile check is likewise weak — each `quantile(q)` over the 7-point `RANK_QS` grid is only required to lie between the true min and max, with no rank error asserted. |
| `kll_normalizes_a_minimum_compactor_capacity_outside_its_supported_range` | An out-of-range `m` is normalized and `k` is raised to `m` when it falls below it. | Asserts `KLL::init_with_seed(200, 0, ..)` reports `wire_m() == 2` with `wire_k()` still `200`, and `KLL::init_with_seed(4, 64, ..)` reports `wire_m() == 64` with `wire_k()` raised to `64`. Then feeds 5_000 uniform values (seed `0x4B11_0102`) into the raised sketch and asserts `count()` lands between `0.85x` and `1.15x` of 5_000; the count is banded, not exact. |
| `kll_minimum_compactor_capacity_at_or_above_the_default_satisfies_the_rank_characterization` | At or above the default minimum compactor capacity, KLL still meets `eps(k)`. | For `m in {8, 16, 64}` x the six `rank_streams(case, 30_000)` shapes (18 trials), builds `KLL::init_with_seed(200, m, kll_axis_seed(0x0200 + case*16 + i))`, reduces each sketch to its worst rank error over `RANK_QS` via `KllRankSpec::datasketches(200)`, and accepts with `assert_independent_binomial` at a per-trial failure probability of `0.01` against `eps(200) ~ 0.0165`. |
| `kll_minimum_compactor_capacity_below_the_default_stays_within_a_widened_rank_band` | Below the default minimum compactor capacity the rank error stays inside a 3x-widened band, with no violations at all. | For `m in {2, 4}` x the six `rank_streams(case + 8, 30_000)` shapes (12 trials), seeds `kll_axis_seed(0x0300 + case*16 + i)`, `k=200`: requires each sketch's worst rank error over `RANK_QS` to be at most `KLL_WIDENED_EPSILON_FACTOR * eps(200) = 3.0 * 0.0165 ~ 0.0496` and closes with `Tally::assert_none`, tolerating zero violations. |
| `kll_small_k_satisfies_the_rank_characterization_at_its_own_epsilon` | Small `k` values are held to their own, looser `eps(k)` rather than to a fixed number. | For `k in {8, 16, 32}` x the six `rank_streams(case + 16, 20_000)` shapes, seeds `kll_axis_seed(0x0400 + case*16 + i)`: asserts `count()` between `0.85x` and `1.15x` of 20_000, then scores each sketch's worst rank error over `RANK_QS` against `KllRankSpec::datasketches(k).epsilon()` (`~0.359`, `~0.187`, `~0.0972`) and accepts by binomial at `p = 0.01`. |
| `a_kll_stream_shorter_than_k_is_answered_exactly` | A stream shorter than `k` is stored verbatim and answered with exact order statistics. | For `n in {1, 2, 7, 50, 150}` at `k=200`, seeds `kll_axis_seed(0x0500 + case)` and stream seeds `0x4B11_0500 + case`: asserts `count() == n` exactly, that `rank_error(sorted, q, est)` is exactly `0.0` at every `q` in `RANK_QS`, that each answer's bit pattern appears in the stream, and that `quantile(0.0)`/`quantile(1.0)` bits equal the exact min/max. |
### Quantiles: DDSketch Relative Value Error
Test file: [`tests/e2e_quantiles.rs`](../tests/e2e_quantiles.rs)
| test_name | test_description | what_is_tested |
| --- | --- | --- |
| `ddsketch_core_and_portable_satisfy_the_relative_value_error_contract` | Both DDSketch implementations meet the relative-value-error guarantee against the order statistic of their own rank convention. | Crosses `alpha in {0.001, 0.01, 0.05, 0.1}` x `n in {1_000, 20_000, 100_000}` x the six `dds_streams` shapes (`adversarial-bucket-edges` log-uniform on `gamma` edges, positive-filtered `normal(1000, 250)`, `exponential(1e-3)`, `uniform` over `[1e6, 1e7)`, `zipf(1.1)` over 8192 keys in `[1e6, 1e7]`, and `wide-dynamic-range` spanning nine decades). Asserts `DDSketch::get_count()` and `PortableDds::total_count()` both equal `n` (no sample dropped), then per alpha tallies `RelativeQuantileSpec::core(alpha)` on `get_value_at_quantile` and `RelativeQuantileSpec::portable(alpha)` on `quantile` over the q grid `[0.0, 0.01, 0.1, 0.5, 0.9, 0.99, 1.0]` and closes both with `assert_none`: every estimate must be within `alpha + 8*f64::EPSILON*(1 + \|ln v\|)` of `sorted[ceil(q*n) - 1]` for the core and `sorted[floor(q*(n-1))]` for the portable twin. Zero violations tolerated, since the guarantee is deterministic. |
| `ddsketch_core_and_portable_answer_different_order_statistics` | The core and portable quantile conventions differ, and the divergence is pinned rather than absorbed into `alpha`. | Runs 8 `(n, q, core_idx, port_idx)` probes — `(3, 0.4, 1, 0)`, `(4, 0.34, 1, 1)`, `(4, 0.3, 1, 0)`, `(7, 0.2, 1, 1)`, `(7, 0.6, 4, 3)`, `(5, 0.5, 2, 2)`, `(10, 0.25, 2, 2)`, `(10, 0.15, 1, 1)` — on values `100 * gamma^(3i)` at `ALPHA = 0.01`, so one rank of movement is a whole bucket. Asserts `DdRankConvention::CeilNearestRank.index(n, q)` equals `core_idx` and `DdRankConvention::LowerFloor.index(n, q)` equals `port_idx`, that each implementation satisfies its own `RelativeQuantileSpec::check` against `sorted[its own index]`, that the two answers are unequal on every probe whose indices disagree, and that at least `3` probes disagree. |
| `ddsketch_core_endpoints_are_exact_and_portable_endpoints_are_alpha_relative` | The core sketch's endpoints are exact while the portable twin's are only `alpha`-relative. | For each of `alpha in {0.001, 0.01, 0.05, 0.1}` over 5_000 `log_uniform_f64` values (seed `4_242`, exponent range `3..30`), asserts `core.get_value_at_quantile(0.0) == Some(truth.min())`, `(1.0) == Some(truth.max())`, and `core.min()`/`core.max()` equal the exact extremes; the portable `quantile(0.0)` and `quantile(1.0)` are only checked through `RelativeQuantileSpec::portable(alpha).check` against the true min/max, i.e. within `alpha + a few ULP`, with no exactness claimed. |
| `ddsketch_satisfies_the_relative_error_contract_at_bucket_boundaries` | Values on, just below and just above a bucket edge all stay inside `alpha` on both sides. | For each of the four alphas and `k in {-40, -7, 0, 1, 13, 60, 200}` computes `edge = gamma^k` and probes `edge`, `edge*(1 - f64::EPSILON)`, `edge*(1 + f64::EPSILON)`, `edge*sqrt(gamma)` and `edge*gamma*(1 - 1e-12)`. Each probe is the single sample of a fresh core and portable sketch, so both rank conventions land on index 0 and the mapping is isolated; `quantile(0.5)` must satisfy each spec's `alpha + numerical_slack` tolerance against the probe itself. Probes the mapping refuses (`get_count() == 0`) are skipped rather than asserted on. |
| `ddsketch_merge_and_delta_replay_preserve_the_relative_error_contract` | Shard merge and bucket-delta replay both leave the relative-error contract intact on both implementations. | Per `alpha in {0.001, 0.01, 0.05, 0.1}` over `zipf_f64(40_000, 8_192, 1.1, 1e3, 1e7)`: a 4-way round-robin core shard merge must report `get_count() == 40_000` exactly and satisfy the contract over the full q grid; a core sketch rebuilt by replaying every non-zero `store_counts()` entry as an `octo_delta::DdDelta` at `store_offset() + i` must reproduce `get_count()` and satisfy the contract over the interior grid `DDS_QS[1..6] = [0.01, 0.1, 0.5, 0.9, 0.99]` (its endpoints are bucket representatives, so `q=0`/`q=1` are excluded). On the portable side, an even/odd split merged with `merge` is scored over the full grid, and a `DdSketchDelta` carrying the merged sketch's buckets plus `d_count` replayed into an empty sketch is scored over the interior grid. All four tallies use `assert_none`. |
| `ddsketch_satisfies_the_relative_value_error_contract_at_extreme_accuracy_parameters` | The relative-value contract still holds at accuracy parameters three orders of magnitude either side of the usual range. | For `alpha in {1e-5, 1e-4, 0.3, 0.5, 0.9}` (seed `0x0DDA_0000 + i*7919`), takes the six `dds_streams(alpha, 20_000, seed)` shapes filtered to `[min, max]` from `ddsketch::ddsketch_indexable_bounds(alpha)`, skipping any shape left with fewer than 100 values. Asserts core `get_count()` and portable `total_count()` both equal the surviving count, then `assert_none` on `RelativeQuantileSpec::core(alpha)` and `::portable(alpha)` over the 7-point `DDS_QS` grid. |
| `ddsketch_bucket_width_widens_monotonically_with_the_accuracy_parameter` | A looser accuracy parameter never needs more buckets. | Feeds 20_000 values `1.0 + uniform_u64(.., 1_000_000, 0x0DDA_9001)` into a `DDSketch` at each `alpha in {1e-5, 1e-4, 0.3, 0.5, 0.9}` in that order, asserts nothing was dropped (`get_count() == 20_000`), and asserts the occupied-bucket count (`store_counts()` entries above zero) is no larger than the previous alpha's. The check is non-strict, so equal bucket counts pass and no bucket width is measured directly. |
### Quantiles: DDSketch Input Rejection
Test file: [`tests/e2e_quantiles.rs`](../tests/e2e_quantiles.rs)
| test_name | test_description | what_is_tested |
| --- | --- | --- |
| `ddsketch_rejects_untrackable_values_and_mapping_mismatches` | Untrackable values are dropped without allocating or corrupting state, and a mismatched mapping is a runtime error on both types. | At `alpha = 0.01` feeds `NAN`, `-INFINITY`, `INFINITY`, `-5.0`, `0.0`, `f64::MIN_POSITIVE`, `5e-324`, `f64::MAX` and `1e308` into both implementations and asserts `get_count() == 0`, `total_count() == 0`, `port.store_counts.len() < 10_000`, and `port.quantile(0.5) == None`. Then `[1.0, 2.0, 4.0, 8.0, 16.0]` must give `get_count() == 5` / `total_count() == 5` with the store between `1` and `512` buckets. Using the shared `ddsketch_indexable_bounds(0.01)`, `min*(1 + 1e-9)` and `max*(1 - 1e-9)` are both accepted (count `2` in both, and the two counts equal), while `min*0.5` and `max*(1 + 1e-6)` leave the counts at `2`. `DDSketch::merge` and `PortableDds::merge` across `alpha = 0.01` vs `0.05` must both return `Err`. Finally at `alpha = 1e-9`, `1e-300` is dropped by both (`total_count() == 0`, `get_count() == 0`) with `store_counts.len() == 0`, so no allocation occurs for a rejected value. |
| `portable_ddsketch_rejects_hostile_delta_spans` | A delta spanning an implausible bucket range is rejected before any allocation, and a benign one still applies. | Seeds a portable sketch at `alpha = 0.01` with `1.0`, then asserts `apply_delta` on `buckets: [(i32::MAX - 1, 1), (7, 3)]` returns `Err` and leaves both `store_counts.len()` and `store_offset` at their prior values. A benign delta `[(6, 5)]` then applies successfully and `quantile(0.9)` must equal exactly `Some(gamma.powf(6.0) * (1.0 + alpha))`, so the applied count is visible through queries. |
### Quantiles: UnivMon-Q Estimators
Test file: [`tests/e2e_quantiles.rs`](../tests/e2e_quantiles.rs)
| test_name | test_description | what_is_tested |
| --- | --- | --- |
| `univmonq_count_min_and_max_are_exact` | `count`, `min` and `max` are maintained exactly, not estimated. | Feeds 20_000 uniform values over `[0, 900)` (seed `3008`) into a default `UnivMonQ` (levels `10`, width `4096`, depth `5`, `ordered_samples` `1_024`, `hash_seed` `5`) and asserts `count() == 20_000`, `min() == Some(truth.min())` and `max() == Some(truth.max())` — three exact equalities, no band. |
| `univmonq_frequency_and_f2_satisfy_the_count_sketch_bounds` | Point frequencies obey the bottom layer's Count Sketch L2 bound and `estimate_f2` obeys the AMS bound. | Builds the default-config sketch over 40 separated heavy keys (key `i` at weight `(i+1)*60`, so `60..2400`) plus a 20_000-draw uniform background over keys `100..900` (seed `3008`). `CountSketchSpec::new(5, 4096).assert_contract` is run over every distinct key with the residual `\|\|f_-i\|\|_2 = sqrt(F2 - f_i^2)` recomputed per key: the simultaneous band `sqrt(kappa/w)*\|\|f_-i\|\|_2`, at the `kappa` whose per-key failure is union-bounded over all keys, tolerates zero violations, while the marginal band `sqrt(3/4096)*\|\|f_-i\|\|_2` is asserted as a failure rate. `SecondMomentSpec::new(5, 4096).check` then requires `estimate_f2()` within `sqrt(2*3/4096) ~ 3.83%` relative of the exact `F2`. |
| `univmonq_ordered_queries_satisfy_the_documented_cdf_and_rank_bounds` | Ordered queries satisfy the documented `eta = 2 E_H + P_hat_R eps_R` bound in both Kolmogorov distance and quantile rank, on both branches of the adaptive gate. | Runs three regimes from `univmonq_ordered_regimes` — `diffuse` (200_000 uniform over `[0, 10M)`, seed `0x0DDE_0001`), `heavy` (`zipf(1.4)` 200_000 over 4_096 keys), `mixed` (60_000 `zipf(1.6)` over 64 keys plus 140_000 uniform offset by `1e4`) — with `TRIALS = 12` sketches each at `hash_seed = 3 + t` and `source_id = 0x0DDE_1000 + t`. Per trial it recomputes `eta` from `ordered_query_diagnostics()`: `E_H` as the summed `\|f_hat - f_exact\|` over the recovered heavy set divided by `N`, `P_hat_R` from `residual_mass_fraction`, and `eps_R = occurrence_sample_epsilon(residual_samples, 0.01)`, asserting `m_R > 0` whenever `P_hat_R > 0` and that the CDF rests on heavy values or samples. Two independent tallies then run: `cdf_sup_distance(estimated, sorted)` must be at most `eta`, and `view.quantile(q)` must pass `rank_violation` within `eta` at every `q` in `[0.01, 0.1, 0.25, 0.5, 0.75, 0.9, 0.99]`; both are accepted by `assert_independent_binomial` at `delta = 0.01`. It also asserts `rank(quantile(q))/n` is within `2*eta + 1e-9` of the value's inclusive true rank at `q in {0.1, 0.5, 0.9}`, that the CDF is non-empty and monotone to `1e-9`, that the gate `estimate_f2()/N^2 >= 1/ordered_samples` fires `0/12` on `diffuse`, `12/12` with a non-empty heavy set on `heavy`, and at least once on `mixed`, that a closed gate implies an empty heavy set, and that both gate branches were exercised somewhere. |
| `cdf_sup_distance_detects_a_gap_a_breakpoint_scan_misses` | The exact CDF sweep catches a missing atom that a per-breakpoint scan scores as perfect. | A hand-built fixture with no sketch: truth `[1, 1, 5, 5, 5, 5, 5, 5, 9, 9]` and estimate `[(1.0, 0.2), (9.0, 1.0)]`. Asserts `breakpoint_rank_interval_distance` is exactly `0.0`, that `cdf_sup_distance` returns a supremum of `0.6` (to `1e-12`) attained at `x = 5.0`, that the exact step CDF `[(1, 0.2), (5, 0.8), (9, 1.0)]` gives exactly `0.0`, and that a too-high estimate `[(1, 0.9), (5, 0.9), (9, 1.0)]` gives `0.7` (to `1e-12`) attained at `x = 1.0`, so the sweep also looks strictly below the first breakpoint. |
| `univmonq_distinct_entropy_and_recall_stay_within_the_documented_empirical_band` | Distinct count, entropy and heavy-hitter recall stay inside the documented empirical band on the reference stream. | On the same stream as the frequency test (40 heavy keys at weights `60..2400` plus a 20_000-draw uniform background over 800 keys, seed `3008`, default `UnivMonQConfig`), asserts `estimate_distinct()` within `[0.90, 1.10]` x the exact distinct count, `estimate_entropy()` within `[0.90, 1.10]` x `FreqTruth::entropy(false)` in nats, and that `heavy_hitters(10)` contains at least `8` of the keys `30..40`. These are empirical bands measured on this exact stream (observed movement ~1.6% distinct, ~0.3% entropy, recall 10/10), not a derived bound. |
| `univmonq_l1_is_exact_and_the_generic_g_sum_reproduces_the_named_estimators` | `estimate_l1` is exact on an insertion-only stream and the generic `g`-sum reproduces the named estimators bit for bit. | Feeds 50_000 uniform values (seed `0x0DDE_9001`) into a default `UnivMonQ` and asserts by exact equality that `estimate_l1() == 50_000.0`, `estimate_l1() == count() as f64`, `estimate_g_sum(\|_\| 1.0).clamp(0.0, count())` equals `estimate_distinct()`, `estimate_g_sum(\|f\| f*f).max(0.0)` equals `estimate_f2()`, and `estimate_g_sum(\|_\| 0.0)` is exactly `0.0`. No tolerances anywhere. |
| `univmonq_universal_entropy_tracks_the_exact_entropy_on_a_diffuse_stream` | The universal entropy estimator tracks the exact entropy on a diffuse stream. | Feeds 200_000 uniform draws over 50_000 keys (seed `0x0DDE_9101`) into a default `UnivMonQ` and asserts `estimate_entropy_universal()` lies within `[0.80, 1.20]` x `FreqTruth::entropy(false)`; a +/-20% band is all that is pinned. |
| `univmonq_occurrence_entropy_is_present_only_when_ordered_samples_are_configured` | Occurrence entropy is reported only when an ordered sample is configured. | Feeds the same 120_000-value `zipf(1.2)` stream over 4_096 keys (seed `0x0DDE_9201`) into two sketches, one with `ordered_samples: 1_024` and one with `ordered_samples: 0`, and asserts `estimate_entropy_occurrence()` is `None` for the unsampled one and `Some` for the sampled one, plus that `estimate_entropy()` stays finite. The returned occurrence entropy is only checked to be finite and non-negative; its value is never compared to the exact entropy, so accuracy is not pinned. |
| `univmonq_universal_rank_is_exact_outside_the_observed_range_and_banded_inside_it` | `estimate_rank_universal` is exact outside the observed range and inside a wide band within it. | On 120_000 `zipf(1.2)` values over 2_048 keys (seed `0x0DDE_9301`, default config), asserts `estimate_rank_universal(min - 1.0) == Some(0)`, `(max) == Some(120_000)`, `(max + 1.0) == Some(120_000)`, and that an empty sketch returns `None`. Interior probes at the truth quantiles `0.25`, `0.5` and `0.75` are only required to have a normalized rank error of at most `0.25` (a quarter of the whole stream), recorded in a tally closed with `assert_none`. |
### Quantiles: Windowed and Per-Key KLL
Test file: [`tests/e2e_quantiles.rs`](../tests/e2e_quantiles.rs)
| test_name | test_description | what_is_tested |
| --- | --- | --- |
| `tumbling_kll_windows_are_exact_and_answers_satisfy_the_rank_contract` | Window membership is exact arithmetic while the answers inside a window carry KLL's rank error. | Drives 4_000 uniform values over `[0, 1M)` (seed `3009`) into a `TumblingWindow<KLL>` with window `400`, `16` retained, `k=200`, `m=8`, pool size `4`, and asserts `closed_count() == 9` by equality. Then 16 trials, each with its own compaction seed `kll_trial_seed(0x7717_0000 + t)`, reduce the three window views — `query_all` against the whole stream, `query_recent(1)` against the last 800 values, and `active_sketch()` against the last 400 — to one worst rank error over the q grid `[0.1, 0.25, 0.5, 0.75, 0.9]`, which must not exceed `eps(200) ~ 0.0165`; accepted by `assert_independent_binomial` at `p = 0.01`. Rotation is then checked by a band, not an equality: `query_all().count()` must drift from 4_000 by at most `eps(200)`, so a dropped window (12.5% of the stream) would fail but the retained mass is not pinned exactly. |
| `portable_hydra_kll_per_key_medians_satisfy_the_rank_characterization` | Each Hydra KLL cell answers its own key under the same rank characterization as a standalone KLL. | Builds `HydraKllSketch::with_seed(3, 256, 200, seed)` for 12 trials with prototype seeds `kll_trial_seed(0x5EED_0500 + t)`, feeding two keys of 4_000 values each in sorted order: `svc-a` from `\|normal(100, 5)\|` (seed `3010`) and `svc-b` from `\|normal(900, 45)\|` (seed `3011`). Because every cell is cloned from one seeded prototype the two keys are not independent, so each grid is reduced to its worst rank error across both keys over the q grid `[0.1, 0.25, 0.5, 0.75, 0.9]` — wider than the median the name mentions — checked against `eps(200) ~ 0.0165` and accepted by `assert_independent_binomial` at `p = 0.01` over the twelve prototype seeds. |
### Quantiles: Documented Input Matrix
Test file: [`tests/e2e_quantiles.rs`](../tests/e2e_quantiles.rs)
| test_name | test_description | what_is_tested |
| --- | --- | --- |
| `the_documented_value_inputs_satisfy_both_quantile_contracts` | The coverage document's value-only streams satisfy the KLL rank contract and DDSketch's relative-value contract. | For inputs `(15)` 100K `normal(1000, 250)`, `(16)` 1M `normal(1000, 250)` and `(17)` 100K `exponential(1e-3)` from `common::inputs::value_input`: for each `k in {50, 200, 800}` builds a single-pass `KLL` at seed `kll_trial_seed(0x00E0_0000 + id*16 + k)`, scores its worst rank error over the decile grid `DOC_QS = [0.0, 0.1, .. 1.0]` against `eps(k)` and closes with `assert_none`; and for each `alpha in {0.1, 0.01, 0.001}` feeds the finite positive subsequence into a core `DDSketch` and `assert_none`s `RelativeQuantileSpec::core(alpha)` over the same grid. Then input `(18)` is rebuilt per alpha by `common::inputs::ddsketch_edge_input(alpha)` (100K log-uniform on that alpha's own bucket edges); the sketch must ingest every value (`get_count()` equals the stream length) and satisfy the contract over `DOC_QS` with zero violations. |
| `kll_family_on_input_{1..12}_holds_its_rank_error` | Each of the twelve documented keyed inputs holds the KLL rank characterization for both implementations, single-pass and shard-merged. | Twelve names generated by `documented_quantile_matrix!`, each calling `kll_documented_matrix(id)` on `common::inputs::key_input(id)`. The shared body first asserts the tests and the coverage table cannot drift: `KllRankSpec::datasketches(k).epsilon()` must be within `5e-5` of the document's quoted `0.0611`, `0.0165` and `0.00447` at `k = 50, 200, 800`. Then for each `k` it builds four sketches — `KLL` and `KLLDynamic`, each under `Feed::SinglePass` and a 4-shard `Feed::ShardMerge`, at seed `kll_trial_seed(0x00D0_0000 + id*16 + i)` — reduces each to its worst rank error over the decile grid `DOC_QS = [0.0, 0.1, .. 1.0]`, and closes with `Tally::assert_none`, so a single trial above `eps(k)` fails. Generated names and their invocation ids: `kll_family_on_input_1_holds_its_rank_error` -> `(1)` 100K uniform `i64` over `[0, 10M)`; `kll_family_on_input_2_holds_its_rank_error` -> `(2)` 1M uniform `i64`; `kll_family_on_input_3_holds_its_rank_error` -> `(3)` 100K `zipf(1.1)` `i64` over 4096 keys; `kll_family_on_input_4_holds_its_rank_error` -> `(4)` 1M `zipf(1.1)` over 4096; `kll_family_on_input_5_holds_its_rank_error` -> `(5)` 100K `zipf(1.1)` over 20000 keys; `kll_family_on_input_6_holds_its_rank_error` -> `(6)` 1M `zipf(1.1)` over 20000; `kll_family_on_input_7_holds_its_rank_error` -> `(7)`, `kll_family_on_input_8_holds_its_rank_error` -> `(8)`, `kll_family_on_input_9_holds_its_rank_error` -> `(9)`, `kll_family_on_input_10_holds_its_rank_error` -> `(10)`, `kll_family_on_input_11_holds_its_rank_error` -> `(11)`, `kll_family_on_input_12_holds_its_rank_error` -> `(12)` — the same six shapes carried on `f64` keys, whose quantile values are `f64::from_bits` of the integer draw. |
| `ddsketch_on_input_{1..12}_holds_its_relative_error` | Each of the twelve documented keyed inputs holds DDSketch's relative-value-error contract, single-pass and after a shard merge. | Twelve names generated by the same `documented_quantile_matrix!` invocation, each calling `ddsketch_documented_matrix(id)`. The shared body takes `key_input(id).values()` filtered to finite strictly-positive values — the question DDSketch actually answers — and for each `alpha in {0.1, 0.01, 0.001}` asserts a single-pass `DDSketch` dropped none of them (`get_count()` equals the positive count), `assert_none`s `RelativeQuantileSpec::core(alpha)` on `get_value_at_quantile` over the decile grid `DOC_QS = [0.0, 0.1, .. 1.0]` (tolerance `alpha` plus a few ULP, truth at `sorted[ceil(q*n) - 1]`), and then requires a 4-way round-robin shard merge to satisfy the identical contract. Generated names and their invocation ids: `ddsketch_on_input_1_holds_its_relative_error` -> `(1)` 100K uniform `i64` over `[0, 10M)`; `ddsketch_on_input_2_holds_its_relative_error` -> `(2)` 1M uniform `i64`; `ddsketch_on_input_3_holds_its_relative_error` -> `(3)` 100K `zipf(1.1)` over 4096 keys; `ddsketch_on_input_4_holds_its_relative_error` -> `(4)` 1M `zipf(1.1)` over 4096; `ddsketch_on_input_5_holds_its_relative_error` -> `(5)` 100K `zipf(1.1)` over 20000 keys; `ddsketch_on_input_6_holds_its_relative_error` -> `(6)` 1M `zipf(1.1)` over 20000; `ddsketch_on_input_7_holds_its_relative_error` -> `(7)`, `ddsketch_on_input_8_holds_its_relative_error` -> `(8)`, `ddsketch_on_input_9_holds_its_relative_error` -> `(9)`, `ddsketch_on_input_10_holds_its_relative_error` -> `(10)`, `ddsketch_on_input_11_holds_its_relative_error` -> `(11)`, `ddsketch_on_input_12_holds_its_relative_error` -> `(12)` — the six `f64`-keyed twins, whose values are `f64::from_bits` of the integer draw. |
### Heavy Hitters: Coco and Elastic Keyed Buckets
Test file: [`tests/e2e_heavy_hitters.rs`](../tests/e2e_heavy_hitters.rs)
| test_name | test_description | what_is_tested |
| --- | --- | --- |
| `coco_passes_frequency_and_merge_conformance` | Coco clears the shared two-sided frequency and merge-equivalence batteries. | Runs `conformance::frequency_battery` and `conformance::merge_equivalence_battery` over a default `Coco<DefaultXxHasher>` (4 arrays of 1,024 buckets), rendering the batteries' integer keys as `flow::{k}` strings and estimating through `estimate_key`, on 60,000 `zipf(1.1)` draws over a 2,048-key domain at seed `9_001`, with `FrequencySpec { one_sided: false, rel_tol: 0.06, abs_tol: 25.0 }`; only keys of true count 25 or more are probed, and the merge battery splits the stream by parity, merges, and requires agreement with a single-pass sketch within `abs_tol + rel_tol * count`. |
| `coco_over_attribution_bounds_with_disjoint_prefixes` | Partial-key matching collects a family's own mass and no more than the whole stream. | Inserts 3,000 `aaa{i%50}` keys at weight 7 and 2,000 `zzz{i%30}` keys at weight 3 into `Coco::init_with_size(256, 2)`, then verifies `estimate_substring("aaa")` and `estimate_with_udf("zzz", starts_with)` each land in `[0.75 * true family sum, total]` — `[15_750, 27_000]` for the 21,000-unit `aaa` family and `[4_500, 27_000]` for the 6,000-unit `zzz` family. The ceiling is the entire inserted mass, so over-attribution between the two disjoint prefixes is not pinned any tighter than "no more than everything inserted", and no query is checked against the other family's keys directly. |
| `coco_point_queries_partition_the_inserted_mass` | A point query partitions the inserted mass exactly, and heavy keys stay inside a derived ceiling. | Inserts 40,000 `zipf(1.2)` draws over a 2,000-key domain at seed `4242`, each at weight 2, into `Coco::init_with_size(128, 3)`, and verifies `estimate_key` summed over every observed key equals the 80,000 inserted units exactly. For the ten heaviest keys (ranked by exact count, ties by key) it verifies each estimate is at most `count + e*(total - count)/128` and at least `0.5x` its true count; the floor is a measured regression pin, not a bound. |
| `coco_point_estimates_are_unbiased_under_heavy_eviction` | The mean point estimate over independent runs tracks the truth even when the target is often evicted. | Over 800 independent `Coco::init_with_size(32, 2)` runs, each fed 200 `bg::{i}` flows at weight 10 with 20 `flow::target` inserts spread evenly through them, verifies the target reads `0` in more than 80 of the runs and that the mean of the 800 `estimate_key` readings lands in `[17.0, 23.0]` around the true 20 via `assert_between`. |
| `coco_recall_meets_the_papers_heavy_hitter_target` | A heavy hitter holding 1% of the traffic is recorded at least 99% of the time. | Over 200 runs of `Coco::init_with_size(900, 2)`, each fed 5,000 `bg::{i}` flows at weight 1 with 51 `flow::heavy` inserts interleaved, verifies `recorded_flows()` contains `flow::heavy` in at least 99% of runs (`recorded/200 >= 0.99`). First checks the configuration itself reaches that operating point: `1 - (1 + 900 * 51/5000)^-2 >= 0.99`. |
| `elastic_passes_frequency_and_merge_conformance` | Elastic clears the shared one-sided frequency and merge-equivalence batteries. | Runs `conformance::frequency_battery` and `conformance::merge_equivalence_battery` over `Elastic::<DefaultXxHasher>::init_with_length(256)` (256 heavy buckets on the default `3x4096` light layer), keying integers as `flow::{k}` and estimating through `query`, on 60,000 `zipf(1.1)` draws over a 2,048-key domain at seed `9_001`, with `FrequencySpec { one_sided: true, rel_tol: 0.0, abs_tol: e/4096 * 60_000 }` (about `39.8`); the one-sided battery also probes the absent key `i64::MIN` and requires `\|est\| <= abs_tol` there. Ingest is through `insert` only, never overload mode. |
| `elastic_tracks_hot_flows` | Three hot flows amid background chatter come back within a fifth of their true size. | Feeds 12,000 records into `Elastic::init_with_length(64)` — `hot-alpha`, `hot-beta` and `hot-gamma` taking a tenth of the stream each, the rest `bg{i%977}` — and verifies `query` for each hot flow lands in `[0.80 * true, 1.20 * true]` via `assert_between`. |
| `elastic_light_dimensions_set_the_error_on_evicted_flows` | The light layer's dimensions reach the estimate of a flow the heavy part evicted. | Inserts `flow::target` 50 times then 20,000 distinct `bg::{i}` flows into `Elastic::init_with_dimensions(8, rows, cols)`, asserting the target is no longer resident in `heavy`, once at `1x64` and once at `3x4096`; verifies both readings are at least the true `50`, that the `3x4096` reading is at most `100`, and that the `1x64` reading is at least four times the `3x4096` one. |
| `elastic_never_underestimates_under_eviction_pressure` | No flow reads below its true count under sustained takeovers, and a resident elephant stays inside the light layer's Count-Min ceiling. | Feeds 60,000 `zipf(1.1)` draws over a 4,000-key domain at seed `909` into `Elastic::init_with_length(16)`, with every 500th record replaced by `flow::elephant`; verifies `query` is at or above the true count for every flow, that at least one flow was pushed out of `heavy`, and that the elephant's estimate sits in `[true, true + e*(N - true)/light.cols()]`. |
### Heavy Hitters: Partial-Key Queries and Heavy-Table Maintenance
Test file: [`tests/e2e_heavy_hitters.rs`](../tests/e2e_heavy_hitters.rs)
| test_name | test_description | what_is_tested |
| --- | --- | --- |
| `coco_group_by_partitions_exactly_the_mass_the_table_records` | `group_by` folds every recorded flow exactly once. | Over the tenant fixture — `Coco::init_with_size(2_048, 4)` fed 8 tenants x 64 flows named `tenant-{t:02}/flow-{f:04}` at weight `5 + i%3` — verifies `group_by(tenant_of)` sums to exactly the mass `recorded_flows()` holds, that the recorded mass is at most the inserted mass, that the projection is non-empty, and that every group key starts with `tenant-`. |
| `coco_projected_and_udf_partial_key_queries_agree_with_group_by` | The three partial-key query forms agree with the projection they implement. | For each of the 8 tenants in the same `4 x 2048` fixture, verifies `estimate_projected(tenant, tenant_of)` and `estimate_with_udf(tenant, \|full, partial\| tenant_of(full) == partial)` both return exactly the `group_by` value, and `estimate_substring(tenant)` returns at least it; also verifies `estimate_projected("tenant-99", tenant_of)` is `0`. |
| `coco_per_key_estimates_sum_to_their_own_group` | A projected query equals the recorded flows it covers. | Folds `recorded_flows()` into per-tenant totals by hand over the same `4 x 2048` fixture and verifies `estimate_projected` returns exactly that total for every tenant present. |
| `a_coco_bucket_reports_its_own_partial_key_membership` | A single bucket answers substring and predicate membership for the key it holds. | On a bare `CocoBucket::new()`, verifies `is_partial_key("tenant-00")` and `is_partial_key_with_udf` both reject; after `update_key("tenant-00/flow-0001")`, `add_v(7)` and `add_v(5)`, verifies substring containment accepts `tenant-00` and `flow-0001` and rejects `tenant-01`, that a tenant-projection predicate accepts `tenant-00` and rejects `flow-0001`, and that `val` is `12`. |
| `elastic_merge_max_never_reads_below_either_side_on_disjoint_flow_sets` | Maximum merging never reads a flow below its own side. | Builds two `Elastic::init_with_dimensions(64, 3, 1_024)` sketches on disjoint streams (16 elephants at 300 repeats plus 2,000 distinct mice each, prefixed `l-` and `r-`), calls `merge_max`, and verifies for every flow of either stream that the merged `query` is at least that flow's own side's `query`. |
| `elastic_merge_max_and_sum_merging_agree_on_every_heavy_flow` | Maximum merging never reads a heavy flow above summing, and never loses it. | Merges the same two disjoint `64 / 3x1024` sketches twice, once with `merge_max` and once with `merge`, then for every flow `heavy_hitters(200)` reports on the summed side verifies the maximum-merged `query` is at most the summed one and strictly above `0`; the two merges are only ordered, not asserted equal, so the name's "agree" is an inequality here. |
| `elastic_merge_heavy_and_absorb_evicted_carry_a_transferred_resident` | A transferred resident and an absorbed eviction both land where a query can reach them. | On fresh `Elastic::init_with_dimensions(64, 3, 1_024)` sketches, verifies `merge_heavy("transferred", 500, false)` makes `query` read exactly `500` and a following `merge_heavy("transferred", 0, true)` leaves it at `500`; that `merge_heavy("spilled", 400, true)` followed by `absorb_evicted("spilled", 90)` still reads at least `400`; and that `absorb_evicted("mouse", 75)` with no heavy bucket reads at least `75` through the light layer. |
| `elastic_insert_heavy_only_never_writes_the_light_layer` | The heavy-only insert path leaves the light layer untouched. | Sends 64 flows named `flow-{e:03}` at 20 records each through `insert_heavy_only` on `Elastic::init_with_dimensions(8, 3, 256)` and verifies `light.estimate(&DataInput::String(id))` is exactly `0` for all 64 flows; what the heavy table stored is not checked. |
| `elastic_expansion_keeps_every_resident_readable_and_compression_restores_the_width` | Expansion keeps every resident readable and compression keeps every one of them present. | Over `Elastic::init_with_dimensions(64, 3, 1_024)` fed 24 `x-` elephants at 250 repeats plus 2,000 mice, records `heavy_hitters(200)` and `full_bucket_count(100)`, calls `expand_heavy()` and verifies every recorded flow's `query` is still at least its pre-expansion size and `full_bucket_count(100)` did not fall, then calls `compress_heavy(2)` and verifies every recorded flow still queries above `0`; the bucket count after compression is never read, so the name's "restores the width" is not asserted. |
| `elastic_heavy_changes_reports_only_flows_that_moved_past_the_threshold` | `heavy_changes` reports exactly the flows whose size moved past the threshold it was given. | Builds two `64 / 3x1024` windows over 16 `w-` elephants at 200 repeats plus 2,000 mice, the second carrying 600 extra `w-elephant-000` records, and verifies `heavy_changes(&first, 100)` includes `w-elephant-000`, that every reported entry's `\|after - before\|` exceeds `100`, that `heavy_changes(&first, 10_000)` is empty, and that the second window compared against itself at a threshold of `0` is empty. |
| `a_heavy_bucket_seats_evicts_and_reports_vacancy` | A heavy bucket seats a flow, hands the slot to a takeover, and reports its own vacancy. | Verifies `HeavyBucket::new()` is vacant; that `occupy("first")` leaves it non-vacant with `flow_id` `first`, `vote_pos` `1`, `vote_neg` `0` and no `eviction` flag; that `occupy_many("bulk", 40)` sets `vote_pos` to `40`; that `evict_many("takeover", 12)` returns `bulk` and leaves `flow_id` `takeover` with `vote_pos` and `vote_neg` both `12` and `eviction` raised; and that `evict("single")` returns `takeover` and leaves `vote_pos` at `1`. |
### Heavy Hitters: Documented Input Matrix
Test file: [`tests/e2e_heavy_hitters.rs`](../tests/e2e_heavy_hitters.rs)
| test_name | test_description | what_is_tested |
| --- | --- | --- |
| `countmin_input_{1..12}_heavy_hitters_hold_the_count_min_bound` | Count-Min holds its one-sided additive contract at the heavy hitters of every documented input. | One shared body per input: takes the top 1% of distinct keys by exact count (`top_percent_keys(&truth, 0.01)`, at least one key) and, for each of the 15 geometries in `{3,5,7} x {2_048, 4_096, 8_192, 16_384, 32_768}` built by `CountMin::with_dimensions` over `Vector2D<i64>`, and again for the fixed-size storages `FixMat1..FixMat15` at those same 15 geometries via `from_storage`, on both `RegularPath` and `FastPath`, verifies at every heavy key that `estimate` never reads below the truth (zero violations tolerated), that the excess is within the union-bounded `b*(N-f)/w` with `b = (D/1e-3)^(1/d)` (zero violations), and that the marginal `e*(N-f)/w` is exceeded at a rate no higher than the theorem's own `e^-d`. Generated for the twelve keyed inputs: `countmin_input_1_heavy_hitters_hold_the_count_min_bound` => 1 (100K uniform `i64` over `[0, 10M)`), `countmin_input_2_heavy_hitters_hold_the_count_min_bound` => 2 (1M uniform `i64`), `countmin_input_3_heavy_hitters_hold_the_count_min_bound` => 3 (100K zipf(1.1) `i64` over 4,096 keys), `countmin_input_4_heavy_hitters_hold_the_count_min_bound` => 4 (1M of the same), `countmin_input_5_heavy_hitters_hold_the_count_min_bound` => 5 (100K zipf(1.1) `i64` over 20,000 keys), `countmin_input_6_heavy_hitters_hold_the_count_min_bound` => 6 (1M of the same), `countmin_input_7_heavy_hitters_hold_the_count_min_bound` => 7, `countmin_input_8_heavy_hitters_hold_the_count_min_bound` => 8, `countmin_input_9_heavy_hitters_hold_the_count_min_bound` => 9, `countmin_input_10_heavy_hitters_hold_the_count_min_bound` => 10, `countmin_input_11_heavy_hitters_hold_the_count_min_bound` => 11 and `countmin_input_12_heavy_hitters_hold_the_count_min_bound` => 12, the last six being the same six shapes carried on `f64` keys. |
| `countsketch_input_{1..12}_heavy_hitters_hold_the_l2_bound` | Count Sketch holds its L2 contract at the heavy hitters of every documented input. | One shared body per input: takes the top 1% of distinct keys by exact count and, for each of the 15 geometries in `{3,5,7} x {2_048, 4_096, 8_192, 16_384, 32_768}` built by `Count::with_dimensions` over `Vector2D<i64>`, and again for `FixMat1..FixMat15` at those same geometries via `from_storage`, on both `RegularPath` and `FastPath`, verifies at every heavy key that `\|est - f\|` is within `sqrt(kappa/w) * \|\|f_-i\|\|_2` at the union-bounded `kappa` from `simultaneous_kappa(probed, 1e-3)` (zero violations tolerated) and that the marginal `sqrt(3/w) * \|\|f_-i\|\|_2` is exceeded at a rate no higher than the spec's own per-key failure probability. The residual norm is recomputed per key as `sqrt(F2 - f^2)`, which is much tighter at a heavy hitter than `\|\|f\|\|_2` would be. Generated for the twelve keyed inputs: `countsketch_input_1_heavy_hitters_hold_the_l2_bound` => 1 (100K uniform `i64` over `[0, 10M)`), `countsketch_input_2_heavy_hitters_hold_the_l2_bound` => 2 (1M uniform `i64`), `countsketch_input_3_heavy_hitters_hold_the_l2_bound` => 3 (100K zipf(1.1) `i64` over 4,096 keys), `countsketch_input_4_heavy_hitters_hold_the_l2_bound` => 4 (1M of the same), `countsketch_input_5_heavy_hitters_hold_the_l2_bound` => 5 (100K zipf(1.1) `i64` over 20,000 keys), `countsketch_input_6_heavy_hitters_hold_the_l2_bound` => 6 (1M of the same), `countsketch_input_7_heavy_hitters_hold_the_l2_bound` => 7, `countsketch_input_8_heavy_hitters_hold_the_l2_bound` => 8, `countsketch_input_9_heavy_hitters_hold_the_l2_bound` => 9, `countsketch_input_10_heavy_hitters_hold_the_l2_bound` => 10, `countsketch_input_11_heavy_hitters_hold_the_l2_bound` => 11 and `countsketch_input_12_heavy_hitters_hold_the_l2_bound` => 12, the last six being the same six shapes on `f64` keys. |
| `space_saving_input_{1..12}_holds_its_capacity_ceiling` | Space-Saving holds the documented `N/m` over-estimate ceiling at every tabulated capacity. | One shared body per input: for capacities `2`, `8`, `64`, `SPACE_SAVING_DEFAULT_CAPACITY` (`1_024`) and `2_048`, fills `SpaceSaving::with_capacity` with the input's whole key stream and verifies `min_count()` is at most `N/m`, that the number of keys reading non-zero equals `summary.len()`, and per monitored key both that `estimate` never reads below the truth and that `estimate - truth` is at most `N/m` — the last two as tallies tolerating zero violations, so a summary that stayed inside the band by dropping the offending keys still fails. Generated for the twelve keyed inputs: `space_saving_input_1_holds_its_capacity_ceiling` => 1 (100K uniform `i64` over `[0, 10M)`), `space_saving_input_2_holds_its_capacity_ceiling` => 2 (1M uniform `i64`), `space_saving_input_3_holds_its_capacity_ceiling` => 3 (100K zipf(1.1) `i64` over 4,096 keys), `space_saving_input_4_holds_its_capacity_ceiling` => 4 (1M of the same), `space_saving_input_5_holds_its_capacity_ceiling` => 5 (100K zipf(1.1) `i64` over 20,000 keys), `space_saving_input_6_holds_its_capacity_ceiling` => 6 (1M of the same), `space_saving_input_7_holds_its_capacity_ceiling` => 7, `space_saving_input_8_holds_its_capacity_ceiling` => 8, `space_saving_input_9_holds_its_capacity_ceiling` => 9, `space_saving_input_10_holds_its_capacity_ceiling` => 10, `space_saving_input_11_holds_its_capacity_ceiling` => 11 and `space_saving_input_12_holds_its_capacity_ceiling` => 12, the last six being the same six shapes on `f64` keys. |
| `elastic_input_{3,4,5,6,9,10,11,12}_hot_flows_stay_within_twenty_percent` | Three injected hot flows stay within the documented 20% on every skewed input. | One shared body per input: over `Elastic::init_with_length(64)` (64 heavy buckets on the default `3x4096` light layer), streams the input's keys as `bg::{key}` while interleaving `hot-alpha`, `hot-beta` and `hot-gamma` in rotation every `stride = background / (per_hot * 3)` records, where `per_hot = round(background * 0.10 / 0.70)` gives each hot flow a tenth of the final stream, and verifies each hot flow's `query` is within a relative `0.20` of its exact injected count. Generated for the eight skewed inputs only: `elastic_input_3_hot_flows_stay_within_twenty_percent` => 3 (100K zipf(1.1) `i64` over 4,096 keys), `elastic_input_4_hot_flows_stay_within_twenty_percent` => 4 (1M of the same), `elastic_input_5_hot_flows_stay_within_twenty_percent` => 5 (100K zipf(1.1) `i64` over 20,000 keys), `elastic_input_6_hot_flows_stay_within_twenty_percent` => 6 (1M of the same), `elastic_input_9_hot_flows_stay_within_twenty_percent` => 9, `elastic_input_10_hot_flows_stay_within_twenty_percent` => 10, `elastic_input_11_hot_flows_stay_within_twenty_percent` => 11 and `elastic_input_12_hot_flows_stay_within_twenty_percent` => 12, the last four being those same four shapes on `f64` keys; the uniform inputs 1, 2, 7 and 8 are not generated. |
### Top-K: Heap-Backed Sketches
Test file: [`tests/e2e_topk.rs`](../tests/e2e_topk.rs)
| test_name | test_description | what_is_tested |
| --- | --- | --- |
| `heaps_satisfy_their_own_bounds_and_stay_heap_consistent` | Both heap-backed sketches hold their own error theorem and keep every heap entry equal to what the sketch estimates. | Feeds 20,000 `zipf(1.1)` draws over a 1,024-key domain at seed `1004` into a `3x4096` `CMSHeap<Vector2D<i64>, RegularPath>` and a `5x4096` `CSHeap<Vector2D<i64>, RegularPath>`, both at `top_k` `16`; runs `CountMinSpec::new(3, 4096).assert_contract` over every key on `cms_heap.estimate` and `CountSketchSpec::new(5, 4096).assert_contract` on `cs_heap.estimate`, then for each heap verifies it holds at most 16 entries, that every entry's stored `count` equals the sketch's current `estimate` for that key (zero violations tolerated), and that at least `15` of the admitted keys have a true count at or above the true 16th count, one displacement slot of slack covering the tie at the boundary. |
### Top-K: Documented Input Matrix
Test file: [`tests/e2e_topk.rs`](../tests/e2e_topk.rs)
| test_name | test_description | what_is_tested |
| --- | --- | --- |
| `heaps_on_input_{3,4,5,6,9,10,11,12}_hold_their_bounds` | Both heaps hold their capacity, per-item error, recall and heap/sketch consistency on every skewed input. | One shared body per input: at `top_k` `32`, `64` and `128`, fills a `5x32768` `CMSHeap<Vector2D<i64>, RegularPath>` and a `5x32768` `CSHeap<Vector2D<i64>, RegularPath>` with the input's whole key stream, then for each heap verifies residency is at most `top_k`, that every entry's stored count equals the sketch's `estimate` for that key, that every entry is within the documented `0.02` per-item relative error of its true count, that at least `top_k - 1` of the admitted keys have a true count at or above the true `top_k`-th count, and that the sketch's own theorem holds at exactly the keys the heap admitted — one-sidedness plus the union-bounded `b*(N-f)/w` for `CMSHeap`, and `sqrt(kappa/w) * \|\|f_-i\|\|_2` with the residual norm recomputed per key for `CSHeap`, both at the `1e-3` simultaneous level and tolerating zero violations. Generated for the eight skewed inputs only: `heaps_on_input_3_hold_their_bounds` => 3 (100K zipf(1.1) `i64` over 4,096 keys), `heaps_on_input_4_hold_their_bounds` => 4 (1M of the same), `heaps_on_input_5_hold_their_bounds` => 5 (100K zipf(1.1) `i64` over 20,000 keys), `heaps_on_input_6_hold_their_bounds` => 6 (1M of the same), `heaps_on_input_9_hold_their_bounds` => 9, `heaps_on_input_10_hold_their_bounds` => 10, `heaps_on_input_11_hold_their_bounds` => 11 and `heaps_on_input_12_hold_their_bounds` => 12, the last four being those same four shapes on `f64` keys. |
### Frameworks: Hydra Pipelines
Test file: [`tests/e2e_frameworks.rs`](../tests/e2e_frameworks.rs)
| test_name | test_description | what_is_tested |
| --- | --- | --- |
| `hydra_cm_multilabel_frequencies` | A Count-Min-backed Hydra answers full keys exactly and generalized keys one-sidedly. | Feeds 25 records of `Str("event")` under each of the four `(region, user)` keys from `[eu, us] x [alice, bob]` into a `4x4096` `Hydra` of `4x4096` fast-path `CountMin` cells, then checks `query_key` with `HydraQuery::Frequency`: full keys `[eu, alice]` and `[us, bob]` within `2.0` of `25`, and the generalized keys `[eu, None]`, `[None, bob]` and `[apac, None]` inside the one-sided band `[expected, expected*1.2 + 1]` around `50`, `50` and `0`. |
| `hydra_kll_head_quantile_and_cdf` | A KLL head answers a median and a CDF inside KLL's own rank error, and zero for an unseen subpopulation. | Ingests 20_000 `uniform_u64(20_000, 1_000_000, 4001)` draws as `F64` under key `s0` into a `4x512` `Hydra` of `KLL::init_kll_with_seed(200, 0x5EED_0600)`, then verifies `Quantile(0.5)` lies between the exact 47th and 53rd percentiles, `Cdf(500_000.0)` is within `KllRankSpec::datasketches(200).epsilon()` (about `0.0165`) of the exact CDF, and `Cdf` under the unseen key `ghost` is exactly `0.0`. |
| `hydra_hll_head_cardinality` | An HLL head recovers each tenant's distinct count. | Inserts `U32(0..500)` under each of tenants `t1` and `t2` into a `4x512` `Hydra` of `HyperLogLog(Default)` cells and verifies `HydraQuery::Cardinality` for both tenants lands in `[450.0, 550.0]`; the estimate is not held to any tighter register model. |
| `hydra_cm_passes_frequency_and_merge_conformance` | A one-column Count-Min grid passes the frequency and merge-equivalence batteries at Count-Min's spec. | Builds `HydraCmAdapter` - a `5x8192` `Hydra` over one key column with `3x64` fast-path `CountMin` cells, keyed by the decimal string of the key and measuring the single value `"hit"` - over `zipf_u64(40_000, 256, 1.1, 5_101)`, and runs `conformance::frequency_battery` and `conformance::merge_equivalence_battery` at `FrequencySpec { one_sided: true, rel_tol: 0.01, abs_tol: 4.0 }`: an absent key must read `\|e\| <= 4.0`, every key with at least 25 occurrences must read in `[count, count*1.01 + 4]`, and the two-shard merge must agree with the single pass within `max(4 + 0.01*count, 2)`. |
| `hydra_cs_passes_signed_frequency_conformance` | A one-column Count Sketch grid passes the two-sided frequency, turnstile and merge batteries. | Same one-column grid with `3x64` `Count` cells (`HydraCsAdapter`) over the same `zipf_u64(40_000, 256, 1.1, 5_101)` stream, run through `frequency_battery`, `turnstile_battery` and `merge_equivalence_battery` at `FrequencySpec { one_sided: false, rel_tol: 0.06, abs_tol: 25.0 }`; the turnstile leg drives key `42` with `+500`, `-200`, `-300` through `Hydra::update`'s `count` and requires `~300` (within `1.0`) and then `0` (within `1e-6`). |
| `hydra_subpopulation_counts_are_exact_on_a_sparse_grid` | Every dense subpopulation of the full lattice is exact on a sparse grid. | Ingests `labelled_stream(30_000, 4_200)` - three key columns (`src_region`, `dst_region`, `status`) over 4/4/3-value domains, measuring a 4-value endpoint - into a `5x4096` `Hydra` of `3x64` `CountMin`, then requires `query_key`'s `Frequency` to equal the exact count with no tolerance for every `(subpopulation, endpoint)` pair of the `2^3 - 1` lattice whose true count is at least 25, and asserts more than 200 such pairs were checked. |
| `hydra_cm_weighted_updates_reach_the_cell_counter` | A weighted update reaches the Count-Min cell, so a subpopulation's frequency is its weighted total. | Through `assert_weighted_updates_reach_the_cell(cell_cm(), \|_\| 0.0)`: ingests `labelled_stream(12_000, 4_240)` into a `5x4096` `Hydra` of `3x64` `CountMin` with per-record weight `1 + i % 7`, and requires every lattice subpopulation whose weighted total is at least 100 to read that total with zero slack, over more than 200 subpopulations. |
| `hydra_cs_weighted_updates_reach_the_cell_counter` | A weighted update reaches the Count Sketch cell within the kit's Count spec. | The same weighted `labelled_stream(12_000, 4_240)` drive over `3x64` `Count` cells, with slack `total*0.06 + 25.0` in place of exactness. |
| `hydra_kll_weighted_updates_repeat_the_value` | A KLL head treats an update's count as multiplicity. | Ingests 20_000 `normal_f64(n, 500.0, 80.0, 4_765)` values under `h2_keys(20_000, 4_760)` two-column keys into a `5x128` `Hydra` of `KLL::init_kll_with_seed(200, 4_766)` with weight `1 + i % 4`, builds the truth by pushing each value `weight` times, and requires every subpopulation of the 2x2 lattice to answer `Quantile(q)` for `q` in `[0.1, 0.25, 0.5, 0.75, 0.9]` inside the exact rank band of half-width `KllRankSpec::datasketches(200).epsilon()`. |
| `hydra_hll_head_subpopulation_cardinalities` | HLL cells answer per-subpopulation distinct counts across the lattice. | Ingests `zipf_u64(40_000, 20_000, 0.2, 4_735)` ids as `U32` under `h2_keys(40_000, 4_730)` into a `5x128` `Hydra` of `HyperLogLog(Default)` cells, asserts the lattice has exactly 8 members, and requires every subpopulation's `Cardinality` to sit in `[0.97, 1.03]` times its exact distinct count. |
| `hydra_kll_head_subpopulation_quantiles` | KLL cells answer per-subpopulation quantiles across the lattice. | Ingests 40_000 `normal_f64(n, 500.0, 80.0, 4_745)` values under `h2_keys(40_000, 4_740)` into a `5x128` `Hydra` of `KLL::init_kll_with_seed(200, 4_746)` and requires every subpopulation of the 2x2 lattice to answer `Quantile(q)` at `q` in `[0.1, 0.25, 0.5, 0.75, 0.9]` inside the exact rank band of half-width `eps(200)` (about `0.0165`). |
| `hydra_marginals_agree_with_the_sum_of_their_children` | A generalized key's answer equals the sum of the full keys beneath it. | Over `labelled_stream(30_000, 5_210)` in a `5x4096` `Hydra` of `3x64` `CountMin`, compares `[Some(region), None, None]` against the summed `Frequency` of all 12 `[Some(region), Some(dst), Some(status)]` full keys, for each of the 4 regions crossed with the 4 endpoints, and requires exact `f64` equality in all 16 cases. |
| `hydra_shard_merge_is_exactly_single_pass` | Merging four Count-Min shards reproduces the single pass with no tolerance. | Ingests `labelled_stream(24_000, 5_220)` once into a `5x2048` `Hydra` of `3x64` `CountMin`, and round-robin into four shards of the same shape, merges them with `Hydra::merge`, then `assert_eq!`s the single-pass and merged `Frequency` answers for every `(subpopulation, endpoint)` key of the `2^3 - 1` lattice, asserting more than 200 comparisons were made. |
| `hydra_columns_sharing_a_value_do_not_alias` | Two key columns over one value domain name distinct subpopulations. | In a `5x1024` `Hydra` of `3x64` `CountMin` over columns `[a, b]`, ingests `[x, y]` 300 times and `[y, x]` 120 times, then asserts `[Some("x"), None]` is `300.0`, `[None, Some("x")]` is `120.0`, `[Some("y"), None]` is `120.0` and `[None, Some("y")]` is `300.0`. |
| `hydra_serde_round_trip_preserves_answers_for_every_counter` | A MessagePack round trip preserves the schema and every counter family's answers. | Runs `serialize_to_bytes` then `deserialize_from_bytes` on five two-column grids, requiring non-empty bytes and `assert_eq!` on the probe answers: `3x512` grids of `3x64` `CountMin` and `3x64` `Count` cells on three frequency probes (`[eu, auth] x /login`, `[eu, None] x /checkout`, `[None, auth] x /query`) with `schema()` equality also checked; a `3x64` grid of `HyperLogLog(Default)` fed `U32(0..2_000)` per key on two `Cardinality` probes; a `3x64` grid of `KLL::init_kll_with_seed(200, 5_301)` fed 6_000 `uniform_u64(_, 100_000, 5_302)` draws on `Quantile(0.5)`, `Quantile(0.9)` and `Cdf(50_000.0)`; and a `3x16` grid of `UnivMon::init_univmon(16, 3, 256, 4)` fed `zipf_u64(6_000, 400, 1.2, 5_303)` on `L1Norm`, `L2Norm`, `Entropy` and `Cardinality`. |
| `hydra_rejects_malformed_keys_and_queries` | Malformed keys, unsupported queries and mismatched merges error, while an empty subpopulation answers zero. | On a `5x256` three-column `Hydra` of `3x64` `CountMin` holding one record, verifies `update` errors on a 2-element and a 4-element key; `query_key` errors on a 1-element key, a 4-element key, the all-`None` key `[None, None, None]` and a `Quantile(0.5)` that a Count-Min cell cannot answer; `merge` errors against a grid whose schema labels differ and against a `5x512` grid; and that `[nowhere, None, None]` reads exactly `0.0` while the single ingested full key reads exactly `1.0`. |
| `hydra_subpopulation_error_stays_within_the_additive_grid_bound` | Subpopulation estimates over-count only, and stay inside the additive grid bound for all but a delta share. | Runs `hydra_additive_bound_config` at `5x4096` and then `5x256`: ingests `zipf_u64(120_000, 8*6*4, 1.1, 4_501)` over columns `region`/`device`/`os` of 8/6/4 values into a `Hydra` of `3x64` `CountMin`, checks the ground truth accounts for exactly `120_000 * 7` post-fan-out units, then asserts every one of the lattice's subpopulations satisfies `est >= truth`, and that the number within `eps*G_s` (`eps = 4/cols`, so `820.3` at 4096 columns and `13_125` at 256) exceeds `total * (1 - delta)` with `delta = median_failure_probability(5, 1/(eps*cols)) = median_failure_probability(5, 0.25)`, about `0.1035`. Also prints a `[hydra additive bound]` diagnostic line per configuration. |
| `hydra_cs_head_subpopulation_frequencies` | A Count Sketch head's dense subpopulations stay inside the symmetric Count band. | Ingests `labelled_stream(30_000, 4_300)` into a `5x4096` `Hydra` of `3x64` `Count` cells and requires every lattice `(subpopulation, endpoint)` pair with at least 25 records to read within `count*0.06 + 25.0` of truth, over more than 200 pairs. |
| `hydra_cs_head_routes_records_to_the_right_cell` | The Count Sketch head routes each record to the cell its subpopulation owns. | Through `assert_head_routes_to_the_right_cell`, which drives a `5x256` two-column `Hydra` over `h2_keys(30_000, seed)` while maintaining one standalone `HydraCounter` clone per lattice subpopulation and then requires `Hydra::query_key` to equal the standalone `HydraCounter::query` exactly for all 8 subpopulations. Here: `3x64` `Count` cells, key seed `4_612`, values `Str(ENDPOINTS[zipf_u64(30_000, 4, 0.5, 4_615)[i]])`, probed with `Frequency(Str("/login"))`. Both sides run the same query code, so this pins routing only, not accuracy. |
| `hydra_hll_head_routes_records_to_the_right_cell` | The HLL head routes each record to the cell its subpopulation owns. | The same routing drive with `HyperLogLog(Default)` cells, key seed `4_610`, values `U32(i.wrapping_mul(2_654_435_761) % 12_000)`, probed with `Cardinality` on all 8 subpopulations. |
| `hydra_kll_head_routes_records_to_the_right_cell` | The KLL head routes each record to the cell its subpopulation owns. | The same routing drive with `KLL::init_kll_with_seed(200, 4_641)` cells, key seed `4_630`, values `F64(normal_f64(30_000, 500.0, 80.0, 4_640)[i])`, probed with `Quantile(0.5)` on all 8 subpopulations. |
| `hydra_univmon_head_routes_records_to_the_right_cell` | The UnivMon head routes each record to the cell its subpopulation owns. | The same routing drive with `UnivMon::init_univmon(32, 5, 256, 8)` cells, key seed `4_650`, values `U32(zipf_u64(30_000, 1000, 1.2, 4_660)[i])`, probed with both `L1Norm` and `Cardinality` on all 8 subpopulations. |
| `hydra_univmon_head_subpopulation_metrics` | UnivMon cells answer L1, L2 and entropy per subpopulation over a weighted stream. | Ingests `zipf_u64(40_000, 1000, 1.2, 4_775)` items as `U32` under `h2_keys(40_000, 4_770)` with weight `1 + i % 7` into a `5x128` `Hydra` of `UnivMon::init_univmon(32, 5, 256, 8)`, asserts the lattice has exactly 8 members, and for each requires `L1Norm` to equal the exact weighted total with no tolerance, `L2Norm` within `5%` and `Entropy` within `12%` of the exact values. |
| `hydra_univmon_head_l1_is_exact_per_subpopulation` | A weighted L1 survives the fan-out exactly in every subpopulation. | Ingests `zipf_u64(30_000, 1000, 1.2, 4_660)` as `U32` under `h2_keys(30_000, 4_650)` with weight `1 + i % 7` into a `5x256` `Hydra` of `UnivMon::init_univmon(32, 5, 256, 8)`, asserts the lattice has exactly 8 members, and `assert_eq!`s `L1Norm` against the exact weighted total for each; no other metric is checked. |
| `hydra_shard_merge_preserves_answers_for_every_counter` | A two-shard merge reproduces the single pass for the Count Sketch, HLL, KLL and UnivMon heads. | For each counter, ingests `h2_keys(24_000, 4_670)` into one single-pass and two shard grids (`5x256`, columns `[region, service]`), splitting by `uniform_u64(24_000, 2, 4_675)`, merges, and probes the three `h2_masks("eu-west", "auth")` keys: `3x64` `Count` cells must match the single pass exactly on all four endpoints; `HyperLogLog(Default)` exactly on `Cardinality`; `KLL::init_kll_with_seed(200, 4_681)` fed shard-separated `normal_f64(_, 300.0, 20.0, 4_680)` and `normal_f64(_, 700.0, 20.0, 4_685)` modes must land in the exact rank band of half-width `eps(200)` at `q` in `[0.1, 0.25, 0.5, 0.75, 0.9]`; and `UnivMon::init_univmon(32, 5, 256, 8)` over `zipf_u64(24_000, 800, 1.2, 4_690)` must give an `L1Norm` exactly equal to both the exact weighted total and the single pass, with `L2Norm` inside `univmon_l2_band(exact, 5, 256)`, i.e. `[L2*sqrt(1-b), L2*sqrt(1+b)]` for `b = sqrt(2*3/256)`. Despite the name, Count-Min is not one of the counters exercised here. |
| `hydra_query_frequency_is_the_frequency_query_it_wraps` | `query_frequency` answers exactly what the `Frequency` query it wraps answers. | Feeds 25 records of `Str("event")` under each of the four `[eu, us] x [alice, bob]` keys into a `4x4096` `Hydra` of `4x4096` fast-path `CountMin`, then `assert_eq!`s `Hydra::query_frequency` against `query_key` with `HydraQuery::Frequency` on five keys (`[eu, alice]`, `[us, bob]`, `[eu, None]`, `[None, bob]`, `[apac, None]`), and verifies a 1-element key is an error while `[apac, nobody]` answers exactly `0.0`. Only agreement with the wrapped query is pinned; no accuracy band is asserted. |
| `hydra_query_quantile_is_the_cumulative_query_it_wraps` | `query_quantile` answers the `Cdf` query it wraps, inside KLL's rank error. | Ingests 20_000 `uniform_u64(20_000, 1_000_000, 4_101)` draws as `F64` under key `s0` into a `4x512` `Hydra` of `KLL::init_kll_with_seed(200, 0x5EED_0700)`, then for `x` in `{100_000, 250_000, 500_000, 750_000, 900_000}` `assert_eq!`s `query_quantile(key, x)` against `query_key(key, Cdf(x))` - the wrapper returns a CDF, not a quantile - and requires it within `eps(200)` (about `0.0165`) of the exact CDF; also that `ghost` reads exactly `0.0` and that an empty key `&[]` is an error. |
### Frameworks: UnivMon Pipelines
Test file: [`tests/e2e_frameworks.rs`](../tests/e2e_frameworks.rs)
| test_name | test_description | what_is_tested |
| --- | --- | --- |
| `univmon_weighted_metrics_and_fast_insert_parity` | UnivMon's weighted L1 is exact and its L2, entropy and cardinality hold their bands, with `fast_insert` tracking the standard path. | Drives two `UnivMon::init_univmon(32, 5, 2048, 8)` sketches over `zipf_u64(20_000, 1000, 1.2, 4003)` with weight `1 + i % 7`, one through `insert` and one through `fast_insert`, then asserts both `calc_l1()` equal the exact weighted total with `assert_eq!`; `calc_l2()` inside `univmon_l2_band(exact, 5, 2048)` (`b = sqrt(2*3/2048)`, about `0.054`); `calc_entropy()` in `[0.88, 1.12]` times the exact bits; `calc_card()` in `[0.94, 1.06]` times the exact distinct count; and the fast path's `calc_l2()` in `[0.85, 1.15]` times exact. |
| `univmon_pyramid_weighted_metrics` | UnivMonPyramid's weighted L1 is exact and its L2 and cardinality hold their bands. | Drives `UnivMonPyramid::with_defaults()` over `zipf_u64(15_000, 800, 1.3, 4004)` with weight `1 + i % 3` and asserts `calc_l1()` equals the exact weighted total with `assert_eq!`, `calc_l2()` is in `[0.85, 1.15]` times exact, and `calc_card()` in `[0.80, 1.20]` times the exact distinct count; entropy is not checked. |
| `univmon_generic_g_sum_reproduces_every_named_estimator` | The generic g-sum reproduces the L2, cardinality and entropy estimators and its own heuristic delegate. | Over `UnivMon::init_univmon(32, 5, 2_048, 8)` fed `zipf_u64(20_000, 1_000, 1.2, 4_201)` with weight `1 + i % 7`, `assert_eq!`s `calc_g_sum(\|x\| x*x, false).sqrt()` against `calc_l2()`, `calc_g_sum(\|_\| 1.0, true)` against `calc_card()`, `calc_g_sum(x^2, false)` against `calc_g_sum_heuristic(x^2, false)`, and `calc_g_sum(\|_\| 0.0, false)` against `0.0`; requires `calc_entropy()` to equal `log2(L1) - gsum(x*log2 x)/L1` within `1e-9`; and checks `calc_g_sum(\|x\| x, false)` only against `[0.50, 1.50]` times the exact L1, so the identity g-sum's agreement with L1 is not pinned tightly. |
| `univmon_g_sum_is_zero_on_an_empty_sketch` | An empty UnivMon reports zero for every estimator. | On a fresh `UnivMon::init_univmon(32, 5, 256, 4)`, `assert_eq!`s `calc_l1()`, `calc_entropy()`, `calc_g_sum(\|x\| x*x, false)` and `calc_card()` each against `0.0`. |
| `a_univmon_pool_recycles_a_returned_sketch_and_hands_back_a_cleared_one` | A returned sketch becomes available again and comes back cleared without a new allocation. | On `UnivSketchPool::new(2, 16, 3, 256, 4)`: asserts `available() == 2` and `total_allocated() == 2` when fresh, `available() == 0` after two `take()`s with `total_allocated()` still `2`, and `total_allocated() == 3` after a third `take()` past capacity; then fills the first sketch with `zipf_u64(5_000, 512, 1.1, 4_202)` inserts (checking `calc_l1() > 0.0`), `put()`s it back and asserts `available() == 1`, and requires the next `take()` to report `calc_l1() == 0.0` with `total_allocated()` still `3`. |
### Frameworks: Windowed Pipelines
Test file: [`tests/e2e_frameworks.rs`](../tests/e2e_frameworks.rs)
| test_name | test_description | what_is_tested |
| --- | --- | --- |
| `exponential_histogram_sliding_window_counts` | An ExponentialHistogram over Count-Min buckets answers a merged interval and reports its retained span. | Builds `ExponentialHistogram::new(8, 100, EHSketchList::CM(3x2048 fast-path CountMin))` and calls `update(t, Str("req"))` at every `t` in `0..500` divisible by 3, then asserts `query_interval_merge(400, 499)`'s Count-Min count for `Str("req")` is in `[26.0, 40.0]` - the 33 events actually in that range are not pinned - that `get_max_time()` is exactly `498`, that `cover(get_min_time(), 498)` is true, and that `cover(500, 600)` is false. The value of `get_min_time()` itself is not asserted. |
| `tumbling_foldcms_weighted_windows_exact_counts` | A TumblingWindow of FoldCMS closes windows on schedule and keeps weighted counts exact across all, recent and flushed queries. | Builds `TumblingWindow::<FoldCMS>::new(10, 16, FoldCMSConfig { rows: 3, full_cols: 2048, fold_level: 0, top_k: 32 }, 4)`, inserts `Str("A")` at weight 2 and `Str("B")` at weight 1 at every `t` in `0..35`, then asserts `closed_count() == 3`; `query_all()` returns exactly `70` for `A` and `35` for `B`; `query_recent(2)` returns exactly `50` and `25` (covering `t` in `[10, 35)`); and after `flush(40)` that `closed_count() == 5` and `query_all()` is still exactly `70` and `35`. |
### Frameworks: Documented Input Matrix
Test file: [`tests/e2e_frameworks.rs`](../tests/e2e_frameworks.rs)
| test_name | test_description | what_is_tested |
| --- | --- | --- |
| `univmon_family_on_input_{1..12}_holds_its_metrics` | UnivMon, its fast-insert path and UnivMonPyramid hold the documented bands on each of the twelve keyed inputs. | `univmon_documented_input(id)` builds two `UnivMon::init_univmon(32, 5, 2_048, 16)` (one driven by `insert`, one by `fast_insert`) plus a `UnivMonPyramid::with_defaults()`, drives every element of `common::inputs::key_input(id)` with weight `1 + i % 7`, and asserts: all three `calc_l1()` equal the exact weighted total with `assert_eq!`; `um.calc_entropy()` in `[0.88, 1.15]` times the exact bits; `calc_l2()` within `11%` (UnivMon), `18%` (fast-insert) and `15%` (pyramid) of the exact L2; and `calc_card()` within `30%` of the exact distinct count for both UnivMon and the pyramid. Generated by `documented_univmon_inputs!` as `univmon_family_on_input_1_holds_its_metrics` (id 1, 100K uniform `i64` over `[0, 10M)`), `univmon_family_on_input_2_holds_its_metrics` (2, 1M uniform `i64`), `univmon_family_on_input_3_holds_its_metrics` (3, 100K Zipf(1.1) over 4096 keys), `univmon_family_on_input_4_holds_its_metrics` (4, 1M Zipf(1.1) over 4096 keys), `univmon_family_on_input_5_holds_its_metrics` (5, 100K Zipf(1.1) over 20000 keys), `univmon_family_on_input_6_holds_its_metrics` (6, 1M Zipf(1.1) over 20000 keys), `univmon_family_on_input_7_holds_its_metrics` (7, 100K uniform as `f64`), `univmon_family_on_input_8_holds_its_metrics` (8, 1M uniform as `f64`), `univmon_family_on_input_9_holds_its_metrics` (9, 100K Zipf(1.1) 4096 keys as `f64`), `univmon_family_on_input_10_holds_its_metrics` (10, 1M Zipf(1.1) 4096 keys as `f64`), `univmon_family_on_input_11_holds_its_metrics` (11, 100K Zipf(1.1) 20000 keys as `f64`) and `univmon_family_on_input_12_holds_its_metrics` (12, 1M Zipf(1.1) 20000 keys as `f64`). |
| `hydra_cm_head_on_input_13_holds_its_additive_grid_bound` | The Count-Min head over the uniform string input over-counts only, and holds both the documented absolute error and Hydra's additive grid bound. | `hydra_cm_head_documented_input(13)` ingests all 100_000 words of `string_input(13)` (uniform 3-character strings over `A-Za-z0-9`) under `[HYDRA_REGIONS[i % 4], word]` into a `4x4096` `Hydra` of `4x4096` fast-path `CountMin`, then asserts: every full key's estimate is within `1_000.0` of truth; every probed full key satisfies `est >= truth` (`one_sided == probed`); the count of full keys within `eps*G_s = (4/4096)*300_000 = 293` exceeds `probed*(1 - delta)` for `delta = median_failure_probability(4, 0.25)`, about `0.0508`; each `[Some(region), None]` query lands in `[truth, truth*1.2 + 1]`; and the unseen `[Some("nowhere"), None]` reads at most `100.0` and at most `293`. |
| `hydra_cm_head_on_input_14_holds_its_additive_grid_bound` | The Count-Min head holds the same bounds on the skewed string input. | The same `hydra_cm_head_documented_input` drive over `string_input(14)` - 100_000 Zipf(1.1) 3-character words over a 4096-word domain - at the same `4x4096` grid and `4x4096` cell geometry, with the same `1_000.0` absolute error, one-sided check, `293` additive bound at `delta ~ 0.0508`, one-`None` band `[truth, truth*1.2 + 1]` and `100.0` unseen-key ceiling. |
| `hydra_kll_head_on_input_7_holds_its_rank_and_cdf_bounds` | The KLL head holds the documented median rank error and CDF error per shard on the 100K float input. | `hydra_kll_head_documented_input(7)` splits `key_input(7)` (100K uniform `[0, 10M)` draws carried as `f64`) round-robin over four shards `s0..s3` of a `4x512` `Hydra` of `KLL::init_kll_with_seed(200, 0x5EED_0700 + 7)`, then per shard asserts `Quantile(0.5)` lies in the exact rank band at tolerance `0.03` via `assert_in_rank_band`, and that `Cdf(truth.quantile(q))` is within `0.03` absolute of the exact CDF at every decile `q = 0.1 .. 0.9`. |
| `hydra_kll_head_on_input_8_holds_its_rank_and_cdf_bounds` | The KLL head holds the same rank and CDF bounds on the 1M float input. | The same four-shard drive over `key_input(8)` - 1M uniform `[0, 10M)` draws as `f64` - at `4x512` with `KLL::init_kll_with_seed(200, 0x5EED_0700 + 8)`, the same `0.03` median rank tolerance and the same `0.03` absolute CDF error at each decile. |
| `hydra_hll_head_on_input_1_recovers_its_subpopulation_cardinalities` | The HLL head recovers each tenant's distinct count inside both the documented error and its own register model. | `hydra_hll_head_documented_input(1)` splits `key_input(1)` (100K uniform `i64` over `[0, 10M)`) round-robin over four tenants `t0..t3` of a `4x512` `Hydra` of `HyperLogLog(Default)` cells, then per tenant asserts `Cardinality`'s relative error against the exact distinct count is at most `0.10`, and that it also passes `CardinalityConfidenceSpec::hll(14, 4.0).check`, the tighter `4 * 1.04/sqrt(16384) = 3.25%` band that actually binds. |
| `hydra_hll_head_on_input_2_recovers_its_subpopulation_cardinalities` | The HLL head holds the same cardinality bounds on the 1M input. | The same four-tenant drive over `key_input(2)` - 1M uniform `i64` draws over `[0, 10M)` - at `4x512` with `HyperLogLog(Default)` cells, the same `10%` documented ceiling and the same binding `3.25%` `CardinalityConfidenceSpec::hll(14, 4.0)` band. |
### Windows: Exponential Histogram Payload Variants
Test file: [`tests/e2e_windows.rs`](../tests/e2e_windows.rs)
| test_name | test_description | what_is_tested |
| --- | --- | --- |
| `every_eh_variant_selects_the_documented_merge_norm` | Each `EHSketchList` payload selects the merge norm its enclosing histogram uses. | For `COUNTL2HH` (`CountL2HH::with_dimensions(3, 512)`) and `UNIVMON` (`UnivMon::init_univmon(32, 3, 512, 4)`) asserts `supports_norm(SketchNorm::L2)` and `!supports_norm(SketchNorm::L1)`, and that `ExponentialHistogram::new(8, 1_000_000, proto).merge_norm` is `SketchNorm::L2`; for `CM` and `CS` (`Vector2D<i32>` `FastPath` at `3x512`), `COCO(512, 4)`, `ELASTIC(512)`, `HLL<ErtlMLE>`, `KLL(k=200, seed 0x5EED_0100)` and `DDS(alpha=0.01)` asserts `supports_norm(SketchNorm::L1)` and `merge_norm == SketchNorm::L1`. |
| `eh_count_min_variant_conforms_to_the_count_min_model_over_the_retained_window` | A Count-Min payload satisfies Count-Min's theorem over the histogram's full retained span. | Feeds `10_000` Zipf(1.1) keys over a `2_048` domain (seed `0x0E11_0001`), one per timestamp `t = 0..9_999`, into `ExponentialHistogram::new(8, 1_000_000, EHSketchList::CM(CountMin::<Vector2D<i32>, FastPath>::with_dimensions(3, 512)))`, merges the full retained span with `query_interval_merge(payload.first().min_time, payload.last().max_time)`, and runs `CountMinSpec::new(3, 512).assert_contract` over the exact truth for that span: one-sidedness `est >= f` with zero violations, the simultaneous budget `b*(N-f)/w` with `b = (D/1e-3)^(1/3)` and zero violations, and the marginal `e*(N-f)/w` as a rate pin at `e^-3 = 0.0498`. |
| `eh_count_sketch_variant_conforms_to_the_l2_model_over_the_retained_window` | A Count Sketch payload satisfies the two-sided L2 bound over the retained span. | Same `10_000`-key Zipf(1.1) stream, domain `2_048`, seed `0x0E11_0001`, `k = 8`, window `1_000_000`, payload `EHSketchList::CS(Count::<Vector2D<i32>, FastPath>::with_dimensions(3, 512))`; the full-span merge is judged by `CountSketchSpec::new(3, 512).assert_contract`, which requires `\|est - f\|` under `sqrt(kappa/512)*\|\|f_-i\|\|_2` at the simultaneous `kappa` (union-bounded to `delta = 1e-3` over every probed key, zero violations) and pins the marginal `sqrt(3/512)*\|\|f_-i\|\|_2` violation rate at `P[Bin(3, 1/3) >= 2] = 7/27`. |
| `eh_countl2hh_variant_satisfies_the_l2_bound_over_the_retained_window` | A `CountL2HH` payload keeps the L2 bound of the Count Sketch matrix underneath it. | Same `10_000`-key Zipf(1.1) stream, domain `2_048`, seed `0x0E11_0001`, `k = 8`, window `1_000_000`, payload `EHSketchList::COUNTL2HH(CountL2HH::with_dimensions(3, 512))`; the full-span merge is held to `CountSketchSpec::new(3, 512).assert_contract` - the simultaneous L2 band at `delta = 1e-3` with zero violations and the marginal `sqrt(3/512)*\|\|f_-i\|\|_2` rate pin - reading frequencies through `merged.query(&DataInput::U64(k))`. |
| `eh_heavy_hitter_variants_stay_one_sided_over_the_retained_window` | The eviction-based payloads never read a retained heavy key below its true count. | For `COCO(1024, 4)` and `ELASTIC(1024)` inside `ExponentialHistogram::new(8, 1_000_000, ..)`, feeds `10_000` Zipf(1.1) draws over a `2_048` domain (seed `0x0E11_0001`) as `DataInput::String("f{k}")` at `t = 0..9_999`, merges the full retained span, and asserts `est >= c` for the truth's top `32` keys with zero violations. Only the one-sided direction is asserted: no upper bound is placed on the reported counts, and keys outside the top `32` are not probed. |
| `eh_hll_variant_satisfies_the_register_error_model_over_the_retained_window` | A merged HLL payload lands inside the register error model for the retained span's cardinality. | Feeds `10_000` uniform draws over `200_000` (seed `0x0E11_0001`) into `ExponentialHistogram::new(8, 1_000_000, EHSketchList::HLL(HyperLogLog::<ErtlMLE>::new()))`, merges the full retained span, and checks `merged.query(&DataInput::Str("card"))` against the exact distinct count of that span under `CardinalityConfidenceSpec::hll(14, 4.0)` - a relative band of `4 * 1.04 / 2^7 = 0.0325` at `m = 2^14` registers. This is a single trial, aggregated by `assert_independent_binomial` at `p = 6.3e-5`, so no violation is tolerated. |
| `eh_kll_variant_satisfies_the_rank_error_characterization_over_the_retained_window` | A merged KLL payload's worst rank error stays inside the DataSketches characterization across independent compaction seeds. | Builds `12` separate `ExponentialHistogram::new(8, 1_000_000, EHSketchList::KLL(KLL::init_kll_with_seed(200, seed)))` instances with `seed = 0x5EED_0200 + t * 0x9E37_79B9_7F4A_7C15`, feeds each the same `10_000` uniform values over `1_000_000` (stream seed `0x0E11_0001`) at `t = 0..9_999`, merges each one's full retained span, and reduces each trial to its worst normalized rank error over the grid `[0.1, 0.25, 0.5, 0.75, 0.9]` read through `merged.query(&DataInput::F64(q))`; `KllRankSpec::datasketches(200)` supplies `eps = 2.446/200^0.9433 = 0.0165`, and the `12` trial outcomes are accepted by `assert_independent_binomial` at `p = 0.01`. |
| `eh_ddsketch_variant_satisfies_the_relative_value_error_contract_over_the_window` | A merged DDSketch payload holds relative value error and retains every observation. | Feeds `10_000` values `1_000_000 + uniform[0, 9_000_000)` (seed `0x0E11_0001`) into `ExponentialHistogram::new(8, 1_000_000, EHSketchList::DDS(DDSketch::new(0.01)))`, merges the full retained span, and checks `merged.query(&DataInput::F64(q))` at `q` in `[0.1, 0.25, 0.5, 0.75, 0.9]` against the span's exact order statistics under `RelativeQuantileSpec::core(0.01)` (`CeilNearestRank` convention, tolerance `alpha` plus a few-ULP slack) with zero violations; then asserts `merged.query(&DataInput::Str("count"))` equals the span's observation count exactly. |
| `eh_univmon_variant_reports_the_exact_l1_over_the_retained_window` | A merged UnivMon payload reports L1 exactly and L2 inside the AMS second-moment band of its own grid. | Feeds `10_000` Zipf(1.1) keys over a `2_048` domain (seed `0x0E11_0001`) into `ExponentialHistogram::new(8, 1_000_000, EHSketchList::UNIVMON(UnivMon::init_univmon(32, 5, 2_048, 8)))`, merges the full retained span, and asserts `query(&DataInput::Str("l1"))` equals the span's exact total mass; then asserts `query(&DataInput::Str("l2"))` lies in `[\|\|f\|\|_2 * sqrt(1-b), \|\|f\|\|_2 * sqrt(1+b)]` with `b = SecondMomentSpec::new(5, 2_048).relative_bound() = sqrt(2*3/2048) = 0.0541`, i.e. about `-2.7%/+2.7%` on the norm. The bound asserted is the terminal layer's, not a composed constant for the recurrence. |
| `every_eh_variant_can_merge_into_its_own_kind` | Every mergeable `EHSketchList` variant has a merge arm, so bucket consolidation cannot silently drop a payload. | For `CM` and `CS` at `3x256`, `COCO(256, 4)`, `COUNTL2HH` at `3x256`, `DDS(0.01)`, `ELASTIC(256)`, `HLL<ErtlMLE>`, `KLL(200, seed 0x5EED_0300)`, `UNIVMON(32, 3, 256, 4)` and - under `--features experimental` - `UNIFORM(UniformSampling::with_seed(0.5, 7))`, feeds each side `64` distinct `DataInput::String` keys and `64` distinct `DataInput::F64` values (`k0..k63` / `1.0..64.0` on the left, `k64..k127` / `100.0..163.0` on the right) and asserts `left.merge(&right).is_ok()`. Only the `Ok` status is asserted; the merged contents are not read back. |
| `eh_uniform_sampling_variant_reports_exact_retention_bookkeeping` | The reservoir payload's retention counters are exact over the merged span and its samples were all observed. | Gated on `#[cfg(feature = "experimental")]`. Feeds `10_000` uniform values over `1_000_000` (seed `0x0E11_0001`) into `ExponentialHistogram::new(8, 1_000_000, EHSketchList::UNIFORM(UniformSampling::with_seed(0.1, 0x5A_9101)))`, merges the full retained span, and asserts `query(&DataInput::Str("total_seen"))` equals `hi - lo + 1` exactly, that `query(&DataInput::Str("len"))` is greater than `0` and at most `total_seen`, and that every sample index `0..len` returns a value whose bit pattern appears in the span. The retained count is not held against the `0.1` rate's budget beyond `<= total_seen`. |
### Windows: Exponential Histogram Semantics
Test file: [`tests/e2e_windows.rs`](../tests/e2e_windows.rs)
| test_name | test_description | what_is_tested |
| --- | --- | --- |
| `eh_expires_buckets_past_the_window_and_reports_its_retained_span` | Buckets older than the window are dropped whole, so the retained span can run longer than the window, and it is reported honestly. | With `ExponentialHistogram::new(8, 100, EHSketchList::CM(CountMin::<Vector2D<i32>, FastPath>::with_dimensions(3, 512)))` updated with `Str("req")` at every `t` in `0..500` divisible by `3`, asserts `get_max_time()` is `498`, `cover(get_min_time(), 498)` is true, `cover(500, 600)` is false, and that every retained bucket's `max_time` is at or past the cutoff `498 - 100 = 398`; the full-span merge is then required only to read `>=` the number of retained multiples of `3`, so the exact retained count is not pinned and `get_min_time()` is not pinned to a value. The survival test is per bucket, not per event: a bucket lives while its `max_time` reaches the cutoff, so its `min_time` may lie before the cutoff and `get_min_time()` may sit up to the oldest bucket's own span earlier than `max_time - 100`. |
| `an_exponential_histogram_expires_against_the_window_length_it_was_last_given` | Expiry is lazy — it runs inside the insert path, so `update_window` takes effect on the next insert and never on its own — and widening the window cannot resurrect expired buckets. | With `ExponentialHistogram::new(8, 10_000, EHSketchList::CM(CountMin::<Vector2D<i32>, FastPath>::with_dimensions(3, 512)))` fed `200` updates of `U64(t % 32)` at timestamps `t*10` (`0` to `1_990`), asserts the retained span starts at `0`; after `update_window(100)` and one update at `t = 2_000`, asserts the span start moved strictly later and `get_max_time() == Some(2_000)`; after `update_window(10_000)` and an update at `t = 2_010`, asserts the span start is still at or past the narrow one. The window changes are checked by inequality only: no exact retained span is pinned after either call. |
| `an_exponential_histogram_custom_bucket_update_matches_repeated_inserts` | `update_with` reproduces `update`'s bucket structure and answers, and a doubled custom insert never reads lower. | Runs two `ExponentialHistogram::new(8, 1_000_000, EHSketchList::CM(CountMin::<Vector2D<i32>, FastPath>::with_dimensions(3, 512)))` over `t = 0..499` with key `U64(t % 64)`, one through `update` and one through `update_with` performing a single `insert`, then asserts equal `bucket_count()` and, for all `64` keys, exactly equal estimates from the two full-span merges. A third histogram whose `update_with` inserts the key twice is asserted only to read `>=` the single-insert histogram per key - the doubling is not pinned to a factor of two. |
### Windows: Tumbling Windows and Sketch Pools
Test file: [`tests/e2e_windows.rs`](../tests/e2e_windows.rs)
| test_name | test_description | what_is_tested |
| --- | --- | --- |
| `tumbling_fold_cs_windows_are_exact_and_answers_satisfy_the_l2_bound` | Every `FoldCS` window slice covers exactly its time range and answers inside the L2 bound at the folded width. | With `FoldCSConfig { rows: 3, full_cols: 4_096, fold_level: 2, top_k: 32 }` in `TumblingWindow::new(500, 16, cfg, 4)` fed `3_000` Zipf(1.1) keys over a `512` domain (seed `0x0E11_0001`) at `t = 0..2_999`, asserts `closed_count() == 5`, then runs `CountSketchSpec::new(3, 1_024)` (`4_096 >> 2`) against exact truth for `active_sketch()` (the last `500` keys), `query_all()` (all `3_000`) and `query_recent(2)` (the last `1_500`). After `flush(3_000)`, inserting `U64(7)` at `t = 3_000` must make the recycled active sketch read exactly `1`, and `closed_count()` must be at least `6`. |
| `tumbling_univmon_q_windows_carry_exact_aggregates_through_rotation` | UnivMon-Q's exact aggregates stay exact on every window slice and survive pool recycling. | With `UnivMonQConfig { levels: 6, width: 1_024, depth: 5, candidates: 256, ordered_samples: 512, ..default() }` in `TumblingWindow::new(500, 16, cfg, 4)` fed `3_000` uniform values over `100_000` (seed `0x0E11_0001`) at `t = 0..2_999`, asserts `closed_count() == 5` and, for `query_all()` (all `3_000`), `query_recent(1)` (the last `1_000`) and `active_sketch()` (the last `500`), that `count()` equals the slice length and `min()`/`max()` equal the slice's exact extremes; after `flush(3_000)` and one insert of `42.0`, asserts `count() == 1` and `min() == max() == Some(42.0)`. UnivMon-Q's estimators are not exercised here. |
| `tumbling_fold_cms_hierarchical_merge_covers_every_observation` | `query_all_hierarchical` on `FoldCMS` never narrows the sketch, never underestimates, and never exceeds the flat merge. | With `FoldCMSConfig { rows: 3, full_cols: 4_096, fold_level: 2, top_k: 32 }` in `TumblingWindow::new(500, 16, cfg, 4)` fed `3_000` Zipf(1.1) keys over a `512` domain (seed `0x0E11_0001`), asserts `query_all_hierarchical().fold_cols() >= query_all().fold_cols()`, runs `CountMinSpec::new(3, hierarchical.fold_cols()).assert_contract` against the exact truth for all `3_000` observations, and asserts per key that the hierarchical estimate is at or above the true count and at or below the flat `query_all()` estimate, plus `total_entries() > 0`. |
| `tumbling_window_pool_accounting_tracks_every_recycled_sketch` | The window pool's allocation accounting balances against the windows that hold its sketches. | With `KLLConfig { k: 200, m: 8, seed: Some(0x7001_0001) }` in `TumblingWindow::new(100, 2, cfg, 4)`, asserts `pool_total_allocated() == 4` and `pool_available() == 3` before any insert; after `800` inserts of `U64(t % 97)` at `t = 0..799`, asserts `closed_count() == 2`, `pool_available() > 0`, `pool_total_allocated() >= 4`, and the invariant `pool_available() + closed_count() + 1 == pool_total_allocated()`. |
| `a_sketch_pool_reuses_a_returned_sketch_before_allocating_a_new_one` | A returned sketch is handed back cleared and in preference to a fresh allocation. | On `SketchPool::<KLL>::new(2, KLLConfig { k: 200, m: 8, seed: Some(0x7001_0002) })` asserts `available() == 2` and `total_allocated() == 2`; two `take()` calls leave `available() == 0` with `total_allocated()` still `2`; a third `take()` raises `total_allocated()` to `3`; the first sketch is dirtied with `1_000` `update` calls and returned with `put`, after which `available() == 1`, the next `take()` returns a sketch with `count() == 0`, and `total_allocated()` is still `3`. |
### Windows: Documented Input Matrix
Test file: [`tests/e2e_windows.rs`](../tests/e2e_windows.rs)
| test_name | test_description | what_is_tested |
| --- | --- | --- |
| `eh_input_{3..6,14}_interval_counts_and_expiry` | The documented sliding-window row holds interval counts, the retained span and expiry on each of its inputs. | One macro-generated body per input, all at the document's configuration: `ExponentialHistogram::new(8, 100, EHSketchList::CM(CountMin::<Vector2D<i32>, FastPath>::with_dimensions(3, 2_048)))`, with the stream spread over `1_000` time units (`t = i * 1_000 / n`) so a window of `100` retains about a tenth of it. Each body asserts `get_max_time()` equals the last timestamp fed, `cover(min_time, max_time)`, `!cover(max_time + 1, max_time + 1_000)`, and `min_time + 200 >= max_time`; then, over the events at or after `min_time` (a superset of the retained window), the full-span merge's excess per key must not exceed `CountMinSpec::new(3, 2_048).simultaneous_bound(retained_mass, f, probed_keys, 1e-3)` with zero violations; finally, for the interval `[min_time + (max_time - min_time)/4, max_time]` the single heaviest key's merged count must be within `21%` relative of the exact interval count - a two-sided band covering `query_interval_merge`'s snapping to bucket boundaries. Generated names and their inputs: `eh_input_3_interval_counts_and_expiry` on `key_input(3)` (100K Zipf(1.1) `i64` over a 4096-key domain), `eh_input_4_interval_counts_and_expiry` on `key_input(4)` (1M, same shape), `eh_input_5_interval_counts_and_expiry` on `key_input(5)` (100K Zipf(1.1) `i64` over a 20000-key domain), `eh_input_6_interval_counts_and_expiry` on `key_input(6)` (1M, same shape), and `eh_input_14_interval_counts_and_expiry` on `string_input(14)` (100K Zipf(1.1) 3-character strings over a 4096-key domain, fed as `DataInput::String`). |
### Composition: HashSketchEnsemble
Test file: [`tests/e2e_composition.rs`](../tests/e2e_composition.rs)
| test_name | test_description | what_is_tested |
| --- | --- | --- |
| `ensemble_members_match_standalone_sketches_fed_the_same_stream` | Matrix members read identically to standalone sketches, and the HLL members read as accurately. | Builds `HashSketchEnsemble::new` over `CountMin::<Vector2D<i32>, FastPath>` and `Count::<Vector2D<i32>, FastPath>` at `3x4096`, `HyperLogLog<ErtlMLE>`, `HyperLogLog<Classic>` and `HyperLogLogHIP`, plus one standalone reference of each, and feeds all of them `40_000` Zipf(1.1) keys over a `2_048` domain (seed `0xC090_5101`). Asserts `ens.estimate(0, ..)` and `ens.estimate(1, ..)` equal the standalone `estimate` exactly for every observed key, with zero violations. The three HLL cells are held to their own bands - `CardinalityConfidenceSpec::hll(14, 4.0)` at `4 * 1.04 / 2^7 = 0.0325` for the two register estimators and `hll_hip(14, 4.0)` at `4 * sqrt(ln2 / 2^14) = 0.026` for HIP - as are the standalone readings, and each ensemble/standalone pair must agree to within `2x` that band (relative to the true distinct count), since the ensemble feeds its HLL members the low 64 bits of the shared matrix hash rather than the canonical seed. The band checks are scored as two trials, one per hash function, by `assert_independent_binomial` at `p = 6.3e-5`. |
| `ensemble_members_stay_inside_their_own_error_models` | Riding the shared hash path leaves each member inside its own family's bound. | On the same five-member ensemble (`CountMinFast` and `CountFast` at `3x4096`, `HLL<ErtlMLE>`, `HLL<Classic>`, `HyperLogLogHIP`) fed `40_000` Zipf(1.1) keys over a `2_048` domain (seed `0xC090_5101`), runs `CountMinSpec::new(3, 4_096).assert_contract` on cell `0` (one-sidedness and the simultaneous `b*(N-f)/w` at `delta = 1e-3` with zero violations, marginal `e*(N-f)/w` rate pinned at `e^-3`) and `CountSketchSpec::new(3, 4_096).assert_contract` on cell `1` (simultaneous L2 band at `delta = 1e-3`, marginal `sqrt(3/4096)*\|\|f_-i\|\|_2` rate pinned at `7/27`). The three HLL cells share one hash, so "every member landed in its band" - `hll(14, 4.0)` for the register estimators, `hll_hip(14, 4.0)` for HIP - is scored as a single trial by `assert_independent_binomial`. |
| `ensemble_composes_by_hash_layout_and_rejects_incompatible_members` | Ensemble compatibility is by hash layout, so equal rows in one packing mode compose at different widths and anything else is refused. | Accepts an ensemble of `CountMin<Vector2D<i32>, FastPath>` at `3x4096`, `CountMin<Vector2D<i64>, FastPath>` at `3x2048` and `Count<Vector2D<i32>, FastPath>` at `3x4096`, asserts `len() == 3`, and after `40_000` Zipf(1.1) keys over a `2_048` domain (seed `0xC090_5101`) judges each member at its own width with `CountMinSpec::new(3, 4_096)`, `CountMinSpec::new(3, 2_048)` and `CountSketchSpec::new(3, 4_096)`. Then asserts `new` errs for a `3x4096` plus `5x4096` pair, that `push` of a `5x4096` `Count` errs and leaves `len()` unchanged, that `5x1024` plus `5x4096` errs because `rows * (mask_bits(cols) + 1)` crosses `64` bits and changes the packing mode (`55` bits versus `65`), that `5x512` plus `5x1024` is accepted, and that pushing a `HyperLogLogHIP` - which carries no matrix dimensions - is accepted. |
### Composition: UnivMon-Q Configuration Surface
Test file: [`tests/e2e_composition.rs`](../tests/e2e_composition.rs)
| test_name | test_description | what_is_tested |
| --- | --- | --- |
| `univmonq_configuration_variants_all_build_and_keep_exact_aggregates` | Each configuration field produces a working sketch whose exact aggregates stay exact. | For `UnivMonQConfig::default()` and the variants `counter_bits: 64`, `width_halving_period: 2` and `hash_seed: 3`, builds with `UnivMonQ::new`, feeds `20_000` uniform values over `100_000` (seed `0xC090_5101`), and asserts `count() == 20_000`, `min()` and `max()` equal the stream's exact extremes, `quantile(0.5).is_some()`, and `config().counter_bits` matches what was passed. Only `counter_bits` is checked for round-trip, and `quantile(0.5)` is checked for presence only - its value is not compared to the truth. |
| `univmonq_with_ordered_samples_disabled_answers_everything_except_ordered_queries` | `ordered_samples = 0` disables only the rank-ordered queries. | Builds `UnivMonQ::new(UnivMonQConfig { ordered_samples: 0, ..default() })`, feeds `10_000` uniform values over `50_000` (seed `0xC090_5101`), then asserts `count() == 10_000`, exact `min()`/`max()`, `estimate_f2() > 0.0` and `estimate_distinct() > 0.0` (magnitudes not pinned), `rank(values[0]) == None`, `cdf()` empty, `quantile(0.5) == None`, and that the endpoints still come from the exact aggregates: `quantile(0.0) == Some(min)` and `quantile(1.0) == Some(max)`. |
| `univmonq_with_window_bound_chooses_a_hierarchy_that_satisfies_its_own_inequality` | `with_window_bound` picks the smallest level count whose deepest stratum still fits the candidate table. | For `max_updates` in `10_000`, `1_000_000` and `100_000_000` at `delta = 1e-3`, calls `UnivMonQConfig::default().with_window_bound` and re-derives the Bernstein upper tail `mean + sqrt(2*mean*ln(1/delta)) + (2/3)*ln(1/delta)` with `mean = max_updates / 2^(levels-1)`, asserting it is strictly below `cfg.candidates`; asserts minimality by requiring the same bound at `levels - 1` to be at or above `candidates` whenever `levels > 2`; asserts `levels` is non-decreasing across the three windows; builds each chosen config and asserts `count() == 1_000` after `1_000` updates; and asserts `with_window_bound(1_000, 1.5)` is an error. |
| `univmonq_multi_shard_merge_with_distinct_source_ids_covers_the_union` | Shards with distinct source ids merge into a sketch whose exact aggregates cover the union. | Builds `4` shards with `UnivMonQ::with_hasher_and_source_id(UnivMonQConfig::default(), i + 1)`, deals `40_000` uniform values over `1_000_000` (seed `0xC090_5101`) round robin by `i % 4`, asserts each shard's `source_id()` is `i + 1`, merges the other three into the first with `merge` returning `Ok`, and asserts the merged `count()` is `40_000` and `min()`/`max()` equal the whole stream's exact extremes. Only the distinct-id path is exercised: no assertion covers a merge of shards that share a source id, and no estimator is checked. |
### Composition: Portable Sketch-With-Heap Facades
Test file: [`tests/e2e_composition.rs`](../tests/e2e_composition.rs)
| test_name | test_description | what_is_tested |
| --- | --- | --- |
| `portable_count_min_with_heap_satisfies_the_count_min_bound_through_merge_and_wire` | The portable Count-Min-plus-heap holds Count-Min's bound and an agreeing heap through a merge and a MessagePack round trip. | Feeds `40_000` Zipf(1.1) keys over a `2_048` domain (seed `0xC090_5101`) as `"k{key}"` strings into `CountMinSketchWithHeap::new(3, 4_096, 32)`, plus even/odd halves into two more. Runs `CountMinSpec::new(3, 4_096).assert_contract` on the single sketch, asserts every `topk_heap_items()` entry's `value` equals `estimate(&item.key)` with zero violations, re-runs the contract on `CountMinSketchWithHeap::merge_refs(&[&left, &right])` against the full truth, and after `to_msgpack`/`from_msgpack` asserts the decoded sketch's `estimate` is exactly equal to the original's for every observed key and still satisfies the contract. |
| `portable_count_sketch_with_heap_satisfies_the_l2_bound_through_merge_and_wire` | The portable Count-Sketch-plus-heap holds the L2 bound and an agreeing heap through a merge and a MessagePack round trip. | Feeds the same `40_000`-key Zipf(1.1) stream (domain `2_048`, seed `0xC090_5101`) as `"k{key}"` strings into `CountSketchWithHeap::new(5, 4_096, 32)`, plus even/odd halves into two more, and runs `CountSketchSpec::new(5, 4_096).assert_contract` (simultaneous L2 band at `delta = 1e-3` with zero violations, marginal `sqrt(3/4096)*\|\|f_-i\|\|_2` rate pinned at `P[Bin(5, 1/3) >= 3] = 51/243`) on the single sketch, on `merge_refs(&[&left, &right])` and on the `from_msgpack` decode; every `topk_heap_items()` entry's `value` must equal `estimate(&item.key)`. Unlike the Count-Min twin, the wire round trip is only re-checked against the band - no per-key equality across the encode/decode is asserted. |
| `portable_kll_sketch_satisfies_the_rank_error_characterization_through_merge_and_wire` | The portable KLL facade holds the rank-error characterization single-pass and after a two-shard merge, and its wire round trip is bit-for-bit. | Over `12` compaction seeds `0x5EED_0400 + t * 0x9E37_79B9_7F4A_7C15`, builds `KllSketch::with_seed(200, seed)` plus even/odd shards at `seed ^ 0xAAAA` and `seed ^ 0x5555`, feeds all of them `40_000` uniform values over `1_000_000` (seed `0xC090_5101`), and merges the shards with `merge`. Each seed records two trials - the single-pass sketch and the merged pair - of the worst normalized rank error over the grid `[0.1, 0.25, 0.5, 0.75, 0.9]` against `KllRankSpec::datasketches(200)`'s `eps = 2.446/200^0.9433 = 0.0165`, and the `24` outcomes are accepted by `assert_independent_binomial` at `p = 0.01`. Per seed it also asserts `to_msgpack`/`from_msgpack` preserves `k() == 200`, `count()`, and every grid quantile exactly, and that merging a `k = 400` sketch into the single-pass one errs. |
### Composition: Documented Input Matrix
Test file: [`tests/e2e_composition.rs`](../tests/e2e_composition.rs)
| test_name | test_description | what_is_tested |
| --- | --- | --- |
| `ensemble_input_{1..12}_cells_answer_as_their_standalone_instances` | Both documented ensemble cells answer as their standalone instances do, on each of the twelve keyed inputs. | One macro-generated body per input, all at the document's geometry: `HashSketchEnsemble::new` over `CountMin::<Vector2D<i32>, FastPath>::with_dimensions(3, 4_096)` and `HyperLogLog::<ErtlMLE>::new()` (precision `14`), against a standalone `CountMin` and `HyperLogLog<ErtlMLE>` fed the same keys in the same `DataInput` encoding. Each body asserts the matrix cell `ens.estimate(0, ..)` equals the standalone `estimate` exactly for every observed key (zero violations), runs `CountMinSpec::new(3, 4_096).assert_contract` on that cell, requires both the HLL cell `ens.cardinality(1)` and the standalone reading to sit inside `CardinalityConfidenceSpec::hll(14, 4.0)`'s band of `4 * 1.04 / 2^7 = 0.0325`, and requires `\|cell - standalone\| / distinct` to be at most `2x` that band, since the cell is fed the low 64 bits of the shared matrix hash rather than the canonical seed. Generated names and their inputs: `ensemble_input_1_cells_answer_as_their_standalone_instances` on `key_input(1)` (100K uniform `i64` over `[0, 10M)`), `ensemble_input_2_cells_answer_as_their_standalone_instances` on `key_input(2)` (1M uniform), `ensemble_input_3_cells_answer_as_their_standalone_instances` on `key_input(3)` (100K Zipf(1.1) over a 4096-key domain), `ensemble_input_4_cells_answer_as_their_standalone_instances` on `key_input(4)` (1M Zipf(1.1), 4096 keys), `ensemble_input_5_cells_answer_as_their_standalone_instances` on `key_input(5)` (100K Zipf(1.1) over a 20000-key domain), `ensemble_input_6_cells_answer_as_their_standalone_instances` on `key_input(6)` (1M Zipf(1.1), 20000 keys), and the `f64`-encoded twins carrying the same draws: `ensemble_input_7_cells_answer_as_their_standalone_instances` on `key_input(7)` (100K uniform), `ensemble_input_8_cells_answer_as_their_standalone_instances` on `key_input(8)` (1M uniform), `ensemble_input_9_cells_answer_as_their_standalone_instances` on `key_input(9)` (100K Zipf(1.1), 4096 keys), `ensemble_input_10_cells_answer_as_their_standalone_instances` on `key_input(10)` (1M Zipf(1.1), 4096 keys), `ensemble_input_11_cells_answer_as_their_standalone_instances` on `key_input(11)` (100K Zipf(1.1), 20000 keys), and `ensemble_input_12_cells_answer_as_their_standalone_instances` on `key_input(12)` (1M Zipf(1.1), 20000 keys). |
### Matrix Instance Coverage
Test file: [`tests/e2e_matrix_instances.rs`](../tests/e2e_matrix_instances.rs)
| test_name | test_description | what_is_tested |
| --- | --- | --- |
| `countmin_{regular_path_instances_satisfy_the_count_min_bound, fast_path_instances_conform_to_the_count_min_model}` | Every built-in `CountMin` storage backend holds Count-Min's contract at its own geometry, on one hashing path per test. | One shared body per storage: builds three `CountMin::<S, P>::default()` sketches, feeds the whole of `zipf_u64(40_000, 4_096, 1.1, 0x10BE_C700)` to one and the even/odd halves to two shards that are then `merge`d, and runs `CountMinSpec::new(rows, cols)` at the dimensions the instance itself reports over both the single-pass and the merged sketch: one-sidedness and the simultaneous `b*(N-f)/w` bound at `delta = 1e-3` with zero violations tolerated, plus the marginal `e*(N-f)/w` bound rate-pinned at `e^-d`. It then requires the merged sketch's `estimate` to equal the single-pass one exactly for every key, merging counter matrices being exact addition. Ten storages each, `Vector2D<i32>`, `Vector2D<i64>`, `Vector2D<i128>`, `Vector2D<f64>`, `DefaultMatrixI32`, `DefaultMatrixI64`, `DefaultMatrixI128` at `3x4096` and `FixedMatrix`, `QuickMatrixI64`, `QuickMatrixI128` at `5x2048`. Generated as `countmin_regular_path_instances_satisfy_the_count_min_bound` (`RegularPath`) and `countmin_fast_path_instances_conform_to_the_count_min_model` (`FastPath`). |
| `countsketch_{regular_path_instances_satisfy_the_l2_bound, fast_path_instances_conform_to_the_l2_model}` | Every built-in `Count` storage backend holds the L2 contract at its own geometry, on one hashing path per test. | One shared body per storage: three `Count::<S, P>::default()` sketches over `zipf_u64(40_000, 4_096, 1.1, 0x10BE_C700)`, whole stream to one and even/odd halves to two shards that are `merge`d, then `CountSketchSpec::new(rows, cols)` over both sketches - the simultaneous `sqrt(kappa/w)*\|\|f_-i\|\|_2` band at the union-bounded `kappa` for `delta = 1e-3` with zero violations tolerated, and the marginal band at `kappa = 3` rate-pinned at `P[Binomial(d, 1/3) >= ceil(d/2)]` - followed by exact per-key equality between the merged and single-pass estimates. Nine storages each, `Vector2D<i32>`, `Vector2D<i64>`, `Vector2D<i128>`, `DefaultMatrixI32`, `DefaultMatrixI64`, `DefaultMatrixI128` at `3x4096` and `FixedMatrix`, `QuickMatrixI64`, `QuickMatrixI128` at `5x2048`. Generated as `countsketch_regular_path_instances_satisfy_the_l2_bound` (`RegularPath`) and `countsketch_fast_path_instances_conform_to_the_l2_model` (`FastPath`). |
| `cmsheap_{regular_path_instances_satisfy_the_count_min_bound, fast_path_instances_conform_to_the_count_min_model}` | Every insertable `CMSHeap` instance carries Count-Min's bound and keeps its heap consistent with the sketch. | One shared body per storage: three `CMSHeap::<S, P>::default()` sketches (top-`32`) over `zipf_u64(40_000, 4_096, 1.1, 0x10BE_C700)`, whole stream to one and even/odd halves to two `merge`d shards, then `CountMinSpec::new(rows, cols)` over both - one-sidedness and simultaneous `b*(N-f)/w` at `delta = 1e-3` with zero tolerance, marginal `e*(N-f)/w` rate-pinned at `e^-d`. `assert_heap_matches_sketch` then requires every heap entry's `count` to equal the sketch's own `estimate` for that key cast to `i64`, and allows at most one of the heap's entries to sit below the true k-th count (`recall + 1 >= items.len()`); an entry whose key is not `HeapItem::U64` panics. Six storages each, `Vector2D<i32>`, `Vector2D<i64>`, `DefaultMatrixI32`, `DefaultMatrixI64` at `3x4096` and `FixedMatrix`, `QuickMatrixI64` at `5x2048`. Generated as `cmsheap_regular_path_instances_satisfy_the_count_min_bound` (`RegularPath`) and `cmsheap_fast_path_instances_conform_to_the_count_min_model` (`FastPath`). |
| `csheap_{regular_path_instances_satisfy_the_l2_bound, fast_path_instances_conform_to_the_l2_model}` | Every `CSHeap` instance carries the L2 bound and keeps its heap consistent with the sketch. | One shared body per storage: three `CSHeap` sketches over `zipf_u64(40_000, 4_096, 1.1, 0x10BE_C700)`, whole stream to one and even/odd halves to two `merge`d shards, then `CountSketchSpec::new(rows, cols)` over both - simultaneous `sqrt(kappa/w)*\|\|f_-i\|\|_2` at the union-bounded `kappa` for `delta = 1e-3` with zero tolerance, marginal band at `kappa = 3` rate-pinned - and `assert_heap_matches_sketch` with `cs_heap_count` as the estimate-to-entry map, requiring every heap entry's `count` to equal `cs_heap_count(estimate)` and at most one entry to sit below the true k-th count. Nine instances each: `Vector2D<i32>`, `Vector2D<i64>`, `DefaultMatrixI32`, `DefaultMatrixI64`, `DefaultMatrixI128` from `Default` at `3x4096`, `FixedMatrix`, `QuickMatrixI64`, `QuickMatrixI128` from `Default` at `5x2048`, and `Vector2D<i128>` built explicitly by `CSHeap::new(3, 4096, 32)` because it has no `Default`. Generated as `csheap_regular_path_instances_satisfy_the_l2_bound` (`RegularPath`) and `csheap_fast_path_instances_conform_to_the_l2_model` (`FastPath`). |
| `countmin_both_paths_are_exact_on_a_collision_free_workload` | On a collision-free workload both hashing paths return exact counts on every storage backend. | Inserts the eight well-separated keys `1`, `7`, `4_242`, `90_210`, `1_000_003`, `2_147_483_647`, `4_294_967_311`, `9_007_199_254_740_993` at multiplicities `10, 20, ..., 80` into a `RegularPath` and a `FastPath` `CountMin` over the same storage, and requires both `estimate` calls to equal the true count exactly for every key, with zero violations. Run over all ten storages: `Vector2D<i32>`, `Vector2D<i64>`, `Vector2D<i128>`, `Vector2D<f64>`, `FixedMatrix`, `DefaultMatrixI32`, `QuickMatrixI64`, `QuickMatrixI128`, `DefaultMatrixI64`, `DefaultMatrixI128`. |
| `countsketch_both_paths_are_exact_on_a_collision_free_workload` | The signed family is likewise exact on both paths when nothing collides. | Same eight keys at multiplicities `10, 20, ..., 80` into a `RegularPath` and a `FastPath` `Count` over the same storage, requiring both `estimate` values to equal the true count exactly with zero violations, over nine storages: `Vector2D<i32>`, `Vector2D<i64>`, `Vector2D<i128>`, `FixedMatrix`, `DefaultMatrixI32`, `QuickMatrixI64`, `QuickMatrixI128`, `DefaultMatrixI64`, `DefaultMatrixI128`. |
| `cmsheap_inert_instances_construct_and_report_their_geometry` | The `CMSHeap` instances whose counter type fails the insert bound still construct and answer their geometry. | For each of eight instances, verifies `rows()`, `cols()`, `cms().rows()` and an empty `heap()`: `CMSHeap::<Vector2D<i128>, _>::new(3, 4096, 32)` and `CMSHeap::<Vector2D<f64>, _>::new(3, 4096, 32)` on both paths at `3x4096`, `CMSHeap::<QuickMatrixI128, _>::default()` on both paths at `5x2048`, and `CMSHeap::<DefaultMatrixI128, _>::default()` on both paths at `3x4096`. This is constructibility only: the test does not assert that `insert`, `insert_many`, `estimate` or `merge` are uncallable, and adding such an impl would leave every assertion here passing. |
| `csheap_i128_counters_saturate_into_the_heap_instead_of_wrapping` | An `i128` `CSHeap` holds mass past `i64::MAX` while its heap entry saturates at the ceiling. | For each of six instances, inserts `insert_many(U64(0xC0FF_EE01), 1 << 40)` and requires `estimate` to equal `2^40` exactly and the heap entry to carry the same `i64`; then, on a fresh sketch, `insert_many` of `i64::MAX as i128 * 4` and requires `estimate >= i64::MAX as f64`, `cs_heap_count(estimate) == i64::MAX`, and the heap entry to read exactly `i64::MAX` rather than a wrapped negative; then merges a second sketch carrying the same overflow weight and requires the heap entry to stay at `i64::MAX`. Instances: `CSHeap::<Vector2D<i128>, _>::new(3, 4096, 32)` on both paths, and `QuickMatrixI128` and `DefaultMatrixI128` from `Default` on both paths. |
| `countmin_counter_widths_carry_the_mass_their_type_allows` | Each `CountMin` counter width carries a count the next narrower one cannot. | On `3x64` `RegularPath` sketches keyed by `U64(0xFEED_FACE)`: `Vector2D<i32>` returns `i32::MAX - 1` after `insert_many` of that weight; `Vector2D<i64>` returns `i32::MAX as i64 * 4`; `Vector2D<i128>` returns `i64::MAX as i128 * 4`. Then merges two `Vector2D<i128>` `3x64` sketches each holding `i64::MAX` and requires the result to be exactly `i64::MAX as i128 * 2`. |
| `countsketch_counter_widths_carry_signed_mass_in_both_directions` | Each `Count` counter width reaches the negative end of its range without wrapping. | On `3x64` `Vector2D<_>` `RegularPath` sketches keyed by `U64(0xDEAD_BEEF)`: `i32` cancels `+i32::MAX/2` against `-(i32::MAX/2)` to exactly `0.0`; `i64` reads `i32::MAX as i64 * 4` and, after a further `-2x` that weight, exactly its negation; `i128` reads `i64::MAX as i128 * 4` and, after a further `-2x`, exactly its negation. |
| `countmin_holds_its_contract_across_the_depth_and_width_axis_on_both_paths` | Count-Min's one-sided and simultaneous bounds hold across the whole depth-by-width grid on both paths. | Over the sixteen geometries `d` in `{1, 2, 3, 9}` by `w` in `{64, 512, 4_096, 8_192}`, builds `CountMin::<Vector2D<i64>, RegularPath>` and `CountMin::<Vector2D<i64>, FastPath>` by `with_dimensions`, feeds `zipf_u64(40_000, 4_096, 1.1, 0x10BE_C700)`, and for each path asserts no key underestimates and no key's excess exceeds `b*(N-f)/w` with `b = (D/1e-3)^(1/d)`, both with zero tolerance. The marginal `e*(N-f)/w` bound is not checked here, and the mean excess `countmin_axis_contract` returns is discarded. |
| `countmin_mean_excess_falls_as_the_width_axis_grows` | Widening the matrix eightfold at least halves the mean over-estimate. | For each `d` in `{1, 2, 3, 9}`, builds `CountMin::<Vector2D<i64>, FastPath>::with_dimensions(d, w)` for `w` in `64, 512, 4_096` in order over `zipf_u64(40_000, 4_096, 1.1, 0x10BE_C700)`, and asserts each width's mean per-key excess over the distinct keys, times `WIDTH_EXCESS_DECAY = 2.0`, is at most the previous width's mean. Only the ratio between consecutive widths is pinned; no absolute excess level is. |
| `countsketch_holds_its_l2_contract_across_the_depth_and_width_axis` | The simultaneous L2 band holds across the depth-by-width grid on both paths. | Over the twelve geometries `d` in `{3, 5, 9}` by `w` in `{64, 512, 4_096, 8_192}`, builds `Count::<Vector2D<i64>, RegularPath>` and `Count::<Vector2D<i64>, FastPath>` by `with_dimensions` over `zipf_u64(40_000, 4_096, 1.1, 0x10BE_C700)` and asserts, per path, zero violations of `\|est - f\| <= sqrt(kappa/w)*\|\|f_-i\|\|_2` at the `kappa` union-bounded for `delta = 1e-3` over the distinct keys. The marginal `sqrt(3/w)` tally is accumulated by `tally_into` but never asserted. |
| `countmin_answers_a_non_power_of_two_width_on_both_paths` | Count-Min's contract survives widths that are not powers of two. | For each `w` in `{3, 100, 1_000, 4_095}` asserts `w` is not a power of two, builds `CountMin::<Vector2D<i64>, _>::with_dimensions(3, w)` on both paths over `zipf_u64(40_000, 4_096, 1.1, 0x10BE_C700)`, checks `cols()` reports exactly `w`, and asserts per path that no key underestimates and no key's excess exceeds `b*(N-f)/w` at `delta = 1e-3`, both with zero tolerance. |
| `countsketch_answers_a_non_power_of_two_width_on_both_paths` | The L2 band survives widths that are not powers of two. | For each `w` in `{3, 100, 1_000, 4_095}` builds `Count::<Vector2D<i64>, _>::with_dimensions(5, w)` on both paths over `zipf_u64(40_000, 4_096, 1.1, 0x10BE_C700)`, checks `cols()` reports exactly `w`, and asserts zero violations of the simultaneous `sqrt(kappa/w)*\|\|f_-i\|\|_2` band at `delta = 1e-3` per path. The marginal tally is accumulated and not asserted, and the width is not re-checked against `is_power_of_two`. |
| `a_non_power_of_two_width_keeps_every_column_index_inside_the_matrix` | The fast path's index fold lands every insert in exactly one counter per row at a non-power-of-two width. | For each `w` in `{3, 100, 1_000, 4_095}` builds `CountMin::<Vector2D<i64>, FastPath>::with_dimensions(3, w)`, inserts `U64(k.wrapping_mul(0x9E37_79B9_7F4A_7C15))` for `k` in `0..20_000`, and asserts through `as_storage().query_one_counter` that at least one counter is non-zero and that the sum over all `3 * w` counters is exactly `20_000 * 3`. |
| `countmin_merge_max_dominates_both_sides_on_disjoint_key_sets` | `merge_max` dominates both inputs and stays below the summing merge. | Splits `zipf_u64(40_000, 4_096, 1.1, 0x10BE_C700)` by key parity into two `CountMin::<Vector2D<i64>, RegularPath>::with_dimensions(4, 2_048)` sketches, records every key's pre-merge estimate on its own side, and after `merge_max` asserts each key's estimate is at or above both its pre-merge value and its side's true count. It then builds the same pair under `merge` and asserts the elementwise-max estimate never exceeds the elementwise-sum estimate, for the left key set. |
| `countmin_merge_max_is_idempotent_and_absorbs_an_empty_sketch` | `merge_max` with an empty or identical sketch leaves every estimate untouched. | Fills a `CountMin::<Vector2D<i64>, RegularPath>::with_dimensions(4, 2_048)` from `zipf_u64(40_000, 4_096, 1.1, 0x10BE_C700)`, records every distinct key's estimate, then asserts that estimate is unchanged after `merge_max` with a fresh empty `4x2_048` sketch and after `merge_max` with a clone of itself. |
| `countmin_precomputed_hash_entry_points_match_the_value_entry_points` | Count-Min's precomputed-hash and bulk entry points agree with the value entry points. | At `4x2_048` on `CountMin::<Vector2D<i64>, FastPath>` over `zipf_u64(40_000, 4_096, 1.1, 0x10BE_C700)`, builds one sketch by `insert`, one by `fast_insert_with_hash_value` on `hash_for_matrix(4, 2_048, ..)` digests, and one by a single `bulk_insert_with_hashes` over the same digest vector, then asserts for every distinct key that all three `estimate` values are equal and that `fast_estimate_with_hash` on the key's digest equals `estimate`. |
| `countmin_weighted_batch_entry_points_match_a_loop_of_single_inserts` | Count-Min's weighted batch entry points match a loop of `insert_many`. | At `4x2_048` on `CountMin::<Vector2D<i64>, FastPath>`, assigns each position of `zipf_u64(40_000, 4_096, 1.1, 0x10BE_C700)` the weight `(i % 5) + 1` and builds three sketches: a loop of `insert_many`, one `bulk_insert_many` over the value/weight pairs, and one `bulk_insert_many_with_hashes` over the `hash_for_matrix` digest/weight pairs, asserting all three estimates agree for every distinct key. Finally, `fast_insert_many_with_hash_value` of the digest of `U64(7)` with weight `9` must make `estimate(U64(7))` exactly `9`. |
| `countsketch_precomputed_hash_entry_points_match_the_value_entry_points` | Count Sketch's precomputed-hash entry points agree with the value entry points. | At `5x2_048` on `Count::<Vector2D<i64>, FastPath>` over `zipf_u64(40_000, 4_096, 1.1, 0x10BE_C700)`, builds one sketch by `insert` and one by `fast_insert_with_hash_value` on `hash_for_matrix(5, 2_048, ..)` digests, and asserts for every distinct key that the two `estimate` values are equal and that `fast_estimate_with_hash` equals `estimate`. Finally, `fast_insert_many_with_hash_value` of the digest of `U64(11)` with weight `6` must make `estimate(U64(11))` exactly `6.0`. |
### Numeric Type Coverage
Test file: [`tests/e2e_numeric_types.rs`](../tests/e2e_numeric_types.rs)
| test_name | test_description | what_is_tested |
| --- | --- | --- |
| `every_numeric_type_satisfies_the_kll_rank_error_characterization` | Every built-in `NumericalValue` type holds the KLL rank-error characterization through both KLL implementations. | For each of the fourteen types - `i8` span `127`, `i16` `32_767`, `i32` `1_000_000_000`, `i64`/`isize`/`i128`/`u64`/`u128`/`usize`/`f64` `1_000_000_000_000_000`, `u8` `255`, `u16` `65_535`, `u32` `4_000_000_000`, `f32` `1_000_000` - folds `uniform_u64(20_000, span, 0x57EA_0001)` into the type as `(v + 1) as T` and runs eighteen trials: three repeats of `KLL<T>` and `KLLDynamic<T>` at `k = 200` in three feed modes (single pass, a two-shard even/odd `merge` whose right shard uses `seed ^ 0x5555`, and `bulk_update`). Each trial is one sketch with its own `kll_trial_seed(t)` compaction seed, scored on its worst normalized rank error over the grid `[0.0, 0.01, 0.1, 0.5, 0.9, 0.99, 1.0]` against `eps(200) = 2.446/200^0.9433` (about `1.65%`), with ground truth taken over the `to_f64`-projected values. The 252 trials are accepted together by `assert_independent_binomial` at a per-trial failure probability of `0.01`. |
| `signed_numeric_types_order_negative_values_correctly_in_kll` | The KLL family orders mixed-sign values correctly and never answers outside the observed range. | For each of `i8` span `100`, `i16` `30_000`, `i32` `1_000_000_000`, `i64`/`i128`/`isize` `1_000_000_000_000_000`, `f32` `1_000_000` and `f64` `1_000_000_000_000_000`, builds a stream symmetric about zero as `uniform_u64(20_000, 2*span, 0x57EA_0001)` mapped to `v - span`, and records six rank trials per type (three repeats of `KLL<T>` and `KLLDynamic<T>` at `k = 200`, single pass, seeds from `kll_trial_seed(0x5164_0000..)`), each scored on its worst rank error over the grid `[0.0, 0.01, 0.1, 0.5, 0.9, 0.99, 1.0]` against `eps(200)`; the 48 trials are accepted by `assert_independent_binomial` at `p = 0.01`. Per type it also asserts on a further `KLL<T>` probe that `quantile(q)` for `q` in `{0.0, 0.25, 0.5, 0.75, 1.0}` lies inside `[min, max]` of the projected stream, and that `\|quantile(0.5)\| <= 0.10 * max`. `q = 0` is deliberately not required to return the exact minimum. |
| `every_numeric_type_satisfies_the_ddsketch_relative_value_error_contract` | `DDSketch::add<T>` holds its relative-value-error guarantee for every built-in `NumericalValue` type. | For each `alpha` in `{0.001, 0.01, 0.05}`, feeds all fourteen types through `DDSketch::new(alpha)` on the same `uniform_u64(20_000, span, 0x57EA_0001)` streams folded as `(v + 1) as T` (spans as in the rank-error test), asserts `get_count()` is exactly `20_000` for each type, and tallies `get_value_at_quantile(q)` over the grid `[0.0, 0.01, 0.1, 0.5, 0.9, 0.99, 1.0]` against the exact order statistic under `RelativeQuantileSpec::core`'s ceil-nearest-rank convention with tolerance `alpha` plus a few-ULP numerical slack. The guarantee is deterministic, so all 42 type-by-alpha batteries are asserted with zero violations tolerated. |
| `the_f64_projection_is_exact_below_two_to_the_53` | The `to_f64` projection is exact up to `2^53`, collapses just past it, and the sketch guarantees survive above it. | Asserts `1`, `1_000`, `2^53 - 1` and `2^53` round-trip through `f64` exactly as both `u128` and `i128` (the latter through `NumericalValue::to_f64`), and that `(2^53 + 1) as f64 == 2^53 as f64`. Then builds 5_000 `u128` values `(uniform_u64(5_000, 1_000_000, 0x57EA_0001) + 1) * 2^70`, feeds them to `DDSketch::new(0.01)`, asserts `get_count() == 5_000` and zero relative-error violations over the seven-point `q` grid against the projected truth, and finally runs sixteen `KLL::<u128>` sketches at `k = 200` with seeds `kll_trial_seed(0x2E70_0000 + t)`, each scored on its worst rank error over that grid, accepted by `assert_independent_binomial` at `p = 0.01`. |
### DataInput Variant Coverage
Test file: [`tests/e2e_data_input.rs`](../tests/e2e_data_input.rs)
| test_name | test_description | what_is_tested |
| --- | --- | --- |
| `every_data_input_variant_reaches_the_hash` | The variant table covers all seventeen `DataInput` variants and each hashes to its own digest. | Asserts the shared table has exactly `17` entries - `I8(-8)`, `I16(-16)`, `I32(-32)`, `I64(-64)`, `I128(-128)`, `ISIZE(-1_000)`, `U8(8)`, `U16(16)`, `U32(32)`, `U64(64)`, `U128(128)`, `USIZE(1_000)`, `F32(1.5)`, `F64(2.5)`, `Str("borrowed")`, `String("owned")`, `Bytes(b"raw-bytes")` - and that inserting each `hash64_seeded(0, v)` into a `HashSet` never collides. Only the 64-bit digest at seed `0` is compared here. |
| `signed_integer_variants_sign_extend_to_one_canonical_digest` | The narrower signed variants sign-extend onto the `I64` digest. | For each probe in `-1`, `-8`, `-128`, `0`, `1`, `42`, `127`, asserts `I8`, `I16`, `I32` and `ISIZE` carrying that value produce the same `hash64_seeded` and `hash128_seeded` digests as `I64` of the same value, at all four seeds `0`, `1`, `3`, `7`. |
| `unsigned_integer_variants_zero_extend_to_one_canonical_digest` | The narrower unsigned variants zero-extend onto the `U64` digest. | For each probe in `0`, `1`, `7`, `255`, asserts `U8`, `U16`, `U32` and `USIZE` carrying that value produce the same 64- and 128-bit digests as `U64` of the same value, at seeds `0`, `1`, `3`, `7`. |
| `a_non_negative_value_hashes_the_same_whether_it_arrives_signed_or_unsigned` | A non-negative integer has one digest regardless of the signedness of the variant carrying it. | For each probe in `0`, `1`, `7`, `100`, `127`, asserts `I8` matches `U8` and `I64` matches `U64` on both the 64- and 128-bit digest at seeds `0`, `1`, `3`, `7`. |
| `a_negative_value_and_its_twos_complement_unsigned_reading_share_a_digest` | A negative value hashes as its sign-extended two's-complement word. | Asserts `I8(-1)` and `I64(-1)` both share every digest with `U64(u64::MAX)` at seeds `0`, `1`, `3`, `7`, and that `I8(-1)` and `U8(255)` differ in both the 64- and 128-bit digest, checked at seed `0` only. |
| `the_128_bit_integer_variants_hash_a_wider_word_than_the_64_bit_ones` | The 128-bit variants hash a sixteen-byte word, distinct from the eight-byte one. | Asserts `I128(7)` shares every digest with `U128(7)` and `I128(-1)` with `U128(u128::MAX)` at seeds `0`, `1`, `3`, `7`, and that `I128(7)` differs from `I64(7)` in both digests, checked at seed `0` only. |
| `the_float_variants_hash_their_own_width_and_do_not_alias_the_integers` | The float variants hash their own bit width and their own bit patterns. | Asserts `F32(1.0)` differs from `F64(1.0)`, `F64(1.0)` from `U64(1)`, and `F64(0.0)` from `F64(-0.0)` - each at seed `0` on both digest widths - while `F64(0.0)` shares every digest with `U64(0)` at seeds `0`, `1`, `3`, `7`. |
| `the_string_and_byte_variants_share_one_digest_for_one_encoding` | Borrowed, owned and raw-byte spellings of the same bytes share one digest. | Asserts `Str("hello")` shares every 64- and 128-bit digest with `String("hello")` and with `Bytes(b"hello")` at seeds `0`, `1`, `3`, `7`, and that `Str("")` differs from `Str("\0")` at seed `0`. |
| `count_min_answers_every_variant_and_folds_the_aliasing_ones_together` | `CountMin` accepts every variant on both paths and folds the aliasing integer spellings into one key. | Inserts each of the seventeen variants ten times into `CountMin::<Vector2D<i64>, RegularPath>::with_dimensions(4, 4_096)` and the `FastPath` twin, asserting `estimate >= 10` for each variant on each path. Then, on a fresh `FastPath` `4x4_096`, inserts `I8(7)`, `U16(7)` and `I64(7)` five times each and asserts `estimate(U64(7))` is exactly `15` while `estimate(I128(7))` is exactly `0`. |
| `count_sketch_answers_every_variant` | `Count` returns a usable estimate for every variant. | Inserts each of the seventeen variants `200` times into `Count::<Vector2D<i64>, RegularPath>::with_dimensions(5, 4_096)` and asserts every variant's estimate is within `60.0` of `200.0`; the estimate is not pinned more tightly than that band. |
| `a_bloom_filter_answers_every_variant_without_a_false_negative` | `Bloom` reports every inserted variant present on both hashing paths. | Inserts all seventeen variants into `Bloom::<RegularPath>::with_capacity(64, 0.01)` and into a `Bloom::<FastPath>` at the same capacity and target false-positive rate, and asserts `contains` is true for each variant on each filter. No false-positive rate is measured here. |
| `hyperloglog_counts_the_variants_as_distinct_identities` | Replaying the same variants through `HyperLogLog` does not move the estimate. | Inserts the seventeen variants into `HyperLogLog::<Classic>::new()`, records `estimate()`, inserts the same seventeen again, and asserts the estimate is unchanged and strictly positive. The estimate is not compared against the true cardinality of `17`, so the count itself is not pinned - only its idempotence under replay and its positivity. |
| `space_saving_tracks_every_variant` | A `SpaceSaving` summary with room for every variant never reads a key below its own count. | Inserts each of the seventeen variants twelve times into `SpaceSaving::with_capacity(64)`, which cannot evict at that residency, and asserts `estimate >= 12` for every variant; the exact estimate and the absence of error allowance are not pinned. |
| `the_numeric_variants_reach_the_quantile_sketches_and_the_others_are_refused` | The numeric `DataInput` variants reach `KLL` and `DDSketch`, and the non-numeric ones are rejected without being counted. | Feeds the fourteen numeric variants carrying the values `1..=14` (`I8(1)` through `F64(14.0)`) into `KLL::<f64>::init_kll_with_seed(200, 0xDA7A_0001)` via `update_data_input` and `DDSketch::new(0.01)` via `add_input`, requiring every call to succeed, `kll.count()` and `dds.get_count()` to be `14`, `kll.quantile(0.0)` to be exactly `1.0` and `kll.quantile(1.0)` exactly `14.0`. It then asserts `Str("x")`, `String("x")` and `Bytes(b"x")` each return `Err` from both entry points and that both counts are still `14`. |
### Experimental: KMV
Test file: [`tests/e2e_experimental.rs`](../tests/e2e_experimental.rs)
Feature: the whole file is `#![cfg(feature = "experimental")]`, so these rows run only under `cargo test --features experimental`.
| test_name | test_description | what_is_tested |
| --- | --- | --- |
| `kmv_estimates_stay_inside_their_relative_standard_error_band_over_independent_hash_seeds` | KMV's estimate stays inside its relative-standard-error band at every distinct-count regime, over independent hash functions. | Runs 144 trials — `k` in `{64, 1_024, 4_096}` × the 8 seed-list indices `[0, 1, 2, 3, 7, 11, 13, 17]` used as independent hash functions × 6 regimes (`k-1`, `k-2`, `k`, `2k`, `8k`, `32k` distinct keys) — each a fresh `KMV::new(k)` fed `n` distinct identities through `KMV::insert_by_hash` from its own namespace (stride `1 << 40`, so no two trials share a hash or an identity), and scores `estimate()` with `CardinalityConfidenceSpec::kmv(k, 4.0)`, whose band is `z * sqrt((n-k+1)/(n(k-2)))` above `k` and exact equality below it. The violation count is accepted by `Tally::assert_independent_binomial` at the `z = 4` two-sided normal failure probability (`6.3e-5`). |
| `kmv_is_exact_below_k_and_estimates_at_k` | The exact/estimated boundary sits at `n < k`, so `n == k` is already the estimator's regime. | For `K = 512`, verifies `CardinalityConfidenceSpec::kmv(512, 4.0).is_exact_regime` is `true` at `511` and `false` at `512`, that `KMV::estimate()` returns exactly `n` for `n` in `{1, 2, 256, 510, 511}`, and that at `n = k = 512` every one of the 8 hash seeds lands inside the spec's band. The "estimator is running" half asserts only that at least one of the 8 estimates differs from `512.0`; no individual seed's value is pinned. |
| `kmv_duplicates_are_inert_and_a_shard_merge_reproduces_the_single_pass_exactly` | Replaying a stream never moves the estimate, and a shard merge reproduces the single pass exactly rather than in-band. | Feeds a 60,000-draw uniform stream over `[0, 500_000)` (stream seed `5001`) into one `k = 4_096` `KMV` and, by arrival parity, into two shards; checks the single-pass `estimate()` against `CardinalityConfidenceSpec::kmv(4_096, 4.0)` at the stream's exact distinct count, that replaying the entire stream leaves `estimate()` equal to that same `f64`, and that `KMV::merge` of the even/odd shards returns that same value by equality. |
| `kmv_k32_over_the_documented_inputs_holds_its_error_model` | KMV at `k = 32` holds the documented `73%` band on all twelve documented keyed inputs. | Runs the shared `kmv_documented_input(32)` body over `KEY_INPUT_IDS` `(1)`–`(12)` (100K/1M draws each: uniform `i64` over `[0, 10M)`, Zipf(1.1) over 4,096 keys, Zipf(1.1) over 20,000 keys, plus the six `f64` twins carrying the same draws). Per input it feeds the whole stream through `KMV::insert`, then asserts `CardinalityConfidenceSpec::kmv(32, 4.0).check` passes at the input's exact distinct count, that the relative error is at most the documented `0.73` (`z = 4` of the `1/sqrt(k-2) = 18.3%` asymptotic RSE), and that replaying the input leaves `estimate()` unchanged. |
| `kmv_k128_over_the_documented_inputs_holds_its_error_model` | KMV at `k = 128` holds the documented `36%` band on all twelve documented keyed inputs. | The same `kmv_documented_input` body at `k = 128` over `KEY_INPUT_IDS` `(1)`–`(12)`: `CardinalityConfidenceSpec::kmv(128, 4.0).check` at the exact distinct count, a relative error of at most the documented `0.36` (`z = 4` of `8.9%`), and an inert duplicate replay. |
### Experimental: UniformSampling
Test file: [`tests/e2e_experimental.rs`](../tests/e2e_experimental.rs)
Feature: the whole file is `#![cfg(feature = "experimental")]`, so these rows run only under `cargo test --features experimental`.
| test_name | test_description | what_is_tested |
| --- | --- | --- |
| `uniform_sampling_retention_is_exact_at_every_rate_and_stream_size` | The retained size is `ceil(n * rate)` exactly, and every retained value is one the sampler was fed. | For rates `{1.0, 0.5, 0.25, 0.1, 0.01}` × stream sizes `{0, 1, 7, 1_000, 10_000, 50_000}`, feeds `uniform_u64(n, u32::MAX, 5002 + i)` cast to `f64` into `UniformSampling::with_seed(rate, 0x5A91_0100 + i)` and asserts `total_seen() == n`, `len() == PrioritySampleSpec::retained(n)` = `ceil(n*rate)` exactly, `len() <= n`, that every value in `samples()` is drawn from the input multiset and no value is retained more often than it was fed, and that `len() == n` at rate `1.0`. |
| `uniform_sampling_is_a_uniform_sample_without_replacement` | The retained set is a uniform sample without replacement, so the sample mean tracks the population mean at the variance that fact predicts. | Over rates `{0.5, 0.1, 0.01}` and `24` trials (one sampler per seed, from `0x5A91_0200`), feeds the `N = 20_000` values `i^1.7` — value correlated with arrival order, so an early/late-biased sampler fails — and asserts `samples().len() == ceil(N*rate)` and that `\|sample_mean - population_mean\| <= 4 * sigma` with `sigma = sqrt(sigma_N^2/m * (N-m)/(N-1))` from `PrioritySampleSpec::mean_sigma`. The 24 outcomes go through `Tally::assert_independent_binomial` at the `z = 4` failure probability. |
| `uniform_sampling_merge_keeps_the_combined_budget_exactly` | A same-rate merge sums the totals and keeps the combined budget, and a rate mismatch is rejected. | For rates `{1.0, 0.5, 0.1, 0.01}`, merges a 10,000-draw sampler (sampler seed `42`, stream seed `5002`) into which the whole left stream was fed with a 5,000-draw one (sampler seed `43`, stream seed `5003`, values offset by `0.5`), then asserts `total_seen() == 15_000`, `len() == PrioritySampleSpec::retained(15_000).min(pooled)` where `pooled` is the two pre-merge pool sizes, that every merged sample's bit pattern is in the union of the two streams, and that `UniformSampling::merge` against a sampler at a different rate (`0.5` when `rate == 1.0`, else `1.0`) returns `Err`. |
| `uniform_sampling_is_reproducible_from_its_seed` | The sample is reproducible from the sampler's seed and genuinely changes with it. | At rate `0.1` over a 5,000-draw uniform stream over `[0, u32::MAX)` (stream seed `5004`), asserts `samples()` from seed `7` equals a second run at seed `7` and is unequal to a run at seed `8`. |
| `uniform_sampling_input_{1,2,7,8}_retains_its_documented_budget` | Each documented uniform input retains the documented budget at rate `0.1`, exactly and through a merge. | One body, `uniform_sampling_documented_input(id)`, at rate `0.1` with sampler seed `0x5A91_0300 + id`: asserts the retained count is within the documented `15%` of `n * 0.1`, that `len()` equals `PrioritySampleSpec::retained(n)` = `ceil(n*rate)` exactly, that `total_seen() == n`, that every sample's bit pattern was in the stream, and then that a split-half merge (first half into a sampler at `seed`, second into one at `seed + 1`) sums `total_seen` back to `n`, holds `ceil(n*rate).min(pooled)` entries, and draws only stream values. Generated as `uniform_sampling_input_1_retains_its_documented_budget` => `1` (the 100K uniform `i64` stream over `[0, 10M)`), `uniform_sampling_input_2_retains_its_documented_budget` => `2` (the 1M draw of that shape), `uniform_sampling_input_7_retains_its_documented_budget` => `7` (the 100K `f64` twin), `uniform_sampling_input_8_retains_its_documented_budget` => `8` (the 1M `f64` twin). |
### Experimental: EHUnivOptimized
Test file: [`tests/e2e_experimental.rs`](../tests/e2e_experimental.rs)
Feature: the whole file is `#![cfg(feature = "experimental")]`, so these rows run only under `cargo test --features experimental`.
| test_name | test_description | what_is_tested |
| --- | --- | --- |
| `eh_univ_optimized_map_tier_exact_windows` | An interval inside the retained map tier is answered exactly, key by key. | Drives `EHUnivOptimized::with_defaults(2, 100)` with 150 updates at `t` in `0..150`, key `U32(t % 10)` and weight `(t % 3) + 1`, then requires `query_interval(120, 149)` to return `EHUnivQueryResult::Map` whose `total_count` equals the exact summed weight over `120..=149`, whose `freq_map.len()` equals the exact distinct-key count, and whose per-key entry equals the exact per-key weight for every key. |
| `eh_univ_optimized_promotes_into_the_sketch_tier_and_answers_from_it` | The map tier promotes into the sketch tier, whose interval answer keeps L1 exact and puts L2 and entropy in their measured bands. | Feeds 80,000 Zipf(1.1) draws over a 30,000-key domain (stream seed `4242`) into `EHUnivOptimized::new(k=2, window=100_000_000, heap=32, rows=3, cols=512, layers=2)`, asserts at least two `um_buckets` exist, queries exactly `[um_buckets[0].min_time, um_buckets.last().max_time]` and requires an `EHUnivQueryResult::Sketch`; then `calc_l1()` must equal the window's exact total weight by equality, `calc_l2()` must lie in `[0.90, 1.10] ×` the exact L2 norm, and `calc_entropy()` in `[0.90, 1.40] ×` the exact entropy in bits (bands measured on this configuration). |
| `eh_univ_optimized_sketch_tier_cardinality_is_documented_as_unrecoverable` | The sketch tier's cardinality estimate is a near-total underestimate, and that is pinned rather than hidden in a tolerance. | On the same stream and configuration (80,000 Zipf(1.1) draws over 30,000 keys, seed `4242`, `k=2`, `rows=3`, `cols=512`, `layers=2`), asserts the premise that `ceil(log2(distinct))` exceeds the `2` sampling layers, and that `calc_card()` over the promoted span is below `0.10 ×` the exact distinct count. Only that upper bound is asserted — the reported value itself is not pinned — and the assertion fails loudly if F0 recovery ever starts working. |
| `eh_univ_optimized_answers_a_mixed_map_and_sketch_interval` | A span crossing the tier boundary is answered as a Sketch and still carries the window's exact L1. | Feeds 60,000 updates `t` in `0..60_000` with key `U64(t % 20_000)` and weight `1` into `EHUnivOptimized::new(k=2, window=1_000_000, heap=32, rows=3, cols=512, layers=2)`, asserts both `um_buckets` and `map_buckets` are non-empty, and requires `query_interval(um_buckets[0].min_time, map_buckets.last().max_time)` to return an `EHUnivQueryResult::Sketch` whose `calc_l1()` equals the exact window weight. Only L1 is asserted on the mixed span. |
| `eh_univ_optimized_expires_buckets_past_the_window` | Expiry drops whole buckets past the window on both tiers, and the retained span and bucket count stay bounded. | Feeds 40,000 updates with key `U64(t % 8_000)` into `EHUnivOptimized::new(k=8, window=5_000, heap=32, rows=3, cols=512, layers=2)`, then asserts `get_max_time() == 39_999`, that `get_min_time() <= get_max_time()`, that every retained `um_buckets` and `map_buckets` entry has `max_time >= max_time - 5_000` (a bucket may still reach back before the cutoff with its `min_time`), that `cover(min_time, max_time)` is `true` and `cover(0, max_time)` is `false`, and that 30,000 further updates leave `bucket_count()` at most double its earlier value. The span-ordering check is trivially satisfiable, and the growth bound is a `2×` loosening rather than a fixed ceiling. |
| `eh_univ_optimized_reuses_pooled_sketches_without_leaking_state` | A sketch recycled through the pool carries no counters from a previous window. | Feeds 80,000 updates with key `U64(t % 20_000)` into `EHUnivOptimized::new(k=8, window=20_000, heap=32, rows=3, cols=512, layers=2)` — long enough that buckets are created, promoted, merged and expired repeatedly — and asserts `query_interval(get_min_time(), get_max_time()).calc_l1()` equals the exact weight of the retained window, which a pooled sketch holding stale counters would inflate. L1 is the only quantity asserted. |
| `eh_univ_optimized_map_tier_matches_exact_per_key_counts_on_a_skewed_stream` | The map tier's per-key counts on a weighted skewed stream are the exact reference the sketch tier is scored against. | Feeds 4,000 Zipf(1.2) draws over a 64-key domain (stream seed `9_001`) with weight `1 + (t % 3)` into `EHUnivOptimized::with_defaults(4, 1_000_000)`, then requires `query_interval(0, 3_999)` to return `EHUnivQueryResult::Map` whose `total_count` equals the exact total weight and whose `freq_map` entry matches the exact weight for every key in the truth. |
### Nitro Sampling
Test file: [`tests/e2e_nitro.rs`](../tests/e2e_nitro.rs)
| test_name | test_description | what_is_tested |
| --- | --- | --- |
| `every_nitro_path_is_unbiased_inside_its_sampling_band_at_every_rate` | Every Nitro ingestion path lands inside the band its own rate earns and is unbiased across seeds. | Crosses the five paths (`CountMin::fast_insert_nitro` and `Count::fast_insert_nitro` over a `3x4096` `Vector2D<i32>`, `NitroBatch::insert`, `NitroBatch::insert_cached_step`, and `NitroBatch<Vector2D<u32>>::insert`) with rates `{1.0, 0.5, 0.3, 0.1, 0.07, 0.01}` and 12 trials at seeds `0x0117_0000 + 5_000*t`, feeding a single key `0xC0FF_EE01` `f = round(1000/rate)` times (`1_000`, `2_000`, `3_333`, `10_000`, `14_286`, `100_000`). Each trial's per-row statistics are checked against `SamplingConfidenceSpec::new(rate, 4.0)`, whose sigma is `sqrt(f((1-p)/p + p*r(1-r)))` for `r = frac(1/p)`; a trial passes only if all its rows do, and the trial outcomes go through `Tally::assert_independent_binomial`. Separately, the mean of the 12 first-row values must be within `4*sigma(f)/sqrt(12)` of `f`, which is what catches a `ceil(1/p)` weight that a single-trial band would pass. |
| `full_sampling_is_exact_and_the_query_reads_the_cells_the_insert_wrote` | At rate `1.0` nothing is approximate, and the estimator reads back exactly the cells the insert wrote. | For `F = 5_000` updates of key `0xC0FF_EE01` at rate `1.0` and seed `0x0117_0000`, asserts every row mass on all five paths equals exactly `5_000` — `0` would mean insert and query disagree on the hash domain, `F / rows` that a path assigned each record to one row instead of all — then that `CountMin::nitro_estimate` returns exactly `5000.0` on a `3x4096` sketch, and that `NitroBatch::estimate_median` returns exactly `5000.0` after `insert` and after `insert_cached_step`. |
| `every_nitro_path_is_reproducible_from_its_seed` | Every path reproduces from its seed, and different seeds admit different subsets. | At rate `0.3` with `f = 3_333`, asserts each of the five paths returns the identical per-row statistics vector on two runs at seed `0x0117_0000`. The differing-seeds half asserts only that the 11 further seeds `0x0117_0000 + 5_000*t` for `t` in `1..12` produce more than one distinct first-row value; no per-seed value is pinned. |
| `nitro_merge_lands_in_the_combined_band` | Merging two same-rate Nitro sketches sums their admitted mass, so a split key lands in the band for the combined work. | For `CountMin::fast_insert_nitro` + `CountMin::merge` and for `NitroBatch::insert` + `NitroBatch::merge`, at each of the rates `{1.0, 0.5, 0.3, 0.1, 0.07, 0.01}`, builds 6 disjoint seed pairs `(0x0117_0000 + 5_000*2p, ... + 5_000*(2p+1))`, feeds `f = round(1000/rate)` updates of key `0xC0FF_EE01` into each shard, merges, and scores the row-0 mass (or `estimate_median`) against `SamplingConfidenceSpec::new(rate, 4.0)` at the combined truth `2f`; the 6 outcomes go through `Tally::assert_independent_binomial`. |
| `row_level_countmin_nitro_tracks_a_zipf_stream_within_the_combined_band` | Under collisions the row-level Count-Min estimate stays between its sampling floor and the sketch's own collision budget, for every key. | Feeds 200,000 Zipf(1.1) draws over a 512-key domain (stream seed `0x0117_2199`) into a `3x4096` `CountMin<Vector2D<i32>, FastPath>` at rates `{1.0, 0.3, 0.1, 0.07}`, seed `0x0117_0000`, and for every distinct key requires `nitro_estimate` to lie in `[f - 4*sigma(f), f + CountMinSpec::new(3, 4096).simultaneous_bound(N, f, distinct, 1e-3) + 4*sigma(N)]`. Both halves are union-bounded, so `Tally::assert_none` tolerates zero violations. |
| `row_level_countmin_nitro_separates_keys_of_similar_frequency` | With many keys of comparable frequency, no single hot flow can carry the per-key estimates. | Inserts each of the 16 keys `0x5EED_0000 + 7919*i` 20,000 times into a `3x4096` `CountMin<Vector2D<i32>, FastPath>` at rates `{1.0, 0.5, 0.3, 0.1}` and seed `0x0117_1388`, then requires every key's `nitro_estimate` to lie in `[20_000 - 4*sigma(20_000), 20_000 + CountMinSpec::new(3, 4096).simultaneous_bound(320_000, 20_000, 16, 1e-3) + 4*sigma(320_000)]`, with `Tally::assert_none` tolerating zero violations. |
| `nitro_saturates_oversized_weights_instead_of_wrapping` | An oversized scaled increment clamps into the counter's domain instead of wrapping negative. | Asserts `nitro_delta_saturated_i32(u64::MAX) == i32::MAX`, `nitro_delta_saturated_u32(u64::MAX) == u32::MAX`, and that both return `7` for `7`. It then feeds 4,000 updates at rate `1e-9` (so `1/rate` exceeds `i32::MAX`) through `NitroBatch::insert` over a `3x4096` Count-Min and through the row-level `fast_insert_nitro` path, but asserts only that `estimate_median` and `nitro_estimate` are `>= 0.0`; the saturated magnitude on those two paths is not pinned. |
| `a_serde_round_trip_after_every_update_reproduces_the_uninterrupted_run` | A sketch encoded and decoded after every update is cell-for-cell identical to one that was never interrupted, and its future agrees too. | At rates `0.3` and `0.07` (reciprocals that are not integers, so the stochastic-rounding stream is live), runs 600 updates of key `0xC0FF_EE01` into two `3x4096` `CountMin<Vector2D<i32>, FastPath>` sketches at seed `0x0117_0000`, round-tripping one through `rmp_serde::to_vec_named` / `from_slice` after every single update, then asserts the two sketches' full 12,288-cell vectors are equal and their `nitro_estimate` values are equal; 200 further updates on both must again leave the cell vectors equal, which catches a decoded sketch that resumed from a reset rounding stream. |
| `a_payload_written_before_the_rounding_field_existed_still_decodes` | A map-encoded payload that lacks `Nitro::rounding_state` decodes with the default stream and keeps sampling. | Serializes a hand-written mirror of the `CountMin` / `Vector2D<i32>` / `Nitro` field layout without `rounding_state` (`rows=3`, `cols=4096`, `mask_bits = 12`, `mask = 4095`, `is_nitro_mode = true`, `sampling_rate = 0.3`, `to_skip = 2`, `delta = 3`, `idx = 9`, and a single counter `data[17] = 4`) with `rmp_serde::to_vec_named`, decodes it as `CountMin<Vector2D<i32>, FastPath>`, asserts the decoded cell vector equals the 12,288-entry `data` exactly, then feeds 2,000 further `fast_insert_nitro` calls and requires the row-0 mass minus the pre-existing `4` to pass `SamplingConfidenceSpec::new(0.3, 4.0).check` against a truth of `2_000`. |
| `a_context_snapshot_restores_the_rest_of_the_stream_exactly` | A `NitroContext` snapshot restored onto a fresh sketch replays the remainder of the stream exactly. | At rates `0.3` and `0.07`, feeds 500 updates of key `0xC0FF_EE01` into a `3x4096` `CountMin<Vector2D<i32>, FastPath>` at seed `0x0117_3A98`, takes `nitro().context()`, records the cell vector, and runs 500 more updates; a fresh sketch at the same rate and seed gets `nitro_mut().restore_context(snapshot)` and the same 500 updates, and its cell vector must equal the continuous run's cell-by-cell difference over that stretch exactly. |
| `count_min_at_full_nitro_sampling_writes_exactly_what_a_plain_insert_writes` | At rate `1.0` the Nitro insert path writes the same Count-Min counters a plain insert writes, and the row median never falls below the row minimum. | Feeds 40,000 Zipf(1.1) draws over a 2,048-key domain (stream seed `0x4E17_0001`) into a plain `4x2048` `CountMin<Vector2D<i32>, FastPath>` via `insert` and into a twin with `enable_nitro(1.0)` via `fast_insert_nitro`, then asserts the two 8,192-counter vectors are equal, and per distinct key that `estimate` agrees between the two sketches and that `nitro_estimate` is at least the true count and at least the plain `estimate`. |
| `count_min_after_disable_nitro_leaves_the_sampled_insert_path_inert` | `disable_nitro` makes the sampled insert path a no-op without disabling the ordinary one. | Feeds the 40,000-draw Zipf(1.1) stream (2,048-key domain, seed `0x4E17_0001`) into a `4x2048` `CountMin<Vector2D<i32>, FastPath>` with `enable_nitro(1.0)`, snapshots the 8,192 counters, calls `disable_nitro()` and replays the whole stream through `fast_insert_nitro` — the counters must be unchanged — then replays it through `insert` and requires the counters to change. |
| `count_min_seeded_nitro_sampling_is_reproducible_and_admits_a_strict_subset` | Seeded sampling at rate `0.1` reproduces its admitted subset and touches strictly fewer counters than an unsampled pass. | Builds two `4x2048` `CountMin<Vector2D<i32>, FastPath>` sketches at rate `0.1` and seed `0x5A11_0001`, feeds each the 40,000-draw Zipf(1.1) stream (2,048-key domain, seed `0x4E17_0001`) through `fast_insert_nitro`, and asserts their 8,192-counter vectors are equal; then counts non-zero counters against an unsampled `insert`-only pass and requires the sampled count to be strictly smaller. Only the strict inequality is asserted, not how much smaller. |
| `count_sketch_at_full_nitro_sampling_writes_exactly_what_a_plain_insert_writes` | At rate `1.0` the Count Sketch Nitro insert path writes the same signed counters a plain insert writes. | Feeds the 40,000-draw Zipf(1.1) stream (2,048-key domain, seed `0x4E17_0001`) into a plain `4x2048` `Count<Vector2D<i32>, FastPath>` via `insert` and into a twin with `enable_nitro(1.0)` via `fast_insert_nitro`, then asserts the two 8,192-counter signed vectors are equal and that `estimate` agrees between the two sketches for every distinct key. The exact per-key truth is read from `FreqTruth` but discarded, so no accuracy floor against the true count is asserted. |
| `count_sketch_seeded_nitro_sampling_is_reproducible` | Two Count Sketches at the same rate and seed admit the same subset. | Builds two `4x2048` `Count<Vector2D<i32>, FastPath>` sketches at rate `0.25` and seed `0x5A11_0002`, feeds each the 40,000-draw Zipf(1.1) stream (2,048-key domain, seed `0x4E17_0001`) through `fast_insert_nitro`, and asserts their 8,192-counter vectors are equal. Reproducibility is all that is asserted: there is no differing-seed check and no accuracy check. |
### ASAPv1 Envelope Round Trips
Test file: [`tests/e2e_wire.rs`](../tests/e2e_wire.rs)
| test_name | test_description | what_is_tested |
| --- | --- | --- |
| `a_bloom_envelope_round_trips_on_both_paths_and_names_its_kind` | A Bloom envelope names kind_id `0x17 0x00` and preserves every answer on both hash paths. | Fills a `Bloom<RegularPath>` and a `Bloom<FastPath>`, each `with_capacity(2_000, 0.01)`, with `DataInput::I64(0..2_000)`, verifies both envelopes carry a `kind_id_len` of `2` and the bytes `0x17 0x00`, that each decode reports all 2,000 members present, that the regular decode answers exactly as its source on the 2,000 non-members `10_000..12_000`, and that `inserted()` is unchanged. |
| `a_coco_envelope_round_trips_and_names_its_kind` | A Coco envelope names kind_id `0x0c 0x00` and preserves every per-key estimate. | Fills `Coco::<DefaultXxHasher>::init_with_size(512, 4)` with the keys `flow-{k}` of a 20,000-draw Zipf stream (domain 1,024, exponent 1.1, seed `0xC1EA_0001`), verifies the envelope's `kind_id_len` of `2` and bytes `0x0c 0x00`, and that `estimate_key` on the decode equals the source for all 1,024 domain keys. |
| `a_ddsketch_envelope_round_trips_and_names_its_kind` | A DDSketch envelope names kind_id `0x05 0x00` and preserves its quantile answers exactly. | Fills `DDSketch::new(0.01)` with `1.0 + v` over `uniform_u64(20_000, 1_000_000, 0x1DE7_0001)`, verifies the envelope's `kind_id_len` of `2` and bytes `0x05 0x00`, and that the decode matches the source on `get_count()`, `alpha()`, and `get_value_at_quantile` at q `0.0`, `0.1`, `0.5`, `0.9` and `1.0`. |
| `a_hydra_envelope_round_trips_and_names_the_counter_it_carries` | A Hydra envelope's kind_id names the counter it carries, and the schema and cells survive. | Builds `Hydra::with_schema(4, 512, ["region", "user"], HydraCounter::CM(CountMin::<Vector2D<i32>, FastPath>::with_dimensions(3, 512)))`, updates each of the nine region/user pairs 40 times with `DataInput::Str("event")`, verifies the `kind_id_len` of `2` and bytes `0x07 0x01`, an unchanged `schema()`, and equal `query_key` answers under `HydraQuery::Frequency` for all nine fully specified keys. |
| `a_kll_dynamic_envelope_round_trips_and_names_its_kind` | A KLLDynamic envelope names kind_id `0x06 0x01` and re-encodes byte-identically. | Fills `KLLDynamic::<f64>::init_kll_with_seed(200, 0x5EED_9001)` from `uniform_u64(20_000, 1_000_000, 0xC0DE_0001)`, verifies the `kind_id_len` of `2` and bytes `0x06 0x01`, an unchanged `count()`, bit-identical `quantile` at q `0.0`, `0.1`, `0.5`, `0.9` and `1.0`, and that the decode re-serializes to the same bytes. |
| `a_space_saving_envelope_round_trips_and_names_its_kind` | A Space-Saving envelope names kind_id `0x18 0x00` and preserves every estimate. | Fills `SpaceSaving::<DefaultXxHasher>::with_capacity(256)` from a 20,000-draw Zipf stream (domain 1,024, exponent 1.1, seed `0xC1EA_0001`), verifies the `kind_id_len` of `2` and bytes `0x18 0x00`, and that `estimate` on the decode equals the source for all 1,024 domain keys. |
| `an_eh_sketch_list_envelope_round_trips_and_names_its_kind` | An EHSketchList envelope names kind_id `0x14 0x00` and keeps the payload sketch it wraps. | Fills an `EHSketchList::CM(CountMin::<Vector2D<i32>, FastPath>::with_dimensions(3, 512))` with the first 5,000 draws of the Zipf stream, verifies the `kind_id_len` of `2` and bytes `0x14 0x00`, an unchanged `sketch_type()`, and equal `query` answers for keys `0..512`. |
| `an_elastic_envelope_round_trips_and_names_its_kind` | An Elastic envelope names kind_id `0x0b 0x00` and preserves every per-key answer. | Fills `Elastic::<DefaultXxHasher>::init_with_dimensions(64, 3, 1_024)` with the keys `flow-{k}` of the 20,000-draw Zipf stream, verifies the `kind_id_len` of `2` and bytes `0x0b 0x00`, and that `query` on the decode equals the source for all 1,024 domain keys. |
| `an_envelope_is_refused_by_every_decoder_but_its_own` | One sketch's envelope never decodes as another's, and malformed buffers are errors. | Verifies a `DDSketch::new(0.01)` envelope over `1..1_000` fails to decode as `Bloom<RegularPath>` and as `SpaceSaving<DefaultXxHasher>`, that a one-key `Bloom<RegularPath>` envelope fails to decode as `DDSketch`, and that both an empty buffer and the first half of the DDSketch envelope are refused. |
| `an_exponential_histogram_envelope_round_trips_and_names_its_kind` | An ExponentialHistogram envelope names kind_id `0x13 0x00` and answers interval merges identically. | Updates `ExponentialHistogram::new(8, 1_000_000, EHSketchList::CM(CountMin::<Vector2D<i32>, FastPath>::with_dimensions(3, 512)))` with the first 3,000 Zipf draws at timestamps `0..3_000`, verifies the `kind_id_len` of `2` and bytes `0x13 0x00`, unchanged `bucket_count()`, `get_min_time()` and `get_max_time()`, and that `query_interval_merge` over the full time span answers identically for keys `0..256`. |
| `the_experimental_envelopes_round_trip_and_name_their_kinds` | The experimental sketches' envelopes name their kinds and preserve their state. | Compiled only under the `experimental` feature: fills `KMV::<DefaultXxHasher>::new(1_024)` from `uniform_u64(50_000, 10_000_000, 0x5EED_1001)` and verifies the `kind_id_len` of `2`, bytes `0x0e 0x00` and an unchanged `estimate()`; fills `UniformSampling::with_seed(0.2, 0x5EED_1002)` from `uniform_u64(20_000, 1_000_000, 0x5EED_1003)` and verifies bytes `0x0d 0x00`, unchanged `len()` and `total_seen()`, and a byte-identical re-encode. |
| `the_heap_backed_matrix_envelopes_round_trip_and_name_their_kinds` | The heap-backed matrix envelopes name their kinds and keep both matrix and heap. | Over the 20,000-draw Zipf stream, verifies `CMSHeap::<Vector2D<i64>, FastPath>::new(4, 2_048, 32)` carries `kind_id_len` `2` and bytes `0x03 0x00` and `CSHeap::<Vector2D<i64>, RegularPath>::new(5, 2_048, 32)` carries `0x0a 0x00`, that both decodes equal their sources on `estimate` for keys `0..1_024`, and that `heap().len()` is unchanged for both. |
| `the_matrix_and_quantile_envelopes_carry_their_answers_unchanged` | The four core envelopes name their kinds and carry their answers unchanged. | Over the 20,000-draw Zipf stream, verifies the kind_id bytes `0x02 0x00` for `CountMin<Vector2D<i64>, FastPath>` at `4x2048`, `0x04 0x00` for `Count<Vector2D<i64>, RegularPath>` at `5x2048`, `0x06 0x00` for `KLL<f64>` at `k = 200` seeded `0x5EED_9002`, and `0x01 0x02` for `HyperLogLog<ErtlMLE>`; then that both matrices agree with their sources on `estimate` for keys `0..1_024`, that KLL's `quantile` is bit-identical at q `0.0`, `0.5` and `1.0`, and that the HyperLogLog `estimate()` is unchanged. |
| `the_univmon_family_envelopes_round_trip_and_name_their_kinds` | The three UnivMon envelopes name their kinds and preserve their aggregate answers. | Over the 20,000-draw Zipf stream, verifies `UnivMon::init_univmon(32, 5, 512, 8)` carries bytes `0x10 0x00` with unchanged `calc_l1()`, `calc_l2()` and `calc_card()`; `UnivMonPyramid::with_defaults()` carries `0x11 0x00` with unchanged `calc_l1()` and `calc_l2()`; and `UnivMonQ::new(Default::default())` carries `0x1a 0x00` with unchanged `count()`, `estimate_f2()` and `quantile` at q `0.1`, `0.5` and `0.9`. |
### ASAPv1 Golden Byte Vectors
Test file: [`tests/asapv1_golden.rs`](../tests/asapv1_golden.rs)
| test_name | test_description | what_is_tested |
| --- | --- | --- |
| `cms_f64_fast_2x3_matches_golden` | A known f64 fast-path Count-Min matrix serializes to its checked-in golden bytes. | Verifies `CountMin::<Vector2D<f64>, FastPath>::from_storage` over the `2x3` matrix `[[0.0, 1.5, 2.25], [3.75, 4.125, 5.0625]]` serializes to `asapv1_golden/cms_f64_fast_2x3.hex`, and that decoding that fixture recovers the six cells in row-major order and re-serializes to the same bytes. |
| `cms_i64_regular_2x3_matches_golden` | A known i64 regular-path Count-Min matrix serializes to its checked-in golden bytes. | Verifies `CountMin::<Vector2D<i64>, RegularPath>::from_storage` over the `2x3` matrix `[[0, 1, 127], [128, 300, 65536]]` serializes to `asapv1_golden/cms_i64_regular_2x3.hex`, and that decoding the fixture reports `rows()` `2`, `cols()` `3`, the six cells in row-major order, and a byte-identical re-serialization. |
| `cs_i32_regular_2x4_matches_golden` | The i32 counter type reaches the metadata, and an i32 golden is not an i64 sketch. | Verifies `Count::<Vector2D<i32>, RegularPath>::from_storage` over `[[0, 127, 128, 65536], [-1, -33, -32768, -2147483648]]` cast to `i32` serializes to `asapv1_golden/cs_i32_regular_2x4.hex`, that decoding it recovers the eight cells and re-serializes identically, that the i32 and i64 regular fixtures have equal length yet differ, and that the i32 fixture fails to decode as `Count<Vector2D<i64>, RegularPath>`. |
| `cs_i64_fast_2x4_matches_golden` | The fast-path mode reaches the bytes, so the same matrix encodes differently per path. | Verifies `Count::<Vector2D<i64>, FastPath>::from_storage` over `[[0, 127, 128, 65536], [-1, -33, -32768, -2147483648]]` serializes to `asapv1_golden/cs_i64_fast_2x4.hex`, that decoding it recovers the eight cells and re-serializes identically, and that the fixture differs from `cs_i64_regular_2x4.hex` built from the same matrix. |
| `cs_i64_regular_2x4_matches_golden` | A known signed Count-Sketch matrix serializes to its checked-in golden bytes. | Verifies `Count::<Vector2D<i64>, RegularPath>::from_storage` over `[[0, 127, 128, 65536], [-1, -33, -32768, -2147483648]]` — sweeping the msgpack integer widths in both directions — serializes to `asapv1_golden/cs_i64_regular_2x4.hex`, and that decoding the fixture reports `rows()` `2`, `cols()` `4`, the eight cells, and a byte-identical re-serialization. |
| `hll_classic_p12_matches_golden` | A known P12 Classic register pattern serializes to its golden bytes on both the portable and native paths. | Builds `HllSketch::from_raw(HllVariant::Regular, 12, regs, 0.0, 0.0, 0.0)` where `regs` is 4,096 zeros with `[0] = 1`, `[1] = 7`, `[100] = 42` and `[4095] = 3`, verifies `to_msgpack()` equals `asapv1_golden/hll_classic_p12.hex`, that `HyperLogLogP12::<Classic>::deserialize_from_bytes` on the fixture recovers those registers and re-serializes identically, and that `HllSketch::from_msgpack` reports the same registers, `precision` `12` and `HllVariant::Regular`. |
| `hll_ertl_mle_p12_matches_golden` | The Datafusion variant tag reaches the bytes for the same P12 register pattern. | Builds `HllSketch::from_raw(HllVariant::Datafusion, 12, regs, 0.0, 0.0, 0.0)` over the shared P12 pattern (`[0] = 1`, `[1] = 7`, `[100] = 42`, `[4095] = 3` in 4,096 registers), verifies `to_msgpack()` equals `asapv1_golden/hll_ertl_mle_p12.hex`, that `HyperLogLogP12::<ErtlMLE>::deserialize_from_bytes` recovers the registers and re-serializes identically, and that `HllSketch::from_msgpack` reports `HllVariant::Datafusion`. |
| `hll_hip_p12_matches_golden` | The HIP variant's three running scalars travel on the wire beside its registers. | Builds `HllSketch::from_raw(HllVariant::Hip, 12, regs, 1.5, 2.5, 3.0)` over the shared P12 pattern, verifies `to_msgpack()` equals `asapv1_golden/hll_hip_p12.hex`, that `HyperLogLogHIPP12::deserialize_from_bytes` re-serializes the fixture identically, and that `HllSketch::from_msgpack` reports the registers, `HllVariant::Hip`, `hip_kxq0` `1.5`, `hip_kxq1` `2.5` and `hip_est` `3.0`. |
| `kll_f64_k200_matches_golden` | A deterministic f64 KLL serializes to its golden bytes, which round-trip unchanged. | Verifies `KLL::<f64>::init_kll_with_seed(200, 42)` fed `1..=50` (below the level-0 capacity, so no compaction fires) serializes to `asapv1_golden/kll_f64_k200.hex`, and that decoding the fixture re-serializes to the same bytes and reports `quantile(0.0)` `1.0` and `quantile(1.0)` `50.0`. |
| `kll_i64_k200_matches_golden` | A deterministic i64 KLL serializes to its golden bytes, which round-trip unchanged. | Verifies `KLL::<i64>::init_kll_with_seed(200, 42)` fed `1..=50` serializes to `asapv1_golden/kll_i64_k200.hex`, and that decoding the fixture re-serializes to the same bytes and reports `quantile(0.0)` `1.0` and `quantile(1.0)` `50.0`. |
### MessagePack Envelope Compatibility
Test file: [`tests/msgpack_compat.rs`](../tests/msgpack_compat.rs)
| test_name | test_description | what_is_tested |
| --- | --- | --- |
| `count_min_decodes_go_bytes` | The test asserts nothing. | The test asserts nothing: the body is empty apart from three commented-out lines sketching an `include_bytes!` of `fixtures/msgpack/count_min.msgpack` and a `CountMinSketch::from_msgpack` check, and it is marked `#[ignore]` with the reason that no cross-language msgpack fixture exists in the repository. |
| `count_min_sketch_round_trip` | A portable `CountMinSketch` survives a msgpack round trip with its geometry intact. | Updates `CountMinSketch::new(3, 64)` with `alpha` `+1.0`, `beta` `+2.0` and `alpha` `+4.0`, then verifies `from_msgpack(to_msgpack())` reports `rows` `3` and `cols` `64`; the counter matrix and the per-key estimates are not checked. |
| `count_min_sketch_with_heap_round_trip` | A portable `CountMinSketchWithHeap` survives a msgpack round trip with its geometry and heap size intact. | Updates `CountMinSketchWithHeap::new(3, 64, 8)` with `hot` `+100.0` and `warm` `+10.0`, then verifies the decode reports `rows` `3`, `cols` `64` and `heap_size` `8`; the heap's contents are not checked. |
| `count_min_wire_shape` | The `CountMinSketchWire` DTO round-trips through `rmp_serde` with its field shape intact. | Serializes `CountMinSketchWire { sketch: vec![vec![1.0, 2.0]; 3], rows: 3, cols: 2 }` with `rmp_serde::to_vec` and reads it back with `rmp_serde::from_slice`, verifying `rows` `3`, `cols` `2` and a `sketch` of length `3`; the cell values are not checked. |
| `count_min_with_heap_wire_shape` | The nested `CountMinSketchWithHeapWire` DTO round-trips through `rmp_serde` with its nesting intact. | Serializes a wire struct holding a `CountMinSketchInnerWire` of `2x4` zeros, one `CmsHeapItem { key: "hot", value: 42.0 }` and `heap_size: 8`, then verifies the `rmp_serde` decode reports `heap_size` `8`, one heap entry and the key `hot`; the item's value and the inner matrix are not re-checked. |
| `count_sketch_round_trip` | A portable `CountSketch` survives a msgpack round trip with its geometry intact. | Updates `CountSketch::new(3, 64)` with `k1` `+1.0` and `k2` `+2.0`, then verifies the decode reports `rows` `3` and `cols` `64`; the signed counters and the estimates are not checked. |
| `dd_sketch_decodes_go_bytes` | The test asserts nothing. | The test asserts nothing: the body is empty and the test is marked `#[ignore]` with the reason that no cross-language msgpack fixture exists in the repository. |
| `dd_sketch_round_trip` | A portable `DdSketch` survives a msgpack round trip carrying its full count in the bucket array. | Updates `DdSketch::new(0.01)` with `1.0`, `10.0` and `100.0`, then verifies the decode's `total_count()` — recovered by summing the buckets, since the count is not on the wire — is `3`; `alpha`, the bucket offset and the quantiles are not checked. |
| `delta_result_round_trip` | A `DeltaResult` survives a msgpack round trip with both of its sets. | Serializes a `DeltaResult` whose `added` holds `a` and whose `removed` holds `b`, then verifies the decode's `added` contains `a` and its `removed` contains `b`. |
| `hll_sketch_decodes_go_bytes` | The test asserts nothing. | The test asserts nothing: the body is empty and the test is marked `#[ignore]` with the reason that no cross-language msgpack fixture exists in the repository. |
| `hll_sketch_round_trip` | A portable `HllSketch` survives a msgpack round trip with its register count intact. | Updates `HllSketch::new(HllVariant::Regular, 8)` with `b"a"`, `b"b"` and `b"c"`, then verifies only that the decode's `registers` has the same length as the source's; the register values, the precision and the variant are not checked. |
| `hydra_kll_decodes_go_bytes` | The test asserts nothing. | The test asserts nothing: the body is empty and the test is marked `#[ignore]` with the reason that no cross-language msgpack fixture exists in the repository. |
| `hydra_kll_sketch_round_trip` | A portable `HydraKllSketch` survives a msgpack round trip with its grid shape intact. | Updates `HydraKllSketch::with_seed(2, 4, 200, 0x5EED_0900)` with `("a", 1.0)`, `("a", 2.0)` and `("b", 3.0)`, then verifies the decode reports `rows` `2` and `cols` `4`; the nested KLL payloads are not checked. |
| `hydra_kll_wire_shape` | The `HydraKllSketchWire` DTO round-trips through `rmp_serde` with its two levels of nesting intact. | Serializes a wire struct of `rows: 2`, `cols: 3` and a `2x3` grid of `KllSketchData { k: 200, sketch_bytes: vec![] }`, then verifies the `rmp_serde` decode reports `rows` `2`, `cols` `3`, an outer length of `2` and an inner length of `3`. |
| `kll_sketch_decodes_go_bytes` | The test asserts nothing. | The test asserts nothing: the body is empty and the test is marked `#[ignore]` with the reason that no cross-language msgpack fixture exists in the repository. |
| `kll_sketch_round_trip` | A portable `KllSketch` survives a msgpack round trip with its `k` and retained mass intact. | Feeds `KllSketch::with_seed(200, 0x5EED_0800)` the values `0..100` as `f64`, then verifies the decode reports `k` `200` and `count()` `100`; the retained items and the quantile answers are not checked. |
| `set_aggregator_round_trip` | A `SetAggregator` survives a msgpack round trip with its members. | Updates a `SetAggregator::new()` with `web` and `api`, then verifies the decode holds two values, one of which is `web`. |
### Conformance Kit
Test file: [`tests/conformance_kit.rs`](../tests/conformance_kit.rs)
| test_name | test_description | what_is_tested |
| --- | --- | --- |
| `core_ddsketch_passes_relative_quantile_conformance` | The core `DDSketch` holds its relative-value-error promise at three accuracy settings. | For alpha `0.001`, `0.01` and `0.05`, runs `relative_quantile_battery` on `DDSketch::new(alpha)` over 30,000 values — 20,000 Zipf draws (domain 4,096, exponent 1.1, seed `7_701`) offset by `1_000.0`, plus 10,000 draws (domain 512, exponent 1.3, seed `7_702`) mapped to `1e6 + v * 1e3` — requiring at q `0.1`, `0.25`, `0.5`, `0.75` and `0.9` a relative error of at most `alpha` plus a few-ULP numerical slack against the exact `ceil(q*n)` order statistic. |
| `count_l2hh_passes_signed_frequency_and_merge_conformance` | `CountL2HH` passes the two-sided frequency, turnstile and merge-equivalence batteries. | Drives `CountL2HH::with_dimensions(5, 4_096)` over a 60,000-draw Zipf stream (domain 2,048, exponent 1.1, seed `9001`) through `frequency_battery` two-sided at `rel_tol` `0.06` and `abs_tol` `25.0` on every key of true count at least `25`, through `turnstile_battery` on key `42` (`+500` then `-200` must estimate `300` within `1.0`, then `-300` must cancel to within `1e-6`), and through `merge_equivalence_battery`, which shards the stream by parity, merges, and requires agreement with a single-pass sketch within `25.0 + 0.06 * count`. |
| `countmin_passes_frequency_and_merge_conformance` | `CountMin` passes the one-sided frequency and merge-equivalence batteries. | Drives `CountMin::<Vector2D<i64>, FastPath>::with_dimensions(4, 4096)` over the 60,000-draw Zipf stream (domain 2,048, exponent 1.1, seed `9001`) through `frequency_battery` one-sided at `rel_tol` `0.01` and `abs_tol` `4.0`, which requires the absent sentinel key `i64::MIN` to estimate within `±4.0` and each key of true count at least `25` to land in `[count, count * 1.01 + 4.0]`, then through `merge_equivalence_battery` at the same spec. |
| `countsketch_passes_signed_frequency_conformance` | `Count` passes the two-sided frequency, turnstile and merge-equivalence batteries. | Drives `Count::<Vector2D<i64>, RegularPath>::with_dimensions(5, 4096)` over the 60,000-draw Zipf stream through `frequency_battery` two-sided at `rel_tol` `0.06` and `abs_tol` `25.0`, `turnstile_battery` on key `42` via `insert_many` (`+500 - 200` must read `300` within `1.0`, then cancel to within `1e-6`), and `merge_equivalence_battery` at the same spec. |
| `ddsketch_passes_relative_quantile_conformance` | The portable `DdSketch` holds its relative-value-error promise under its own rank convention. | Runs `relative_quantile_battery` on `PortableDds::new(0.01)` over the positive samples of `normal_f64(40_000, 500.0, 80.0, 7001)`, requiring at q `0.1`, `0.25`, `0.5`, `0.75` and `0.9` a relative error of at most `0.01` plus a few-ULP numerical slack against the exact `floor(q*(n-1))` order statistic. |
| `heap_backed_frequency_sketches_pass_frequency_and_merge_conformance` | Both heap-backed matrix sketches pass the frequency and merge-equivalence batteries. | Over the 60,000-draw Zipf stream (domain 2,048, exponent 1.1, seed `9001`), drives `CMSHeap::<Vector2D<i64>, FastPath>::new(4, 4_096, 64)` through `frequency_battery` and `merge_equivalence_battery` one-sided at `rel_tol` `0.01` and `abs_tol` `8.0`, and `CSHeap::<Vector2D<i64>, RegularPath>::new(5, 4_096, 64)` through both two-sided at `rel_tol` `0.06` and `abs_tol` `25.0`. |
| `hll_variants_pass_cardinality_conformance` | All three native HyperLogLog estimators and the portable one estimate within 3%. | Runs `cardinality_battery` at `rel_tol` `0.03` over 100,000 distinct keys `i.wrapping_mul(0x9E37_79B9_7F4A_7C15)` on `HyperLogLog<Classic>`, `HyperLogLog<ErtlMLE>`, `HyperLogLogHIP` and the portable `HllSketch::new(HllVariant::Regular, 14)`; each must estimate `100_000` within 3% and stay in band after the whole stream is replayed as duplicates. |
| `kll_family_passes_quantile_conformance` | The three KLL adapters hold the shared rank-error band. | Runs `quantile_battery` at the default `rank_tol` of `0.03` over q `0.1`, `0.25`, `0.5`, `0.75` and `0.9` on the positive samples of `normal_f64(40_000, 500.0, 80.0, 7001)` for `KLL::init_kll_with_seed(200, 0x4017_0001)`, `KLLDynamic::<f64>::init_kll_with_seed(200, 0x4017_0001)`, and a `KLL` at the same `k` and seed queried through `quantile_cached`. |
| `kmv_passes_cardinality_conformance` | `KMV` estimates a 100,000-key distinct count within 8%. | Compiled only under the `experimental` feature: runs `cardinality_battery` at `rel_tol` `0.08` on `KMV::new(4_096)` over 100,000 distinct keys `i.wrapping_mul(0x9E37_79B9_7F4A_7C15)`, requiring the estimate in band both after the first pass and after the duplicate replay. |
| `uniform_sampling_at_full_rate_passes_quantile_conformance` | A sampler retaining everything answers quantiles exactly. | Compiled only under the `experimental` feature: runs `quantile_battery` at `rank_tol` `0.0` on `UniformSampling::with_seed(1.0, 7_704)` over 20,000 Zipf draws (domain 4,096, exponent 1.1, seed `7_703`), with each quantile read from the sorted retained samples at index `ceil(q * len)`. |
| `univmonq_passes_quantile_conformance` | `UnivMonQ` holds a 4% rank band on a uniform stream. | Runs `quantile_battery` at `rank_tol` `0.04` over q `0.1`, `0.25`, `0.5`, `0.75` and `0.9` on `UnivMonQ::new(Default::default())` fed the 30,000 values of `uniform_u64(30_000, 50_000, 7002)` as `f64`. |
### Statistical Spec Self-Tests
Test file: [`tests/spec_self_tests.rs`](../tests/spec_self_tests.rs)
| test_name | test_description | what_is_tested |
| --- | --- | --- |
| `bad_row_threshold_is_ceil_half_the_depth` | The bad-row threshold is `ceil(d/2)`, and both specs report the same one. | Verifies `CountSketchSpec::new(rows, 1024).bad_row_threshold()` is `1, 1, 2, 2, 3, 3, 4` for depths `1..=7`, that it equals `rows / 2 + 1` at odd depth and is strictly below it at even depth, and that `SecondMomentSpec::new(rows, 1024)` reports the same threshold for every depth `1..=8`. |
| `marginal_failure_probabilities_match_the_hand_computed_tails` | The binomial tails the threshold selects match their hand-computed values. | Verifies `CountSketchSpec::marginal_failure()` is within `1e-9` of `0.259_259_259_259` at `d = 3`, `0.407_407_407_407` at `d = 4`, `0.209_876_543_209` at `d = 5` and `0.319_615_912_208` at `d = 6`, asserting the thresholds `2, 2, 3, 3` alongside, and that `binomial_tail_ge(4, 3, 1.0 / 3.0)` is within `1e-9` of `0.111_111_111_111`. |
| `simultaneous_kappa_reflects_the_corrected_threshold` | The simultaneous `kappa` search reaches its target and is wider than a `d/2 + 1` threshold demands. | For `CountSketchSpec::new(4, 2048)`, verifies `simultaneous_kappa(512, SIMULTANEOUS_LEVEL)` at a level of `1e-3` yields a `kappa` whose `key_failure_at(kappa)` is at most `1e-3 / 512`, and that this `kappa` is strictly larger than the one a geometric-then-bisection search over `binomial_tail_ge(4, 3, 1.0 / kappa)` finds for the same target. |
| `two_same_direction_bad_rows_move_an_averaged_four_row_median_out_of_band` | Two same-direction bad rows break a four-row averaged median, and one does not. | With an inline median-of-four `(v[1] + v[2]) / 2`, a true value of `100.0` and an error scale of `10.0` (band `[90, 110]`), verifies `[95, 105, 100, 10_000]` stays in band, `[95, 105, 10_000, 10_000]` leaves it, and `[95, 105, -10_000, 10_000]` stays in band, asserting the bad-row count of each fixture first. |
### Proto Envelope Parity Probe
Test file: [`tests/sketches_go_parity_probe.rs`](../tests/sketches_go_parity_probe.rs)
| test_name | test_description | what_is_tested |
| --- | --- | --- |
| `sketches_count_fastpath_matches_go_count_sketch_envelope` | A `sketches::Count` fast-path matrix encodes to the checked-in Count-Sketch envelope bytes. | Fills `Count<Vector2D<i64>, FastPath, DefaultXxHasher>` at `3x512` with 25 `insert_many` calls over the five keys `k-a`..`k-e`, packs the row-major cells and per-row L2 sums into a `CountSketchState` with `counter_type` `INT64` inside a `SketchEnvelope { format_version: 1 }` with no producer or hash_spec, and verifies the prost encoding equals the 1,577-byte fixture `tests/cs_envelope_golden.hex`. |
| `sketches_countmin_fastpath_matches_go_count_min_envelope` | A `sketches::CountMin` fast-path matrix encodes to the checked-in Count-Min envelope bytes. | Fills `CountMin<Vector2D<f64>, FastPath, DefaultXxHasher>` at `4x2048` with 50 `insert_many` calls over the ten keys `flow-0`..`flow-9`, packs the cells cast to `i64` plus per-row L1 and L2 sums into a `CountMinState` with `counter_type` `INT64`, and verifies the prost encoding matches the 8,275-byte fixture `src/sketches/testdata/cms_envelope_golden.hex` in length and then byte for byte. |
| `sketches_ddsketch_matches_go_envelope` | A `sketches::DDSketch` encodes to the DDSketch envelope hex constant held in the test file. | Fills `DDSketch::new(0.01)` with `1..=50` as `f64`, encodes a `DdSketchState` carrying `store_counts`, `store_offset` and an alpha round-tripped through gamma (`gamma = (1 + a) / (1 - a)`, `alpha_wire = (gamma - 1) / (gamma + 1)`), and verifies the envelope matches the 403-byte inline hex constant in length and then byte for byte; the comment on that constant records it as this crate's own output rather than a fixture from another implementation, so no cross-language parity is pinned. |
| `sketches_hll_classic_matches_go_envelope` | An ErtlMLE P14 register set encodes to the checked-in HyperLogLog envelope bytes. | Feeds `HyperLogLogImpl<ErtlMLE, HllBucketListP14, DefaultXxHasher>` the `hash64_seeded(CANONICAL_HASH_SEED, ...)` digests of the IEEE-754 little-endian bytes of `1.0..=50.0` through `insert_with_hash`, encodes a `HyperLogLogState` with `variant` `2`, `precision` `14`, the dense registers, zeroed HIP scalars and no sparse form, and verifies the envelope matches the 16,398-byte fixture `src/sketches/testdata/hll_envelope_golden.hex` in length and then byte for byte; despite the name, the variant under test is `ErtlMLE`, not `Classic`. |
### Cross-Language Proto Consumer
Test file: [`tests/xtest_consumer.rs`](../tests/xtest_consumer.rs)
| test_name | test_description | what_is_tested |
| --- | --- | --- |
| `cross_language_proto` | Protobuf envelopes read from the cross-language fixture directory answer their point queries in band. | Asserts nothing unless fixtures are available: with no `XTEST_DIR` and no discoverable producer directory holding `tests/cross_language/xtest_producer_test.go`, it prints a skip line and returns. With fixtures it decodes nine `SketchEnvelope` files and records a pass or failure for each — `countmin.pb` min-frequency for `item:42` at least `101`, `kll.pb` p50 within 5% of `5000` and p99 within 5% of `9900`, `ddsketch.pb` the same two quantiles within 2%, `hll.pb` an ErtlMLE cardinality inside `[40_000, 65_000]`, `countsketch.pb` `cs:hot` at least `200`, `coco.pb` `coco:hot` at least `500`, `elastic.pb` `elephant` at least `900`, `univmon.pb` a cardinality inside `[1_000, 15_000]`, `hydra.pb` `hydra:42` at least `51` — using the hash seeds `0xcafe3553`, `0x6a09e667` and `0xbb67ae85`, and, when `countmin_sampled.pb` and `hll_sampled.pb` exist, requires `effective_sample_p` of `0.1` and a `rescale_count` by `1/p` within 5% of `100_000` and 6% of `200_000`. A single `assert!` at the end fails if any check failed; a missing or mistyped envelope panics on the spot. |
### HLL Custom Precision
Test file: [`tests/hll_custom_precision.rs`](../tests/hll_custom_precision.rs)
| test_name | test_description | what_is_tested |
| --- | --- | --- |
| `custom_precision_indexing_and_iteration` | A macro-generated register storage indexes, slices and iterates. | On an `HllBucketListP10` built by `impl_hll_bucket_list!` outside the crate, sets index `0` to `7` and index `NUM_REGISTERS - 1` to `3`, verifies both read back, that `storage[0..2]` is `[7, 0]`, that `copy_from_slice` of `[1, 2]` into `1..3` lands in `as_slice()`, and that iterating the whole storage sums to `13`. |
| `custom_precision_merges` | A merge at a custom precision estimates the union. | Fills `HyperLogLogImpl<Classic, HllBucketListP18>` with items `key-{i:08}` for `i` in `0..60_000` and a second with `40_000..100_000`, merges them, and verifies the estimate is within 2% relative of the 100,000-item union. |
| `custom_precision_round_trips_through_serde` | A custom-precision sketch round-trips through the derived serde impls. | Fills `HyperLogLogImpl<Classic, HllBucketListP13>` with 5,000 distinct `key-{i:08}` items and verifies an `rmp_serde::to_vec` / `from_slice` round trip preserves the register slice exactly and the `estimate()`. |
| `custom_precision_round_trips_through_the_asapv1_wire_format` | The ASAPv1 envelope carries a custom precision and refuses a mismatched register count. | Over 5,000 distinct `key-{i:08}` items at `lg_k = 13`, verifies `serialize_to_bytes` / `deserialize_from_bytes` preserves the registers and `estimate()` for both `Classic` and `ErtlMLE`, preserves `estimate()` for `HyperLogLogHIPImpl` so that its running `kxq0`, `kxq1` and `est` travel rather than being recomputed, and that a fresh `lg_k = 18` envelope fails to decode as `HllBucketListP13`. |
| `custom_precisions_estimate_correctly` | Every macro-generated precision reports the right constants and estimates in band. | Through a shared `check_precision` helper, verifies for each precision that `PRECISION` is `lg_k`, `NUM_REGISTERS` is `1 << lg_k`, `REGISTER_BITS` is `64 - lg_k` and `P_MASK` is `NUM_REGISTERS - 1`, that a default storage has that length, is non-empty and is zeroed, that at least one register is set after the inserts and none exceeds `REGISTER_BITS + 1`, and that the `Classic`, `ErtlMLE` and HIP estimates all fall inside the tolerance; invoked at `lg_k` `4` with 100 items at `0.60`, `8` with 1,000 at `0.30`, `10` with 10,000 at `0.15`, `13` with 50,000 at `0.06` and `18` with 200,000 at `0.02`. |
| `large_precision_allocates_on_the_heap` | Register storage is allocated on the heap, so a 4 MiB precision constructs on a test thread. | Verifies a fresh `HyperLogLogImpl<Classic, HllBucketListP22>` — `1 << 22` registers, past the 2 MiB test-thread stack — reports `NUM_REGISTERS` registers that are all zero, and that an `HllBucketListP18` sketch over 1,000 `key-{i:08}` items survives an `rmp_serde` round trip with an identical register slice. |
### Accuracy-Probe Regressions
Test file: [`tests/bug_verification.rs`](../tests/bug_verification.rs)
| test_name | test_description | what_is_tested |
| --- | --- | --- |
| `portable_ddsketch_respects_alpha_at_bucket_edges` | Both DDSketch implementations hold the advertised relative accuracy on a value sitting at a bucket's lower edge. | Sets `alpha = 0.05`, `gamma = (1+alpha)/(1-alpha)`, and feeds the bucket-edge value `gamma^20 * (1 + 1e-6)` 10,000 times into both `message_pack_format::portable::ddsketch::DdSketch::new(0.05)` and `DDSketch::new(0.05)`, then asserts the portable `quantile(0.5)` and the core `get_value_at_quantile(0.5)` are each within `alpha * (1 + 1e-6)` relative error of that value — a representative reported as the bucket log-midpoint `gamma^(k+0.5)` gives about `5.13%` here and fails. Exact agreement between the two is not asserted, because the core sketch clamps representatives to its observed min/max and the portable wire format does not carry them. |
| `countl2hh_f2_survives_beyond_i64_max` | `CountL2HH`'s hot-path L2 accumulation stays exact inside `i64` and saturates beyond it. | Builds `CountL2HH::<DefaultXxHasher>::with_dimensions_and_seed(4, 2048, 7)` and calls `fast_insert_with_count(&DataInput::U32(1), 3_000_000_000)`, asserting `get_l2_sqr()` matches the exact `9e18` to a relative `1e-12`; a second key `U32(2)` at the same count puts the true F2 at `1.8e19`, past `i64::MAX`, and `get_l2_sqr()` must then equal `i64::MAX` (`9.223e18`) to a relative `1e-12` rather than wrapping to `0` or panicking in debug. |