This is an automated email from the ASF dual-hosted git repository.
tisonkun pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/datasketches-rust.git
The following commit(s) were added to refs/heads/main by this push:
new 1e13991 test(hll): cover union rebuild regressions (#206)
1e13991 is described below
commit 1e139915981a410b3000d7227728f0496d3ee1e7
Author: tison <[email protected]>
AuthorDate: Thu Aug 20 00:49:31 2026 +0800
test(hll): cover union rebuild regressions (#206)
---
datasketches/tests/hll_test/union.rs | 115 +++++++++++++++++++++++++++++++++++
1 file changed, 115 insertions(+)
diff --git a/datasketches/tests/hll_test/union.rs
b/datasketches/tests/hll_test/union.rs
index ef67b39..529ffc0 100644
--- a/datasketches/tests/hll_test/union.rs
+++ b/datasketches/tests/hll_test/union.rs
@@ -32,6 +32,47 @@ use datasketches::hll::HllSketch;
use datasketches::hll::HllType;
use datasketches::hll::HllUnion;
+const HLL_TYPES: [HllType; 3] = [HllType::Hll4, HllType::Hll6, HllType::Hll8];
+
+fn make_hll_sketch(hll_type: HllType, lg_config_k: u8, start: u64, end: u64)
-> HllSketch {
+ let mut sketch = HllSketch::new(lg_config_k, hll_type);
+ for value in start..end {
+ sketch.update(value);
+ }
+ sketch
+}
+
+fn assert_estimate_within(estimate: f64, expected: f64, relative_error: f64) {
+ let actual_relative_error = (estimate - expected).abs() / expected;
+ assert!(
+ actual_relative_error <= relative_error,
+ "Expected estimate within {:.1}% of {}, got {} ({:.1}% error)",
+ relative_error * 100.0,
+ expected,
+ estimate,
+ actual_relative_error * 100.0,
+ );
+}
+
+fn serialize_flat_union(first: &HllSketch, second: &HllSketch, third:
&HllSketch) -> Vec<u8> {
+ let mut union = HllUnion::new(8);
+ union.update(first);
+ union.update(second);
+ union.update(third);
+ union.to_sketch(HllType::Hll8).serialize()
+}
+
+fn serialize_nested_union(first: &HllSketch, second: &HllSketch, third:
&HllSketch) -> Vec<u8> {
+ let mut prefix = HllUnion::new(8);
+ prefix.update(first);
+ prefix.update(second);
+
+ let mut union = HllUnion::new(8);
+ union.update(&prefix.to_sketch(HllType::Hll8));
+ union.update(third);
+ union.to_sketch(HllType::Hll8).serialize()
+}
+
#[test]
fn test_union_basic_operations() {
let mut union = HllUnion::new(12);
@@ -287,6 +328,80 @@ fn test_union_lg_k_handling() {
);
}
+// Regression coverage for https://github.com/apache/datasketches-cpp/pull/512.
+#[test]
+fn test_union_downsampling_merge_is_not_empty() {
+ for hll_type in HLL_TYPES {
+ let sketch = make_hll_sketch(hll_type, 15, 0, 100_000);
+ let mut union = HllUnion::new(8);
+ union.update(&sketch);
+
+ assert!(!union.is_empty(), "{hll_type:?} union should not be empty");
+ }
+}
+
+#[test]
+fn test_union_mixed_lg_k_estimate_is_merge_order_independent() {
+ const N: u64 = 100_000;
+
+ for hll_type in HLL_TYPES {
+ let a = make_hll_sketch(hll_type, 15, 0, N);
+ let b = make_hll_sketch(hll_type, 8, N, 2 * N);
+ let expected = 2.0 * N as f64;
+
+ let mut larger_first = HllUnion::new(8);
+ larger_first.update(&a);
+ larger_first.update(&b);
+ let larger_first_estimate = larger_first.estimate();
+ assert_estimate_within(larger_first_estimate, expected, 0.1);
+
+ let mut smaller_first = HllUnion::new(8);
+ smaller_first.update(&b);
+ smaller_first.update(&a);
+ let smaller_first_estimate = smaller_first.estimate();
+ assert_estimate_within(smaller_first_estimate, expected, 0.1);
+ assert_eq!(
+ larger_first_estimate, smaller_first_estimate,
+ "{hll_type:?} estimate should be merge-order independent",
+ );
+ }
+}
+
+#[test]
+fn test_union_scalar_update_after_downsampling_merge() {
+ const N: u64 = 100_000;
+
+ for hll_type in HLL_TYPES {
+ let sketch = make_hll_sketch(hll_type, 15, 0, N);
+ let mut union = HllUnion::new(8);
+ union.update(&sketch);
+ for value in N..2 * N {
+ union.update_value(value);
+ }
+
+ assert_estimate_within(union.estimate(), 2.0 * N as f64, 0.1);
+ }
+}
+
+#[test]
+fn test_union_serialization_is_grouping_independent() {
+ const N: u64 = 100_000;
+
+ for hll_type in HLL_TYPES {
+ let a = make_hll_sketch(hll_type, 15, 0, N);
+ let b = make_hll_sketch(hll_type, 8, N, 2 * N);
+ let c = make_hll_sketch(hll_type, 11, N / 2, N + N / 2);
+
+ for (first, second, third) in [(&b, &c, &a), (&a, &c, &b), (&a, &b,
&c)] {
+ assert_eq!(
+ serialize_nested_union(first, second, third),
+ serialize_flat_union(first, second, third),
+ "{hll_type:?} serialization should be grouping independent",
+ );
+ }
+ }
+}
+
#[test]
fn test_union_bounds() {
let mut union = HllUnion::new(12);
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]