vrl/stdlib/
match_datadog_query.rs

1use crate::compiler::prelude::*;
2use crate::datadog_filter::{
3    Filter, Matcher, Resolver, Run, build_matcher,
4    regex::{wildcard_regex, word_regex},
5};
6use crate::datadog_search_syntax::{Comparison, ComparisonValue, Field, ParseError, QueryNode};
7use crate::owned_value_path;
8use crate::path::{OwnedValuePath, PathParseError, parse_value_path};
9use crate::prelude::function::Error::InvalidArgument;
10use std::borrow::Cow;
11
12const QUERY_KEYWORD: &str = "query";
13
14#[derive(Clone, Copy, Debug)]
15pub struct MatchDatadogQuery;
16
17impl Function for MatchDatadogQuery {
18    fn identifier(&self) -> &'static str {
19        "match_datadog_query"
20    }
21
22    fn usage(&self) -> &'static str {
23        "Matches an object against a [Datadog Search Syntax](https://docs.datadoghq.com/logs/explorer/search_syntax/) query."
24    }
25
26    fn category(&self) -> &'static str {
27        Category::Object.as_ref()
28    }
29
30    fn return_kind(&self) -> u16 {
31        kind::BOOLEAN
32    }
33
34    fn examples(&self) -> &'static [Example] {
35        &[
36            example! {
37                title: "OR query",
38                source: r#"match_datadog_query({"message": "contains this and that"}, "this OR that")"#,
39                result: Ok("true"),
40            },
41            example! {
42                title: "AND query",
43                source: r#"match_datadog_query({"message": "contains only this"}, "this AND that")"#,
44                result: Ok("false"),
45            },
46            example! {
47                title: "Attribute wildcard",
48                source: r#"match_datadog_query({"name": "foobar"}, "@name:foo*")"#,
49                result: Ok("true"),
50            },
51            example! {
52                title: "Tag range",
53                source: r#"match_datadog_query({"tags": ["a:x", "b:y", "c:z"]}, s'b:["x" TO "z"]')"#,
54                result: Ok("true"),
55            },
56        ]
57    }
58
59    fn compile(
60        &self,
61        state: &state::TypeState,
62        _ctx: &mut FunctionCompileContext,
63        arguments: ArgumentList,
64    ) -> Compiled {
65        let value = arguments.required("value");
66        let query_value = arguments.required_literal(QUERY_KEYWORD, state)?;
67
68        // Query should always be a string.
69        let query = query_value
70            .try_bytes_utf8_lossy()
71            .expect("datadog search query should be a UTF8 string");
72
73        // Compile the Datadog search query to AST.
74        let node: QueryNode = query.parse().map_err(|e: ParseError| {
75            Box::new(ExpressionError::from(e.to_string())) as Box<dyn DiagnosticMessage>
76        })?;
77
78        // Build the matcher function that accepts a VRL event value. This will parse the `node`
79        // at boot-time and return a boxed func that contains just the logic required to match a
80        // VRL `Value` against the Datadog Search Syntax literal.
81        let filter = build_matcher(&node, &VrlFilter).map_err(|_| {
82            Box::new(InvalidArgument {
83                keyword: QUERY_KEYWORD,
84                value: query_value,
85                error: "failed to build matcher",
86            }) as Box<dyn DiagnosticMessage>
87        })?;
88
89        Ok(MatchDatadogQueryFn { value, filter }.as_expr())
90    }
91
92    fn parameters(&self) -> &'static [Parameter] {
93        const PARAMETERS: &[Parameter] = &[
94            Parameter::required("value", kind::OBJECT, "The object."),
95            Parameter::required("query", kind::BYTES, "The Datadog Search Syntax query."),
96        ];
97        PARAMETERS
98    }
99}
100
101#[derive(Debug, Clone)]
102struct MatchDatadogQueryFn {
103    value: Box<dyn Expression>,
104    filter: Box<dyn Matcher<Value>>,
105}
106
107impl FunctionExpression for MatchDatadogQueryFn {
108    fn resolve(&self, ctx: &mut Context) -> Resolved {
109        let value = self.value.resolve(ctx)?;
110
111        // Provide the current VRL event `Value` to the matcher function to determine
112        // whether the data matches the given Datadog Search syntax literal.
113        Ok(self.filter.run(&value).into())
114    }
115
116    fn type_def(&self, _: &state::TypeState) -> TypeDef {
117        type_def()
118    }
119}
120
121fn type_def() -> TypeDef {
122    TypeDef::boolean().infallible()
123}
124
125#[derive(Default, Clone)]
126struct VrlFilter;
127
128/// Implements `Resolver`, which translates Datadog Search Syntax literal names into
129/// fields.
130impl Resolver for VrlFilter {}
131
132/// Implements `Filter`, which provides methods for matching against (in this case) VRL values.
133impl Filter<Value> for VrlFilter {
134    fn exists(&self, field: Field) -> Result<Box<dyn Matcher<Value>>, PathParseError> {
135        let buf = lookup_field(&field)?;
136
137        Ok(match field {
138            // Tags need to check the element value.
139            Field::Tag(tag) => {
140                let starts_with = format!("{tag}:");
141
142                resolve_value(
143                    buf,
144                    Run::boxed(move |value| match value {
145                        Value::Array(v) => v.iter().any(|v| {
146                            let str_value = string_value(v);
147
148                            // The tag matches using either 'key' or 'key:value' syntax.
149                            str_value == tag || str_value.starts_with(&starts_with)
150                        }),
151                        _ => false,
152                    }),
153                )
154            }
155            // Literal field 'tags' needs to be compared by key.
156            Field::Reserved(f) if f == "tags" => resolve_value(
157                buf,
158                Run::boxed(|value| match value {
159                    Value::Array(v) => v.iter().any(|v| v == value),
160                    _ => false,
161                }),
162            ),
163
164            // Other field types have already resolved at this point, so just return true.
165            _ => resolve_value(buf, Box::new(true)),
166        })
167    }
168
169    fn equals(
170        &self,
171        field: Field,
172        to_match: &str,
173    ) -> Result<Box<dyn Matcher<Value>>, PathParseError> {
174        let buf = lookup_field(&field)?;
175
176        Ok(match field {
177            // Default fields are compared by word boundary.
178            Field::Default(_) => {
179                let re = word_regex(to_match);
180
181                resolve_value(
182                    buf,
183                    Run::boxed(move |value| match value {
184                        Value::Bytes(val) => re.is_match(&String::from_utf8_lossy(val)),
185                        _ => false,
186                    }),
187                )
188            }
189            // A literal "tags" field should match by key.
190            Field::Reserved(f) if f == "tags" => {
191                let to_match = to_match.to_owned();
192
193                resolve_value(
194                    buf,
195                    Run::boxed(move |value| match value {
196                        Value::Array(v) => {
197                            v.contains(&Value::Bytes(Bytes::copy_from_slice(to_match.as_bytes())))
198                        }
199                        _ => false,
200                    }),
201                )
202            }
203            // Individual tags are compared by element key:value.
204            Field::Tag(tag) => {
205                let value_bytes = Value::Bytes(format!("{tag}:{to_match}").into());
206
207                resolve_value(
208                    buf,
209                    Run::boxed(move |value| match value {
210                        Value::Array(v) => v.contains(&value_bytes),
211                        _ => false,
212                    }),
213                )
214            }
215            // Everything else is matched by string equality.
216            _ => {
217                let to_match = to_match.to_owned();
218
219                resolve_value(
220                    buf,
221                    Run::boxed(move |value| string_value(value) == to_match),
222                )
223            }
224        })
225    }
226
227    fn prefix(
228        &self,
229        field: Field,
230        prefix: &str,
231    ) -> Result<Box<dyn Matcher<Value>>, PathParseError> {
232        let buf = lookup_field(&field)?;
233
234        Ok(match field {
235            // Default fields are matched by word boundary.
236            Field::Default(_) => {
237                let re = word_regex(&format!("{prefix}*"));
238
239                resolve_value(
240                    buf,
241                    Run::boxed(move |value| re.is_match(&string_value(value))),
242                )
243            }
244            // Tags are recursed until a match is found.
245            Field::Tag(tag) => {
246                let starts_with = format!("{tag}:{prefix}");
247
248                resolve_value(
249                    buf,
250                    Run::boxed(move |value| match value {
251                        Value::Array(v) => {
252                            v.iter().any(|v| string_value(v).starts_with(&starts_with))
253                        }
254                        _ => false,
255                    }),
256                )
257            }
258            // All other field types are compared by complete value.
259            _ => {
260                let prefix = prefix.to_owned();
261
262                resolve_value(
263                    buf,
264                    Run::boxed(move |value| string_value(value).starts_with(&prefix)),
265                )
266            }
267        })
268    }
269
270    fn wildcard(
271        &self,
272        field: Field,
273        wildcard: &str,
274    ) -> Result<Box<dyn Matcher<Value>>, PathParseError> {
275        let buf = lookup_field(&field)?;
276
277        Ok(match field {
278            Field::Default(_) => {
279                let re = word_regex(wildcard);
280
281                resolve_value(
282                    buf,
283                    Run::boxed(move |value| re.is_match(&string_value(value))),
284                )
285            }
286            Field::Tag(tag) => {
287                let re = wildcard_regex(&format!("{tag}:{wildcard}"));
288
289                resolve_value(
290                    buf,
291                    Run::boxed(move |value| match value {
292                        Value::Array(v) => v.iter().any(|v| re.is_match(&string_value(v))),
293                        _ => false,
294                    }),
295                )
296            }
297            _ => {
298                let re = wildcard_regex(wildcard);
299
300                resolve_value(
301                    buf,
302                    Run::boxed(move |value| re.is_match(&string_value(value))),
303                )
304            }
305        })
306    }
307
308    #[allow(clippy::cast_precision_loss)] //TODO evaluate removal options
309    fn compare(
310        &self,
311        field: Field,
312        comparator: Comparison,
313        comparison_value: ComparisonValue,
314    ) -> Result<Box<dyn Matcher<Value>>, PathParseError> {
315        let buf = lookup_field(&field)?;
316
317        let rhs = Cow::from(comparison_value.to_string());
318
319        Ok(match field {
320            // Attributes are compared numerically if the value is numeric, or as strings otherwise.
321            Field::Attribute(_) => {
322                resolve_value(
323                    buf,
324                    Run::boxed(move |value| match (value, &comparison_value) {
325                        // Integers.
326                        (Value::Integer(lhs), ComparisonValue::Integer(rhs)) => match comparator {
327                            Comparison::Lt => *lhs < *rhs,
328                            Comparison::Lte => *lhs <= *rhs,
329                            Comparison::Gt => *lhs > *rhs,
330                            Comparison::Gte => *lhs >= *rhs,
331                        },
332                        // Integer value - Float boundary
333                        (Value::Integer(lhs), ComparisonValue::Float(rhs)) => match comparator {
334                            Comparison::Lt => (*lhs as f64) < *rhs,
335                            Comparison::Lte => *lhs as f64 <= *rhs,
336                            Comparison::Gt => *lhs as f64 > *rhs,
337                            Comparison::Gte => *lhs as f64 >= *rhs,
338                        },
339                        // Floats.
340                        (Value::Float(lhs), ComparisonValue::Float(rhs)) => {
341                            let lhs = lhs.into_inner();
342                            match comparator {
343                                Comparison::Lt => lhs < *rhs,
344                                Comparison::Lte => lhs <= *rhs,
345                                Comparison::Gt => lhs > *rhs,
346                                Comparison::Gte => lhs >= *rhs,
347                            }
348                        }
349                        // Float value - Integer boundary
350                        (Value::Float(lhs), ComparisonValue::Integer(rhs)) => {
351                            let lhs = lhs.into_inner();
352                            match comparator {
353                                Comparison::Lt => lhs < *rhs as f64,
354                                Comparison::Lte => lhs <= *rhs as f64,
355                                Comparison::Gt => lhs > *rhs as f64,
356                                Comparison::Gte => lhs >= *rhs as f64,
357                            }
358                        }
359                        // Where the rhs is a string ref, the lhs is coerced into a string.
360                        (_, ComparisonValue::String(rhs)) => {
361                            let lhs = string_value(value);
362                            let rhs = Cow::from(rhs);
363
364                            match comparator {
365                                Comparison::Lt => lhs < rhs,
366                                Comparison::Lte => lhs <= rhs,
367                                Comparison::Gt => lhs > rhs,
368                                Comparison::Gte => lhs >= rhs,
369                            }
370                        }
371                        // Otherwise, compare directly as strings.
372                        _ => {
373                            let lhs = string_value(value);
374
375                            match comparator {
376                                Comparison::Lt => lhs < rhs,
377                                Comparison::Lte => lhs <= rhs,
378                                Comparison::Gt => lhs > rhs,
379                                Comparison::Gte => lhs >= rhs,
380                            }
381                        }
382                    }),
383                )
384            }
385            // Tag values need extracting by "key:value" to be compared.
386            Field::Tag(_) => resolve_value(
387                buf,
388                Run::boxed(move |value| match value {
389                    Value::Array(v) => v.iter().any(|v| match string_value(v).split_once(':') {
390                        Some((_, lhs)) => {
391                            let lhs = Cow::from(lhs);
392
393                            match comparator {
394                                Comparison::Lt => lhs < rhs,
395                                Comparison::Lte => lhs <= rhs,
396                                Comparison::Gt => lhs > rhs,
397                                Comparison::Gte => lhs >= rhs,
398                            }
399                        }
400                        _ => false,
401                    }),
402                    _ => false,
403                }),
404            ),
405            // All other tag types are compared by string.
406            _ => resolve_value(
407                buf,
408                Run::boxed(move |value| {
409                    let lhs = string_value(value);
410
411                    match comparator {
412                        Comparison::Lt => lhs < rhs,
413                        Comparison::Lte => lhs <= rhs,
414                        Comparison::Gt => lhs > rhs,
415                        Comparison::Gte => lhs >= rhs,
416                    }
417                }),
418            ),
419        })
420    }
421}
422
423fn resolve_value(
424    buf: OwnedValuePath,
425    match_fn: Box<dyn Matcher<Value>>,
426) -> Box<dyn Matcher<Value>> {
427    let func = move |obj: &Value| {
428        // Get the value by path, or return early with `false` if it doesn't exist.
429        let Some(value) = obj.get(&buf) else {
430            return false;
431        };
432
433        match_fn.run(value)
434    };
435
436    Run::boxed(func)
437}
438
439/// If the provided field is a `Field::Tag`, will return a "tags" lookup buf. Otherwise,
440/// parses the field and returns a lookup buf is the lookup itself is valid.
441fn lookup_field(field: &Field) -> Result<OwnedValuePath, PathParseError> {
442    match field {
443        Field::Default(p) | Field::Reserved(p) | Field::Attribute(p) => {
444            parse_value_path(p.as_str())
445        }
446        Field::Tag(_) => Ok(owned_value_path!("tags")),
447    }
448}
449
450/// Returns a string value from a VRL `Value`. This differs from the regular `Display`
451/// implementation by treating Bytes values as special-- returning the UTF8 representation
452/// instead of the raw control characters.
453fn string_value(value: &Value) -> Cow<'_, str> {
454    match value {
455        Value::Bytes(val) => String::from_utf8_lossy(val),
456        _ => Cow::from(value.to_string()),
457    }
458}
459
460#[cfg(test)]
461mod test {
462    use crate::value;
463
464    use super::*;
465
466    test_function![
467        match_datadog_query => MatchDatadogQuery;
468
469        message_exists {
470            args: func_args![value: value!({"message": "test message"}), query: "_exists_:message"],
471            want: Ok(true),
472            tdef: type_def(),
473        }
474
475        not_message_exists {
476            args: func_args![value: value!({"message": "test message"}), query: "NOT _exists_:message"],
477            want: Ok(false),
478            tdef: type_def(),
479        }
480
481        negate_message_exists {
482            args: func_args![value: value!({"message": "test message"}), query: "-_exists_:message"],
483            want: Ok(false),
484            tdef: type_def(),
485        }
486
487        facet_exists {
488            args: func_args![value: value!({"a": "value" }), query: "_exists_:@a"],
489            want: Ok(true),
490            tdef: type_def(),
491        }
492
493        not_facet_exists {
494            args: func_args![value: value!({"a": "value" }), query: "NOT _exists_:@a"],
495            want: Ok(false),
496            tdef: type_def(),
497        }
498
499        negate_facet_exists {
500            args: func_args![value: value!({"a": "value" }), query: "-_exists_:@a"],
501            want: Ok(false),
502            tdef: type_def(),
503        }
504
505        hyphen_facet_exists {
506            args: func_args![value: value!({"a-b": "value"}), query: "_exists_:@a-b"],
507            want: Ok(true),
508            tdef: type_def(),
509        }
510
511        tag_bare {
512            args: func_args![value: value!({"tags": ["a","b","c"]}), query: "tags:a"],
513            want: Ok(true),
514            tdef: type_def(),
515        }
516
517        tag_bare_no_match {
518            args: func_args![value: value!({"tags": ["a","b","c"]}), query: "tags:d"],
519            want: Ok(false),
520            tdef: type_def(),
521        }
522
523        not_tag_bare {
524            args: func_args![value: value!({"tags": ["a","b","c"]}), query: "NOT tags:a"],
525            want: Ok(false),
526            tdef: type_def(),
527        }
528
529        negate_tag_bare {
530            args: func_args![value: value!({"tags": ["a","b","c"]}), query: "-tags:a"],
531            want: Ok(false),
532            tdef: type_def(),
533        }
534
535        tag_exists_bare {
536            args: func_args![value: value!({"tags": ["a","b","c"]}), query: "_exists_:a"],
537            want: Ok(true),
538            tdef: type_def(),
539        }
540
541        not_tag_exists_bare {
542            args: func_args![value: value!({"tags": ["a","b","c"]}), query: "NOT _exists_:a"],
543            want: Ok(false),
544            tdef: type_def(),
545        }
546
547        negate_tag_exists_bare {
548            args: func_args![value: value!({"tags": ["a","b","c"]}), query: "-_exists_:a"],
549            want: Ok(false),
550            tdef: type_def(),
551        }
552
553        tag_exists {
554            args: func_args![value: value!({"tags": ["a:1","b:2","c:3"]}), query: "_exists_:a"],
555            want: Ok(true),
556            tdef: type_def(),
557        }
558
559        not_tag_exists {
560            args: func_args![value: value!({"tags": ["a:1","b:2","c:3"]}), query: "NOT _exists_:a"],
561            want: Ok(false),
562            tdef: type_def(),
563        }
564
565        negate_tag_exists {
566            args: func_args![value: value!({"tags": ["a:1","b:2","c:3"]}), query: "-_exists_:a"],
567            want: Ok(false),
568            tdef: type_def(),
569        }
570
571        message_missing {
572            args: func_args![value: value!({}), query: "_missing_:message"],
573            want: Ok(true),
574            tdef: type_def(),
575        }
576
577        not_message_missing {
578            args: func_args![value: value!({}), query: "NOT _missing_:message"],
579            want: Ok(false),
580            tdef: type_def(),
581        }
582
583        negate_message_missing {
584            args: func_args![value: value!({}), query: "-_missing_:message"],
585            want: Ok(false),
586            tdef: type_def(),
587        }
588
589        facet_missing {
590            args: func_args![value: value!({"b": "value" }), query: "_missing_:@a"],
591            want: Ok(true),
592            tdef: type_def(),
593        }
594
595        not_facet_missing {
596            args: func_args![value: value!({"b": "value" }), query: "NOT _missing_:@a"],
597            want: Ok(false),
598            tdef: type_def(),
599        }
600
601        negate_facet_missing {
602            args: func_args![value: value!({"b": "value" }), query: "-_missing_:@a"],
603            want: Ok(false),
604            tdef: type_def(),
605        }
606
607        hyphen_facet_missing {
608            args: func_args![value: value!({"a-b": "value"}), query: "_missing_:@c-d"],
609            want: Ok(true),
610            tdef: type_def(),
611        }
612
613        tag_bare_missing {
614            args: func_args![value: value!({"tags": ["b","c"]}), query: "_missing_:a"],
615            want: Ok(true),
616            tdef: type_def(),
617        }
618
619        not_tag_bare_missing {
620            args: func_args![value: value!({"tags": ["b","c"]}), query: "NOT _missing_:a"],
621            want: Ok(false),
622            tdef: type_def(),
623        }
624
625        negate_tag_bare_missing {
626            args: func_args![value: value!({"tags": ["b","c"]}), query: "-_missing_:a"],
627            want: Ok(false),
628            tdef: type_def(),
629        }
630
631        tag_missing {
632            args: func_args![value: value!({"tags": ["b:1","c:2"]}), query: "_missing_:a"],
633            want: Ok(true),
634            tdef: type_def(),
635        }
636
637        not_tag_missing {
638            args: func_args![value: value!({"tags": ["b:1","c:2"]}), query: "NOT _missing_:a"],
639            want: Ok(false),
640            tdef: type_def(),
641        }
642
643        negate_tag_missing {
644            args: func_args![value: value!({"tags": ["b:1","c:2"]}), query: "-_missing_:a"],
645            want: Ok(false),
646            tdef: type_def(),
647        }
648
649        equals_message {
650            args: func_args![value: value!({"message": "match by word boundary"}), query: "match"],
651            want: Ok(true),
652            tdef: type_def(),
653        }
654
655        not_equals_message {
656            args: func_args![value: value!({"message": "match by word boundary"}), query: "NOT match"],
657            want: Ok(false),
658            tdef: type_def(),
659        }
660
661        negate_equals_message {
662            args: func_args![value: value!({"message": "match by word boundary"}), query: "-match"],
663            want: Ok(false),
664            tdef: type_def(),
665        }
666
667        equals_message_no_match {
668            args: func_args![value: value!({"message": "another value"}), query: "match"],
669            want: Ok(false),
670            tdef: type_def(),
671        }
672
673        not_equals_message_no_match {
674            args: func_args![value: value!({"message": "another value"}), query: "NOT match"],
675            want: Ok(true),
676            tdef: type_def(),
677        }
678
679        negate_equals_message_no_match {
680            args: func_args![value: value!({"message": "another value"}), query: "-match"],
681            want: Ok(true),
682            tdef: type_def(),
683        }
684
685        equals_tag {
686            args: func_args![value: value!({"tags": ["x:1", "y:2", "z:3"]}), query: "y:2"],
687            want: Ok(true),
688            tdef: type_def(),
689        }
690
691        not_equals_tag {
692            args: func_args![value: value!({"tags": ["x:1", "y:2", "z:3"]}), query: "NOT y:2"],
693            want: Ok(false),
694            tdef: type_def(),
695        }
696
697        negate_equals_tag {
698            args: func_args![value: value!({"tags": ["x:1", "y:2", "z:3"]}), query: "-y:2"],
699            want: Ok(false),
700            tdef: type_def(),
701        }
702
703        equals_tag_no_match {
704            args: func_args![value: value!({"tags": ["x:1", "y:2", "z:3"]}), query: "y:3"],
705            want: Ok(false),
706            tdef: type_def(),
707        }
708
709        not_equals_tag_no_match {
710            args: func_args![value: value!({"tags": ["x:1", "y:2", "z:3"]}), query: "NOT y:3"],
711            want: Ok(true),
712            tdef: type_def(),
713        }
714
715        negate_equals_tag_no_match {
716            args: func_args![value: value!({"tags": ["x:1", "y:2", "z:3"]}), query: "-y:3"],
717            want: Ok(true),
718            tdef: type_def(),
719        }
720
721        equals_facet {
722            args: func_args![value: value!({"z": 1}), query: "@z:1"],
723            want: Ok(true),
724            tdef: type_def(),
725        }
726
727        not_equals_facet {
728            args: func_args![value: value!({"z": 1}), query: "NOT @z:1"],
729            want: Ok(false),
730            tdef: type_def(),
731        }
732
733        negate_equals_facet {
734            args: func_args![value: value!({"z": 1}), query: "-@z:1"],
735            want: Ok(false),
736            tdef: type_def(),
737        }
738
739        wildcard_prefix_message {
740            args: func_args![value: value!({"message": "vector"}), query: "*tor"],
741            want: Ok(true),
742            tdef: type_def(),
743        }
744
745        not_wildcard_prefix_message {
746            args: func_args![value: value!({"message": "vector"}), query: "NOT *tor"],
747            want: Ok(false),
748            tdef: type_def(),
749        }
750
751        negate_wildcard_prefix_message {
752            args: func_args![value: value!({"message": "vector"}), query: "-*tor"],
753            want: Ok(false),
754            tdef: type_def(),
755        }
756
757        wildcard_prefix_message_no_match {
758            args: func_args![value: value!({"message": "torvec"}), query: "*tor"],
759            want: Ok(false),
760            tdef: type_def(),
761        }
762
763        not_wildcard_prefix_message_no_match {
764            args: func_args![value: value!({"message": "torvec"}), query: "NOT *tor"],
765            want: Ok(true),
766            tdef: type_def(),
767        }
768
769        negate_wildcard_prefix_message_no_match {
770            args: func_args![value: value!({"message": "torvec"}), query: "-*tor"],
771            want: Ok(true),
772            tdef: type_def(),
773        }
774
775        wildcard_prefix_tag {
776            args: func_args![value: value!({"tags": ["a:vector"]}), query: "a:*tor"],
777            want: Ok(true),
778            tdef: type_def(),
779        }
780
781        not_wildcard_prefix_tag {
782            args: func_args![value: value!({"tags": ["a:vector"]}), query: "NOT a:*tor"],
783            want: Ok(false),
784            tdef: type_def(),
785        }
786
787        negate_wildcard_prefix_tag {
788            args: func_args![value: value!({"tags": ["a:vector"]}), query: "-a:*tor"],
789            want: Ok(false),
790            tdef: type_def(),
791        }
792
793        wildcard_prefix_tag_no_match {
794            args: func_args![value: value!({"tags": ["b:vector"]}), query: "a:*tor"],
795            want: Ok(false),
796            tdef: type_def(),
797        }
798
799        not_wildcard_prefix_tag_no_match {
800            args: func_args![value: value!({"tags": ["b:vector"]}), query: "NOT a:*tor"],
801            want: Ok(true),
802            tdef: type_def(),
803        }
804
805        negate_wildcard_prefix_tag_no_match {
806            args: func_args![value: value!({"tags": ["b:vector"]}), query: "-a:*tor"],
807            want: Ok(true),
808            tdef: type_def(),
809        }
810
811        wildcard_prefix_facet {
812            args: func_args![value: value!({"a": "vector"}), query: "@a:*tor"],
813            want: Ok(true),
814            tdef: type_def(),
815        }
816
817        not_wildcard_prefix_facet {
818            args: func_args![value: value!({"a": "vector"}), query: "NOT @a:*tor"],
819            want: Ok(false),
820            tdef: type_def(),
821        }
822
823        negate_wildcard_prefix_facet {
824            args: func_args![value: value!({"a": "vector"}), query: "-@a:*tor"],
825            want: Ok(false),
826            tdef: type_def(),
827        }
828
829        wildcard_prefix_facet_no_match {
830            args: func_args![value: value!({"b": "vector"}), query: "@a:*tor"],
831            want: Ok(false),
832            tdef: type_def(),
833        }
834
835        not_wildcard_prefix_facet_no_match {
836            args: func_args![value: value!({"b": "vector"}), query: "NOT @a:*tor"],
837            want: Ok(true),
838            tdef: type_def(),
839        }
840
841        negate_wildcard_prefix_facet_no_match {
842            args: func_args![value: value!({"b": "vector"}), query: "-@a:*tor"],
843            want: Ok(true),
844            tdef: type_def(),
845        }
846
847        wildcard_suffix_message {
848            args: func_args![value: value!({"message": "vector"}), query: "vec*"],
849            want: Ok(true),
850            tdef: type_def(),
851        }
852
853        not_wildcard_suffix_message {
854            args: func_args![value: value!({"message": "vector"}), query: "NOT vec*"],
855            want: Ok(false),
856            tdef: type_def(),
857        }
858
859        negate_wildcard_suffix_message {
860            args: func_args![value: value!({"message": "vector"}), query: "-vec*"],
861            want: Ok(false),
862            tdef: type_def(),
863        }
864
865        wildcard_suffix_message_no_match {
866            args: func_args![value: value!({"message": "torvec"}), query: "vec*"],
867            want: Ok(false),
868            tdef: type_def(),
869        }
870
871        not_wildcard_suffix_message_no_match {
872            args: func_args![value: value!({"message": "torvec"}), query: "NOT vec*"],
873            want: Ok(true),
874            tdef: type_def(),
875        }
876
877        negate_wildcard_suffix_message_no_match {
878            args: func_args![value: value!({"message": "torvec"}), query: "-vec*"],
879            want: Ok(true),
880            tdef: type_def(),
881        }
882
883        wildcard_suffix_tag {
884            args: func_args![value: value!({"tags": ["a:vector"]}), query: "a:vec*"],
885            want: Ok(true),
886            tdef: type_def(),
887        }
888
889        not_wildcard_suffix_tag {
890            args: func_args![value: value!({"tags": ["a:vector"]}), query: "NOT a:vec*"],
891            want: Ok(false),
892            tdef: type_def(),
893        }
894
895        negate_wildcard_suffix_tag {
896            args: func_args![value: value!({"tags": ["a:vector"]}), query: "-a:vec*"],
897            want: Ok(false),
898            tdef: type_def(),
899        }
900
901        wildcard_suffix_tag_no_match {
902            args: func_args![value: value!({"tags": ["b:vector"]}), query: "a:vec*"],
903            want: Ok(false),
904            tdef: type_def(),
905        }
906
907        not_wildcard_suffix_tag_no_match {
908            args: func_args![value: value!({"tags": ["b:vector"]}), query: "NOT a:vec*"],
909            want: Ok(true),
910            tdef: type_def(),
911        }
912
913        negate_wildcard_suffix_tag_no_match {
914            args: func_args![value: value!({"tags": ["b:vector"]}), query: "-a:vec*"],
915            want: Ok(true),
916            tdef: type_def(),
917        }
918
919        wildcard_suffix_facet {
920            args: func_args![value: value!({"a": "vector"}), query: "@a:vec*"],
921            want: Ok(true),
922            tdef: type_def(),
923        }
924
925        not_wildcard_suffix_facet {
926            args: func_args![value: value!({"a": "vector"}), query: "NOT @a:vec*"],
927            want: Ok(false),
928            tdef: type_def(),
929        }
930
931        negate_wildcard_suffix_facet {
932            args: func_args![value: value!({"a": "vector"}), query: "-@a:vec*"],
933            want: Ok(false),
934            tdef: type_def(),
935        }
936
937        wildcard_suffix_facet_no_match {
938            args: func_args![value: value!({"b": "vector"}), query: "@a:vec*"],
939            want: Ok(false),
940            tdef: type_def(),
941        }
942
943        not_wildcard_suffix_facet_no_match {
944            args: func_args![value: value!({"b": "vector"}), query: "NOT @a:vec*"],
945            want: Ok(true),
946            tdef: type_def(),
947        }
948
949        negate_wildcard_suffix_facet_no_match {
950            args: func_args![value: value!({"b": "vector"}), query: "-@a:vec*"],
951            want: Ok(true),
952            tdef: type_def(),
953        }
954
955        wildcard_multiple_message {
956            args: func_args![value: value!({"message": "vector"}), query: "v*c*r"],
957            want: Ok(true),
958            tdef: type_def(),
959        }
960
961        not_wildcard_multiple_message {
962            args: func_args![value: value!({"message": "vector"}), query: "NOT v*c*r"],
963            want: Ok(false),
964            tdef: type_def(),
965        }
966
967        negate_wildcard_multiple_message {
968            args: func_args![value: value!({"message": "vector"}), query: "-v*c*r"],
969            want: Ok(false),
970            tdef: type_def(),
971        }
972
973        wildcard_multiple_message_no_match {
974            args: func_args![value: value!({"message": "torvec"}), query: "v*c*r"],
975            want: Ok(false),
976            tdef: type_def(),
977        }
978
979        not_wildcard_multiple_message_no_match {
980            args: func_args![value: value!({"message": "torvec"}), query: "NOT v*c*r"],
981            want: Ok(true),
982            tdef: type_def(),
983        }
984
985        negate_wildcard_multiple_message_no_match {
986            args: func_args![value: value!({"message": "torvec"}), query: "-v*c*r"],
987            want: Ok(true),
988            tdef: type_def(),
989        }
990
991        wildcard_multiple_tag {
992            args: func_args![value: value!({"tags": ["a:vector"]}), query: "a:v*c*r"],
993            want: Ok(true),
994            tdef: type_def(),
995        }
996
997        not_wildcard_multiple_tag {
998            args: func_args![value: value!({"tags": ["a:vector"]}), query: "NOT a:v*c*r"],
999            want: Ok(false),
1000            tdef: type_def(),
1001        }
1002
1003        negate_wildcard_multiple_tag {
1004            args: func_args![value: value!({"tags": ["a:vector"]}), query: "-a:v*c*r"],
1005            want: Ok(false),
1006            tdef: type_def(),
1007        }
1008
1009        wildcard_multiple_tag_no_match {
1010            args: func_args![value: value!({"tags": ["b:vector"]}), query: "a:v*c*r"],
1011            want: Ok(false),
1012            tdef: type_def(),
1013        }
1014
1015        not_wildcard_multiple_tag_no_match {
1016            args: func_args![value: value!({"tags": ["b:vector"]}), query: "NOT a:v*c*r"],
1017            want: Ok(true),
1018            tdef: type_def(),
1019        }
1020
1021        negate_wildcard_multiple_tag_no_match {
1022            args: func_args![value: value!({"tags": ["b:vector"]}), query: "-a:v*c*r"],
1023            want: Ok(true),
1024            tdef: type_def(),
1025        }
1026
1027        wildcard_multiple_facet {
1028            args: func_args![value: value!({"a": "vector"}), query: "@a:v*c*r"],
1029            want: Ok(true),
1030            tdef: type_def(),
1031        }
1032
1033        not_wildcard_multiple_facet {
1034            args: func_args![value: value!({"a": "vector"}), query: "NOT @a:v*c*r"],
1035            want: Ok(false),
1036            tdef: type_def(),
1037        }
1038
1039        negate_wildcard_multiple_facet {
1040            args: func_args![value: value!({"a": "vector"}), query: "-@a:v*c*r"],
1041            want: Ok(false),
1042            tdef: type_def(),
1043        }
1044
1045        wildcard_multiple_facet_no_match {
1046            args: func_args![value: value!({"b": "vector"}), query: "@a:v*c*r"],
1047            want: Ok(false),
1048            tdef: type_def(),
1049        }
1050
1051        not_wildcard_multiple_facet_no_match {
1052            args: func_args![value: value!({"b": "vector"}), query: "NOT @a:v*c*r"],
1053            want: Ok(true),
1054            tdef: type_def(),
1055        }
1056
1057        negate_wildcard_multiple_facet_no_match {
1058            args: func_args![value: value!({"b": "vector"}), query: "-@a:v*c*r"],
1059            want: Ok(true),
1060            tdef: type_def(),
1061        }
1062
1063        range_message_unbounded {
1064            args: func_args![value: value!({"message": "1"}), query: "[* TO *]"],
1065            want: Ok(true),
1066            tdef: type_def(),
1067        }
1068
1069        not_range_message_unbounded {
1070            args: func_args![value: value!({"message": "1"}), query: "NOT [* TO *]"],
1071            want: Ok(false),
1072            tdef: type_def(),
1073        }
1074
1075        negate_range_message_unbounded {
1076            args: func_args![value: value!({"message": "1"}), query: "-[* TO *]"],
1077            want: Ok(false),
1078            tdef: type_def(),
1079        }
1080
1081        range_message_lower_bound {
1082            args: func_args![value: value!({"message": "400"}), query: "[4 TO *]"],
1083            want: Ok(true),
1084            tdef: type_def(),
1085        }
1086
1087        not_range_message_lower_bound {
1088            args: func_args![value: value!({"message": "400"}), query: "NOT [4 TO *]"],
1089            want: Ok(false),
1090            tdef: type_def(),
1091        }
1092
1093        negate_range_message_lower_bound {
1094            args: func_args![value: value!({"message": "400"}), query: "-[4 TO *]"],
1095            want: Ok(false),
1096            tdef: type_def(),
1097        }
1098
1099        range_message_lower_bound_no_match {
1100            args: func_args![value: value!({"message": "400"}), query: "[50 TO *]"],
1101            want: Ok(false),
1102            tdef: type_def(),
1103        }
1104
1105        not_range_message_lower_bound_no_match {
1106            args: func_args![value: value!({"message": "400"}), query: "NOT [50 TO *]"],
1107            want: Ok(true),
1108            tdef: type_def(),
1109        }
1110
1111        negate_range_message_lower_bound_no_match {
1112            args: func_args![value: value!({"message": "400"}), query: "-[50 TO *]"],
1113            want: Ok(true),
1114            tdef: type_def(),
1115        }
1116
1117        range_message_lower_bound_string {
1118            args: func_args![value: value!({"message": "400"}), query: r#"["4" TO *]"#],
1119            want: Ok(true),
1120            tdef: type_def(),
1121        }
1122
1123        not_range_message_lower_bound_string {
1124            args: func_args![value: value!({"message": "400"}), query: r#"NOT ["4" TO *]"#],
1125            want: Ok(false),
1126            tdef: type_def(),
1127        }
1128
1129        negate_range_message_lower_bound_string {
1130            args: func_args![value: value!({"message": "400"}), query: r#"-["4" TO *]"#],
1131            want: Ok(false),
1132            tdef: type_def(),
1133        }
1134
1135        range_message_lower_bound_string_no_match {
1136            args: func_args![value: value!({"message": "400"}), query: r#"["50" TO *]"#],
1137            want: Ok(false),
1138            tdef: type_def(),
1139        }
1140
1141        not_range_message_lower_bound_string_no_match {
1142            args: func_args![value: value!({"message": "400"}), query: r#"NOT ["50" TO *]"#],
1143            want: Ok(true),
1144            tdef: type_def(),
1145        }
1146
1147        negate_range_message_lower_bound_string_no_match {
1148            args: func_args![value: value!({"message": "400"}), query: r#"-["50" TO *]"#],
1149            want: Ok(true),
1150            tdef: type_def(),
1151        }
1152
1153        range_message_upper_bound {
1154            args: func_args![value: value!({"message": "300"}), query: "[* TO 4]"],
1155            want: Ok(true),
1156            tdef: type_def(),
1157        }
1158
1159        not_range_message_upper_bound {
1160            args: func_args![value: value!({"message": "300"}), query: "NOT [* TO 4]"],
1161            want: Ok(false),
1162            tdef: type_def(),
1163        }
1164
1165        negate_range_message_upper_bound {
1166            args: func_args![value: value!({"message": "300"}), query: "-[* TO 4]"],
1167            want: Ok(false),
1168            tdef: type_def(),
1169        }
1170
1171        range_message_upper_bound_no_match {
1172            args: func_args![value: value!({"message": "50"}), query: "[* TO 400]"],
1173            want: Ok(false),
1174            tdef: type_def(),
1175        }
1176
1177        not_range_message_upper_bound_no_match {
1178            args: func_args![value: value!({"message": "50"}), query: "NOT [* TO 400]"],
1179            want: Ok(true),
1180            tdef: type_def(),
1181        }
1182
1183        negate_range_message_upper_bound_no_match {
1184            args: func_args![value: value!({"message": "50"}), query: "-[* TO 400]"],
1185            want: Ok(true),
1186            tdef: type_def(),
1187        }
1188
1189        range_message_upper_bound_string {
1190            args: func_args![value: value!({"message": "300"}), query: r#"[* TO "4"]"#],
1191            want: Ok(true),
1192            tdef: type_def(),
1193        }
1194
1195        not_range_message_upper_bound_string {
1196            args: func_args![value: value!({"message": "300"}), query: r#"NOT [* TO "4"]"#],
1197            want: Ok(false),
1198            tdef: type_def(),
1199        }
1200
1201        negate_range_message_upper_bound_string {
1202            args: func_args![value: value!({"message": "300"}), query: r#"-[* TO "4"]"#],
1203            want: Ok(false),
1204            tdef: type_def(),
1205        }
1206
1207        range_message_upper_bound_string_no_match {
1208            args: func_args![value: value!({"message": "50"}), query: r#"[* TO "400"]"#],
1209            want: Ok(false),
1210            tdef: type_def(),
1211        }
1212
1213        not_range_message_upper_bound_string_no_match {
1214            args: func_args![value: value!({"message": "50"}), query: r#"NOT [* TO "400"]"#],
1215            want: Ok(true),
1216            tdef: type_def(),
1217        }
1218
1219        negate_range_message_upper_bound_string_no_match {
1220            args: func_args![value: value!({"message": "50"}), query: r#"NOT [* TO "400"]"#],
1221            want: Ok(true),
1222            tdef: type_def(),
1223        }
1224
1225        range_message_between {
1226            args: func_args![value: value!({"message": 500}), query: "[1 TO 6]"],
1227            want: Ok(true),
1228            tdef: type_def(),
1229        }
1230
1231        not_range_message_between {
1232            args: func_args![value: value!({"message": 500}), query: "NOT [1 TO 6]"],
1233            want: Ok(false),
1234            tdef: type_def(),
1235        }
1236
1237        negate_range_message_between {
1238            args: func_args![value: value!({"message": 500}), query: "-[1 TO 6]"],
1239            want: Ok(false),
1240            tdef: type_def(),
1241        }
1242
1243        range_message_between_no_match {
1244            args: func_args![value: value!({"message": 70}), query: "[1 TO 6]"],
1245            want: Ok(false),
1246            tdef: type_def(),
1247        }
1248
1249        not_range_message_between_no_match {
1250            args: func_args![value: value!({"message": 70}), query: "NOT [1 TO 6]"],
1251            want: Ok(true),
1252            tdef: type_def(),
1253        }
1254
1255        negate_range_message_between_no_match {
1256            args: func_args![value: value!({"message": 70}), query: "-[1 TO 6]"],
1257            want: Ok(true),
1258            tdef: type_def(),
1259        }
1260
1261        range_message_between_string {
1262            args: func_args![value: value!({"message": "500"}), query: r#"["1" TO "6"]"#],
1263            want: Ok(true),
1264            tdef: type_def(),
1265        }
1266
1267        not_range_message_between_string {
1268            args: func_args![value: value!({"message": "500"}), query: r#"NOT ["1" TO "6"]"#],
1269            want: Ok(false),
1270            tdef: type_def(),
1271        }
1272
1273        negate_range_message_between_string {
1274            args: func_args![value: value!({"message": "500"}), query: r#"-["1" TO "6"]"#],
1275            want: Ok(false),
1276            tdef: type_def(),
1277        }
1278
1279        range_message_between_no_match_string {
1280            args: func_args![value: value!({"message": "70"}), query: r#"["1" TO "6"]"#],
1281            want: Ok(false),
1282            tdef: type_def(),
1283        }
1284
1285        not_range_message_between_no_match_string {
1286            args: func_args![value: value!({"message": "70"}), query: r#"NOT ["1" TO "6"]"#],
1287            want: Ok(true),
1288            tdef: type_def(),
1289        }
1290
1291        negate_range_message_between_no_match_string {
1292            args: func_args![value: value!({"message": "70"}), query: r#"-["1" TO "6"]"#],
1293            want: Ok(true),
1294            tdef: type_def(),
1295        }
1296
1297        range_tag_key {
1298            args: func_args![value: value!({"tags": ["a"]}), query: "a:[* TO *]"],
1299            want: Ok(true),
1300            tdef: type_def(),
1301        }
1302
1303        range_tag_key_no_match {
1304            args: func_args![value: value!({"tags": ["b"]}), query: "a:[* TO *]"],
1305            want: Ok(false),
1306            tdef: type_def(),
1307        }
1308
1309        range_tag_unbounded {
1310            args: func_args![value: value!({"tags": ["a:1"]}), query: "a:[* TO *]"],
1311            want: Ok(true),
1312            tdef: type_def(),
1313        }
1314
1315        not_range_tag_unbounded {
1316            args: func_args![value: value!({"tags": ["a:1"]}), query: "NOT a:[* TO *]"],
1317            want: Ok(false),
1318            tdef: type_def(),
1319        }
1320
1321        negate_range_tag_unbounded {
1322            args: func_args![value: value!({"tags": ["a:1"]}), query: "-a:[* TO *]"],
1323            want: Ok(false),
1324            tdef: type_def(),
1325        }
1326
1327        range_tag_lower_bound {
1328            args: func_args![value: value!({"tags": ["a:400"]}), query: "a:[4 TO *]"],
1329            want: Ok(true),
1330            tdef: type_def(),
1331        }
1332
1333        not_range_tag_lower_bound {
1334            args: func_args![value: value!({"tags": ["a:400"]}), query: "NOT a:[4 TO *]"],
1335            want: Ok(false),
1336            tdef: type_def(),
1337        }
1338
1339        negate_range_tag_lower_bound {
1340            args: func_args![value: value!({"tags": ["a:400"]}), query: "-a:[4 TO *]"],
1341            want: Ok(false),
1342            tdef: type_def(),
1343        }
1344
1345        range_tag_lower_bound_no_match {
1346            args: func_args![value: value!({"tags": ["a:400"]}), query: "a:[50 TO *]"],
1347            want: Ok(false),
1348            tdef: type_def(),
1349        }
1350
1351        not_range_tag_lower_bound_no_match {
1352            args: func_args![value: value!({"tags": ["a:400"]}), query: "NOT a:[50 TO *]"],
1353            want: Ok(true),
1354            tdef: type_def(),
1355        }
1356
1357        negate_range_tag_lower_bound_no_match {
1358            args: func_args![value: value!({"tags": ["a:400"]}), query: "-a:[50 TO *]"],
1359            want: Ok(true),
1360            tdef: type_def(),
1361        }
1362
1363        range_tag_lower_bound_string {
1364            args: func_args![value: value!({"tags": ["a:400"]}), query: r#"a:["4" TO *]"#],
1365            want: Ok(true),
1366            tdef: type_def(),
1367        }
1368
1369        not_range_tag_lower_bound_string {
1370            args: func_args![value: value!({"tags": ["a:400"]}), query: r#"NOT a:["4" TO *]"#],
1371            want: Ok(false),
1372            tdef: type_def(),
1373        }
1374
1375        negate_range_tag_lower_bound_string {
1376            args: func_args![value: value!({"tags": ["a:400"]}), query: r#"-a:["4" TO *]"#],
1377            want: Ok(false),
1378            tdef: type_def(),
1379        }
1380
1381        range_tag_lower_bound_string_no_match {
1382            args: func_args![value: value!({"tags": ["a:400"]}), query: r#"a:["50" TO *]"#],
1383            want: Ok(false),
1384            tdef: type_def(),
1385        }
1386
1387        not_range_tag_lower_bound_string_no_match {
1388            args: func_args![value: value!({"tags": ["a:400"]}), query: r#"NOT a:["50" TO *]"#],
1389            want: Ok(true),
1390            tdef: type_def(),
1391        }
1392
1393        negate_range_tag_lower_bound_string_no_match {
1394            args: func_args![value: value!({"tags": ["a:400"]}), query: r#"-a:["50" TO *]"#],
1395            want: Ok(true),
1396            tdef: type_def(),
1397        }
1398
1399        range_tag_upper_bound {
1400            args: func_args![value: value!({"tags": ["a:300"]}), query: "a:[* TO 4]"],
1401            want: Ok(true),
1402            tdef: type_def(),
1403        }
1404
1405        not_range_tag_upper_bound {
1406            args: func_args![value: value!({"tags": ["a:300"]}), query: "NOT a:[* TO 4]"],
1407            want: Ok(false),
1408            tdef: type_def(),
1409        }
1410
1411        negate_range_tag_upper_bound {
1412            args: func_args![value: value!({"tags": ["a:300"]}), query: "-a:[* TO 4]"],
1413            want: Ok(false),
1414            tdef: type_def(),
1415        }
1416
1417        range_tag_upper_bound_no_match {
1418            args: func_args![value: value!({"tags": ["a:50"]}), query: "a:[* TO 400]"],
1419            want: Ok(false),
1420            tdef: type_def(),
1421        }
1422
1423        not_range_tag_upper_bound_no_match {
1424            args: func_args![value: value!({"tags": ["a:50"]}), query: "NOT a:[* TO 400]"],
1425            want: Ok(true),
1426            tdef: type_def(),
1427        }
1428
1429        negate_range_tag_upper_bound_no_match {
1430            args: func_args![value: value!({"tags": ["a:50"]}), query: "-a:[* TO 400]"],
1431            want: Ok(true),
1432            tdef: type_def(),
1433        }
1434
1435        range_tag_upper_bound_string {
1436            args: func_args![value: value!({"tags": ["a:300"]}), query: r#"a:[* TO "4"]"#],
1437            want: Ok(true),
1438            tdef: type_def(),
1439        }
1440
1441        not_range_tag_upper_bound_string {
1442            args: func_args![value: value!({"tags": ["a:300"]}), query: r#"NOT a:[* TO "4"]"#],
1443            want: Ok(false),
1444            tdef: type_def(),
1445        }
1446
1447        negate_range_tag_upper_bound_string {
1448            args: func_args![value: value!({"tags": ["a:300"]}), query: r#"-a:[* TO "4"]"#],
1449            want: Ok(false),
1450            tdef: type_def(),
1451        }
1452
1453        range_tag_upper_bound_string_no_match {
1454            args: func_args![value: value!({"tags": ["a:50"]}), query: r#"a:[* TO "400"]"#],
1455            want: Ok(false),
1456            tdef: type_def(),
1457        }
1458
1459        not_range_tag_upper_bound_string_no_match {
1460            args: func_args![value: value!({"tags": ["a:50"]}), query: r#"NOT a:[* TO "400"]"#],
1461            want: Ok(true),
1462            tdef: type_def(),
1463        }
1464
1465        negate_range_tag_upper_bound_string_no_match {
1466            args: func_args![value: value!({"tags": ["a:50"]}), query: r#"-a:[* TO "400"]"#],
1467            want: Ok(true),
1468            tdef: type_def(),
1469        }
1470
1471        range_tag_between {
1472            args: func_args![value: value!({"tags": ["a:500"]}), query: "a:[1 TO 6]"],
1473            want: Ok(true),
1474            tdef: type_def(),
1475        }
1476
1477        not_range_tag_between {
1478            args: func_args![value: value!({"tags": ["a:500"]}), query: "NOT a:[1 TO 6]"],
1479            want: Ok(false),
1480            tdef: type_def(),
1481        }
1482
1483        negate_range_tag_between {
1484            args: func_args![value: value!({"tags": ["a:500"]}), query: "-a:[1 TO 6]"],
1485            want: Ok(false),
1486            tdef: type_def(),
1487        }
1488
1489        range_tag_between_no_match {
1490            args: func_args![value: value!({"tags": ["a:70"]}), query: "a:[1 TO 6]"],
1491            want: Ok(false),
1492            tdef: type_def(),
1493        }
1494
1495        not_range_tag_between_no_match {
1496            args: func_args![value: value!({"tags": ["a:70"]}), query: "NOT a:[1 TO 6]"],
1497            want: Ok(true),
1498            tdef: type_def(),
1499        }
1500
1501        negate_range_tag_between_no_match {
1502            args: func_args![value: value!({"tags": ["a:70"]}), query: "-a:[1 TO 6]"],
1503            want: Ok(true),
1504            tdef: type_def(),
1505        }
1506
1507        range_tag_between_string {
1508            args: func_args![value: value!({"tags": ["a:500"]}), query: r#"a:["1" TO "6"]"#],
1509            want: Ok(true),
1510            tdef: type_def(),
1511        }
1512
1513        not_range_tag_between_string {
1514            args: func_args![value: value!({"tags": ["a:500"]}), query: r#"NOT a:["1" TO "6"]"#],
1515            want: Ok(false),
1516            tdef: type_def(),
1517        }
1518
1519        negate_range_tag_between_string {
1520            args: func_args![value: value!({"tags": ["a:500"]}), query: r#"-a:["1" TO "6"]"#],
1521            want: Ok(false),
1522            tdef: type_def(),
1523        }
1524
1525        range_tag_between_no_match_string {
1526            args: func_args![value: value!({"tags": ["a:70"]}), query: r#"a:["1" TO "6"]"#],
1527            want: Ok(false),
1528            tdef: type_def(),
1529        }
1530
1531        not_range_tag_between_no_match_string {
1532            args: func_args![value: value!({"tags": ["a:70"]}), query: r#"NOT a:["1" TO "6"]"#],
1533            want: Ok(true),
1534            tdef: type_def(),
1535        }
1536
1537        negate_range_tag_between_no_match_string {
1538            args: func_args![value: value!({"tags": ["a:70"]}), query: r#"-a:["1" TO "6"]"#],
1539            want: Ok(true),
1540            tdef: type_def(),
1541        }
1542
1543        range_facet_unbounded {
1544            args: func_args![value: value!({"a": 1}), query: "@a:[* TO *]"],
1545            want: Ok(true),
1546            tdef: type_def(),
1547        }
1548
1549        not_range_facet_unbounded {
1550            args: func_args![value: value!({"a": 1}), query: "NOT @a:[* TO *]"],
1551            want: Ok(false),
1552            tdef: type_def(),
1553        }
1554
1555        negate_range_facet_unbounded {
1556            args: func_args![value: value!({"a": 1}), query: "-@a:[* TO *]"],
1557            want: Ok(false),
1558            tdef: type_def(),
1559        }
1560
1561        range_facet_lower_bound {
1562            args: func_args![value: value!({"a": 5}), query: "@a:[4 TO *]"],
1563            want: Ok(true),
1564            tdef: type_def(),
1565        }
1566
1567        not_range_facet_lower_bound {
1568            args: func_args![value: value!({"a": 5}), query: "NOT @a:[4 TO *]"],
1569            want: Ok(false),
1570            tdef: type_def(),
1571        }
1572
1573        negate_range_facet_lower_bound {
1574            args: func_args![value: value!({"a": 5}), query: "-@a:[4 TO *]"],
1575            want: Ok(false),
1576            tdef: type_def(),
1577        }
1578
1579        range_facet_lower_bound_no_match {
1580            args: func_args![value: value!({"a": 5}), query: "@a:[50 TO *]"],
1581            want: Ok(false),
1582            tdef: type_def(),
1583        }
1584
1585        not_range_facet_lower_bound_no_match {
1586            args: func_args![value: value!({"a": 5}), query: "NOT @a:[50 TO *]"],
1587            want: Ok(true),
1588            tdef: type_def(),
1589        }
1590
1591        negate_range_facet_lower_bound_no_match {
1592            args: func_args![value: value!({"a": 5}), query: "-@a:[50 TO *]"],
1593            want: Ok(true),
1594            tdef: type_def(),
1595        }
1596
1597        range_facet_lower_bound_string {
1598            args: func_args![value: value!({"a": "5"}), query: r#"@a:["4" TO *]"#],
1599            want: Ok(true),
1600            tdef: type_def(),
1601        }
1602
1603        not_range_facet_lower_bound_string {
1604            args: func_args![value: value!({"a": "5"}), query: r#"NOT @a:["4" TO *]"#],
1605            want: Ok(false),
1606            tdef: type_def(),
1607        }
1608
1609        negate_range_facet_lower_bound_string {
1610            args: func_args![value: value!({"a": "5"}), query: r#"-@a:["4" TO *]"#],
1611            want: Ok(false),
1612            tdef: type_def(),
1613        }
1614
1615        range_facet_lower_bound_string_no_match {
1616            args: func_args![value: value!({"a": "400"}), query: r#"@a:["50" TO *]"#],
1617            want: Ok(false),
1618            tdef: type_def(),
1619        }
1620
1621        not_range_facet_lower_bound_string_no_match {
1622            args: func_args![value: value!({"a": "400"}), query: r#"NOT @a:["50" TO *]"#],
1623            want: Ok(true),
1624            tdef: type_def(),
1625        }
1626
1627        negate_range_facet_lower_bound_string_no_match {
1628            args: func_args![value: value!({"a": "400"}), query: r#"-@a:["50" TO *]"#],
1629            want: Ok(true),
1630            tdef: type_def(),
1631        }
1632
1633        range_facet_upper_bound {
1634            args: func_args![value: value!({"a": 1}), query: "@a:[* TO 4]"],
1635            want: Ok(true),
1636            tdef: type_def(),
1637        }
1638
1639        not_range_facet_upper_bound {
1640            args: func_args![value: value!({"a": 1}), query: "NOT @a:[* TO 4]"],
1641            want: Ok(false),
1642            tdef: type_def(),
1643        }
1644
1645        negate_range_facet_upper_bound {
1646            args: func_args![value: value!({"a": 1}), query: "-@a:[* TO 4]"],
1647            want: Ok(false),
1648            tdef: type_def(),
1649        }
1650
1651        range_facet_upper_bound_no_match {
1652            args: func_args![value: value!({"a": 500}), query: "@a:[* TO 400]"],
1653            want: Ok(false),
1654            tdef: type_def(),
1655        }
1656
1657        not_range_facet_upper_bound_no_match {
1658            args: func_args![value: value!({"a": 500}), query: "NOT @a:[* TO 400]"],
1659            want: Ok(true),
1660            tdef: type_def(),
1661        }
1662
1663        negate_range_facet_upper_bound_no_match {
1664            args: func_args![value: value!({"a": 500}), query: "-@a:[* TO 400]"],
1665            want: Ok(true),
1666            tdef: type_def(),
1667        }
1668
1669        range_facet_upper_bound_string {
1670            args: func_args![value: value!({"a": "3"}), query: r#"@a:[* TO "4"]"#],
1671            want: Ok(true),
1672            tdef: type_def(),
1673        }
1674
1675        not_range_facet_upper_bound_string {
1676            args: func_args![value: value!({"a": "3"}), query: r#"NOT @a:[* TO "4"]"#],
1677            want: Ok(false),
1678            tdef: type_def(),
1679        }
1680
1681        negate_range_facet_upper_bound_string {
1682            args: func_args![value: value!({"a": "3"}), query: r#"-@a:[* TO "4"]"#],
1683            want: Ok(false),
1684            tdef: type_def(),
1685        }
1686
1687        range_facet_upper_bound_string_no_match {
1688            args: func_args![value: value!({"a": "5"}), query: r#"@a:[* TO "400"]"#],
1689            want: Ok(false),
1690            tdef: type_def(),
1691        }
1692
1693        not_range_facet_upper_bound_string_no_match {
1694            args: func_args![value: value!({"a": "5"}), query: r#"NOT @a:[* TO "400"]"#],
1695            want: Ok(true),
1696            tdef: type_def(),
1697        }
1698
1699        negate_range_facet_upper_bound_string_no_match {
1700            args: func_args![value: value!({"a": "5"}), query: r#"-@a:[* TO "400"]"#],
1701            want: Ok(true),
1702            tdef: type_def(),
1703        }
1704
1705        range_facet_between {
1706            args: func_args![value: value!({"a": 5}), query: "@a:[1 TO 6]"],
1707            want: Ok(true),
1708            tdef: type_def(),
1709        }
1710
1711        not_range_facet_between {
1712            args: func_args![value: value!({"a": 5}), query: "NOT @a:[1 TO 6]"],
1713            want: Ok(false),
1714            tdef: type_def(),
1715        }
1716
1717        negate_range_facet_between {
1718            args: func_args![value: value!({"a": 5}), query: "-@a:[1 TO 6]"],
1719            want: Ok(false),
1720            tdef: type_def(),
1721        }
1722
1723        range_facet_between_no_match {
1724            args: func_args![value: value!({"a": 200}), query: "@a:[1 TO 6]"],
1725            want: Ok(false),
1726            tdef: type_def(),
1727        }
1728
1729        not_range_facet_between_no_match {
1730            args: func_args![value: value!({"a": 200}), query: "NOT @a:[1 TO 6]"],
1731            want: Ok(true),
1732            tdef: type_def(),
1733        }
1734
1735        negate_range_facet_between_no_match {
1736            args: func_args![value: value!({"a": 200}), query: "-@a:[1 TO 6]"],
1737            want: Ok(true),
1738            tdef: type_def(),
1739        }
1740
1741        range_facet_between_string {
1742            args: func_args![value: value!({"a": "500"}), query: r#"@a:["1" TO "6"]"#],
1743            want: Ok(true),
1744            tdef: type_def(),
1745        }
1746
1747        not_range_facet_between_string {
1748            args: func_args![value: value!({"a": "500"}), query: r#"NOT @a:["1" TO "6"]"#],
1749            want: Ok(false),
1750            tdef: type_def(),
1751        }
1752
1753        negate_range_facet_between_string {
1754            args: func_args![value: value!({"a": "500"}), query: r#"-@a:["1" TO "6"]"#],
1755            want: Ok(false),
1756            tdef: type_def(),
1757        }
1758
1759        range_facet_between_no_match_string {
1760            args: func_args![value: value!({"a": "7"}), query: r#"@a:["1" TO "60"]"#],
1761            want: Ok(false),
1762            tdef: type_def(),
1763        }
1764
1765        not_range_facet_between_no_match_string {
1766            args: func_args![value: value!({"a": "7"}), query: r#"NOT @a:["1" TO "60"]"#],
1767            want: Ok(true),
1768            tdef: type_def(),
1769        }
1770
1771        negate_range_facet_between_no_match_string {
1772            args: func_args![value: value!({"a": "7"}), query: r#"-@a:["1" TO "60"]"#],
1773            want: Ok(true),
1774            tdef: type_def(),
1775        }
1776
1777        exclusive_range_message {
1778            args: func_args![value: value!({"message": "100"}), query: "{1 TO 2}"],
1779            want: Ok(true),
1780            tdef: type_def(),
1781        }
1782
1783        not_exclusive_range_message {
1784            args: func_args![value: value!({"message": "100"}), query: "NOT {1 TO 2}"],
1785            want: Ok(false),
1786            tdef: type_def(),
1787        }
1788
1789        negate_exclusive_range_message {
1790            args: func_args![value: value!({"message": "100"}), query: "-{1 TO 2}"],
1791            want: Ok(false),
1792            tdef: type_def(),
1793        }
1794
1795        exclusive_range_message_no_match {
1796            args: func_args![value: value!({"message": "1"}), query: "{1 TO 2}"],
1797            want: Ok(false),
1798            tdef: type_def(),
1799        }
1800
1801        not_exclusive_range_message_no_match {
1802            args: func_args![value: value!({"message": "1"}), query: "NOT {1 TO 2}"],
1803            want: Ok(true),
1804            tdef: type_def(),
1805        }
1806
1807        negate_exclusive_range_message_no_match {
1808            args: func_args![value: value!({"message": "1"}), query: "-{1 TO 2}"],
1809            want: Ok(true),
1810            tdef: type_def(),
1811        }
1812
1813        exclusive_range_message_lower {
1814            args: func_args![value: value!({"message": "200"}), query: "{1 TO *}"],
1815            want: Ok(true),
1816            tdef: type_def(),
1817        }
1818
1819        not_exclusive_range_message_lower {
1820            args: func_args![value: value!({"message": "200"}), query: "NOT {1 TO *}"],
1821            want: Ok(false),
1822            tdef: type_def(),
1823        }
1824
1825        negate_exclusive_range_message_lower {
1826            args: func_args![value: value!({"message": "200"}), query: "-{1 TO *}"],
1827            want: Ok(false),
1828            tdef: type_def(),
1829        }
1830
1831        exclusive_range_message_lower_no_match {
1832            args: func_args![value: value!({"message": "1"}), query: "{1 TO *}"],
1833            want: Ok(false),
1834            tdef: type_def(),
1835        }
1836
1837        not_exclusive_range_message_lower_no_match {
1838            args: func_args![value: value!({"message": "1"}), query: "NOT {1 TO *}"],
1839            want: Ok(true),
1840            tdef: type_def(),
1841        }
1842
1843        negate_exclusive_range_message_lower_no_match {
1844            args: func_args![value: value!({"message": "1"}), query: "-{1 TO *}"],
1845            want: Ok(true),
1846            tdef: type_def(),
1847        }
1848
1849        exclusive_range_message_upper {
1850            args: func_args![value: value!({"message": "200"}), query: "{* TO 3}"],
1851            want: Ok(true),
1852            tdef: type_def(),
1853        }
1854
1855        not_exclusive_range_message_upper {
1856            args: func_args![value: value!({"message": "200"}), query: "NOT {* TO 3}"],
1857            want: Ok(false),
1858            tdef: type_def(),
1859        }
1860
1861        negate_exclusive_range_message_upper {
1862            args: func_args![value: value!({"message": "200"}), query: "-{* TO 3}"],
1863            want: Ok(false),
1864            tdef: type_def(),
1865        }
1866
1867        exclusive_range_message_upper_no_match {
1868            args: func_args![value: value!({"message": "3"}), query: "{* TO 3}"],
1869            want: Ok(false),
1870            tdef: type_def(),
1871        }
1872
1873        not_exclusive_range_message_upper_no_match {
1874            args: func_args![value: value!({"message": "3"}), query: "NOT {* TO 3}"],
1875            want: Ok(true),
1876            tdef: type_def(),
1877        }
1878
1879        negate_exclusive_range_message_upper_no_match {
1880            args: func_args![value: value!({"message": "3"}), query: "-{* TO 3}"],
1881            want: Ok(true),
1882            tdef: type_def(),
1883        }
1884
1885        message_and {
1886            args: func_args![value: value!({"message": "this contains that"}), query: "this AND that"],
1887            want: Ok(true),
1888            tdef: type_def(),
1889        }
1890
1891        message_and_not {
1892            args: func_args![value: value!({"message": "this contains that"}), query: "this AND NOT that"],
1893            want: Ok(false),
1894            tdef: type_def(),
1895        }
1896
1897        message_or {
1898            args: func_args![value: value!({"message": "only contains that"}), query: "this OR that"],
1899            want: Ok(true),
1900            tdef: type_def(),
1901        }
1902
1903        message_or_not {
1904            args: func_args![value: value!({"message": "only contains that"}), query: "this OR NOT that"],
1905            want: Ok(false),
1906            tdef: type_def(),
1907        }
1908
1909        message_and_or {
1910            args: func_args![value: value!({"message": "this contains that"}), query: "this AND (that OR the_other)"],
1911            want: Ok(true),
1912            tdef: type_def(),
1913        }
1914
1915        not_message_and_or {
1916            args: func_args![value: value!({"message": "this contains that"}), query: "this AND NOT (that OR the_other)"],
1917            want: Ok(false),
1918            tdef: type_def(),
1919        }
1920
1921        negate_message_and_or {
1922            args: func_args![value: value!({"message": "this contains that"}), query: "this AND -(that OR the_other)"],
1923            want: Ok(false),
1924            tdef: type_def(),
1925        }
1926
1927        message_and_or_2 {
1928            args: func_args![value: value!({"message": "this contains the_other"}), query: "this AND (that OR the_other)"],
1929            want: Ok(true),
1930            tdef: type_def(),
1931        }
1932
1933        not_message_and_or_2 {
1934            args: func_args![value: value!({"message": "this contains the_other"}), query: "this AND NOT (that OR the_other)"],
1935            want: Ok(false),
1936            tdef: type_def(),
1937        }
1938
1939        negate_message_and_or_2 {
1940            args: func_args![value: value!({"message": "this contains the_other"}), query: "this AND -(that OR the_other)"],
1941            want: Ok(false),
1942            tdef: type_def(),
1943        }
1944
1945        message_or_and {
1946            args: func_args![value: value!({"message": "just this"}), query: "this OR (that AND the_other)"],
1947            want: Ok(true),
1948            tdef: type_def(),
1949        }
1950
1951        message_or_and_no_match {
1952            args: func_args![value: value!({"message": "that and nothing else"}), query: "this OR (that AND the_other)"],
1953            want: Ok(false),
1954            tdef: type_def(),
1955        }
1956
1957        message_or_and_2 {
1958            args: func_args![value: value!({"message": "that plus the_other"}), query: "this OR (that AND the_other)"],
1959            want: Ok(true),
1960            tdef: type_def(),
1961        }
1962
1963        message_or_and_2_no_match {
1964            args: func_args![value: value!({"message": "nothing plus the_other"}), query: "this OR (that AND the_other)"],
1965            want: Ok(false),
1966            tdef: type_def(),
1967        }
1968
1969        kitchen_sink {
1970            args: func_args![value: value!({"host": "this"}), query: "host:this OR ((@b:test* AND c:that) AND d:the_other @e:[1 TO 5])"],
1971            want: Ok(true),
1972            tdef: type_def(),
1973        }
1974
1975        kitchen_sink_2 {
1976            args: func_args![value: value!({"tags": ["c:that", "d:the_other"], "b": "testing", "e": 3}), query: "host:this OR ((@b:test* AND c:that) AND d:the_other @e:[1 TO 5])"],
1977            want: Ok(true),
1978            tdef: type_def(),
1979        }
1980
1981        integer_range_float_value_match {
1982            args: func_args![value: value!({"level": 7.0}), query: "@level:[7 TO 10]"],
1983            want: Ok(true),
1984            tdef: type_def(),
1985        }
1986
1987        integer_range_float_value_no_match {
1988            args: func_args![value: value!({"level": 6.9}), query: "@level:[7 TO 10]"],
1989            want: Ok(false),
1990            tdef: type_def(),
1991        }
1992
1993        float_range_integer_value_match {
1994            args: func_args![value: value!({"level": 7}), query: "@level:[7.0 TO 10.0]"],
1995            want: Ok(true),
1996            tdef: type_def(),
1997        }
1998
1999        float_range_integer_value_no_match {
2000            args: func_args![value: value!({"level": 6}), query: "@level:[7.0 TO 10.0]"],
2001            want: Ok(false),
2002            tdef: type_def(),
2003        }
2004
2005        path_parser_hyphen {
2006            args: func_args![value: value!({"a-b": "3"}), query: "@a-b:3"],
2007            want: Ok(true),
2008            tdef: type_def(),
2009        }
2010
2011        path_parser_failure {
2012            args: func_args![value: value!({"a-b": "3"}), query: "@a%:3"],
2013            want: Err("invalid argument"),
2014            tdef: type_def(),
2015        }
2016
2017        quoted_query_key_match {
2018            args: func_args![value: value!({"a-b": 1}), query: "@\\\"a-b\\\":1"],
2019            want: Ok(true),
2020            tdef: type_def(),
2021        }
2022    ];
2023}