kanidm/server/lib/src/macros.rs

676 lines
16 KiB
Rust
Raw Normal View History

2022-11-02 10:46:09 +01:00
#[cfg(test)]
macro_rules! setup_test {
2021-09-21 04:42:00 +02:00
() => {{
2022-08-09 05:07:06 +02:00
let _ = sketching::test_init();
// Create an in memory BE
2021-09-21 04:42:00 +02:00
let schema_outer = Schema::new().expect("Failed to init schema");
let idxmeta = {
let schema_txn = schema_outer.write_blocking();
schema_txn.reload_idxmeta()
};
let be = Backend::new(BackendConfig::new_test("main"), idxmeta, false)
.expect("Failed to init BE");
let qs = QueryServer::new(be, schema_outer, "example.com".to_string())
.expect("Failed to setup Query Server");
2023-03-27 03:38:09 +02:00
tokio::runtime::Builder::new_current_thread()
.enable_all()
.build()
.unwrap()
.block_on(qs.initialise_helper(duration_from_epoch_now()))
.expect("init failed!");
qs
}};
(
$preload_entries:expr
) => {{
use crate::prelude::duration_from_epoch_now;
2022-10-01 08:08:51 +02:00
2022-08-09 05:07:06 +02:00
let _ = sketching::test_init();
// Create an in memory BE
2021-09-21 04:42:00 +02:00
let schema_outer = Schema::new().expect("Failed to init schema");
let idxmeta = {
2022-10-24 01:50:31 +02:00
let schema_txn = schema_outer.write();
schema_txn.reload_idxmeta()
};
let be = Backend::new(BackendConfig::new_test("main"), idxmeta, false)
.expect("Failed to init BE");
let qs = QueryServer::new(be, schema_outer, "example.com".to_string())
.expect("Failed to setup Query Server");
2023-03-27 03:38:09 +02:00
tokio::runtime::Builder::new_current_thread()
.enable_all()
.build()
.unwrap()
.block_on(qs.initialise_helper(duration_from_epoch_now()))
.expect("init failed!");
if !$preload_entries.is_empty() {
2023-03-27 03:38:09 +02:00
let mut qs_write = tokio::runtime::Builder::new_current_thread()
.enable_all()
.build()
.unwrap()
.block_on(qs.write(duration_from_epoch_now()));
qs_write
2021-09-21 04:42:00 +02:00
.internal_create($preload_entries)
.expect("Failed to preload entries");
2021-09-21 04:42:00 +02:00
assert!(qs_write.commit().is_ok());
}
qs
}};
}
// Test helpers for all plugins.
// #[macro_export]
#[cfg(test)]
macro_rules! run_create_test {
(
$expect:expr,
$preload_entries:ident,
$create_entries:ident,
$internal:expr,
$check:expr
) => {{
use crate::be::{Backend, BackendConfig};
use crate::event::CreateEvent;
2021-04-25 03:35:02 +02:00
use crate::prelude::*;
use crate::schema::Schema;
2022-10-01 08:08:51 +02:00
let qs = setup_test!($preload_entries);
let ce = match $internal {
None => CreateEvent::new_internal($create_entries.clone()),
2022-11-13 23:40:05 +01:00
Some(ent) => CreateEvent::new_impersonate_identity(
Identity::from_impersonate_entry_readwrite(ent),
$create_entries.clone(),
),
2022-10-01 08:08:51 +02:00
};
{
2023-03-27 03:38:09 +02:00
let mut qs_write = tokio::runtime::Builder::new_current_thread()
.enable_all()
.build()
.unwrap()
.block_on(qs.write(duration_from_epoch_now()));
2022-10-01 08:08:51 +02:00
let r = qs_write.create(&ce);
trace!("test result: {:?}", r);
assert!(r == $expect);
$check(&mut qs_write);
2022-10-01 08:08:51 +02:00
match r {
Ok(_) => {
qs_write.commit().expect("commit failure!");
}
Err(e) => {
admin_error!("Rolling back => {:?}", e);
}
}
2022-10-01 08:08:51 +02:00
}
// Make sure there are no errors.
trace!("starting verification");
2023-03-27 03:38:09 +02:00
let ver = tokio::runtime::Builder::new_current_thread()
.enable_all()
.build()
.unwrap()
.block_on(qs.verify());
2022-10-01 08:08:51 +02:00
trace!("verification -> {:?}", ver);
assert!(ver.len() == 0);
}};
}
#[cfg(test)]
/// Runs a test with preloaded entries, then modifies based on a filter/list, then runs a given check
macro_rules! run_modify_test {
(
// expected outcome
$expect:expr,
// things to preload
$preload_entries:ident,
// the targets to modify
$modify_filter:expr,
// changes to make
$modify_list:expr,
$internal:expr,
// something to run after the preload but before the modification, takes `&mut qs_write`
2022-07-07 05:28:36 +02:00
$pre_hook:expr,
// the result we expect
$check:expr
) => {{
use crate::be::{Backend, BackendConfig};
use crate::event::ModifyEvent;
2021-04-25 03:35:02 +02:00
use crate::prelude::*;
use crate::schema::Schema;
2022-10-01 08:08:51 +02:00
let qs = setup_test!($preload_entries);
2022-10-01 08:08:51 +02:00
{
2023-03-27 03:38:09 +02:00
let mut qs_write = tokio::runtime::Builder::new_current_thread()
.enable_all()
.build()
.unwrap()
.block_on(qs.write(duration_from_epoch_now()));
2022-10-24 01:50:31 +02:00
$pre_hook(&mut qs_write);
2022-10-01 08:08:51 +02:00
qs_write.commit().expect("commit failure!");
}
let me = match $internal {
2023-07-31 04:20:52 +02:00
None => ModifyEvent::new_internal_invalid($modify_filter, $modify_list),
Some(ent) => ModifyEvent::new_impersonate_entry(ent, $modify_filter, $modify_list),
2022-10-01 08:08:51 +02:00
};
2022-07-07 05:28:36 +02:00
2022-10-01 08:08:51 +02:00
{
2023-03-27 03:38:09 +02:00
let mut qs_write = tokio::runtime::Builder::new_current_thread()
.enable_all()
.build()
.unwrap()
.block_on(qs.write(duration_from_epoch_now()));
2022-10-01 08:08:51 +02:00
let r = qs_write.modify(&me);
$check(&mut qs_write);
2022-10-01 08:08:51 +02:00
trace!("test result: {:?}", r);
assert!(r == $expect);
match r {
Ok(_) => {
qs_write.commit().expect("commit failure!");
}
Err(e) => {
admin_error!("Rolling back => {:?}", e);
}
}
2022-10-01 08:08:51 +02:00
}
// Make sure there are no errors.
trace!("starting verification");
2023-03-27 03:38:09 +02:00
let ver = tokio::runtime::Builder::new_current_thread()
.enable_all()
.build()
.unwrap()
.block_on(qs.verify());
2022-10-01 08:08:51 +02:00
trace!("verification -> {:?}", ver);
assert!(ver.len() == 0);
}};
}
// #[macro_export]
#[cfg(test)]
macro_rules! run_delete_test {
(
$expect:expr,
$preload_entries:ident,
$delete_filter:expr,
$internal:expr,
$check:expr
) => {{
use crate::be::{Backend, BackendConfig};
use crate::event::DeleteEvent;
2021-04-25 03:35:02 +02:00
use crate::prelude::*;
use crate::schema::Schema;
2022-10-01 08:08:51 +02:00
let qs = setup_test!($preload_entries);
let de = match $internal {
2023-07-31 04:20:52 +02:00
Some(ent) => DeleteEvent::new_impersonate_entry(ent, $delete_filter.clone()),
None => DeleteEvent::new_internal_invalid($delete_filter.clone()),
2022-10-01 08:08:51 +02:00
};
{
2023-03-27 03:38:09 +02:00
let mut qs_write = tokio::runtime::Builder::new_current_thread()
.enable_all()
.build()
.unwrap()
.block_on(qs.write(duration_from_epoch_now()));
2022-10-01 08:08:51 +02:00
let r = qs_write.delete(&de);
trace!("test result: {:?}", r);
2022-10-24 01:50:31 +02:00
$check(&mut qs_write);
2022-10-01 08:08:51 +02:00
assert!(r == $expect);
match r {
Ok(_) => {
qs_write.commit().expect("commit failure!");
}
Err(e) => {
admin_error!("Rolling back => {:?}", e);
}
}
2022-10-01 08:08:51 +02:00
}
// Make sure there are no errors.
trace!("starting verification");
2023-03-27 03:38:09 +02:00
let ver = tokio::runtime::Builder::new_current_thread()
.enable_all()
.build()
.unwrap()
.block_on(qs.verify());
2022-10-01 08:08:51 +02:00
trace!("verification -> {:?}", ver);
assert!(ver.len() == 0);
}};
}
#[allow(unused_macros)]
#[macro_export]
macro_rules! modlist {
(
$vs:expr
) => {{
let s: Box<[Modify]> = Box::new($vs);
ModifyList::new_list(s.into_vec())
}};
}
#[allow(unused_macros)]
#[macro_export]
macro_rules! f_and {
(
$vs:expr
) => {{
let s: Box<[FC]> = Box::new($vs);
f_and(s.into_vec())
}};
}
#[allow(unused_macros)]
#[macro_export]
macro_rules! f_inc {
(
$vs:expr
) => {{
let s: Box<[FC]> = Box::new($vs);
f_inc(s.into_vec())
}};
}
#[allow(unused_macros)]
#[macro_export]
macro_rules! f_or {
(
$vs:expr
) => {{
let s: Box<[FC]> = Box::new($vs);
f_or(s.into_vec())
}};
}
#[allow(unused_macros)]
#[macro_export]
macro_rules! filter {
(
$fc:expr
) => {{
Filter::new_ignore_hidden($fc)
}};
}
#[allow(unused_macros)]
#[macro_export]
macro_rules! filter_rec {
(
$fc:expr
) => {{
Filter::new_recycled($fc)
}};
}
#[allow(unused_macros)]
#[macro_export]
macro_rules! filter_all {
(
$fc:expr
) => {{
Filter::new($fc)
}};
}
#[macro_export]
/// Build a filter which matches class == input
macro_rules! match_class_filter {
($class:expr) => {
ProtoFilter::Eq(Attribute::Class.to_string(), $class.to_string())
};
}
#[cfg(test)]
#[allow(unused_macros)]
#[macro_export]
macro_rules! filter_valid {
(
$fc:expr
) => {{
let f: Filter<FilterInvalid> = Filter::new($fc);
// Create a resolved filter, via the most unsafe means possible!
f.into_valid()
}};
}
#[cfg(test)]
#[allow(unused_macros)]
#[macro_export]
macro_rules! filter_resolved {
(
$fc:expr
) => {{
let f: Filter<FilterInvalid> = Filter::new($fc);
// Create a resolved filter, via the most unsafe means possible!
f.into_valid_resolved()
}};
}
#[cfg(test)]
#[allow(unused_macros)]
#[macro_export]
macro_rules! pvalue_utf8 {
(
$v:expr
) => {{
PartialValue::new_utf8(v.to_string())
}};
}
#[cfg(test)]
#[allow(unused_macros)]
#[macro_export]
macro_rules! pvalue_iutf8 {
(
$v:expr
) => {{
PartialValue::new_iutf8(v.to_string())
}};
}
#[allow(unused_macros)]
#[macro_export]
macro_rules! btreeset {
() => (
compile_error!("BTreeSet needs at least 1 element")
);
($e:expr) => ({
use std::collections::BTreeSet;
let mut x: BTreeSet<_> = BTreeSet::new();
assert!(x.insert($e));
x
});
($e:expr,) => ({
btreeset!($e)
});
($e:expr, $($item:expr),*) => ({
use std::collections::BTreeSet;
let mut x: BTreeSet<_> = BTreeSet::new();
assert!(x.insert($e));
$(assert!(x.insert($item));)*
x
});
}
#[allow(unused_macros)]
#[macro_export]
macro_rules! smolset {
() => (
compile_error!("SmolSet needs at least 1 element")
);
($e:expr) => ({
use smolset::SmolSet;
let mut x: SmolSet<_> = SmolSet::new();
assert!(x.insert($e));
x
});
($e:expr,) => ({
smolset!($e)
});
($e:expr, $($item:expr),*) => ({
use smolset::SmolSet;
let mut x: SmolSet<_> = SmolSet::new();
assert!(x.insert($e));
$(assert!(x.insert($item));)*
x
});
}
#[allow(unused_macros)]
#[macro_export]
macro_rules! btreemap {
() => (
compile_error!("BTreeSet needs at least 1 element")
);
($e:expr) => ({
use std::collections::BTreeMap;
let mut x: BTreeMap<_, _> = BTreeMap::new();
let (a, b) = $e;
x.insert(a, b);
x
});
($e:expr,) => ({
btreemap!($e)
});
($e:expr, $($item:expr),*) => ({
use std::collections::BTreeMap;
let mut x: BTreeMap<_, _> = BTreeMap::new();
let (a, b) = $e;
x.insert(a, b);
$(
let (a, b) = $item;
x.insert(a, b);
)*
x
});
}
#[allow(unused_macros)]
#[macro_export]
macro_rules! entry_init {
() => ({
let e1: Entry<EntryInit, EntryNew> = Entry::new();
e1
});
($ava:expr) => ({
let mut e1: Entry<EntryInit, EntryNew> = Entry::new();
e1.add_ava($ava.0, $ava.1);
e1
});
($ava:expr, $($item:expr),*) => ({
let mut e1: Entry<EntryInit, EntryNew> = Entry::new();
e1.add_ava($ava.0, $ava.1);
$(e1.add_ava($item.0, $item.1);)*
e1
});
}
#[allow(unused_macros)]
#[macro_export]
macro_rules! mergesets {
(
$a:expr,
$b:expr
) => {{
$b.iter().for_each(|v| {
$a.insert(v.clone());
});
Ok(())
}};
}
#[allow(unused_macros)]
#[macro_export]
macro_rules! mergemaps {
(
$a:expr,
$b:expr
) => {{
$b.iter().for_each(|(k, v)| {
// I think to be consistent, we need the content of b to always
// the content of a
// if !$a.contains_key(k) {
$a.insert(k.clone(), v.clone());
// }
});
Ok(())
}};
}
#[allow(unused_macros)]
#[macro_export]
macro_rules! vs_utf8 {
() => (
compile_error!("ValueSetUtf8 needs at least 1 element")
);
($e:expr) => ({
ValueSetUtf8::new($e)
});
($e:expr, $($item:expr),*) => ({
let mut x = ValueSetUtf8::new($e);
$(assert!(x.push($item));)*
x
});
}
#[allow(unused_macros)]
#[macro_export]
/// Takes EntryClass objects and makes a VaueSetIutf8
macro_rules! vs_iutf8 {
() => (
compile_error!("ValueSetIutf8 needs at least 1 element")
);
($e:expr) => ({
ValueSetIutf8::new($e)
});
($e:expr, $($item:expr),*) => ({
let mut x = ValueSetIutf8::new($e);
$(assert!(x.push($item));)*
x
});
}
#[allow(unused_macros)]
#[macro_export]
macro_rules! vs_iname {
() => (
compile_error!("ValueSetIname needs at least 1 element")
);
($e:expr) => ({
ValueSetIname::new($e)
});
($e:expr, $($item:expr),*) => ({
let mut x = ValueSetIname::new($e);
$(assert!(x.push($item));)*
x
});
}
#[allow(unused_macros)]
#[macro_export]
macro_rules! vs_uuid {
() => (
compile_error!("ValueSetUuid needs at least 1 element")
);
($e:expr) => ({
ValueSetUuid::new($e)
});
($e:expr, $($item:expr),*) => ({
let mut x = ValueSetUuid::new($e);
$(assert!(x.push($item));)*
x
});
}
#[allow(unused_macros)]
#[macro_export]
macro_rules! vs_refer {
() => (
compile_error!("ValueSetRefer needs at least 1 element")
);
($e:expr) => ({
ValueSetRefer::new($e)
});
($e:expr, $($item:expr),*) => ({
let mut x = ValueSetRefer::new($e);
$(assert!(x.push($item));)*
x
});
}
#[allow(unused_macros)]
#[macro_export]
macro_rules! vs_bool {
() => (
compile_error!("ValueSetBool needs at least 1 element")
);
($e:expr) => ({
ValueSetBool::new($e)
});
($e:expr, $($item:expr),*) => ({
let mut x = ValueSetBool::new($e);
$(assert!(x.push($item));)*
x
});
}
#[allow(unused_macros)]
#[macro_export]
macro_rules! vs_syntax {
() => (
compile_error!("ValueSetSyntax needs at least 1 element")
);
($e:expr) => ({
ValueSetSyntax::new($e)
});
($e:expr, $($item:expr),*) => ({
let mut x = ValueSetSyntax::new($e);
$(assert!(x.push($item));)*
x
});
}
#[allow(unused_macros)]
#[macro_export]
macro_rules! vs_index {
() => (
compile_error!("ValueSetIndex needs at least 1 element")
);
($e:expr) => ({
ValueSetIndex::new($e)
});
($e:expr, $($item:expr),*) => ({
let mut x = ValueSetIndex::new($e);
$(assert!(x.push($item));)*
x
});
}
#[allow(unused_macros)]
#[macro_export]
macro_rules! vs_cid {
() => (
compile_error!("ValueSetCid needs at least 1 element")
);
($e:expr) => ({
ValueSetCid::new($e)
});
($e:expr, $($item:expr),*) => ({
let mut x = ValueSetCid::new($e);
$(assert!(x.push($item));)*
x
});
}
2022-10-05 01:48:48 +02:00
macro_rules! limmediate_warning {
($($arg:tt)*) => ({
eprint!($($arg)*)
})
}
macro_rules! str_concat {
($str_iter:expr, $join_char:expr) => {{
// Sub 1 here because we need N minus 1 join chars
let max_join_chars: usize = $str_iter.len() - 1;
let data_len: usize = $str_iter
.iter()
.map(|s| s.len())
.fold(max_join_chars, |acc, x| acc + x);
let mut joined = String::with_capacity(data_len);
for (i, value) in $str_iter.iter().enumerate() {
joined.push_str(value);
if i < max_join_chars {
joined.push($join_char);
}
}
joined
}};
}