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> = htrie.prefix_iter(var_expr!(42, 315).as_ref_var()).collect();
289        let result = HashSet::from_iter([var_expr!(&42, &315, &43770)].iter().copied());
290        assert_eq!(v, result);
291
292        let v: HashSet<ResultType> = htrie.prefix_iter(var_expr!(42u8).as_ref_var()).collect();
293        #[expect(
294            clippy::disallowed_methods,
295            reason = "nondeterministic iteration order, fine to collect into set"
296        )]
297        let result = input
298            .iter()
299            .filter(|t: &&InputType| t.0 == 42)
300            .map(|t: &InputType| var_expr!(&t.0, &t.1.0, &t.1.1.0))
301            .collect();
302        assert_eq!(v, result);
303
304        for row in htrie.prefix_iter(var_expr!(42, 315, 43770).as_ref_var()) {
305            assert_eq!(row, var_expr!(&42, &315, &43770));
306        }
307    }
308
309    #[test]
310    fn test_prefix_iter_complex() {
311        use variadics::{VariadicExt, var_expr, var_type};
312
313        use crate::GhtType;
314        use crate::ght::{GeneralizedHashTrieNode, GhtPrefixIter};
315
316        type MyGht = GhtType!(bool, u32, &'static str => i32: VariadicCountedHashSetStd);
317        type InputType = var_type!(bool, u32, &'static str, i32);
318        type ResultType<'a> = var_type!(&'a bool, &'a u32, &'a &'static str, &'a i32);
319        let input: HashSet<InputType> = HashSet::from_iter(
320            [
321                (true, 1, "hello", -5),
322                (true, 1, "hi", -2),
323                (true, 1, "hi", -3),
324                (true, 1, "hi", -4),
325                (true, 1, "hi", -5),
326                (true, 2, "hello", 1),
327                (false, 10, "bye", 5),
328            ]
329            .iter()
330            .map(|&(a, b, c, d)| var_expr!(a, b, c, d)),
331        );
332
333        let htrie = MyGht::new_from(input.clone());
334
335        let v: HashSet<ResultType> = htrie
336            .prefix_iter(var_expr!(true, 1, "hi").as_ref_var())
337            .collect();
338        #[expect(
339            clippy::disallowed_methods,
340            reason = "nondeterministic iteration order, fine to collect into set"
341        )]
342        let result = input
343            .iter()
344            .filter(|t: &&InputType| t.0 && t.1.0 == 1 && t.1.1.0 == "hi")
345            //.map(|t: &InputType| (&t.0, &t.1 .0, (&t.1 .1 .0, (&t.1 .1 .1 .0, ()))))
346            .map(|t| t.as_ref_var())
347            .collect();
348        assert_eq!(v, result);
349
350        let v: HashSet<ResultType> = htrie.prefix_iter(var_expr!(true).as_ref_var()).collect();
351        #[expect(
352            clippy::disallowed_methods,
353            reason = "nondeterministic iteration order, fine to collect into set"
354        )]
355        let result = input
356            .iter()
357            .filter(|t: &&InputType| t.0)
358            .map(|t: &InputType| t.as_ref_var())
359            .collect();
360        assert_eq!(v, result);
361    }
362
363    #[test]
364    fn test_merge() {
365        use variadics::{var_expr, var_type};
366
367        use crate::ght::GeneralizedHashTrieNode;
368        use crate::{GhtType, Merge};
369
370        type MyGht = GhtType!(u32, u64 => u16, &'static str: VariadicHashSetStd);
371
372        let mut test_ght1 = MyGht::new_from(vec![var_expr!(42, 314, 10, "hello")]);
373        let test_ght2 = MyGht::new_from(vec![var_expr!(42, 314, 10, "hello")]);
374
375        assert_eq!(
376            test_ght1
377                .recursive_iter()
378                .collect::<Vec<var_type!(&u32, &u64, &u16, &&'static str)>>()
379                .len(),
380            1
381        );
382        test_ght1.merge(test_ght2.clone());
383        // merge does not contain duplicate copy of the tuple
384        assert_eq!(
385            test_ght1
386                .recursive_iter()
387                .collect::<Vec<var_type!(&u32, &u64, &u16, &&'static str)>>()
388                .len(),
389            1
390        );
391        assert!(!test_ght1.merge(test_ght2.clone()));
392
393        let mut test_ght1 = MyGht::new_from(vec![var_expr!(42, 314, 10, "hello")]);
394        let mut test_ght2 = MyGht::new_from(vec![var_expr!(42, 314, 10, "hello")]);
395        test_ght1.merge(test_ght2.clone());
396
397        test_ght1.insert(var_expr!(42, 314, 20, "goodbye"));
398        test_ght2.insert(var_expr!(42, 314, 20, "again"));
399
400        // change on merge
401        assert!(test_ght1.merge(test_ght2.clone()));
402        for k in test_ght2.recursive_iter() {
403            assert!(test_ght1.contains(k))
404        }
405    }
406
407    #[test]
408    fn test_node_lattice() {
409        use variadics::var_expr;
410
411        use crate::ght::GeneralizedHashTrieNode;
412        use crate::{GhtType, NaiveLatticeOrd};
413
414        type MyGht = GhtType!(u32, u64 => u16, &'static str: VariadicHashSetStd);
415        type MyGhtNode = GhtType!(u32, u64 => u16, &'static str: VariadicHashSetStd);
416
417        let mut test_vec: Vec<MyGhtNode> = Vec::new();
418
419        let empty_ght = MyGht::new_from(vec![]);
420        let test_ght1 = MyGht::new_from(vec![var_expr!(42, 314, 10, "hello")]);
421        let mut test_ght2 = MyGht::new_from(vec![var_expr!(42, 314, 10, "hello")]);
422        test_ght2.insert(var_expr!(42, 314, 20, "again"));
423        let mut test_ght3 = test_ght2.clone();
424        test_ght3.insert(var_expr!(42, 400, 1, "level 2"));
425        let mut test_ght4 = test_ght3.clone();
426        test_ght4.insert(var_expr!(43, 1, 1, "level 1"));
427
428        let test_vec_wrap = [empty_ght, test_ght1, test_ght2, test_ght3, test_ght4];
429
430        for ght in test_vec_wrap.iter().cloned() {
431            ght.naive_cmp(&ght.clone());
432            test_vec.push(ght);
433        }
434        crate::test::check_all(&test_vec);
435        crate::test::check_all(&test_vec_wrap);
436    }
437
438    #[test]
439    fn test_cartesian_bimorphism() {
440        use variadics::var_expr;
441
442        use crate::ght::GeneralizedHashTrieNode;
443        use crate::ght::lattice::GhtCartesianProductBimorphism;
444        use crate::{GhtType, LatticeBimorphism};
445
446        type MyGhtA = GhtType!(u32, u64 => u16, &'static str: VariadicHashSetStd);
447        type MyGhtB = GhtType!(u32, u64, u16 => &'static str: VariadicHashSetStd);
448
449        let mut ght_a = MyGhtA::default();
450        let mut ght_b = MyGhtB::default();
451
452        ght_a.insert(var_expr!(123, 2, 5, "hello"));
453        ght_a.insert(var_expr!(50, 1, 1, "hi"));
454        ght_a.insert(var_expr!(5, 1, 7, "hi"));
455        ght_b.insert(var_expr!(5, 1, 8, "hi"));
456        ght_b.insert(var_expr!(10, 1, 2, "hi"));
457        ght_b.insert(var_expr!(12, 10, 98, "bye"));
458
459        type MyGhtAb = GhtType!(u32, u64, u16, &'static str, u32, u64 => u16, &'static str: VariadicCountedHashSetStd);
460
461        let mut bim = GhtCartesianProductBimorphism::<MyGhtAb>::default();
462        let ght_out = bim.call(&ght_a, &ght_b);
463        assert_eq!(
464            ght_out.recursive_iter().count(),
465            ght_a.recursive_iter().count() * ght_b.recursive_iter().count()
466        );
467    }
468
469    #[test]
470    fn test_join_bimorphism() {
471        use variadics::variadic_collections::{VariadicCountedHashSetStd, VariadicHashSetStd};
472        use variadics::{var_expr, var_type};
473
474        use crate::ght::lattice::{
475            DeepJoinLatticeBimorphism, GhtNodeKeyedBimorphism, GhtValTypeProductBimorphism,
476        };
477        use crate::ght::{GeneralizedHashTrieNode, GhtInner, GhtLeaf};
478        use crate::{GhtType, LatticeBimorphism};
479
480        type ResultSchemaType = var_type!(u32, u64, u16, &'static str, &'static str);
481        type ResultSchemaRefType<'a> = var_type!(
482            &'a u32,
483            &'a u64,
484            &'a u16,
485            &'a &'static str,
486            &'a &'static str
487        );
488        type MyGhtATrie = GhtType!(u32, u64, u16 => &'static str: VariadicHashSetStd);
489        type MyGhtBTrie = GhtType!(u32, u64, u16 => &'static str: VariadicHashSetStd);
490
491        let mut ght_a = MyGhtATrie::default();
492        let mut ght_b = MyGhtBTrie::default();
493
494        ght_a.insert(var_expr!(123, 2, 5, "hello"));
495        ght_a.insert(var_expr!(50, 1, 1, "hi"));
496        ght_a.insert(var_expr!(5, 1, 7, "hi"));
497
498        ght_b.insert(var_expr!(5, 1, 8, "hi"));
499        ght_b.insert(var_expr!(5, 1, 7, "world"));
500        ght_b.insert(var_expr!(10, 1, 2, "hi"));
501        ght_b.insert(var_expr!(12, 10, 98, "bye"));
502
503        let result: HashSet<ResultSchemaRefType> = [var_expr!(&5, &1, &7, &"hi", &"world")]
504            .iter()
505            .copied()
506            .collect();
507        {
508            // here we manually construct the proper bimorphism stack.
509            // note that the bottommost bimorphism is GhtValTypeProductBimorphism,
510            // which ensures that the Schema of the resulting output GhtLeaf and GhtInner
511            // nodes correctly includes the key columns, not just the cross-product of the values.
512            type MyGhtOut = GhtInner<
513                &'static str,
514                GhtLeaf<
515                    ResultSchemaType,
516                    var_type!(&'static str),
517                    VariadicCountedHashSetStd<ResultSchemaType>,
518                >,
519            >;
520            // let mut bim = GhtNodeKeyedBimorphism::new(GhtNodeKeyedBimorphism::new(
521            //     GhtNodeKeyedBimorphism::new(GhtValTypeProductBimorphism::<MyGhtOut>::default()),
522            // ));
523            let mut bim = GhtNodeKeyedBimorphism::new(GhtNodeKeyedBimorphism::new(
524                GhtNodeKeyedBimorphism::new(GhtValTypeProductBimorphism::<MyGhtOut>::default()),
525            ));
526            let out = bim.call(&ght_a, &ght_b);
527            let out: HashSet<ResultSchemaRefType> = out.recursive_iter().collect();
528            assert_eq!(out, result);
529        }
530        {
531            // Here we use DeepJoinLatticeBimorphism as a more compact representation of the
532            // manual stack of bimorphisms above. This is the recommended approach.
533            type MyNodeBim<'a> = <(MyGhtATrie, MyGhtBTrie) as DeepJoinLatticeBimorphism<
534                VariadicHashSetStd<ResultSchemaType>,
535            >>::DeepJoinLatticeBimorphism;
536            let mut bim = <MyNodeBim as Default>::default();
537            let out = bim.call(&ght_a, &ght_b);
538            let out: HashSet<ResultSchemaRefType> = out.recursive_iter().collect();
539            assert_eq!(out, result);
540        }
541    }
542
543    #[test]
544    fn test_ght_with_tuple_macro() {
545        use variadics::{VariadicExt, var_expr};
546        use variadics_macro::tuple;
547
548        use crate::GhtType;
549        use crate::ght::GeneralizedHashTrieNode;
550
551        type MyRoot = GhtType!(u16, u32 => u64: VariadicCountedHashSetStd);
552
553        let mut trie1 = MyRoot::default();
554        assert_eq!(3, <<MyRoot as GeneralizedHashTrieNode>::Schema>::LEN);
555        trie1.insert(var_expr!(1, 2, 3));
556        let t = trie1.recursive_iter().next().unwrap();
557        let tup = tuple!(t, 3);
558        assert_eq!(tup, (&1, &2, &3));
559    }
560
561    #[test]
562    fn test_triangle_generic_join() {
563        use std::hash::{BuildHasherDefault, DefaultHasher};
564
565        use variadics::var_expr;
566
567        use crate::GhtType;
568        use crate::ght::{GeneralizedHashTrieNode, GhtPrefixIter};
569
570        const MATCHES: u32 = 1000;
571        type MyGht = GhtType!(u32 => u32: VariadicCountedHashSetStd);
572
573        let r_iter = (0..MATCHES)
574            .map(|i| (0, i))
575            .chain((1..MATCHES).map(|i| (i, 0)));
576
577        let s_iter = (0..MATCHES)
578            .map(|i| (0, i))
579            .chain((1..MATCHES).map(|i| (i, 0)));
580
581        let t_iter = (0..MATCHES)
582            .map(|i| (0, i))
583            .chain((1..MATCHES).map(|i| (i, 0)));
584
585        let rx_ght = MyGht::new_from(r_iter.clone().map(|(x, y)| var_expr!(x, y)));
586        let sb_ght = MyGht::new_from(s_iter.clone().map(|(y, b)| var_expr!(b, y)));
587        let tx_ght = MyGht::new_from(t_iter.map(|(z, x)| var_expr!(x, z)));
588
589        let r_x = r_iter
590            .map(|(x, _y)| x)
591            .collect::<HashSet<_, BuildHasherDefault<DefaultHasher>>>();
592        let t_x = s_iter
593            .clone()
594            .map(|(_z, x)| x)
595            .collect::<HashSet<_, BuildHasherDefault<DefaultHasher>>>();
596        let x_inter = r_x.intersection(&t_x);
597        let len = x_inter.clone().count();
598        if len > 1 {
599            assert_eq!(1000, len);
600        }
601
602        let mut output: Vec<(u32, u32, u32)> = Vec::new();
603        let mut x_iters = 0usize;
604        let mut y_iters = 0usize;
605        let mut z_iters = 0usize;
606        for a in x_inter {
607            x_iters += 1;
608            let r = rx_ght
609                .prefix_iter(var_expr!(a))
610                .map(|(_x, (y, ()))| *y)
611                .collect::<HashSet<_, BuildHasherDefault<DefaultHasher>>>();
612            let s_y = s_iter
613                .clone()
614                .map(|(y, _z)| y)
615                .collect::<HashSet<_, BuildHasherDefault<DefaultHasher>>>();
616            let y_inter = r.intersection(&s_y);
617            let len = y_inter.clone().count();
618            if len > 1 {
619                assert_eq!(1000, len);
620            }
621            for b in y_inter {
622                y_iters += 1;
623                let s = sb_ght
624                    .prefix_iter(var_expr!(b))
625                    .map(|(_b, (z, ()))| *z)
626                    .collect::<HashSet<_, BuildHasherDefault<DefaultHasher>>>();
627                let t = tx_ght
628                    .prefix_iter(var_expr!(a))
629                    .map(|(_x, (z, ()))| *z)
630                    .collect::<HashSet<_, BuildHasherDefault<DefaultHasher>>>();
631                let z_inter = s.intersection(&t);
632                let len = z_inter.clone().count();
633                if len > 1 {
634                    assert_eq!(1000, len);
635                }
636                for c in z_inter {
637                    z_iters += 1;
638                    output.push((*a, *b, *c));
639                }
640            }
641        }
642
643        assert_eq!(1000, x_iters);
644        assert_eq!(1999, y_iters);
645        assert_eq!(2998, z_iters);
646        assert_eq!(2998, output.len());
647    }
648
649    fn clover_setup(
650        matches: usize,
651    ) -> (
652        impl Iterator<Item = (u32, u32)>,
653        impl Iterator<Item = (u32, u32)>,
654        impl Iterator<Item = (u32, u32)>,
655    ) {
656        let r_iter = (1..matches)
657            .map(|i| (1u32, i as u32))
658            .chain((1..matches).map(|i| (2, i as u32)))
659            .chain([(0, 0)]);
660
661        let s_iter = (1..matches)
662            .map(|i| (2u32, i as u32))
663            .chain((1..matches).map(|i| (3, i as u32)))
664            .chain([(0, 0)]);
665
666        let t_iter = (1..matches)
667            .map(|i| (3u32, i as u32))
668            .chain((1..matches).map(|i| (1, i as u32)))
669            .chain([(0, 0)]);
670        (r_iter, s_iter, t_iter)
671    }
672
673    #[test]
674    fn clover_generic_join() {
675        use variadics::var_expr;
676
677        use crate::GhtType;
678        use crate::ght::{GeneralizedHashTrieNode, GhtGet};
679
680        const MATCHES: usize = 1000;
681        let (r_iter, s_iter, t_iter) = clover_setup(MATCHES);
682
683        type MyGht = GhtType!(u32 => u32: VariadicCountedHashSetStd);
684        let rx_ght = MyGht::new_from(r_iter.map(|(x, a)| var_expr!(x, a)));
685        let sx_ght = MyGht::new_from(s_iter.map(|(x, b)| var_expr!(x, b)));
686        let tx_ght = MyGht::new_from(t_iter.map(|(x, c)| var_expr!(x, c)));
687        for x in rx_ght.iter() {
688            if let (Some(r), Some(s), Some(t)) = (rx_ght.get(&x), sx_ght.get(&x), tx_ght.get(&x)) {
689                // All unwraps succeeded, use `r`, `s`, `t` here
690                for a in r.iter() {
691                    for b in s.iter() {
692                        for c in t.iter() {
693                            assert_eq!((x, a, b, c), (0, 0, 0, 0));
694                        }
695                    }
696                }
697            } else {
698                // If any unwrap fails, continue to the next iteration
699                continue;
700            }
701        }
702    }
703
704    #[test]
705    fn clover_factorized_join() {
706        use variadics::var_expr;
707
708        use crate::GhtType;
709        use crate::ght::{GeneralizedHashTrieNode, GhtGet};
710
711        const MATCHES: usize = 1000;
712        let (r_iter, s_iter, t_iter) = clover_setup(MATCHES);
713
714        type Ght1 = GhtType!(() => u32, u32: VariadicCountedHashSetStd);
715        type Ght2 = GhtType!(u32 => u32: VariadicCountedHashSetStd);
716        let rx_ght = Ght1::new_from(r_iter.map(|(x, a)| var_expr!(x, a)));
717        let sx_ght = Ght2::new_from(s_iter.map(|(x, b)| var_expr!(x, b)));
718        let tx_ght = Ght2::new_from(t_iter.map(|(x, c)| var_expr!(x, c)));
719
720        for t in rx_ght.recursive_iter() {
721            let (x, (a, ())): (&u32, (&u32, _)) = t;
722            if let (Some(s), Some(t)) = (sx_ght.get(x), tx_ght.get(x)) {
723                // All unwraps succeeded, use `s`, `t` here
724                for b in s.iter() {
725                    for c in t.iter() {
726                        assert_eq!((x, a, b, c), (&0, &0, 0, 0));
727                    }
728                }
729            } else {
730                // If any unwrap fails, continue to the next iteration
731                continue;
732            }
733        }
734    }
735
736    #[test]
737    fn test_force() {
738        use variadics::var_expr;
739
740        use crate::GhtType;
741        use crate::ght::GeneralizedHashTrieNode;
742        use crate::ght::colt::ColtForestNode;
743
744        type LeafType = GhtType!(() => u16, u32, u64: VariadicCountedHashSetStd);
745        let n = LeafType::new_from(vec![
746            var_expr!(1, 1, 1),
747            var_expr!(1, 2, 2),
748            var_expr!(1, 3, 3),
749            var_expr!(2, 4, 4),
750        ]);
751        let out = n.force().unwrap();
752        assert_eq!(out.height(), 1);
753    }
754
755    #[test]
756    fn test_forest_macro() {
757        use crate::ColtType;
758
759        type Forest4 = ColtType!(u8, u16, u32, u64);
760        let _f4 = Forest4::default();
761
762        type Forest3 = ColtType!(u8, u16, u32);
763        let _f3 = Forest3::default();
764
765        type Forest2 = ColtType!(u8, u16);
766        let _f2 = Forest2::default();
767
768        type Forest1 = ColtType!(u8);
769        let _f2 = Forest1::default();
770
771        type Forest01 = ColtType!(() => u16);
772        let _f01 = Forest01::default();
773
774        type Forest02 = ColtType!(() => u8, u16);
775        let _f02 = Forest02::default();
776
777        type Forest10 = ColtType!(u8 => ());
778        let _f10 = Forest10::default();
779
780        type Forest11 = ColtType!(u8 => u16);
781        let _f11 = Forest11::default();
782
783        type Forest12 = ColtType!(u8 => u16, u32);
784        let _f12 = Forest12::default();
785
786        type Forest20 = ColtType!(u8, u16 => ());
787        let _f20 = Forest20::default();
788
789        type Forest21 = ColtType!(u8, u16 => u32);
790        let _f21 = Forest21::default();
791
792        type Forest22 = ColtType!(u8, u16 => u32, u64);
793        let _f22 = Forest22::default();
794    }
795
796    #[test]
797    fn test_colt_little_get() {
798        use variadics::variadic_collections::VariadicCollection;
799        use variadics::{VariadicExt, var_expr};
800
801        use crate::ColtType;
802        use crate::ght::GeneralizedHashTrieNode;
803        use crate::ght::colt::ColtGet;
804
805        type MyForest = ColtType!(u8);
806
807        let mut forest = MyForest::default();
808
809        forest.0.insert(var_expr!(1));
810        forest.0.insert(var_expr!(2));
811        forest.0.insert(var_expr!(3));
812
813        assert_eq!(2, forest.len());
814        assert_eq!(3, forest.0.elements.len());
815
816        let result = ColtGet::get(forest.as_mut_var(), &3);
817        assert_eq!(1, result.len());
818        assert_eq!(0, forest.0.elements.len());
819        assert!(forest.0.forced);
820    }
821
822    #[test]
823    fn test_colt_get() {
824        use variadics::variadic_collections::VariadicCollection;
825        use variadics::{VariadicExt, var_expr};
826
827        use crate::ColtType;
828        use crate::ght::colt::ColtGet;
829        use crate::ght::{GeneralizedHashTrieNode, GhtGet};
830
831        type MyForest = ColtType!(u8, u16, u32, u64);
832        let mut forest = MyForest::default();
833        forest.0.insert(var_expr!(1, 1, 1, 1));
834        forest.0.insert(var_expr!(2, 2, 2, 2));
835        forest.0.insert(var_expr!(3, 3, 3, 3));
836
837        let len = forest.len();
838        assert_eq!(5, len);
839        {
840            let get_result = ColtGet::get(forest.as_mut_var(), &1);
841            assert_eq!(get_result.len(), len - 1);
842            assert_eq!(get_result.0.height(), 0);
843            let get_result2 = ColtGet::get(get_result, &1);
844            assert_eq!(get_result2.len(), len - 2);
845            let get_result3 = ColtGet::get(get_result2, &1);
846            assert_eq!(get_result3.len(), len - 3);
847            assert_eq!(
848                get_result3.0.elements.iter().next(),
849                Some(var_expr!(1, 1, 1, 1).as_ref_var())
850            );
851            assert_eq!(get_result3.1.0.children.len(), 0);
852        }
853        {
854            let get_result = ColtGet::get(forest.as_mut_var(), &3);
855            assert_eq!(get_result.len(), len - 1);
856            let get_result2 = ColtGet::get(get_result, &3);
857            assert_eq!(get_result2.len(), len - 2);
858            assert_eq!(
859                get_result2.0.elements.iter().next(),
860                Some(var_expr!(3, 3, 3, 3).as_ref_var())
861            );
862            assert_eq!(get_result2.1.0.children.len(), 0);
863        }
864        assert!(forest.0.forced);
865        assert_eq!(3, forest.1.0.children.len()); // keys 1, 2 and 3
866        assert_eq!(0, forest.1.0.get(&1).unwrap().elements.len());
867        assert_eq!(1, forest.1.0.get(&2).unwrap().elements.len());
868        assert_eq!(0, forest.1.0.get(&3).unwrap().elements.len());
869        assert_eq!(2, forest.1.1.0.children.len()); // keys 1 and 3
870        assert_eq!(
871            0,
872            forest
873                .1
874                .1
875                .0
876                .get(&1)
877                .unwrap()
878                .get(&1)
879                .unwrap()
880                .elements
881                .len()
882        );
883        assert!(forest.1.1.0.get(&2).is_none());
884        assert_eq!(
885            1,
886            forest
887                .1
888                .1
889                .0
890                .get(&3)
891                .unwrap()
892                .get(&3)
893                .unwrap()
894                .elements
895                .len()
896        );
897        assert_eq!(
898            1,
899            forest
900                .1
901                .1
902                .1
903                .0
904                .get(&1)
905                .unwrap()
906                .get(&1)
907                .unwrap()
908                .get(&1)
909                .unwrap()
910                .elements
911                .len()
912        );
913    }
914
915    #[test]
916    fn test_colt_scale() {
917        use variadics::variadic_collections::VariadicCollection;
918        use variadics::{VariadicExt, var_expr};
919
920        use crate::ght::colt::ColtGet;
921        use crate::ght::{GeneralizedHashTrieNode, GhtPrefixIter};
922
923        type MyColt = crate::ColtType!(i32, bool, usize, &'static str);
924        let mut forest = MyColt::default();
925        for i in 1..100000 {
926            forest.0.insert(var_expr!(i, true, 1, "hello"));
927        }
928        {
929            let result = forest.as_mut_var().get(&3);
930            assert_eq!(result.len(), 4);
931        }
932        // check: first Leaf trie is forced
933        assert!(forest.0.forced);
934        assert_eq!(forest.0.elements.len(), 0);
935        {
936            let result = forest.as_mut_var().get(&3);
937            let result2 = result.get(&true);
938            assert_eq!(result2.len(), 3);
939        }
940        {
941            // check: leaf below 3 in first non-empty trie is forced
942            let result = forest.as_mut_var().get(&3);
943            assert!(result.0.forced);
944            assert_eq!(result.0.elements.len(), 0);
945        }
946        // check: prefix (3, true) is now found in the third trie: forest.1.1.0
947        assert!(
948            forest
949                .1
950                .1
951                .0
952                .prefix_iter(var_expr!(3, true).as_ref_var())
953                .next()
954                .is_some()
955        );
956        {
957            let result = forest.as_mut_var().get(&3);
958            let result2 = result.get(&true);
959            assert_eq!(result2.len(), 3);
960            let result3 = result2.get(&1);
961            assert_eq!(result3.len(), 2);
962            let result4 = result3.get(&"hello");
963            assert_eq!(result4.0.elements.len(), 1);
964            assert_eq!(
965                result4.0.elements.iter().next(),
966                Some(var_expr!(3, true, 1, "hello").as_ref_var())
967            );
968        }
969    }
970}