1use std::cmp::Ordering;
2
3use regex::Regex;
4use tracing::error;
5
6use opcua_types::{
7 AttributeId, EventFieldList, FilterOperator, NodeId, NumericRange, QualifiedName, Variant,
8 VariantScalarTypeId, VariantTypeId,
9};
10
11use crate::TypeTree;
12
13use super::{
14 event::Event,
15 validation::{
16 ParsedContentFilter, ParsedEventFilter, ParsedOperand, ParsedSimpleAttributeOperand,
17 },
18};
19
20impl ParsedEventFilter {
21 pub fn evaluate(
25 &self,
26 event: &dyn Event,
27 client_handle: u32,
28 type_tree: &dyn TypeTree,
29 ) -> Option<EventFieldList> {
30 if !self.content_filter.evaluate(event, type_tree) {
31 return None;
32 }
33
34 let fields: Vec<_> = self
35 .select_clauses
36 .iter()
37 .map(|c| get_field(event, c))
38 .collect();
39 Some(EventFieldList {
40 client_handle,
41 event_fields: Some(fields),
42 })
43 }
44}
45
46macro_rules! cmp_op {
47 ($slf:ident, $evt:ident, $tt:ident, $op:ident, $pt:pat) => {
48 matches!(
49 ParsedContentFilter::compare_op(
50 $slf.evaluate_operand($evt, $tt, &$op.operands[0]),
51 $slf.evaluate_operand($evt, $tt, &$op.operands[1]),
52 ),
53 $pt
54 )
55 .into()
56 };
57}
58
59macro_rules! as_type {
60 ($v:expr, $t:ident, $def:expr) => {{
61 let v = $v.convert(VariantTypeId::Scalar(VariantScalarTypeId::$t));
62 let Variant::$t(v) = v else {
63 return $def;
64 };
65 v
66 }};
67}
68
69macro_rules! bw_op {
70 ($lhs:expr, $rhs:expr, $op:expr) => {{
71 match $op {
72 BitOperation::And => ($lhs & $rhs).into(),
73 BitOperation::Or => ($lhs | $rhs).into(),
74 }
75 }};
76}
77
78pub trait AttributeQueryable: Copy {
83 fn get_attribute(
85 &self,
86 type_definition_id: &NodeId,
87 browse_path: &[QualifiedName],
88 attribute_id: AttributeId,
89 index_range: &NumericRange,
90 ) -> Variant;
91
92 fn get_type(&self) -> NodeId;
94}
95
96impl AttributeQueryable for &dyn Event {
97 fn get_attribute(
98 &self,
99 type_definition_id: &NodeId,
100 browse_path: &[QualifiedName],
101 attribute_id: AttributeId,
102 index_range: &NumericRange,
103 ) -> Variant {
104 self.get_field(type_definition_id, attribute_id, index_range, browse_path)
105 }
106
107 fn get_type(&self) -> NodeId {
108 self.event_type_id().clone()
109 }
110}
111
112enum BitOperation {
113 And,
114 Or,
115}
116
117impl ParsedContentFilter {
118 pub fn evaluate(&self, item: impl AttributeQueryable, type_tree: &dyn TypeTree) -> bool {
121 if self.elements.is_empty() {
122 return true;
123 }
124 matches!(
125 self.evulate_element(item, type_tree, 0),
126 Variant::Boolean(true)
127 )
128 }
129
130 fn evulate_element(
131 &self,
132 item: impl AttributeQueryable,
133 type_tree: &dyn TypeTree,
134 index: usize,
135 ) -> Variant {
136 let Some(op) = self.elements.get(index) else {
137 return Variant::Empty;
138 };
139
140 match op.operator {
141 FilterOperator::Equals => cmp_op!(self, item, type_tree, op, Some(Ordering::Equal)),
142 FilterOperator::IsNull => {
143 (self.evaluate_operand(item, type_tree, &op.operands[0]) == Variant::Empty).into()
144 }
145 FilterOperator::GreaterThan => {
146 cmp_op!(self, item, type_tree, op, Some(Ordering::Greater))
147 }
148 FilterOperator::LessThan => cmp_op!(self, item, type_tree, op, Some(Ordering::Less)),
149 FilterOperator::GreaterThanOrEqual => {
150 cmp_op!(
151 self,
152 item,
153 type_tree,
154 op,
155 Some(Ordering::Equal | Ordering::Greater)
156 )
157 }
158 FilterOperator::LessThanOrEqual => {
159 cmp_op!(
160 self,
161 item,
162 type_tree,
163 op,
164 Some(Ordering::Equal | Ordering::Less)
165 )
166 }
167 FilterOperator::Like => Self::like(
168 self.evaluate_operand(item, type_tree, &op.operands[0]),
169 self.evaluate_operand(item, type_tree, &op.operands[1]),
170 )
171 .into(),
172 FilterOperator::Not => {
173 Self::not(self.evaluate_operand(item, type_tree, &op.operands[0]))
174 }
175 FilterOperator::Between => Self::between(
176 self.evaluate_operand(item, type_tree, &op.operands[0]),
177 self.evaluate_operand(item, type_tree, &op.operands[1]),
178 self.evaluate_operand(item, type_tree, &op.operands[2]),
179 )
180 .into(),
181 FilterOperator::InList => Self::in_list(
182 self.evaluate_operand(item, type_tree, &op.operands[0]),
183 op.operands
184 .iter()
185 .skip(1)
186 .map(|o| self.evaluate_operand(item, type_tree, o)),
187 )
188 .into(),
189 FilterOperator::And => Self::and(
190 self.evaluate_operand(item, type_tree, &op.operands[0]),
191 self.evaluate_operand(item, type_tree, &op.operands[1]),
192 ),
193 FilterOperator::Or => Self::or(
194 self.evaluate_operand(item, type_tree, &op.operands[0]),
195 self.evaluate_operand(item, type_tree, &op.operands[1]),
196 ),
197 FilterOperator::Cast => Self::cast(
198 self.evaluate_operand(item, type_tree, &op.operands[0]),
199 self.evaluate_operand(item, type_tree, &op.operands[1]),
200 ),
201 FilterOperator::BitwiseAnd => Self::bitwise_op(
202 self.evaluate_operand(item, type_tree, &op.operands[0]),
203 self.evaluate_operand(item, type_tree, &op.operands[1]),
204 BitOperation::And,
205 ),
206 FilterOperator::BitwiseOr => Self::bitwise_op(
207 self.evaluate_operand(item, type_tree, &op.operands[0]),
208 self.evaluate_operand(item, type_tree, &op.operands[1]),
209 BitOperation::Or,
210 ),
211 FilterOperator::OfType => Self::of_type(
212 self.evaluate_operand(item, type_tree, &op.operands[0]),
213 item,
214 type_tree,
215 )
216 .into(),
217 _ => Variant::Empty,
220 }
221 }
222
223 fn evaluate_operand(
224 &self,
225 item: impl AttributeQueryable,
226 type_tree: &dyn TypeTree,
227 op: &ParsedOperand,
228 ) -> Variant {
229 match op {
230 ParsedOperand::ElementOperand(o) => {
231 self.evulate_element(item, type_tree, o.index as usize)
232 }
233 ParsedOperand::LiteralOperand(o) => o.value.clone(),
234 ParsedOperand::AttributeOperand(_) => unreachable!(),
235 ParsedOperand::SimpleAttributeOperand(o) => item.get_attribute(
236 &o.type_definition_id,
237 &o.browse_path,
238 o.attribute_id,
239 &o.index_range,
240 ),
241 }
242 }
243
244 fn in_list(lhs: Variant, rhs: impl Iterator<Item = Variant>) -> bool {
245 for it in rhs {
246 if matches!(Self::compare_op(lhs.clone(), it), Some(Ordering::Equal)) {
247 return true;
248 }
249 }
250 false
251 }
252
253 fn between(it: Variant, gte: Variant, lte: Variant) -> bool {
254 matches!(
255 Self::compare_op(it.clone(), gte),
256 Some(Ordering::Greater | Ordering::Equal)
257 ) && matches!(
258 Self::compare_op(it, lte),
259 Some(Ordering::Less | Ordering::Equal)
260 )
261 }
262
263 fn not(rhs: Variant) -> Variant {
264 let rhs = as_type!(rhs, Boolean, Variant::Empty);
265 (!rhs).into()
266 }
267
268 fn and(lhs: Variant, rhs: Variant) -> Variant {
269 let lhs = as_type!(lhs, Boolean, Variant::Empty);
270 let rhs = as_type!(rhs, Boolean, Variant::Empty);
271
272 (lhs && rhs).into()
273 }
274
275 fn or(lhs: Variant, rhs: Variant) -> Variant {
276 let lhs = as_type!(lhs, Boolean, Variant::Empty);
277 let rhs = as_type!(rhs, Boolean, Variant::Empty);
278
279 (lhs || rhs).into()
280 }
281
282 fn like(lhs: Variant, rhs: Variant) -> bool {
283 let lhs = as_type!(lhs, String, false);
284 let rhs = as_type!(rhs, String, false);
285 let Ok(re) = like_to_regex(rhs.as_ref()) else {
286 return false;
287 };
288 re.is_match(lhs.as_ref())
289 }
290
291 fn cast(lhs: Variant, rhs: Variant) -> Variant {
292 let type_id = match rhs {
293 Variant::NodeId(n) => {
294 let Ok(t) = VariantTypeId::try_from(&*n) else {
295 return Variant::Empty;
296 };
297 t
298 }
299 Variant::ExpandedNodeId(n) => {
300 let Ok(t) = VariantTypeId::try_from(&n.node_id) else {
301 return Variant::Empty;
302 };
303 t
304 }
305 _ => return Variant::Empty,
306 };
307 lhs.cast(type_id)
308 }
309
310 fn convert(lhs: Variant, rhs: Variant) -> (Variant, Variant) {
311 let lhs_type = lhs.type_id();
312 match lhs_type.precedence().cmp(&rhs.type_id().precedence()) {
313 std::cmp::Ordering::Less => {
314 let c = rhs.convert(lhs_type);
315 (lhs, c)
316 }
317 std::cmp::Ordering::Equal => (lhs, rhs),
318 std::cmp::Ordering::Greater => (lhs.convert(rhs.type_id()), rhs),
319 }
320 }
321
322 fn bitwise_op(lhs: Variant, rhs: Variant, op: BitOperation) -> Variant {
323 let (lhs, rhs) = Self::convert(lhs, rhs);
324
325 match (lhs, rhs) {
326 (Variant::SByte(lhs), Variant::SByte(rhs)) => bw_op!(lhs, rhs, op),
327 (Variant::Byte(lhs), Variant::Byte(rhs)) => bw_op!(lhs, rhs, op),
328 (Variant::Int16(lhs), Variant::Int16(rhs)) => bw_op!(lhs, rhs, op),
329 (Variant::Int32(lhs), Variant::Int32(rhs)) => bw_op!(lhs, rhs, op),
330 (Variant::Int64(lhs), Variant::Int64(rhs)) => bw_op!(lhs, rhs, op),
331 (Variant::UInt16(lhs), Variant::UInt16(rhs)) => bw_op!(lhs, rhs, op),
332 (Variant::UInt32(lhs), Variant::UInt32(rhs)) => bw_op!(lhs, rhs, op),
333 (Variant::UInt64(lhs), Variant::UInt64(rhs)) => bw_op!(lhs, rhs, op),
334 _ => Variant::Empty,
335 }
336 }
337
338 fn compare_op(lhs: Variant, rhs: Variant) -> Option<Ordering> {
339 let (lhs, rhs) = Self::convert(lhs, rhs);
340 match (lhs, rhs) {
341 (Variant::SByte(lhs), Variant::SByte(rhs)) => Some(lhs.cmp(&rhs)),
342 (Variant::Byte(lhs), Variant::Byte(rhs)) => Some(lhs.cmp(&rhs)),
343 (Variant::Int16(lhs), Variant::Int16(rhs)) => Some(lhs.cmp(&rhs)),
344 (Variant::Int32(lhs), Variant::Int32(rhs)) => Some(lhs.cmp(&rhs)),
345 (Variant::Int64(lhs), Variant::Int64(rhs)) => Some(lhs.cmp(&rhs)),
346 (Variant::UInt16(lhs), Variant::UInt16(rhs)) => Some(lhs.cmp(&rhs)),
347 (Variant::UInt32(lhs), Variant::UInt32(rhs)) => Some(lhs.cmp(&rhs)),
348 (Variant::UInt64(lhs), Variant::UInt64(rhs)) => Some(lhs.cmp(&rhs)),
349 (Variant::Double(lhs), Variant::Double(rhs)) => Some(lhs.total_cmp(&rhs)),
350 (Variant::Float(lhs), Variant::Float(rhs)) => Some(lhs.total_cmp(&rhs)),
351 (Variant::Boolean(lhs), Variant::Boolean(rhs)) => Some(lhs.cmp(&rhs)),
352 _ => None,
353 }
354 }
355
356 fn of_type(lhs: Variant, item: impl AttributeQueryable, type_tree: &dyn TypeTree) -> bool {
357 let type_id = as_type!(lhs, NodeId, false);
358
359 let item_type = item.get_type();
360 type_tree.is_subtype_of(&item_type, &type_id)
361 }
362}
363
364fn get_field(event: &dyn Event, attr: &ParsedSimpleAttributeOperand) -> Variant {
365 event.get_field(
366 &attr.type_definition_id,
367 attr.attribute_id,
368 &attr.index_range,
369 &attr.browse_path,
370 )
371}
372
373fn like_to_regex(v: &str) -> Result<Regex, ()> {
375 let mut pattern = String::with_capacity(v.len() * 2);
377
378 let mut in_list = false;
379
380 let v = v.chars().collect::<Vec<char>>();
382
383 pattern.push('^');
384 v.iter().enumerate().for_each(|(i, c)| {
385 if in_list {
386 if *c == ']' && (i == 0 || v[i - 1] != '\\') {
387 in_list = false;
389 pattern.push(*c);
390 } else {
391 match c {
393 '$' | '(' | ')' | '.' | '+' | '*' | '?' => {
394 pattern.push('\\');
396 pattern.push(*c);
397 }
398 _ => {
399 pattern.push(*c);
401 }
402 }
403 }
404 } else {
405 match c {
406 '$' | '^' | '(' | ')' | '.' | '+' | '*' | '?' => {
407 pattern.push('\\');
409 pattern.push(*c);
410 }
411 '[' => {
412 if i == 0 || v[i - 1] != '\\' {
414 in_list = true;
416 }
417 pattern.push(*c);
418 }
419 '%' => {
420 if i == 0 || v[i - 1] != '\\' {
421 pattern.push_str(".*");
423 } else {
424 pattern.push(*c);
425 }
426 }
427 '_' => {
428 if i == 0 || v[i - 1] != '\\' {
429 pattern.push('?');
431 } else {
432 let _ = pattern.pop();
434 pattern.push(*c);
435 }
436 }
437 _ => {
438 pattern.push(*c);
439 }
440 }
441 }
442 });
443 pattern.push('$');
444 Regex::new(&pattern).map_err(|err| {
445 error!("Problem parsing, error = {}", err);
446 })
447}
448
449#[cfg(test)]
450mod tests {
451 use regex::Regex;
452
453 use crate::{
454 events::evaluate::like_to_regex, BaseEventType, DefaultTypeTree, Event, ParsedContentFilter,
455 };
456 use opcua_types::{
457 AttributeId, ByteString, ContentFilter, ContentFilterElement, DateTime, FilterOperator,
458 LocalizedText, NodeClass, NodeId, NumericRange, ObjectTypeId, Operand,
459 };
460
461 fn compare_regex(r1: Regex, r2: Regex) {
462 assert_eq!(r1.as_str(), r2.as_str());
463 }
464
465 #[test]
466 fn like_to_regex_tests() {
467 compare_regex(like_to_regex("").unwrap(), Regex::new("^$").unwrap());
468 compare_regex(like_to_regex("^$").unwrap(), Regex::new(r"^\^\$$").unwrap());
469 compare_regex(like_to_regex("%").unwrap(), Regex::new("^.*$").unwrap());
470 compare_regex(like_to_regex("[%]").unwrap(), Regex::new("^[%]$").unwrap());
471 compare_regex(like_to_regex("[_]").unwrap(), Regex::new("^[_]$").unwrap());
472 compare_regex(
473 like_to_regex(r"[\]]").unwrap(),
474 Regex::new(r"^[\]]$").unwrap(),
475 );
476 compare_regex(
477 like_to_regex("[$().+*?]").unwrap(),
478 Regex::new(r"^[\$\(\)\.\+\*\?]$").unwrap(),
479 );
480 compare_regex(like_to_regex("_").unwrap(), Regex::new("^?$").unwrap());
481 compare_regex(
482 like_to_regex("[a-z]").unwrap(),
483 Regex::new("^[a-z]$").unwrap(),
484 );
485 compare_regex(
486 like_to_regex("[abc]").unwrap(),
487 Regex::new("^[abc]$").unwrap(),
488 );
489 compare_regex(
490 like_to_regex(r"\[\]").unwrap(),
491 Regex::new(r"^\[\]$").unwrap(),
492 );
493 compare_regex(
494 like_to_regex("[^0-9]").unwrap(),
495 Regex::new("^[^0-9]$").unwrap(),
496 );
497
498 let re = like_to_regex("Th[ia][ts]%").unwrap();
500 assert!(re.is_match("That is fine"));
501 assert!(re.is_match("This is fine"));
502 assert!(re.is_match("That as one"));
503 assert!(!re.is_match("Then at any")); let re = like_to_regex("%en%").unwrap();
506 assert!(re.is_match("entail"));
507 assert!(re.is_match("green"));
508 assert!(re.is_match("content"));
509
510 let re = like_to_regex("abc[13-68]").unwrap();
511 assert!(re.is_match("abc1"));
512 assert!(!re.is_match("abc2"));
513 assert!(re.is_match("abc3"));
514 assert!(re.is_match("abc4"));
515 assert!(re.is_match("abc5"));
516 assert!(re.is_match("abc6"));
517 assert!(!re.is_match("abc7"));
518 assert!(re.is_match("abc8"));
519
520 let re = like_to_regex("ABC[^13-5]").unwrap();
521 assert!(!re.is_match("ABC1"));
522 assert!(re.is_match("ABC2"));
523 assert!(!re.is_match("ABC3"));
524 assert!(!re.is_match("ABC4"));
525 assert!(!re.is_match("ABC5"));
526 }
527
528 mod opcua {
529 pub(super) use crate as nodes;
530 pub(super) use opcua_types as types;
531 }
532
533 #[derive(Event)]
534 #[opcua(identifier = "i=123", namespace = "my:namespace:uri")]
535 struct TestEvent {
536 base: BaseEventType,
537 own_namespace_index: u16,
538 field: i32,
539 }
540
541 impl TestEvent {
542 pub(super) fn new(
543 type_id: impl Into<NodeId>,
544 event_id: ByteString,
545 message: impl Into<LocalizedText>,
546 time: DateTime,
547 field: i32,
548 ) -> Self {
549 Self {
550 base: BaseEventType::new(type_id, event_id, message, time),
551 field,
552 own_namespace_index: 1,
553 }
554 }
555 }
556
557 fn type_tree() -> DefaultTypeTree {
558 let mut type_tree = DefaultTypeTree::new();
559
560 let event_type_id = NodeId::new(1, 123);
561 type_tree.add_type_node(
562 &event_type_id,
563 &ObjectTypeId::BaseEventType.into(),
564 NodeClass::ObjectType,
565 );
566 type_tree.add_type_property(
567 &NodeId::new(1, "field"),
568 &event_type_id,
569 &[&"Field".into()],
570 NodeClass::Variable,
571 );
572
573 type_tree
574 }
575
576 fn filter(
577 elements: Vec<ContentFilterElement>,
578 type_tree: &DefaultTypeTree,
579 ) -> ParsedContentFilter {
580 let (_, f) = ParsedContentFilter::parse(
581 ContentFilter {
582 elements: Some(elements),
583 },
584 type_tree,
585 false,
586 &[FilterOperator::InView, FilterOperator::RelatedTo],
587 );
588 f.unwrap()
589 }
590
591 fn filter_elem(operands: &[Operand], op: FilterOperator) -> ContentFilterElement {
592 ContentFilterElement {
593 filter_operator: op,
594 filter_operands: Some(operands.iter().map(|o| o.into()).collect()),
595 }
596 }
597
598 fn event(field: i32) -> TestEvent {
599 TestEvent::new(
600 NodeId::new(1, 123),
601 ByteString::null(),
602 "message",
603 DateTime::now(),
604 field,
605 )
606 }
607
608 #[test]
609 fn test_equality_filter() {
610 let type_tree = type_tree();
611 let f = filter(
612 vec![filter_elem(
613 &[Operand::literal(10), Operand::literal(9)],
614 FilterOperator::Equals,
615 )],
616 &type_tree,
617 );
618 let event = event(2);
619 assert!(!f.evaluate(&event as &dyn Event, &type_tree));
620 let f = filter(
621 vec![filter_elem(
622 &[
623 Operand::literal(2),
624 Operand::simple_attribute(
625 ObjectTypeId::BaseEventType,
626 "Field",
627 AttributeId::Value,
628 NumericRange::None,
629 ),
630 ],
631 FilterOperator::Equals,
632 )],
633 &type_tree,
634 );
635 assert!(f.evaluate(&event as &dyn Event, &type_tree));
636 }
637
638 #[test]
639 fn test_lt_filter() {
640 let type_tree = type_tree();
641 let f = filter(
642 vec![filter_elem(
643 &[Operand::literal(10), Operand::literal(9)],
644 FilterOperator::LessThan,
645 )],
646 &type_tree,
647 );
648 let event = event(2);
649 assert!(!f.evaluate(&event as &dyn Event, &type_tree));
650 let f = filter(
651 vec![filter_elem(
652 &[
653 Operand::literal(1),
654 Operand::simple_attribute(
655 ObjectTypeId::BaseEventType,
656 "Field",
657 AttributeId::Value,
658 NumericRange::None,
659 ),
660 ],
661 FilterOperator::LessThan,
662 )],
663 &type_tree,
664 );
665 assert!(f.evaluate(&event as &dyn Event, &type_tree));
666 let f = filter(
667 vec![filter_elem(
668 &[
669 Operand::literal(2),
670 Operand::simple_attribute(
671 ObjectTypeId::BaseEventType,
672 "Field",
673 AttributeId::Value,
674 NumericRange::None,
675 ),
676 ],
677 FilterOperator::LessThan,
678 )],
679 &type_tree,
680 );
681 assert!(!f.evaluate(&event as &dyn Event, &type_tree));
682 }
683
684 #[test]
685 fn test_lte_filter() {
686 let type_tree = type_tree();
687 let f = filter(
688 vec![filter_elem(
689 &[Operand::literal(10), Operand::literal(9)],
690 FilterOperator::LessThanOrEqual,
691 )],
692 &type_tree,
693 );
694 let event = event(2);
695 assert!(!f.evaluate(&event as &dyn Event, &type_tree));
696 let f = filter(
697 vec![filter_elem(
698 &[
699 Operand::literal(1),
700 Operand::simple_attribute(
701 ObjectTypeId::BaseEventType,
702 "Field",
703 AttributeId::Value,
704 NumericRange::None,
705 ),
706 ],
707 FilterOperator::LessThanOrEqual,
708 )],
709 &type_tree,
710 );
711 assert!(f.evaluate(&event as &dyn Event, &type_tree));
712 let f = filter(
713 vec![filter_elem(
714 &[
715 Operand::literal(2),
716 Operand::simple_attribute(
717 ObjectTypeId::BaseEventType,
718 "Field",
719 AttributeId::Value,
720 NumericRange::None,
721 ),
722 ],
723 FilterOperator::LessThanOrEqual,
724 )],
725 &type_tree,
726 );
727 assert!(f.evaluate(&event as &dyn Event, &type_tree));
728 }
729
730 #[test]
731 fn test_gt_filter() {
732 let type_tree = type_tree();
733 let f = filter(
734 vec![filter_elem(
735 &[Operand::literal(10), Operand::literal(9)],
736 FilterOperator::GreaterThan,
737 )],
738 &type_tree,
739 );
740 let event = event(2);
741 assert!(f.evaluate(&event as &dyn Event, &type_tree));
742 let f = filter(
743 vec![filter_elem(
744 &[
745 Operand::literal(3),
746 Operand::simple_attribute(
747 ObjectTypeId::BaseEventType,
748 "Field",
749 AttributeId::Value,
750 NumericRange::None,
751 ),
752 ],
753 FilterOperator::GreaterThan,
754 )],
755 &type_tree,
756 );
757 assert!(f.evaluate(&event as &dyn Event, &type_tree));
758 let f = filter(
759 vec![filter_elem(
760 &[
761 Operand::literal(2),
762 Operand::simple_attribute(
763 ObjectTypeId::BaseEventType,
764 "Field",
765 AttributeId::Value,
766 NumericRange::None,
767 ),
768 ],
769 FilterOperator::GreaterThan,
770 )],
771 &type_tree,
772 );
773 assert!(!f.evaluate(&event as &dyn Event, &type_tree));
774 }
775
776 #[test]
777 fn test_gte_filter() {
778 let type_tree = type_tree();
779 let f = filter(
780 vec![filter_elem(
781 &[Operand::literal(10), Operand::literal(9)],
782 FilterOperator::GreaterThanOrEqual,
783 )],
784 &type_tree,
785 );
786 let event = event(2);
787 assert!(f.evaluate(&event as &dyn Event, &type_tree));
788 let f = filter(
789 vec![filter_elem(
790 &[
791 Operand::literal(3),
792 Operand::simple_attribute(
793 ObjectTypeId::BaseEventType,
794 "Field",
795 AttributeId::Value,
796 NumericRange::None,
797 ),
798 ],
799 FilterOperator::GreaterThanOrEqual,
800 )],
801 &type_tree,
802 );
803 assert!(f.evaluate(&event as &dyn Event, &type_tree));
804 let f = filter(
805 vec![filter_elem(
806 &[
807 Operand::literal(2),
808 Operand::simple_attribute(
809 ObjectTypeId::BaseEventType,
810 "Field",
811 AttributeId::Value,
812 NumericRange::None,
813 ),
814 ],
815 FilterOperator::GreaterThanOrEqual,
816 )],
817 &type_tree,
818 );
819 assert!(f.evaluate(&event as &dyn Event, &type_tree));
820 }
821
822 #[test]
823 fn test_not_filter() {
824 let type_tree = type_tree();
825 let f = filter(
826 vec![filter_elem(&[Operand::literal(false)], FilterOperator::Not)],
827 &type_tree,
828 );
829 let evt = event(2);
830 assert!(f.evaluate(&evt as &dyn Event, &type_tree));
831
832 let f = filter(
833 vec![
834 filter_elem(&[Operand::element(1)], FilterOperator::Not),
835 filter_elem(
836 &[
837 Operand::simple_attribute(
838 ObjectTypeId::BaseEventType,
839 "Field",
840 AttributeId::Value,
841 NumericRange::None,
842 ),
843 Operand::literal(3),
844 ],
845 FilterOperator::Equals,
846 ),
847 ],
848 &type_tree,
849 );
850 assert!(f.evaluate(&evt as &dyn Event, &type_tree));
851 let evt = event(3);
852 assert!(!f.evaluate(&evt as &dyn Event, &type_tree));
853 }
854
855 #[test]
856 fn test_between_filter() {
857 let type_tree = type_tree();
858 let f = filter(
859 vec![filter_elem(
860 &[
861 Operand::literal(9),
862 Operand::literal(8),
863 Operand::literal(10),
864 ],
865 FilterOperator::Between,
866 )],
867 &type_tree,
868 );
869 let evt = event(2);
870 assert!(f.evaluate(&evt as &dyn Event, &type_tree));
871 let f = filter(
872 vec![filter_elem(
873 &[
874 Operand::simple_attribute(
875 ObjectTypeId::BaseEventType,
876 "Field",
877 AttributeId::Value,
878 NumericRange::None,
879 ),
880 Operand::literal(8),
881 Operand::literal(10),
882 ],
883 FilterOperator::Between,
884 )],
885 &type_tree,
886 );
887 assert!(!f.evaluate(&evt as &dyn Event, &type_tree));
888 let evt = event(9);
889 assert!(f.evaluate(&evt as &dyn Event, &type_tree));
890 let evt = event(10);
891 assert!(f.evaluate(&evt as &dyn Event, &type_tree));
892 let evt = event(8);
893 assert!(f.evaluate(&evt as &dyn Event, &type_tree));
894 let evt = event(11);
895 assert!(!f.evaluate(&evt as &dyn Event, &type_tree));
896 }
897
898 #[test]
899 fn test_and_filter() {
900 let type_tree = type_tree();
901 let f = filter(
902 vec![filter_elem(
903 &[Operand::literal(true), Operand::literal(false)],
904 FilterOperator::And,
905 )],
906 &type_tree,
907 );
908 let evt = event(2);
909 assert!(!f.evaluate(&evt as &dyn Event, &type_tree));
910 let f = filter(
911 vec![
912 filter_elem(
913 &[Operand::element(1), Operand::element(2)],
914 FilterOperator::And,
915 ),
916 filter_elem(
917 &[
918 Operand::simple_attribute(
919 ObjectTypeId::BaseEventType,
920 "Field",
921 AttributeId::Value,
922 NumericRange::None,
923 ),
924 Operand::literal(3),
925 ],
926 FilterOperator::Equals,
927 ),
928 filter_elem(
929 &[Operand::literal(3), Operand::literal(3)],
930 FilterOperator::Equals,
931 ),
932 ],
933 &type_tree,
934 );
935
936 assert!(!f.evaluate(&evt as &dyn Event, &type_tree));
937 let evt = event(3);
938 assert!(f.evaluate(&evt as &dyn Event, &type_tree));
939 }
940
941 #[test]
942 fn test_or_filter() {
943 let type_tree = type_tree();
944 let f = filter(
945 vec![filter_elem(
946 &[Operand::literal(true), Operand::literal(false)],
947 FilterOperator::Or,
948 )],
949 &type_tree,
950 );
951 let evt = event(2);
952 assert!(f.evaluate(&evt as &dyn Event, &type_tree));
953 let f = filter(
954 vec![
955 filter_elem(
956 &[Operand::element(1), Operand::element(2)],
957 FilterOperator::Or,
958 ),
959 filter_elem(
960 &[
961 Operand::simple_attribute(
962 ObjectTypeId::BaseEventType,
963 "Field",
964 AttributeId::Value,
965 NumericRange::None,
966 ),
967 Operand::literal(3),
968 ],
969 FilterOperator::Equals,
970 ),
971 filter_elem(
972 &[Operand::literal(3), Operand::literal(2)],
973 FilterOperator::Equals,
974 ),
975 ],
976 &type_tree,
977 );
978
979 assert!(!f.evaluate(&evt as &dyn Event, &type_tree));
980 let evt = event(3);
981 assert!(f.evaluate(&evt as &dyn Event, &type_tree));
982 }
983
984 #[test]
985 fn test_in_list() {
986 let type_tree = type_tree();
987 let f = filter(
988 vec![filter_elem(
989 &[
990 Operand::literal(1),
991 Operand::literal(2),
992 Operand::literal(3),
993 Operand::literal(1),
994 ],
995 FilterOperator::InList,
996 )],
997 &type_tree,
998 );
999 let evt = event(2);
1000 assert!(f.evaluate(&evt as &dyn Event, &type_tree));
1001 let f = filter(
1002 vec![filter_elem(
1003 &[
1004 Operand::simple_attribute(
1005 ObjectTypeId::BaseEventType,
1006 "Field",
1007 AttributeId::Value,
1008 NumericRange::None,
1009 ),
1010 Operand::literal(1),
1011 Operand::literal(2),
1012 Operand::literal(3),
1013 ],
1014 FilterOperator::InList,
1015 )],
1016 &type_tree,
1017 );
1018 assert!(f.evaluate(&evt as &dyn Event, &type_tree));
1019 let evt = event(4);
1020 assert!(!f.evaluate(&evt as &dyn Event, &type_tree));
1021 }
1022
1023 #[test]
1024 fn test_of_type() {
1025 let type_tree = type_tree();
1026 let f = filter(
1027 vec![filter_elem(
1028 &[Operand::literal(NodeId::new(1, 123))],
1029 FilterOperator::OfType,
1030 )],
1031 &type_tree,
1032 );
1033 let evt = event(2);
1034 assert!(f.evaluate(&evt as &dyn Event, &type_tree));
1035
1036 let f = filter(
1038 vec![filter_elem(
1039 &[Operand::literal(NodeId::new(1, 456))],
1040 FilterOperator::OfType,
1041 )],
1042 &type_tree,
1043 );
1044 let evt = event(2);
1045 assert!(!f.evaluate(&evt as &dyn Event, &type_tree));
1046
1047 let f = filter(
1049 vec![filter_elem(
1050 &[Operand::literal(ObjectTypeId::BaseEventType)],
1051 FilterOperator::OfType,
1052 )],
1053 &type_tree,
1054 );
1055 let evt = event(2);
1056 assert!(f.evaluate(&evt as &dyn Event, &type_tree));
1057 }
1058}