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_partial_cmp_incomparable_children() {
441        use std::cmp::Ordering::{Equal, Greater, Less};
442
443        use variadics::var_expr;
444
445        use crate::GhtType;
446        use crate::ght::GeneralizedHashTrieNode;
447
448        // Counted multisets are not lattices; `PartialOrd` is only implemented for set storage.
449        type MyGht = GhtType!(u32 => u32: VariadicHashSetStd);
450
451        // Disjoint keys.
452        let left = MyGht::new_from(vec![var_expr!(1, 10)]);
453        let right = MyGht::new_from(vec![var_expr!(2, 20)]);
454        assert_eq!(left.partial_cmp(&right), None);
455        assert_eq!(right.partial_cmp(&left), None);
456
457        // One child is greater and another is less.
458        let left = MyGht::new_from(vec![var_expr!(1, 10), var_expr!(1, 11), var_expr!(2, 20)]);
459        let right = MyGht::new_from(vec![var_expr!(1, 10), var_expr!(2, 20), var_expr!(2, 21)]);
460        assert_eq!(left.partial_cmp(&right), None);
461        assert_eq!(right.partial_cmp(&left), None);
462
463        // Subset and equality stay ordered.
464        let smaller = MyGht::new_from(vec![var_expr!(1, 10)]);
465        let larger = MyGht::new_from(vec![var_expr!(1, 10), var_expr!(1, 11)]);
466        assert_eq!(smaller.partial_cmp(&larger), Some(Less));
467        assert_eq!(larger.partial_cmp(&smaller), Some(Greater));
468
469        let same = MyGht::new_from(vec![var_expr!(1, 10), var_expr!(2, 20)]);
470        let same_again = MyGht::new_from(vec![var_expr!(2, 20), var_expr!(1, 10)]);
471        assert_eq!(same.partial_cmp(&same_again), Some(Equal));
472
473        let empty = MyGht::default();
474        assert_eq!(empty.partial_cmp(&MyGht::default()), Some(Equal));
475        assert_eq!(empty.partial_cmp(&smaller), Some(Less));
476        assert_eq!(smaller.partial_cmp(&empty), Some(Greater));
477    }
478
479    #[test]
480    fn test_cartesian_bimorphism() {
481        use variadics::var_expr;
482
483        use crate::ght::GeneralizedHashTrieNode;
484        use crate::ght::lattice::GhtCartesianProductBimorphism;
485        use crate::{GhtType, LatticeBimorphism};
486
487        type MyGhtA = GhtType!(u32, u64 => u16, &'static str: VariadicHashSetStd);
488        type MyGhtB = GhtType!(u32, u64, u16 => &'static str: VariadicHashSetStd);
489
490        let mut ght_a = MyGhtA::default();
491        let mut ght_b = MyGhtB::default();
492
493        ght_a.insert(var_expr!(123, 2, 5, "hello"));
494        ght_a.insert(var_expr!(50, 1, 1, "hi"));
495        ght_a.insert(var_expr!(5, 1, 7, "hi"));
496        ght_b.insert(var_expr!(5, 1, 8, "hi"));
497        ght_b.insert(var_expr!(10, 1, 2, "hi"));
498        ght_b.insert(var_expr!(12, 10, 98, "bye"));
499
500        type MyGhtAb = GhtType!(u32, u64, u16, &'static str, u32, u64 => u16, &'static str: VariadicCountedHashSetStd);
501
502        let mut bim = GhtCartesianProductBimorphism::<MyGhtAb>::default();
503        let ght_out = bim.call(&ght_a, &ght_b);
504        assert_eq!(
505            ght_out.recursive_iter().count(),
506            ght_a.recursive_iter().count() * ght_b.recursive_iter().count()
507        );
508    }
509
510    #[test]
511    fn test_join_bimorphism() {
512        use variadics::variadic_collections::{VariadicCountedHashSetStd, VariadicHashSetStd};
513        use variadics::{var_expr, var_type};
514
515        use crate::ght::lattice::{
516            DeepJoinLatticeBimorphism, GhtNodeKeyedBimorphism, GhtValTypeProductBimorphism,
517        };
518        use crate::ght::{GeneralizedHashTrieNode, GhtInner, GhtLeaf};
519        use crate::{GhtType, LatticeBimorphism};
520
521        type ResultSchemaType = var_type!(u32, u64, u16, &'static str, &'static str);
522        type ResultSchemaRefType<'a> = var_type!(
523            &'a u32,
524            &'a u64,
525            &'a u16,
526            &'a &'static str,
527            &'a &'static str
528        );
529        type MyGhtATrie = GhtType!(u32, u64, u16 => &'static str: VariadicHashSetStd);
530        type MyGhtBTrie = GhtType!(u32, u64, u16 => &'static str: VariadicHashSetStd);
531
532        let mut ght_a = MyGhtATrie::default();
533        let mut ght_b = MyGhtBTrie::default();
534
535        ght_a.insert(var_expr!(123, 2, 5, "hello"));
536        ght_a.insert(var_expr!(50, 1, 1, "hi"));
537        ght_a.insert(var_expr!(5, 1, 7, "hi"));
538
539        ght_b.insert(var_expr!(5, 1, 8, "hi"));
540        ght_b.insert(var_expr!(5, 1, 7, "world"));
541        ght_b.insert(var_expr!(10, 1, 2, "hi"));
542        ght_b.insert(var_expr!(12, 10, 98, "bye"));
543
544        let result: HashSet<ResultSchemaRefType<'_>> = [var_expr!(&5, &1, &7, &"hi", &"world")]
545            .iter()
546            .copied()
547            .collect();
548        {
549            // here we manually construct the proper bimorphism stack.
550            // note that the bottommost bimorphism is GhtValTypeProductBimorphism,
551            // which ensures that the Schema of the resulting output GhtLeaf and GhtInner
552            // nodes correctly includes the key columns, not just the cross-product of the values.
553            type MyGhtOut = GhtInner<
554                &'static str,
555                GhtLeaf<
556                    ResultSchemaType,
557                    var_type!(&'static str),
558                    VariadicCountedHashSetStd<ResultSchemaType>,
559                >,
560            >;
561            // let mut bim = GhtNodeKeyedBimorphism::new(GhtNodeKeyedBimorphism::new(
562            //     GhtNodeKeyedBimorphism::new(GhtValTypeProductBimorphism::<MyGhtOut>::default()),
563            // ));
564            let mut bim = GhtNodeKeyedBimorphism::new(GhtNodeKeyedBimorphism::new(
565                GhtNodeKeyedBimorphism::new(GhtValTypeProductBimorphism::<MyGhtOut>::default()),
566            ));
567            let out = bim.call(&ght_a, &ght_b);
568            let out: HashSet<ResultSchemaRefType<'_>> = out.recursive_iter().collect();
569            assert_eq!(out, result);
570        }
571        {
572            // Here we use DeepJoinLatticeBimorphism as a more compact representation of the
573            // manual stack of bimorphisms above. This is the recommended approach.
574            type MyNodeBim<'a> = <(MyGhtATrie, MyGhtBTrie) as DeepJoinLatticeBimorphism<
575                VariadicHashSetStd<ResultSchemaType>,
576            >>::DeepJoinLatticeBimorphism;
577            let mut bim = <MyNodeBim<'_> as Default>::default();
578            let out = bim.call(&ght_a, &ght_b);
579            let out: HashSet<ResultSchemaRefType<'_>> = out.recursive_iter().collect();
580            assert_eq!(out, result);
581        }
582    }
583
584    #[test]
585    fn test_ght_with_tuple_macro() {
586        use variadics::{VariadicExt, var_expr};
587        use variadics_macro::tuple;
588
589        use crate::GhtType;
590        use crate::ght::GeneralizedHashTrieNode;
591
592        type MyRoot = GhtType!(u16, u32 => u64: VariadicCountedHashSetStd);
593
594        let mut trie1 = MyRoot::default();
595        assert_eq!(3, <<MyRoot as GeneralizedHashTrieNode>::Schema>::LEN);
596        trie1.insert(var_expr!(1, 2, 3));
597        let t = trie1.recursive_iter().next().unwrap();
598        let tup = tuple!(t, 3);
599        assert_eq!(tup, (&1, &2, &3));
600    }
601
602    #[test]
603    fn test_triangle_generic_join() {
604        use std::hash::{BuildHasherDefault, DefaultHasher};
605
606        use variadics::var_expr;
607
608        use crate::GhtType;
609        use crate::ght::{GeneralizedHashTrieNode, GhtPrefixIter};
610
611        const MATCHES: u32 = 1000;
612        type MyGht = GhtType!(u32 => u32: VariadicCountedHashSetStd);
613
614        let r_iter = (0..MATCHES)
615            .map(|i| (0, i))
616            .chain((1..MATCHES).map(|i| (i, 0)));
617
618        let s_iter = (0..MATCHES)
619            .map(|i| (0, i))
620            .chain((1..MATCHES).map(|i| (i, 0)));
621
622        let t_iter = (0..MATCHES)
623            .map(|i| (0, i))
624            .chain((1..MATCHES).map(|i| (i, 0)));
625
626        let rx_ght = MyGht::new_from(r_iter.clone().map(|(x, y)| var_expr!(x, y)));
627        let sb_ght = MyGht::new_from(s_iter.clone().map(|(y, b)| var_expr!(b, y)));
628        let tx_ght = MyGht::new_from(t_iter.map(|(z, x)| var_expr!(x, z)));
629
630        let r_x = r_iter
631            .map(|(x, _y)| x)
632            .collect::<HashSet<_, BuildHasherDefault<DefaultHasher>>>();
633        let t_x = s_iter
634            .clone()
635            .map(|(_z, x)| x)
636            .collect::<HashSet<_, BuildHasherDefault<DefaultHasher>>>();
637        let x_inter = r_x.intersection(&t_x);
638        let len = x_inter.clone().count();
639        if len > 1 {
640            assert_eq!(1000, len);
641        }
642
643        let mut output: Vec<(u32, u32, u32)> = Vec::new();
644        let mut x_iters = 0usize;
645        let mut y_iters = 0usize;
646        let mut z_iters = 0usize;
647        for a in x_inter {
648            x_iters += 1;
649            let r = rx_ght
650                .prefix_iter(var_expr!(a))
651                .map(|(_x, (y, ()))| *y)
652                .collect::<HashSet<_, BuildHasherDefault<DefaultHasher>>>();
653            let s_y = s_iter
654                .clone()
655                .map(|(y, _z)| y)
656                .collect::<HashSet<_, BuildHasherDefault<DefaultHasher>>>();
657            let y_inter = r.intersection(&s_y);
658            let len = y_inter.clone().count();
659            if len > 1 {
660                assert_eq!(1000, len);
661            }
662            for b in y_inter {
663                y_iters += 1;
664                let s = sb_ght
665                    .prefix_iter(var_expr!(b))
666                    .map(|(_b, (z, ()))| *z)
667                    .collect::<HashSet<_, BuildHasherDefault<DefaultHasher>>>();
668                let t = tx_ght
669                    .prefix_iter(var_expr!(a))
670                    .map(|(_x, (z, ()))| *z)
671                    .collect::<HashSet<_, BuildHasherDefault<DefaultHasher>>>();
672                let z_inter = s.intersection(&t);
673                let len = z_inter.clone().count();
674                if len > 1 {
675                    assert_eq!(1000, len);
676                }
677                for c in z_inter {
678                    z_iters += 1;
679                    output.push((*a, *b, *c));
680                }
681            }
682        }
683
684        assert_eq!(1000, x_iters);
685        assert_eq!(1999, y_iters);
686        assert_eq!(2998, z_iters);
687        assert_eq!(2998, output.len());
688    }
689
690    fn clover_setup(
691        matches: usize,
692    ) -> (
693        impl Iterator<Item = (u32, u32)>,
694        impl Iterator<Item = (u32, u32)>,
695        impl Iterator<Item = (u32, u32)>,
696    ) {
697        let r_iter = (1..matches)
698            .map(|i| (1u32, i as u32))
699            .chain((1..matches).map(|i| (2, i as u32)))
700            .chain([(0, 0)]);
701
702        let s_iter = (1..matches)
703            .map(|i| (2u32, i as u32))
704            .chain((1..matches).map(|i| (3, i as u32)))
705            .chain([(0, 0)]);
706
707        let t_iter = (1..matches)
708            .map(|i| (3u32, i as u32))
709            .chain((1..matches).map(|i| (1, i as u32)))
710            .chain([(0, 0)]);
711        (r_iter, s_iter, t_iter)
712    }
713
714    #[test]
715    fn clover_generic_join() {
716        use variadics::var_expr;
717
718        use crate::GhtType;
719        use crate::ght::{GeneralizedHashTrieNode, GhtGet};
720
721        const MATCHES: usize = 1000;
722        let (r_iter, s_iter, t_iter) = clover_setup(MATCHES);
723
724        type MyGht = GhtType!(u32 => u32: VariadicCountedHashSetStd);
725        let rx_ght = MyGht::new_from(r_iter.map(|(x, a)| var_expr!(x, a)));
726        let sx_ght = MyGht::new_from(s_iter.map(|(x, b)| var_expr!(x, b)));
727        let tx_ght = MyGht::new_from(t_iter.map(|(x, c)| var_expr!(x, c)));
728        for x in rx_ght.iter() {
729            if let (Some(r), Some(s), Some(t)) = (rx_ght.get(&x), sx_ght.get(&x), tx_ght.get(&x)) {
730                // All unwraps succeeded, use `r`, `s`, `t` here
731                for a in r.iter() {
732                    for b in s.iter() {
733                        for c in t.iter() {
734                            assert_eq!((x, a, b, c), (0, 0, 0, 0));
735                        }
736                    }
737                }
738            } else {
739                // If any unwrap fails, continue to the next iteration
740                continue;
741            }
742        }
743    }
744
745    #[test]
746    fn clover_factorized_join() {
747        use variadics::var_expr;
748
749        use crate::GhtType;
750        use crate::ght::{GeneralizedHashTrieNode, GhtGet};
751
752        const MATCHES: usize = 1000;
753        let (r_iter, s_iter, t_iter) = clover_setup(MATCHES);
754
755        type Ght1 = GhtType!(() => u32, u32: VariadicCountedHashSetStd);
756        type Ght2 = GhtType!(u32 => u32: VariadicCountedHashSetStd);
757        let rx_ght = Ght1::new_from(r_iter.map(|(x, a)| var_expr!(x, a)));
758        let sx_ght = Ght2::new_from(s_iter.map(|(x, b)| var_expr!(x, b)));
759        let tx_ght = Ght2::new_from(t_iter.map(|(x, c)| var_expr!(x, c)));
760
761        for t in rx_ght.recursive_iter() {
762            let (x, (a, ())): (&u32, (&u32, _)) = t;
763            if let (Some(s), Some(t)) = (sx_ght.get(x), tx_ght.get(x)) {
764                // All unwraps succeeded, use `s`, `t` here
765                for b in s.iter() {
766                    for c in t.iter() {
767                        assert_eq!((x, a, b, c), (&0, &0, 0, 0));
768                    }
769                }
770            } else {
771                // If any unwrap fails, continue to the next iteration
772                continue;
773            }
774        }
775    }
776
777    #[test]
778    fn test_force() {
779        use variadics::var_expr;
780
781        use crate::GhtType;
782        use crate::ght::GeneralizedHashTrieNode;
783        use crate::ght::colt::ColtForestNode;
784
785        type LeafType = GhtType!(() => u16, u32, u64: VariadicCountedHashSetStd);
786        let n = LeafType::new_from(vec![
787            var_expr!(1, 1, 1),
788            var_expr!(1, 2, 2),
789            var_expr!(1, 3, 3),
790            var_expr!(2, 4, 4),
791        ]);
792        let out = n.force().unwrap();
793        assert_eq!(out.height(), 1);
794    }
795
796    #[test]
797    fn test_forest_macro() {
798        use crate::ColtType;
799
800        type Forest4 = ColtType!(u8, u16, u32, u64);
801        let _f4 = Forest4::default();
802
803        type Forest3 = ColtType!(u8, u16, u32);
804        let _f3 = Forest3::default();
805
806        type Forest2 = ColtType!(u8, u16);
807        let _f2 = Forest2::default();
808
809        type Forest1 = ColtType!(u8);
810        let _f2 = Forest1::default();
811
812        type Forest01 = ColtType!(() => u16);
813        let _f01 = Forest01::default();
814
815        type Forest02 = ColtType!(() => u8, u16);
816        let _f02 = Forest02::default();
817
818        type Forest10 = ColtType!(u8 => ());
819        let _f10 = Forest10::default();
820
821        type Forest11 = ColtType!(u8 => u16);
822        let _f11 = Forest11::default();
823
824        type Forest12 = ColtType!(u8 => u16, u32);
825        let _f12 = Forest12::default();
826
827        type Forest20 = ColtType!(u8, u16 => ());
828        let _f20 = Forest20::default();
829
830        type Forest21 = ColtType!(u8, u16 => u32);
831        let _f21 = Forest21::default();
832
833        type Forest22 = ColtType!(u8, u16 => u32, u64);
834        let _f22 = Forest22::default();
835    }
836
837    #[test]
838    fn test_colt_little_get() {
839        use variadics::variadic_collections::VariadicCollection;
840        use variadics::{VariadicExt, var_expr};
841
842        use crate::ColtType;
843        use crate::ght::GeneralizedHashTrieNode;
844        use crate::ght::colt::ColtGet;
845
846        type MyForest = ColtType!(u8);
847
848        let mut forest = MyForest::default();
849
850        forest.0.insert(var_expr!(1));
851        forest.0.insert(var_expr!(2));
852        forest.0.insert(var_expr!(3));
853
854        assert_eq!(2, forest.len());
855        assert_eq!(3, forest.0.elements.len());
856
857        let result = ColtGet::get(forest.as_mut_var(), &3);
858        assert_eq!(1, result.len());
859        assert_eq!(0, forest.0.elements.len());
860        assert!(forest.0.forced);
861    }
862
863    #[test]
864    fn test_colt_get() {
865        use variadics::variadic_collections::VariadicCollection;
866        use variadics::{VariadicExt, var_expr};
867
868        use crate::ColtType;
869        use crate::ght::colt::ColtGet;
870        use crate::ght::{GeneralizedHashTrieNode, GhtGet};
871
872        type MyForest = ColtType!(u8, u16, u32, u64);
873        let mut forest = MyForest::default();
874        forest.0.insert(var_expr!(1, 1, 1, 1));
875        forest.0.insert(var_expr!(2, 2, 2, 2));
876        forest.0.insert(var_expr!(3, 3, 3, 3));
877
878        let len = forest.len();
879        assert_eq!(5, len);
880        {
881            let get_result = ColtGet::get(forest.as_mut_var(), &1);
882            assert_eq!(get_result.len(), len - 1);
883            assert_eq!(get_result.0.height(), 0);
884            let get_result2 = ColtGet::get(get_result, &1);
885            assert_eq!(get_result2.len(), len - 2);
886            let get_result3 = ColtGet::get(get_result2, &1);
887            assert_eq!(get_result3.len(), len - 3);
888            assert_eq!(
889                get_result3.0.elements.iter().next(),
890                Some(var_expr!(1, 1, 1, 1).as_ref_var())
891            );
892            assert_eq!(get_result3.1.0.children.len(), 0);
893        }
894        {
895            let get_result = ColtGet::get(forest.as_mut_var(), &3);
896            assert_eq!(get_result.len(), len - 1);
897            let get_result2 = ColtGet::get(get_result, &3);
898            assert_eq!(get_result2.len(), len - 2);
899            assert_eq!(
900                get_result2.0.elements.iter().next(),
901                Some(var_expr!(3, 3, 3, 3).as_ref_var())
902            );
903            assert_eq!(get_result2.1.0.children.len(), 0);
904        }
905        assert!(forest.0.forced);
906        assert_eq!(3, forest.1.0.children.len()); // keys 1, 2 and 3
907        assert_eq!(0, forest.1.0.get(&1).unwrap().elements.len());
908        assert_eq!(1, forest.1.0.get(&2).unwrap().elements.len());
909        assert_eq!(0, forest.1.0.get(&3).unwrap().elements.len());
910        assert_eq!(2, forest.1.1.0.children.len()); // keys 1 and 3
911        assert_eq!(
912            0,
913            forest
914                .1
915                .1
916                .0
917                .get(&1)
918                .unwrap()
919                .get(&1)
920                .unwrap()
921                .elements
922                .len()
923        );
924        assert!(forest.1.1.0.get(&2).is_none());
925        assert_eq!(
926            1,
927            forest
928                .1
929                .1
930                .0
931                .get(&3)
932                .unwrap()
933                .get(&3)
934                .unwrap()
935                .elements
936                .len()
937        );
938        assert_eq!(
939            1,
940            forest
941                .1
942                .1
943                .1
944                .0
945                .get(&1)
946                .unwrap()
947                .get(&1)
948                .unwrap()
949                .get(&1)
950                .unwrap()
951                .elements
952                .len()
953        );
954    }
955
956    #[test]
957    fn test_colt_scale() {
958        use variadics::variadic_collections::VariadicCollection;
959        use variadics::{VariadicExt, var_expr};
960
961        use crate::ght::colt::ColtGet;
962        use crate::ght::{GeneralizedHashTrieNode, GhtPrefixIter};
963
964        type MyColt = crate::ColtType!(i32, bool, usize, &'static str);
965        let mut forest = MyColt::default();
966        for i in 1..100000 {
967            forest.0.insert(var_expr!(i, true, 1, "hello"));
968        }
969        {
970            let result = forest.as_mut_var().get(&3);
971            assert_eq!(result.len(), 4);
972        }
973        // check: first Leaf trie is forced
974        assert!(forest.0.forced);
975        assert_eq!(forest.0.elements.len(), 0);
976        {
977            let result = forest.as_mut_var().get(&3);
978            let result2 = result.get(&true);
979            assert_eq!(result2.len(), 3);
980        }
981        {
982            // check: leaf below 3 in first non-empty trie is forced
983            let result = forest.as_mut_var().get(&3);
984            assert!(result.0.forced);
985            assert_eq!(result.0.elements.len(), 0);
986        }
987        // check: prefix (3, true) is now found in the third trie: forest.1.1.0
988        assert!(
989            forest
990                .1
991                .1
992                .0
993                .prefix_iter(var_expr!(3, true).as_ref_var())
994                .next()
995                .is_some()
996        );
997        {
998            let result = forest.as_mut_var().get(&3);
999            let result2 = result.get(&true);
1000            assert_eq!(result2.len(), 3);
1001            let result3 = result2.get(&1);
1002            assert_eq!(result3.len(), 2);
1003            let result4 = result3.get(&"hello");
1004            assert_eq!(result4.0.elements.len(), 1);
1005            assert_eq!(
1006                result4.0.elements.iter().next(),
1007                Some(var_expr!(3, true, 1, "hello").as_ref_var())
1008            );
1009        }
1010    }
1011}