kanidmd_lib/
macros.rs

1#[cfg(test)]
2macro_rules! setup_test {
3    () => {{
4        sketching::test_init();
5
6        // Create an in memory BE
7        let schema_outer = Schema::new().expect("Failed to init schema");
8        let idxmeta = {
9            let schema_txn = schema_outer.write_blocking();
10            schema_txn.reload_idxmeta()
11        };
12        let be = Backend::new(BackendConfig::new_test("main"), idxmeta, false)
13            .expect("Failed to init BE");
14
15        let qs = QueryServer::new(be, schema_outer, "example.com".to_string(), Duration::ZERO)
16            .expect("Failed to setup Query Server");
17        tokio::runtime::Builder::new_current_thread()
18            .enable_all()
19            .build()
20            .unwrap()
21            .block_on(qs.initialise_helper(duration_from_epoch_now(), DOMAIN_TGT_LEVEL))
22            .expect("init failed!");
23        qs
24    }};
25    (
26        $preload_entries:expr
27    ) => {{
28        use crate::prelude::duration_from_epoch_now;
29
30        sketching::test_init();
31
32        // Create an in memory BE
33        let schema_outer = Schema::new().expect("Failed to init schema");
34        let idxmeta = {
35            let schema_txn = schema_outer.write();
36            schema_txn.reload_idxmeta()
37        };
38        let be = Backend::new(BackendConfig::new_test("main"), idxmeta, false)
39            .expect("Failed to init BE");
40
41        let qs = QueryServer::new(be, schema_outer, "example.com".to_string(), Duration::ZERO)
42            .expect("Failed to setup Query Server");
43        tokio::runtime::Builder::new_current_thread()
44            .enable_all()
45            .build()
46            .unwrap()
47            .block_on(qs.initialise_helper(duration_from_epoch_now(), DOMAIN_TGT_LEVEL))
48            .expect("init failed!");
49
50        if !$preload_entries.is_empty() {
51            let mut qs_write = tokio::runtime::Builder::new_current_thread()
52                .enable_all()
53                .build()
54                .unwrap()
55                .block_on(qs.write(duration_from_epoch_now()))
56                .expect("txn");
57            qs_write
58                .internal_create($preload_entries)
59                .expect("Failed to preload entries");
60            assert!(qs_write.commit().is_ok());
61        }
62        qs
63    }};
64}
65
66// Test helpers for all plugins.
67// #[macro_export]
68#[cfg(test)]
69macro_rules! run_create_test {
70    (
71        $expect:expr,
72        $preload_entries:ident,
73        $create_entries:ident,
74        $internal:expr,
75        $check:expr
76    ) => {{
77        use crate::be::{Backend, BackendConfig};
78        use crate::event::CreateEvent;
79        use crate::prelude::*;
80        use crate::schema::Schema;
81
82        let qs = setup_test!($preload_entries);
83
84        let ce = match $internal {
85            None => CreateEvent::new_internal($create_entries.clone()),
86            Some(ent) => CreateEvent::new_impersonate_identity(
87                Identity::from_impersonate_entry_readwrite(ent),
88                $create_entries.clone(),
89            ),
90        };
91
92        {
93            let mut qs_write = tokio::runtime::Builder::new_current_thread()
94                .enable_all()
95                .build()
96                .unwrap()
97                .block_on(qs.write(duration_from_epoch_now()))
98                .unwrap();
99            let r = qs_write.create(&ce);
100            trace!("test result: {:?}", r);
101            assert_eq!(r, $expect);
102            $check(&mut qs_write);
103            match r {
104                Ok(_) => {
105                    qs_write.commit().expect("commit failure!");
106                }
107                Err(e) => {
108                    admin_error!("Rolling back => {:?}", e);
109                }
110            }
111        }
112        // Make sure there are no errors.
113        trace!("starting verification");
114        let ver = tokio::runtime::Builder::new_current_thread()
115            .enable_all()
116            .build()
117            .unwrap()
118            .block_on(qs.verify());
119        trace!("verification -> {:?}", ver);
120        assert_eq!(ver.len(), 0);
121    }};
122}
123
124#[cfg(test)]
125/// Runs a test with preloaded entries, then modifies based on a filter/list, then runs a given check
126macro_rules! run_modify_test {
127    (
128        // expected outcome
129        $expect:expr,
130        // things to preload
131        $preload_entries:ident,
132        // the targets to modify
133        $modify_filter:expr,
134        // changes to make
135        $modify_list:expr,
136        $internal:expr,
137        // something to run after the preload but before the modification, takes `&mut qs_write`
138        $pre_hook:expr,
139        // the result we expect
140        $check:expr
141    ) => {{
142        use crate::be::{Backend, BackendConfig};
143        use crate::event::ModifyEvent;
144        use crate::prelude::*;
145        use crate::schema::Schema;
146
147        let qs = setup_test!($preload_entries);
148
149        {
150            let mut qs_write = tokio::runtime::Builder::new_current_thread()
151                .enable_all()
152                .build()
153                .unwrap()
154                .block_on(qs.write(duration_from_epoch_now()))
155                .expect("txn");
156            $pre_hook(&mut qs_write);
157            qs_write.commit().expect("commit failure!");
158        }
159
160        let me = match $internal {
161            None => ModifyEvent::new_internal_invalid($modify_filter, $modify_list),
162            Some(ent) => ModifyEvent::new_impersonate_entry(ent, $modify_filter, $modify_list),
163        };
164
165        {
166            let mut qs_write = tokio::runtime::Builder::new_current_thread()
167                .enable_all()
168                .build()
169                .unwrap()
170                .block_on(qs.write(duration_from_epoch_now()))
171                .expect("txn");
172            let r = qs_write.modify(&me);
173            $check(&mut qs_write);
174            trace!("test result: {:?}", r);
175            assert_eq!(r, $expect);
176            match r {
177                Ok(_) => {
178                    qs_write.commit().expect("commit failure!");
179                }
180                Err(e) => {
181                    admin_error!("Rolling back => {:?}", e);
182                }
183            }
184        }
185        // Make sure there are no errors.
186        trace!("starting verification");
187        let ver = tokio::runtime::Builder::new_current_thread()
188            .enable_all()
189            .build()
190            .unwrap()
191            .block_on(qs.verify());
192        trace!("verification -> {:?}", ver);
193        assert_eq!(ver.len(), 0);
194    }};
195}
196
197// #[macro_export]
198#[cfg(test)]
199macro_rules! run_delete_test {
200    (
201        $expect:expr,
202        $preload_entries:ident,
203        $delete_filter:expr,
204        $internal:expr,
205        $check:expr
206    ) => {{
207        use crate::be::{Backend, BackendConfig};
208        use crate::event::DeleteEvent;
209        use crate::prelude::*;
210        use crate::schema::Schema;
211
212        let qs = setup_test!($preload_entries);
213
214        let de = match $internal {
215            Some(ent) => DeleteEvent::new_impersonate_entry(ent, $delete_filter.clone()),
216            None => DeleteEvent::new_internal_invalid($delete_filter.clone()),
217        };
218
219        {
220            let mut qs_write = tokio::runtime::Builder::new_current_thread()
221                .enable_all()
222                .build()
223                .unwrap()
224                .block_on(qs.write(duration_from_epoch_now()))
225                .expect("txn");
226            let r = qs_write.delete(&de);
227            trace!("test result: {:?}", r);
228            $check(&mut qs_write);
229            assert_eq!(r, $expect);
230            match r {
231                Ok(_) => {
232                    qs_write.commit().expect("commit failure!");
233                }
234                Err(e) => {
235                    admin_error!("Rolling back => {:?}", e);
236                }
237            }
238        }
239        // Make sure there are no errors.
240        trace!("starting verification");
241        let ver = tokio::runtime::Builder::new_current_thread()
242            .enable_all()
243            .build()
244            .unwrap()
245            .block_on(qs.verify());
246        trace!("verification -> {:?}", ver);
247        assert_eq!(ver.len(), 0);
248    }};
249}
250
251#[allow(unused_macros)]
252#[macro_export]
253macro_rules! modlist {
254    (
255        $vs:expr
256    ) => {{
257        let s: Box<[Modify]> = Box::new($vs);
258        ModifyList::new_list(s.into_vec())
259    }};
260}
261
262#[allow(unused_macros)]
263#[macro_export]
264macro_rules! f_and {
265    (
266        $vs:expr
267    ) => {{
268        let s: Box<[FC]> = Box::new($vs);
269        f_and(s.into_vec())
270    }};
271}
272
273#[allow(unused_macros)]
274#[macro_export]
275macro_rules! f_inc {
276    (
277        $vs:expr
278    ) => {{
279        let s: Box<[FC]> = Box::new($vs);
280        f_inc(s.into_vec())
281    }};
282}
283
284#[allow(unused_macros)]
285#[macro_export]
286macro_rules! f_or {
287    (
288        $vs:expr
289    ) => {{
290        let s: Box<[FC]> = Box::new($vs);
291        f_or(s.into_vec())
292    }};
293}
294
295#[allow(unused_macros)]
296#[macro_export]
297macro_rules! filter {
298    (
299        $fc:expr
300    ) => {{
301        Filter::new_ignore_hidden($fc)
302    }};
303}
304
305#[allow(unused_macros)]
306#[macro_export]
307macro_rules! filter_rec {
308    (
309        $fc:expr
310    ) => {{
311        Filter::new_recycled($fc)
312    }};
313}
314
315#[allow(unused_macros)]
316#[macro_export]
317macro_rules! filter_all {
318    (
319        $fc:expr
320    ) => {{
321        Filter::new($fc)
322    }};
323}
324
325#[macro_export]
326/// Build a filter which matches class == input
327macro_rules! match_class_filter {
328    ($class:expr) => {
329        ProtoFilter::Eq(Attribute::Class.to_string(), $class.to_string())
330    };
331}
332
333#[cfg(test)]
334#[allow(unused_macros)]
335#[macro_export]
336macro_rules! filter_valid {
337    (
338        $fc:expr
339    ) => {{
340        let f: Filter<FilterInvalid> = Filter::new($fc);
341        // Create a resolved filter, via the most unsafe means possible!
342        f.into_valid()
343    }};
344}
345
346#[cfg(test)]
347#[allow(unused_macros)]
348#[macro_export]
349macro_rules! filter_resolved {
350    (
351        $fc:expr
352    ) => {{
353        let f: Filter<FilterInvalid> = Filter::new($fc);
354        // Create a resolved filter, via the most unsafe means possible!
355        f.into_valid_resolved()
356    }};
357}
358
359#[cfg(test)]
360#[allow(unused_macros)]
361#[macro_export]
362macro_rules! pvalue_utf8 {
363    (
364        $v:expr
365    ) => {{
366        PartialValue::new_utf8(v.to_string())
367    }};
368}
369
370#[cfg(test)]
371#[allow(unused_macros)]
372#[macro_export]
373macro_rules! pvalue_iutf8 {
374    (
375        $v:expr
376    ) => {{
377        PartialValue::new_iutf8(v.to_string())
378    }};
379}
380
381#[allow(unused_macros)]
382#[macro_export]
383macro_rules! btreeset {
384    () => (
385        compile_error!("BTreeSet needs at least 1 element")
386    );
387    ($e:expr) => ({
388        use std::collections::BTreeSet;
389        let mut x: BTreeSet<_> = BTreeSet::new();
390        assert!(x.insert($e));
391        x
392    });
393    ($e:expr,) => ({
394        btreeset!($e)
395    });
396    ($e:expr, $($item:expr),*) => ({
397        use std::collections::BTreeSet;
398        let mut x: BTreeSet<_> = BTreeSet::new();
399        assert!(x.insert($e));
400        $(assert!(x.insert($item));)*
401        x
402    });
403}
404
405#[allow(unused_macros)]
406#[macro_export]
407macro_rules! smolset {
408    () => (
409        compile_error!("SmolSet needs at least 1 element")
410    );
411    ($e:expr) => ({
412        use smolset::SmolSet;
413        let mut x: SmolSet<_> = SmolSet::new();
414        assert!(x.insert($e));
415        x
416    });
417    ($e:expr,) => ({
418        smolset!($e)
419    });
420    ($e:expr, $($item:expr),*) => ({
421        use smolset::SmolSet;
422        let mut x: SmolSet<_> = SmolSet::new();
423        assert!(x.insert($e));
424        $(assert!(x.insert($item));)*
425        x
426    });
427}
428
429#[allow(unused_macros)]
430#[macro_export]
431macro_rules! btreemap {
432    () => (
433        compile_error!("BTreeSet needs at least 1 element")
434    );
435    ($e:expr) => ({
436        use std::collections::BTreeMap;
437        let mut x: BTreeMap<_, _> = BTreeMap::new();
438        let (a, b) = $e;
439        x.insert(a, b);
440        x
441    });
442    ($e:expr,) => ({
443        btreemap!($e)
444    });
445    ($e:expr, $($item:expr),*) => ({
446        use std::collections::BTreeMap;
447        let mut x: BTreeMap<_, _> = BTreeMap::new();
448        let (a, b) = $e;
449        x.insert(a, b);
450        $(
451            let (a, b) = $item;
452            x.insert(a, b);
453        )*
454        x
455    });
456}
457
458#[allow(unused_macros)]
459#[macro_export]
460macro_rules! entry_init {
461    () => ({
462        let e1: Entry<EntryInit, EntryNew> = Entry::new();
463        e1
464    });
465    ($ava:expr) => ({
466        let mut e1: Entry<EntryInit, EntryNew> = Entry::new();
467        e1.add_ava($ava.0, $ava.1);
468        e1
469    });
470    ($ava:expr, $($item:expr),*) => ({
471        let mut e1: Entry<EntryInit, EntryNew> = Entry::new();
472        e1.add_ava($ava.0, $ava.1);
473        $(e1.add_ava($item.0, $item.1);)*
474        e1
475    });
476}
477
478#[allow(unused_macros)]
479#[macro_export]
480macro_rules! mergesets {
481    (
482        $a:expr,
483        $b:expr
484    ) => {{
485        $b.iter().for_each(|v| {
486            $a.insert(v.clone());
487        });
488        Ok(())
489    }};
490}
491
492#[allow(unused_macros)]
493#[macro_export]
494macro_rules! mergemaps {
495    (
496        $a:expr,
497        $b:expr
498    ) => {{
499        $b.iter().for_each(|(k, v)| {
500            // I think to be consistent, we need the content of b to always
501            // the content of a
502            // if !$a.contains_key(k) {
503            $a.insert(k.clone(), v.clone());
504            // }
505        });
506        Ok(())
507    }};
508}
509
510#[allow(unused_macros)]
511#[macro_export]
512macro_rules! vs_utf8 {
513    () => (
514        compile_error!("ValueSetUtf8 needs at least 1 element")
515    );
516    ($e:expr) => ({
517        ValueSetUtf8::new($e)
518    });
519    ($e:expr, $($item:expr),*) => ({
520        let mut x = ValueSetUtf8::new($e);
521        $(assert!(x.push($item));)*
522        x
523    });
524}
525
526#[allow(unused_macros)]
527#[macro_export]
528/// Takes EntryClass objects and makes a ValueSetIutf8
529macro_rules! vs_iutf8 {
530    () => (
531        compile_error!("ValueSetIutf8 needs at least 1 element")
532    );
533    ($e:expr) => ({
534        ValueSetIutf8::new($e)
535    });
536    ($e:expr, $($item:expr),*) => ({
537        let mut x = ValueSetIutf8::new($e);
538        $(assert!(x.push($item));)*
539        x
540    });
541}
542
543#[allow(unused_macros)]
544#[macro_export]
545macro_rules! vs_iname {
546    () => (
547        compile_error!("ValueSetIname needs at least 1 element")
548    );
549    ($e:expr) => ({
550        ValueSetIname::new($e)
551    });
552    ($e:expr, $($item:expr),*) => ({
553        let mut x = ValueSetIname::new($e);
554        $(assert!(x.push($item));)*
555        x
556    });
557}
558
559#[allow(unused_macros)]
560#[macro_export]
561macro_rules! vs_uuid {
562    () => (
563        compile_error!("ValueSetUuid needs at least 1 element")
564    );
565    ($e:expr) => ({
566        ValueSetUuid::new($e)
567    });
568    ($e:expr, $($item:expr),*) => ({
569        let mut x = ValueSetUuid::new($e);
570        $(assert!(x.push($item));)*
571        x
572    });
573}
574
575#[allow(unused_macros)]
576#[macro_export]
577macro_rules! vs_refer {
578    () => (
579        compile_error!("ValueSetRefer needs at least 1 element")
580    );
581    ($e:expr) => ({
582        ValueSetRefer::new($e)
583    });
584    ($e:expr, $($item:expr),*) => ({
585        let mut x = ValueSetRefer::new($e);
586        $(assert!(x.push($item));)*
587        x
588    });
589}
590
591#[allow(unused_macros)]
592#[macro_export]
593macro_rules! vs_bool {
594    () => (
595        compile_error!("ValueSetBool needs at least 1 element")
596    );
597    ($e:expr) => ({
598        ValueSetBool::new($e)
599    });
600    ($e:expr, $($item:expr),*) => ({
601        let mut x = ValueSetBool::new($e);
602        $(assert!(x.push($item));)*
603        x
604    });
605}
606
607#[allow(unused_macros)]
608#[macro_export]
609macro_rules! vs_syntax {
610    () => (
611        compile_error!("ValueSetSyntax needs at least 1 element")
612    );
613    ($e:expr) => ({
614        ValueSetSyntax::new($e)
615    });
616    ($e:expr, $($item:expr),*) => ({
617        let mut x = ValueSetSyntax::new($e);
618        $(assert!(x.push($item));)*
619        x
620    });
621}
622
623#[allow(unused_macros)]
624#[macro_export]
625macro_rules! vs_cid {
626    () => (
627        compile_error!("ValueSetCid needs at least 1 element")
628    );
629    ($e:expr) => ({
630        ValueSetCid::new($e)
631    });
632    ($e:expr, $($item:expr),*) => ({
633        let mut x = ValueSetCid::new($e);
634        $(assert!(x.push($item));)*
635        x
636    });
637}
638
639macro_rules! str_concat {
640    ($str_iter:expr, $join_char:expr) => {{
641        use itertools::Itertools;
642        $str_iter.iter().join($join_char)
643    }};
644}