vrl/compiler/
test_util.rs1#[macro_export]
2macro_rules! test_type_def {
3 ($($name:ident { expr: $expr:expr_2021, want: $def:expr_2021, })+) => {
4 mod type_def {
5 use super::*;
6
7 $(
8 #[test]
9 fn $name() {
10 let mut state = $crate::compiler::state::TypeState::default();
11 #[allow(clippy::redundant_closure_call)]
12 let expression = Box::new($expr(&mut state));
13
14 assert_eq!(expression.type_def(&state), $def);
15 }
16 )+
17 }
18 };
19}
20
21#[macro_export]
22macro_rules! func_args {
23 () => (
24 ::std::collections::HashMap::<&'static str, $crate::value::Value>::default()
25 );
26 ($($k:tt: $v:expr_2021),+ $(,)?) => {
27 vec![$((stringify!($k), $v.into())),+]
28 .into_iter()
29 .collect::<::std::collections::HashMap<&'static str, $crate::value::Value>>()
30 };
31}
32
33#[macro_export]
34macro_rules! bench_function {
35 ($name:tt => $func:path; $($case:ident { args: $args:expr_2021, want: $(Ok($ok:expr_2021))? $(Err($err:expr_2021))? $(,)* })+) => {
36 fn $name(c: &mut criterion::Criterion) {
37 let mut group = c.benchmark_group(&format!("vrl_stdlib/functions/{}", stringify!($name)));
38 group.throughput(criterion::Throughput::Elements(1));
39 $(
40 group.bench_function(&stringify!($case).to_string(), |b| {
41 let mut state = $crate::compiler::state::TypeState::default();
42
43 let (expression, want) = $crate::__prep_bench_or_test!($func, &state, $args, $(Ok($crate::value::Value::from($ok)))? $(Err($err.to_owned()))?);
44 let expression = expression.unwrap();
45 let mut runtime_state = $crate::compiler::state::RuntimeState::default();
46 let mut target: $crate::value::Value = ::std::collections::BTreeMap::default().into();
47 let tz = $crate::compiler::TimeZone::Named(chrono_tz::Tz::UTC);
48 let mut ctx = $crate::compiler::Context::new(&mut target, &mut runtime_state, &tz);
49
50 b.iter(|| {
51 let got = expression.resolve(&mut ctx).map_err(|e| e.to_string());
52 debug_assert_eq!(got, want);
53 got
54 })
55 });
56 )+
57 }
58 };
59}
60
61#[macro_export]
62macro_rules! test_function {
63
64 ($name:tt => $func:path; $($case:ident { args: $args:expr_2021, want: $(Ok($ok:expr_2021))? $(Err($err:expr_2021))?, tdef: $tdef:expr_2021, $(,)* })+) => {
65 test_function!($name => $func; before_each => {} $($case { args: $args, want: $(Ok($ok))? $(Err($err))?, tdef: $tdef, tz: $crate::compiler::TimeZone::Named(chrono_tz::Tz::UTC), })+);
66 };
67
68 ($name:tt => $func:path; $($case:ident { args: $args:expr_2021, want: $(Ok($ok:expr_2021))? $(Err($err:expr_2021))?, tdef: $tdef:expr_2021, tz: $tz:expr_2021, $(,)* })+) => {
69 test_function!($name => $func; before_each => {} $($case { args: $args, want: $(Ok($ok))? $(Err($err))?, tdef: $tdef, tz: $tz, })+);
70 };
71
72 ($name:tt => $func:path; before_each => $before:block $($case:ident { args: $args:expr_2021, want: $(Ok($ok:expr_2021))? $(Err($err:expr_2021))?, tdef: $tdef:expr_2021, $(,)* })+) => {
73 test_function!($name => $func; before_each => $before $($case { args: $args, want: $(Ok($ok))? $(Err($err))?, tdef: $tdef, tz: $crate::compiler::TimeZone::Named(chrono_tz::Tz::UTC), })+);
74 };
75
76 ($name:tt => $func:path; before_each => $before:block $($case:ident { args: $args:expr_2021, want: $(Ok($ok:expr_2021))? $(Err($err:expr_2021))?, tdef: $tdef:expr_2021, tz: $tz:expr_2021, $(,)* })+) => {
77 paste::paste!{$(
78 #[test]
79 fn [<$name _ $case:snake:lower>]() {
80 $before
81 let state = $crate::compiler::state::TypeState::default();
82
83 let (expression, want) = $crate::__prep_bench_or_test!($func, &state, $args, $(Ok($crate::value::Value::from($ok)))? $(Err($err.to_owned()))?);
84 match expression {
85 Ok(expression) => {
86 let mut runtime_state = $crate::compiler::state::RuntimeState::default();
87 let mut target: $crate::value::Value = ::std::collections::BTreeMap::default().into();
88 let tz = $tz;
89 let mut ctx = $crate::compiler::Context::new(&mut target, &mut runtime_state, &tz);
90
91 let got_value = expression.resolve(&mut ctx)
92 .map_err(|e| format!("{:#}", anyhow::anyhow!(e)));
93
94 assert!(got_value == want, "assertion failed for `{}` case:\n got: {:?}\n wanted: {:?}", stringify!($case), got_value, want);
95 let got_tdef = expression.type_def(&state);
96 assert_eq!(got_tdef, $tdef);
97 }
98 err@Err(_) => {
99 assert_eq!(err
101 .map(|_| $crate::value::Value::Null)
104 .map_err(|e| format!("{:#}", e.message())), want);
105 }
106 }
107 }
108 )+}
109 };
110}
111
112#[doc(hidden)]
113#[macro_export]
114macro_rules! __prep_bench_or_test {
115 ($func:path, $state:expr_2021, $args:expr_2021, $want:expr_2021) => {{
116 let config = $crate::compiler::CompileConfig::default();
117 (
118 $func.compile(
119 $state,
120 &mut $crate::compiler::function::FunctionCompileContext::new(
121 $crate::diagnostic::Span::new(0, 0),
122 config,
123 ),
124 $args.into(),
125 ),
126 $want,
127 )
128 }};
129}
130
131#[macro_export]
132macro_rules! type_def {
133 (unknown) => {
134 TypeDef::any()
135 };
136
137 (bytes) => {
138 TypeDef::bytes()
139 };
140
141 (object {$(unknown => $unknown:expr_2021,)? $($key:literal => $value:expr_2021,)+ }) => {{
142 #[allow(unused_mut)]
143 let mut v = $crate::value::kind::Collection::from(::std::collections::BTreeMap::from([$(($key.into(), $value.into()),)+]));
144 $(v.set_unknown($crate::value::Kind::from($unknown));)?
145
146 TypeDef::object(v)
147 }};
148
149 (array [ $($value:expr_2021,)+ ]) => {{
150 $(let v = $crate::value::kind::Collection::from_unknown($crate::value::Kind::from($value));)+
151
152 TypeDef::array(v)
153 }};
154
155 (array { $(unknown => $unknown:expr_2021,)? $($idx:literal => $value:expr_2021,)+ }) => {{
156 let mut v = $crate::value::kind::Collection::from(::std::collections::BTreeMap::from([$(($idx.into(), $value.into()),)+]));
157 $(v.set_unknown($crate::value::Kind::from($unknown));)?
158
159 TypeDef::array(v)
160 }};
161
162 (array) => {
163 TypeDef::array($crate::value::kind::Collection::any())
164 };
165}