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