Skip to main content

lattices/ght/
test.rs

1//! Tests for the GHT code
2#[cfg(test)]
3mod tests {
4    use std::collections::HashSet;
5
6    #[test]
7    fn basic_test() {
8        use variadics::var_expr;
9
10        use crate::GhtType;
11        use crate::ght::GeneralizedHashTrieNode;
12
13        // Example usage
14        type MyTrie1 = GhtType!(u32, u32 => &'static str: VariadicCountedHashSet);
15
16        fn ght_type<T: GeneralizedHashTrieNode>() {}
17        ght_type::<MyTrie1>();
18
19        let htrie1 = MyTrie1::new_from(vec![var_expr!(42, 314, "hello")]);
20        assert!(htrie1.contains(var_expr!(&42, &314, &"hello")));
21        assert_eq!(htrie1.recursive_iter().count(), 1);
22
23        type MyTrie2 = GhtType!(u32 => u32: VariadicCountedHashSet);
24        let htrie2 = MyTrie2::new_from(vec![var_expr!(42, 314)]);
25        assert!(htrie2.contains(var_expr!(&42, &314)));
26        assert_eq!(htrie1.recursive_iter().count(), 1);
27
28        type MyTrie3 = GhtType!(u32, u64, u16 => &'static str: VariadicCountedHashSet);
29        let htrie3 = MyTrie3::new_from(vec![
30            var_expr!(123, 2, 5, "hello"),
31            var_expr!(50, 1, 1, "hi"),
32            var_expr!(5, 1, 7, "hi"),
33            var_expr!(5, 1, 7, "bye"),
34        ]);
35        assert!(htrie3.contains(var_expr!(&50, &1, &1, &"hi")));
36        assert_eq!(htrie3.recursive_iter().count(), 4);
37    }
38    #[test]
39    fn test_ght_node_type_macro() {
40        use variadics::var_expr;
41
42        use crate::GhtType;
43        use crate::ght::GeneralizedHashTrieNode;
44
45        // 0 => 1
46        type LilTrie = GhtType!(() => u32: VariadicCountedHashSet);
47        let _j = LilTrie::default();
48        let _l = LilTrie::new_from(vec![var_expr!(1)]);
49
50        // 0 => >1
51        type LilTrie2 = GhtType!(() => u32, u64: VariadicCountedHashSet);
52        let _l = LilTrie2::default();
53        let _l = LilTrie2::new_from(vec![var_expr!(1, 1)]);
54
55        // 1 => 0
56        type KeyNoValTrie = GhtType!(u32 => (): VariadicCountedHashSet);
57        let l = KeyNoValTrie::new_from(vec![var_expr!(1)]);
58        let _: KeyNoValTrie = l;
59
60        // 1 => 1
61        type SmallTrie = GhtType!(u32 => &'static str: VariadicCountedHashSet);
62        type SmallKeyedTrie = GhtType!(u32 => &'static str: VariadicCountedHashSet);
63        let l = SmallTrie::new_from(vec![var_expr!(1, "hello")]);
64        let _: SmallKeyedTrie = l;
65
66        // 1 => >1
67        type SmallKeyLongValTrie = GhtType!(u32 => u64, u16, &'static str: VariadicCountedHashSet);
68        let _x = SmallKeyLongValTrie::new_from(vec![var_expr!(1, 999, 222, "hello")]);
69
70        // >1 => 0
71        type LongKeyNoValTrie = GhtType!(u32, u64 => (): VariadicCountedHashSet);
72        let l = LongKeyNoValTrie::new_from(vec![var_expr!(1, 999)]);
73        let _: LongKeyNoValTrie = l;
74
75        // >1 => 1
76        type LongKeySmallValTrie = GhtType!(u32, u16 => &'static str: VariadicCountedHashSet);
77        type LongKeySmallValKeyedTrie = GhtType!(u32, u16 => &'static str: VariadicCountedHashSet);
78        let x = LongKeySmallValTrie::new_from(vec![var_expr!(1, 314, "hello")]);
79        let _: LongKeySmallValKeyedTrie = x;
80        let _ = LongKeySmallValTrie::new_from(vec![var_expr!(1, 314, "hello")]);
81
82        // >1 => >1
83        type LongKeyLongValTrie = GhtType!(u32, u64 => u16, &'static str: VariadicCountedHashSet);
84        let _x = LongKeyLongValTrie::new_from(vec![var_expr!(1, 999, 222, "hello")]);
85    }
86
87    #[test]
88    fn test_insert() {
89        use variadics::var_expr;
90
91        use crate::GhtType;
92        use crate::ght::GeneralizedHashTrieNode;
93
94        type MyGht = GhtType!(u16, u32 => u64: VariadicCountedHashSet);
95        let mut htrie = MyGht::default();
96        htrie.insert(var_expr!(42, 314, 43770));
97        assert_eq!(htrie.recursive_iter().count(), 1);
98        assert_eq!(MyGht::HEIGHT, 2);
99        htrie.insert(var_expr!(42, 315, 43770));
100        assert_eq!(htrie.recursive_iter().count(), 2);
101        htrie.insert(var_expr!(42, 314, 30619));
102        assert_eq!(htrie.recursive_iter().count(), 3);
103        htrie.insert(var_expr!(43, 10, 600));
104        assert_eq!(htrie.recursive_iter().count(), 4);
105        assert!(htrie.contains(var_expr!(&42, &314, &30619)));
106        assert!(htrie.contains(var_expr!(&42, &315, &43770)));
107        assert!(htrie.contains(var_expr!(&43, &10, &600)));
108
109        type LongKeyLongValTrie = GhtType!(u32, u64 => u16, &'static str: VariadicCountedHashSet);
110        let mut htrie = LongKeyLongValTrie::new_from(vec![var_expr!(1, 999, 222, "hello")]);
111        htrie.insert(var_expr!(1, 999, 111, "bye"));
112        htrie.insert(var_expr!(1, 1000, 123, "cya"));
113        assert!(htrie.contains(var_expr!(&1, &999, &222, &"hello")));
114        assert!(htrie.contains(var_expr!(&1, &999, &111, &"bye")));
115        assert!(htrie.contains(var_expr!(&1, &1000, &123, &"cya")));
116    }
117
118    #[test]
119    fn test_scale() {
120        use variadics::var_expr;
121
122        use crate::GhtType;
123        use crate::ght::GeneralizedHashTrieNode;
124
125        type MyGht = GhtType!(bool, usize, &'static str => i32: VariadicCountedHashSet);
126        let mut htrie = MyGht::new_from(vec![var_expr!(true, 1, "hello", -5)]);
127        assert_eq!(htrie.recursive_iter().count(), 1);
128        for i in 1..1000000 {
129            htrie.insert(var_expr!(true, 1, "hello", i));
130        }
131        assert_eq!(htrie.recursive_iter().count(), 1000000);
132    }
133
134    #[test]
135    fn test_contains() {
136        use variadics::{VariadicExt, var_expr};
137
138        use crate::GhtType;
139        use crate::ght::GeneralizedHashTrieNode;
140
141        type MyGht = GhtType!(u16, u32 => u64: VariadicCountedHashSet);
142        let htrie = MyGht::new_from(vec![var_expr!(42_u16, 314_u32, 43770_u64)]);
143        let x = var_expr!(&42, &314, &43770);
144        assert!(htrie.contains(x));
145        assert!(htrie.contains(var_expr!(42, 314, 43770).as_ref_var()));
146        assert!(htrie.contains(var_expr!(&42, &314, &43770)));
147        assert!(!htrie.contains(var_expr!(42, 314, 30619).as_ref_var()));
148        assert!(!htrie.contains(var_expr!(&42, &315, &43770)));
149        assert!(!htrie.contains(var_expr!(&43, &314, &43770)));
150    }
151
152    #[test]
153    fn test_get() {
154        use variadics::{VariadicExt, var_expr};
155
156        use crate::GhtType;
157        use crate::ght::{GeneralizedHashTrieNode, GhtGet};
158
159        type MyGht = GhtType!(u32, u32 => u32: VariadicCountedHashSet);
160        let ht_root = MyGht::new_from(vec![var_expr!(42, 314, 43770)]);
161
162        let inner = ht_root.get(&42).unwrap();
163        let t = inner.recursive_iter().next().unwrap();
164        assert_eq!(t, var_expr!(&42, &314, &43770));
165
166        let leaf = inner.get(&314).unwrap();
167        let t = leaf.recursive_iter().next().unwrap();
168        assert_eq!(t, var_expr!(42, 314, 43770).as_ref_var());
169    }
170
171    #[test]
172    fn test_iter() {
173        use variadics::var_expr;
174
175        use crate::GhtType;
176        use crate::ght::{GeneralizedHashTrieNode, GhtGet};
177        type MyGht = GhtType!(u32, u32 => u32: VariadicCountedHashSet);
178        let ht_root = MyGht::new_from(vec![var_expr!(42, 314, 43770)]);
179        let inner_key = ht_root.iter().next().unwrap();
180        let inner = ht_root.get(&inner_key).unwrap();
181        let t = inner.recursive_iter().next().unwrap();
182        assert_eq!(t, var_expr!(&42, &314, &43770));
183
184        let leaf_key = inner.iter().next().unwrap();
185        let leaf = inner.get(&leaf_key).unwrap();
186        // iter() on leaf should return None
187        let t = leaf.iter().next();
188        assert!(t.is_none());
189    }
190
191    #[test]
192    fn test_recursive_iter() {
193        use variadics::{VariadicExt, var_expr, var_type};
194
195        use crate::GhtType;
196        use crate::ght::GeneralizedHashTrieNode;
197
198        type MyGht = GhtType!(u32, u32 => u32: VariadicCountedHashSet);
199        type InputType = var_type!(u32, u32, u32);
200        type ResultType<'a> = var_type!(&'a u32, &'a u32, &'a u32);
201        let input: HashSet<InputType> = HashSet::from_iter(
202            [
203                (42, 314, 30619),
204                (42, 314, 43770),
205                (42, 315, 43770),
206                (43, 10, 600),
207            ]
208            .iter()
209            .map(|&(a, b, c)| var_expr!(a, b, c)),
210        );
211        let htrie = MyGht::new_from(input.clone());
212        #[expect(
213            clippy::disallowed_methods,
214            reason = "nondeterministic iteration order, fine to collect into set"
215        )]
216        let result = input.iter().map(|v| v.as_ref_var()).collect();
217        let v: HashSet<ResultType> = htrie.recursive_iter().collect();
218        assert_eq!(v, result);
219    }
220
221    #[test]
222    fn test_prefix_iter_leaf() {
223        use variadics::variadic_collections::VariadicCountedHashSet;
224        use variadics::{var_expr, var_type};
225
226        use crate::ght::{GeneralizedHashTrieNode, GhtLeaf, GhtPrefixIter};
227
228        type InputType = var_type!(u8, u16, u32);
229        type ResultType<'a> = var_type!(&'a u8, &'a u16, &'a u32);
230
231        let input: HashSet<InputType> = HashSet::from_iter(
232            [
233                (42, 314, 30619),
234                (42, 314, 43770),
235                (42, 315, 43770),
236                (43, 10, 600),
237            ]
238            .iter()
239            .map(|&(a, b, c)| var_expr!(a, b, c)),
240        );
241        let leaf =
242            GhtLeaf::<InputType, var_type!(u16, u32), VariadicCountedHashSet<InputType>>::new_from(
243                input.clone(),
244            );
245        // let key = var_expr!(42u8).as_ref_var();
246        let key = (); // (var_expr!().as_ref_var();)
247        let v: HashSet<ResultType> = leaf.prefix_iter(key).collect();
248        #[expect(
249            clippy::disallowed_methods,
250            reason = "nondeterministic iteration order, fine to collect into set"
251        )]
252        let result = input
253            .iter()
254            // .filter(|t: &&InputType| t.0 == 42)
255            .map(|t: &InputType| var_expr!(&t.0, &t.1 .0, &t.1 .1 .0))
256            .collect();
257        assert_eq!(v, result);
258    }
259
260    #[test]
261    fn test_prefix_iter() {
262        use variadics::{VariadicExt, var_expr, var_type};
263
264        use crate::GhtType;
265        use crate::ght::{GeneralizedHashTrieNode, GhtPrefixIter};
266
267        type MyGht = GhtType!(u8, u16 => u32: VariadicCountedHashSet);
268        type InputType = var_type!(u8, u16, u32);
269        type ResultType<'a> = var_type!(&'a u8, &'a u16, &'a u32);
270        let input: HashSet<InputType> = HashSet::from_iter(
271            [
272                (42, 314, 30619),
273                (42, 314, 43770),
274                (42, 315, 43770),
275                (43, 10, 600),
276            ]
277            .iter()
278            .map(|&(a, b, c)| var_expr!(a, b, c)),
279        );
280        let htrie = MyGht::new_from(input.clone());
281
282        let v: HashSet<ResultType> = htrie.prefix_iter(var_expr!(42, 315).as_ref_var()).collect();
283        let result = HashSet::from_iter([var_expr!(&42, &315, &43770)].iter().copied());
284        assert_eq!(v, result);
285
286        let v: HashSet<ResultType> = htrie.prefix_iter(var_expr!(42u8).as_ref_var()).collect();
287        #[expect(
288            clippy::disallowed_methods,
289            reason = "nondeterministic iteration order, fine to collect into set"
290        )]
291        let result = input
292            .iter()
293            .filter(|t: &&InputType| t.0 == 42)
294            .map(|t: &InputType| var_expr!(&t.0, &t.1.0, &t.1.1.0))
295            .collect();
296        assert_eq!(v, result);
297
298        for row in htrie.prefix_iter(var_expr!(42, 315, 43770).as_ref_var()) {
299            assert_eq!(row, var_expr!(&42, &315, &43770));
300        }
301    }
302
303    #[test]
304    fn test_prefix_iter_complex() {
305        use variadics::{VariadicExt, var_expr, var_type};
306
307        use crate::GhtType;
308        use crate::ght::{GeneralizedHashTrieNode, GhtPrefixIter};
309
310        type MyGht = GhtType!(bool, u32, &'static str => i32: VariadicCountedHashSet);
311        type InputType = var_type!(bool, u32, &'static str, i32);
312        type ResultType<'a> = var_type!(&'a bool, &'a u32, &'a &'static str, &'a i32);
313        let input: HashSet<InputType> = HashSet::from_iter(
314            [
315                (true, 1, "hello", -5),
316                (true, 1, "hi", -2),
317                (true, 1, "hi", -3),
318                (true, 1, "hi", -4),
319                (true, 1, "hi", -5),
320                (true, 2, "hello", 1),
321                (false, 10, "bye", 5),
322            ]
323            .iter()
324            .map(|&(a, b, c, d)| var_expr!(a, b, c, d)),
325        );
326
327        let htrie = MyGht::new_from(input.clone());
328
329        let v: HashSet<ResultType> = htrie
330            .prefix_iter(var_expr!(true, 1, "hi").as_ref_var())
331            .collect();
332        #[expect(
333            clippy::disallowed_methods,
334            reason = "nondeterministic iteration order, fine to collect into set"
335        )]
336        let result = input
337            .iter()
338            .filter(|t: &&InputType| t.0 && t.1.0 == 1 && t.1.1.0 == "hi")
339            //.map(|t: &InputType| (&t.0, &t.1 .0, (&t.1 .1 .0, (&t.1 .1 .1 .0, ()))))
340            .map(|t| t.as_ref_var())
341            .collect();
342        assert_eq!(v, result);
343
344        let v: HashSet<ResultType> = htrie.prefix_iter(var_expr!(true).as_ref_var()).collect();
345        #[expect(
346            clippy::disallowed_methods,
347            reason = "nondeterministic iteration order, fine to collect into set"
348        )]
349        let result = input
350            .iter()
351            .filter(|t: &&InputType| t.0)
352            .map(|t: &InputType| t.as_ref_var())
353            .collect();
354        assert_eq!(v, result);
355    }
356
357    #[test]
358    fn test_merge() {
359        use variadics::{var_expr, var_type};
360
361        use crate::ght::GeneralizedHashTrieNode;
362        use crate::{GhtType, Merge};
363
364        type MyGht = GhtType!(u32, u64 => u16, &'static str: VariadicHashSet);
365
366        let mut test_ght1 = MyGht::new_from(vec![var_expr!(42, 314, 10, "hello")]);
367        let test_ght2 = MyGht::new_from(vec![var_expr!(42, 314, 10, "hello")]);
368
369        assert_eq!(
370            test_ght1
371                .recursive_iter()
372                .collect::<Vec<var_type!(&u32, &u64, &u16, &&'static str)>>()
373                .len(),
374            1
375        );
376        test_ght1.merge(test_ght2.clone());
377        // merge does not contain duplicate copy of the tuple
378        assert_eq!(
379            test_ght1
380                .recursive_iter()
381                .collect::<Vec<var_type!(&u32, &u64, &u16, &&'static str)>>()
382                .len(),
383            1
384        );
385        assert!(!test_ght1.merge(test_ght2.clone()));
386
387        let mut test_ght1 = MyGht::new_from(vec![var_expr!(42, 314, 10, "hello")]);
388        let mut test_ght2 = MyGht::new_from(vec![var_expr!(42, 314, 10, "hello")]);
389        test_ght1.merge(test_ght2.clone());
390
391        test_ght1.insert(var_expr!(42, 314, 20, "goodbye"));
392        test_ght2.insert(var_expr!(42, 314, 20, "again"));
393
394        // change on merge
395        assert!(test_ght1.merge(test_ght2.clone()));
396        for k in test_ght2.recursive_iter() {
397            assert!(test_ght1.contains(k))
398        }
399    }
400
401    #[test]
402    fn test_node_lattice() {
403        use variadics::var_expr;
404
405        use crate::ght::GeneralizedHashTrieNode;
406        use crate::{GhtType, NaiveLatticeOrd};
407
408        type MyGht = GhtType!(u32, u64 => u16, &'static str: VariadicHashSet);
409        type MyGhtNode = GhtType!(u32, u64 => u16, &'static str: VariadicHashSet);
410
411        let mut test_vec: Vec<MyGhtNode> = Vec::new();
412
413        let empty_ght = MyGht::new_from(vec![]);
414        let test_ght1 = MyGht::new_from(vec![var_expr!(42, 314, 10, "hello")]);
415        let mut test_ght2 = MyGht::new_from(vec![var_expr!(42, 314, 10, "hello")]);
416        test_ght2.insert(var_expr!(42, 314, 20, "again"));
417        let mut test_ght3 = test_ght2.clone();
418        test_ght3.insert(var_expr!(42, 400, 1, "level 2"));
419        let mut test_ght4 = test_ght3.clone();
420        test_ght4.insert(var_expr!(43, 1, 1, "level 1"));
421
422        let test_vec_wrap = [empty_ght, test_ght1, test_ght2, test_ght3, test_ght4];
423
424        for ght in test_vec_wrap.iter().cloned() {
425            ght.naive_cmp(&ght.clone());
426            test_vec.push(ght);
427        }
428        crate::test::check_all(&test_vec);
429        crate::test::check_all(&test_vec_wrap);
430    }
431
432    #[test]
433    fn test_cartesian_bimorphism() {
434        use variadics::var_expr;
435
436        use crate::ght::GeneralizedHashTrieNode;
437        use crate::ght::lattice::GhtCartesianProductBimorphism;
438        use crate::{GhtType, LatticeBimorphism};
439
440        type MyGhtA = GhtType!(u32, u64 => u16, &'static str: VariadicHashSet);
441        type MyGhtB = GhtType!(u32, u64, u16 => &'static str: VariadicHashSet);
442
443        let mut ght_a = MyGhtA::default();
444        let mut ght_b = MyGhtB::default();
445
446        ght_a.insert(var_expr!(123, 2, 5, "hello"));
447        ght_a.insert(var_expr!(50, 1, 1, "hi"));
448        ght_a.insert(var_expr!(5, 1, 7, "hi"));
449        ght_b.insert(var_expr!(5, 1, 8, "hi"));
450        ght_b.insert(var_expr!(10, 1, 2, "hi"));
451        ght_b.insert(var_expr!(12, 10, 98, "bye"));
452
453        type MyGhtAb = GhtType!(u32, u64, u16, &'static str, u32, u64 => u16, &'static str: VariadicCountedHashSet);
454
455        let mut bim = GhtCartesianProductBimorphism::<MyGhtAb>::default();
456        let ght_out = bim.call(&ght_a, &ght_b);
457        assert_eq!(
458            ght_out.recursive_iter().count(),
459            ght_a.recursive_iter().count() * ght_b.recursive_iter().count()
460        );
461    }
462
463    #[test]
464    fn test_join_bimorphism() {
465        use variadics::variadic_collections::{VariadicCountedHashSet, VariadicHashSet};
466        use variadics::{var_expr, var_type};
467
468        use crate::ght::lattice::{
469            DeepJoinLatticeBimorphism, GhtNodeKeyedBimorphism, GhtValTypeProductBimorphism,
470        };
471        use crate::ght::{GeneralizedHashTrieNode, GhtInner, GhtLeaf};
472        use crate::{GhtType, LatticeBimorphism};
473
474        type ResultSchemaType = var_type!(u32, u64, u16, &'static str, &'static str);
475        type ResultSchemaRefType<'a> = var_type!(
476            &'a u32,
477            &'a u64,
478            &'a u16,
479            &'a &'static str,
480            &'a &'static str
481        );
482        type MyGhtATrie = GhtType!(u32, u64, u16 => &'static str: VariadicHashSet);
483        type MyGhtBTrie = GhtType!(u32, u64, u16 => &'static str: VariadicHashSet);
484
485        let mut ght_a = MyGhtATrie::default();
486        let mut ght_b = MyGhtBTrie::default();
487
488        ght_a.insert(var_expr!(123, 2, 5, "hello"));
489        ght_a.insert(var_expr!(50, 1, 1, "hi"));
490        ght_a.insert(var_expr!(5, 1, 7, "hi"));
491
492        ght_b.insert(var_expr!(5, 1, 8, "hi"));
493        ght_b.insert(var_expr!(5, 1, 7, "world"));
494        ght_b.insert(var_expr!(10, 1, 2, "hi"));
495        ght_b.insert(var_expr!(12, 10, 98, "bye"));
496
497        let result: HashSet<ResultSchemaRefType> = [var_expr!(&5, &1, &7, &"hi", &"world")]
498            .iter()
499            .copied()
500            .collect();
501        {
502            // here we manually construct the proper bimorphism stack.
503            // note that the bottommost bimorphism is GhtValTypeProductBimorphism,
504            // which ensures that the Schema of the resulting output GhtLeaf and GhtInner
505            // nodes correctly includes the key columns, not just the cross-product of the values.
506            type MyGhtOut = GhtInner<
507                &'static str,
508                GhtLeaf<
509                    ResultSchemaType,
510                    var_type!(&'static str),
511                    VariadicCountedHashSet<ResultSchemaType>,
512                >,
513            >;
514            // let mut bim = GhtNodeKeyedBimorphism::new(GhtNodeKeyedBimorphism::new(
515            //     GhtNodeKeyedBimorphism::new(GhtValTypeProductBimorphism::<MyGhtOut>::default()),
516            // ));
517            let mut bim = GhtNodeKeyedBimorphism::new(GhtNodeKeyedBimorphism::new(
518                GhtNodeKeyedBimorphism::new(GhtValTypeProductBimorphism::<MyGhtOut>::default()),
519            ));
520            let out = bim.call(&ght_a, &ght_b);
521            let out: HashSet<ResultSchemaRefType> = out.recursive_iter().collect();
522            assert_eq!(out, result);
523        }
524        {
525            // Here we use DeepJoinLatticeBimorphism as a more compact representation of the
526            // manual stack of bimorphisms above. This is the recommended approach.
527            type MyNodeBim<'a> = <(MyGhtATrie, MyGhtBTrie) as DeepJoinLatticeBimorphism<
528                VariadicHashSet<ResultSchemaType>,
529            >>::DeepJoinLatticeBimorphism;
530            let mut bim = <MyNodeBim as Default>::default();
531            let out = bim.call(&ght_a, &ght_b);
532            let out: HashSet<ResultSchemaRefType> = out.recursive_iter().collect();
533            assert_eq!(out, result);
534        }
535    }
536
537    #[test]
538    fn test_ght_with_tuple_macro() {
539        use variadics::{VariadicExt, var_expr};
540        use variadics_macro::tuple;
541
542        use crate::GhtType;
543        use crate::ght::GeneralizedHashTrieNode;
544
545        type MyRoot = GhtType!(u16, u32 => u64: VariadicCountedHashSet);
546
547        let mut trie1 = MyRoot::default();
548        assert_eq!(3, <<MyRoot as GeneralizedHashTrieNode>::Schema>::LEN);
549        trie1.insert(var_expr!(1, 2, 3));
550        let t = trie1.recursive_iter().next().unwrap();
551        let tup = tuple!(t, 3);
552        assert_eq!(tup, (&1, &2, &3));
553    }
554
555    #[test]
556    fn test_triangle_generic_join() {
557        use std::hash::{BuildHasherDefault, DefaultHasher};
558
559        use variadics::var_expr;
560
561        use crate::GhtType;
562        use crate::ght::{GeneralizedHashTrieNode, GhtPrefixIter};
563
564        const MATCHES: u32 = 1000;
565        type MyGht = GhtType!(u32 => u32: VariadicCountedHashSet);
566
567        let r_iter = (0..MATCHES)
568            .map(|i| (0, i))
569            .chain((1..MATCHES).map(|i| (i, 0)));
570
571        let s_iter = (0..MATCHES)
572            .map(|i| (0, i))
573            .chain((1..MATCHES).map(|i| (i, 0)));
574
575        let t_iter = (0..MATCHES)
576            .map(|i| (0, i))
577            .chain((1..MATCHES).map(|i| (i, 0)));
578
579        let rx_ght = MyGht::new_from(r_iter.clone().map(|(x, y)| var_expr!(x, y)));
580        let sb_ght = MyGht::new_from(s_iter.clone().map(|(y, b)| var_expr!(b, y)));
581        let tx_ght = MyGht::new_from(t_iter.map(|(z, x)| var_expr!(x, z)));
582
583        let r_x = r_iter
584            .map(|(x, _y)| x)
585            .collect::<HashSet<_, BuildHasherDefault<DefaultHasher>>>();
586        let t_x = s_iter
587            .clone()
588            .map(|(_z, x)| x)
589            .collect::<HashSet<_, BuildHasherDefault<DefaultHasher>>>();
590        let x_inter = r_x.intersection(&t_x);
591        let len = x_inter.clone().count();
592        if len > 1 {
593            assert_eq!(1000, len);
594        }
595
596        let mut output: Vec<(u32, u32, u32)> = Vec::new();
597        let mut x_iters = 0usize;
598        let mut y_iters = 0usize;
599        let mut z_iters = 0usize;
600        for a in x_inter {
601            x_iters += 1;
602            let r = rx_ght
603                .prefix_iter(var_expr!(a))
604                .map(|(_x, (y, ()))| *y)
605                .collect::<HashSet<_, BuildHasherDefault<DefaultHasher>>>();
606            let s_y = s_iter
607                .clone()
608                .map(|(y, _z)| y)
609                .collect::<HashSet<_, BuildHasherDefault<DefaultHasher>>>();
610            let y_inter = r.intersection(&s_y);
611            let len = y_inter.clone().count();
612            if len > 1 {
613                assert_eq!(1000, len);
614            }
615            for b in y_inter {
616                y_iters += 1;
617                let s = sb_ght
618                    .prefix_iter(var_expr!(b))
619                    .map(|(_b, (z, ()))| *z)
620                    .collect::<HashSet<_, BuildHasherDefault<DefaultHasher>>>();
621                let t = tx_ght
622                    .prefix_iter(var_expr!(a))
623                    .map(|(_x, (z, ()))| *z)
624                    .collect::<HashSet<_, BuildHasherDefault<DefaultHasher>>>();
625                let z_inter = s.intersection(&t);
626                let len = z_inter.clone().count();
627                if len > 1 {
628                    assert_eq!(1000, len);
629                }
630                for c in z_inter {
631                    z_iters += 1;
632                    output.push((*a, *b, *c));
633                }
634            }
635        }
636
637        assert_eq!(1000, x_iters);
638        assert_eq!(1999, y_iters);
639        assert_eq!(2998, z_iters);
640        assert_eq!(2998, output.len());
641    }
642
643    fn clover_setup(
644        matches: usize,
645    ) -> (
646        impl Iterator<Item = (u32, u32)>,
647        impl Iterator<Item = (u32, u32)>,
648        impl Iterator<Item = (u32, u32)>,
649    ) {
650        let r_iter = (1..matches)
651            .map(|i| (1u32, i as u32))
652            .chain((1..matches).map(|i| (2, i as u32)))
653            .chain([(0, 0)]);
654
655        let s_iter = (1..matches)
656            .map(|i| (2u32, i as u32))
657            .chain((1..matches).map(|i| (3, i as u32)))
658            .chain([(0, 0)]);
659
660        let t_iter = (1..matches)
661            .map(|i| (3u32, i as u32))
662            .chain((1..matches).map(|i| (1, i as u32)))
663            .chain([(0, 0)]);
664        (r_iter, s_iter, t_iter)
665    }
666
667    #[test]
668    fn clover_generic_join() {
669        use variadics::var_expr;
670
671        use crate::GhtType;
672        use crate::ght::{GeneralizedHashTrieNode, GhtGet};
673
674        const MATCHES: usize = 1000;
675        let (r_iter, s_iter, t_iter) = clover_setup(MATCHES);
676
677        type MyGht = GhtType!(u32 => u32: VariadicCountedHashSet);
678        let rx_ght = MyGht::new_from(r_iter.map(|(x, a)| var_expr!(x, a)));
679        let sx_ght = MyGht::new_from(s_iter.map(|(x, b)| var_expr!(x, b)));
680        let tx_ght = MyGht::new_from(t_iter.map(|(x, c)| var_expr!(x, c)));
681        for x in rx_ght.iter() {
682            if let (Some(r), Some(s), Some(t)) = (rx_ght.get(&x), sx_ght.get(&x), tx_ght.get(&x)) {
683                // All unwraps succeeded, use `r`, `s`, `t` here
684                for a in r.iter() {
685                    for b in s.iter() {
686                        for c in t.iter() {
687                            assert_eq!((x, a, b, c), (0, 0, 0, 0));
688                        }
689                    }
690                }
691            } else {
692                // If any unwrap fails, continue to the next iteration
693                continue;
694            }
695        }
696    }
697
698    #[test]
699    fn clover_factorized_join() {
700        use variadics::var_expr;
701
702        use crate::GhtType;
703        use crate::ght::{GeneralizedHashTrieNode, GhtGet};
704
705        const MATCHES: usize = 1000;
706        let (r_iter, s_iter, t_iter) = clover_setup(MATCHES);
707
708        type Ght1 = GhtType!(() => u32, u32: VariadicCountedHashSet);
709        type Ght2 = GhtType!(u32 => u32: VariadicCountedHashSet);
710        let rx_ght = Ght1::new_from(r_iter.map(|(x, a)| var_expr!(x, a)));
711        let sx_ght = Ght2::new_from(s_iter.map(|(x, b)| var_expr!(x, b)));
712        let tx_ght = Ght2::new_from(t_iter.map(|(x, c)| var_expr!(x, c)));
713
714        for t in rx_ght.recursive_iter() {
715            let (x, (a, ())): (&u32, (&u32, _)) = t;
716            if let (Some(s), Some(t)) = (sx_ght.get(x), tx_ght.get(x)) {
717                // All unwraps succeeded, use `s`, `t` here
718                for b in s.iter() {
719                    for c in t.iter() {
720                        assert_eq!((x, a, b, c), (&0, &0, 0, 0));
721                    }
722                }
723            } else {
724                // If any unwrap fails, continue to the next iteration
725                continue;
726            }
727        }
728    }
729
730    #[test]
731    fn test_force() {
732        use variadics::var_expr;
733
734        use crate::GhtType;
735        use crate::ght::GeneralizedHashTrieNode;
736        use crate::ght::colt::ColtForestNode;
737
738        type LeafType = GhtType!(() => u16, u32, u64: VariadicCountedHashSet);
739        let n = LeafType::new_from(vec![
740            var_expr!(1, 1, 1),
741            var_expr!(1, 2, 2),
742            var_expr!(1, 3, 3),
743            var_expr!(2, 4, 4),
744        ]);
745        let out = n.force().unwrap();
746        assert_eq!(out.height(), 1);
747    }
748
749    #[test]
750    fn test_forest_macro() {
751        use crate::ColtType;
752
753        type Forest4 = ColtType!(u8, u16, u32, u64);
754        let _f4 = Forest4::default();
755
756        type Forest3 = ColtType!(u8, u16, u32);
757        let _f3 = Forest3::default();
758
759        type Forest2 = ColtType!(u8, u16);
760        let _f2 = Forest2::default();
761
762        type Forest1 = ColtType!(u8);
763        let _f2 = Forest1::default();
764
765        type Forest01 = ColtType!(() => u16);
766        let _f01 = Forest01::default();
767
768        type Forest02 = ColtType!(() => u8, u16);
769        let _f02 = Forest02::default();
770
771        type Forest10 = ColtType!(u8 => ());
772        let _f10 = Forest10::default();
773
774        type Forest11 = ColtType!(u8 => u16);
775        let _f11 = Forest11::default();
776
777        type Forest12 = ColtType!(u8 => u16, u32);
778        let _f12 = Forest12::default();
779
780        type Forest20 = ColtType!(u8, u16 => ());
781        let _f20 = Forest20::default();
782
783        type Forest21 = ColtType!(u8, u16 => u32);
784        let _f21 = Forest21::default();
785
786        type Forest22 = ColtType!(u8, u16 => u32, u64);
787        let _f22 = Forest22::default();
788    }
789
790    #[test]
791    fn test_colt_little_get() {
792        use variadics::variadic_collections::VariadicCollection;
793        use variadics::{VariadicExt, var_expr};
794
795        use crate::ColtType;
796        use crate::ght::GeneralizedHashTrieNode;
797        use crate::ght::colt::ColtGet;
798
799        type MyForest = ColtType!(u8);
800
801        let mut forest = MyForest::default();
802
803        forest.0.insert(var_expr!(1));
804        forest.0.insert(var_expr!(2));
805        forest.0.insert(var_expr!(3));
806
807        assert_eq!(2, forest.len());
808        assert_eq!(3, forest.0.elements.len());
809
810        let result = ColtGet::get(forest.as_mut_var(), &3);
811        assert_eq!(1, result.len());
812        assert_eq!(0, forest.0.elements.len());
813        assert!(forest.0.forced);
814    }
815
816    #[test]
817    fn test_colt_get() {
818        use variadics::variadic_collections::VariadicCollection;
819        use variadics::{VariadicExt, var_expr};
820
821        use crate::ColtType;
822        use crate::ght::colt::ColtGet;
823        use crate::ght::{GeneralizedHashTrieNode, GhtGet};
824
825        type MyForest = ColtType!(u8, u16, u32, u64);
826        let mut forest = MyForest::default();
827        forest.0.insert(var_expr!(1, 1, 1, 1));
828        forest.0.insert(var_expr!(2, 2, 2, 2));
829        forest.0.insert(var_expr!(3, 3, 3, 3));
830
831        let len = forest.len();
832        assert_eq!(5, len);
833        {
834            let get_result = ColtGet::get(forest.as_mut_var(), &1);
835            assert_eq!(get_result.len(), len - 1);
836            assert_eq!(get_result.0.height(), 0);
837            let get_result2 = ColtGet::get(get_result, &1);
838            assert_eq!(get_result2.len(), len - 2);
839            let get_result3 = ColtGet::get(get_result2, &1);
840            assert_eq!(get_result3.len(), len - 3);
841            assert_eq!(
842                get_result3.0.elements.iter().next(),
843                Some(var_expr!(1, 1, 1, 1).as_ref_var())
844            );
845            assert_eq!(get_result3.1.0.children.len(), 0);
846        }
847        {
848            let get_result = ColtGet::get(forest.as_mut_var(), &3);
849            assert_eq!(get_result.len(), len - 1);
850            let get_result2 = ColtGet::get(get_result, &3);
851            assert_eq!(get_result2.len(), len - 2);
852            assert_eq!(
853                get_result2.0.elements.iter().next(),
854                Some(var_expr!(3, 3, 3, 3).as_ref_var())
855            );
856            assert_eq!(get_result2.1.0.children.len(), 0);
857        }
858        assert!(forest.0.forced);
859        assert_eq!(3, forest.1.0.children.len()); // keys 1, 2 and 3
860        assert_eq!(0, forest.1.0.get(&1).unwrap().elements.len());
861        assert_eq!(1, forest.1.0.get(&2).unwrap().elements.len());
862        assert_eq!(0, forest.1.0.get(&3).unwrap().elements.len());
863        assert_eq!(2, forest.1.1.0.children.len()); // keys 1 and 3
864        assert_eq!(
865            0,
866            forest
867                .1
868                .1
869                .0
870                .get(&1)
871                .unwrap()
872                .get(&1)
873                .unwrap()
874                .elements
875                .len()
876        );
877        assert!(forest.1.1.0.get(&2).is_none());
878        assert_eq!(
879            1,
880            forest
881                .1
882                .1
883                .0
884                .get(&3)
885                .unwrap()
886                .get(&3)
887                .unwrap()
888                .elements
889                .len()
890        );
891        assert_eq!(
892            1,
893            forest
894                .1
895                .1
896                .1
897                .0
898                .get(&1)
899                .unwrap()
900                .get(&1)
901                .unwrap()
902                .get(&1)
903                .unwrap()
904                .elements
905                .len()
906        );
907    }
908
909    #[test]
910    fn test_colt_scale() {
911        use variadics::variadic_collections::VariadicCollection;
912        use variadics::{VariadicExt, var_expr};
913
914        use crate::ght::colt::ColtGet;
915        use crate::ght::{GeneralizedHashTrieNode, GhtPrefixIter};
916
917        type MyColt = crate::ColtType!(i32, bool, usize, &'static str);
918        let mut forest = MyColt::default();
919        for i in 1..100000 {
920            forest.0.insert(var_expr!(i, true, 1, "hello"));
921        }
922        {
923            let result = forest.as_mut_var().get(&3);
924            assert_eq!(result.len(), 4);
925        }
926        // check: first Leaf trie is forced
927        assert!(forest.0.forced);
928        assert_eq!(forest.0.elements.len(), 0);
929        {
930            let result = forest.as_mut_var().get(&3);
931            let result2 = result.get(&true);
932            assert_eq!(result2.len(), 3);
933        }
934        {
935            // check: leaf below 3 in first non-empty trie is forced
936            let result = forest.as_mut_var().get(&3);
937            assert!(result.0.forced);
938            assert_eq!(result.0.elements.len(), 0);
939        }
940        // check: prefix (3, true) is now found in the third trie: forest.1.1.0
941        assert!(
942            forest
943                .1
944                .1
945                .0
946                .prefix_iter(var_expr!(3, true).as_ref_var())
947                .next()
948                .is_some()
949        );
950        {
951            let result = forest.as_mut_var().get(&3);
952            let result2 = result.get(&true);
953            assert_eq!(result2.len(), 3);
954            let result3 = result2.get(&1);
955            assert_eq!(result3.len(), 2);
956            let result4 = result3.get(&"hello");
957            assert_eq!(result4.0.elements.len(), 1);
958            assert_eq!(
959                result4.0.elements.iter().next(),
960                Some(var_expr!(3, true, 1, "hello").as_ref_var())
961            );
962        }
963    }
964}