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 '%' if i == 0 || v[i - 1] != '\\' => {
421 pattern.push_str(".*");
422 }
423 '_' => {
424 if i == 0 || v[i - 1] != '\\' {
425 pattern.push('?');
427 } else {
428 let _ = pattern.pop();
430 pattern.push(*c);
431 }
432 }
433 _ => {
434 pattern.push(*c);
435 }
436 }
437 }
438 });
439 pattern.push('$');
440 Regex::new(&pattern).map_err(|err| {
441 error!("Problem parsing, error = {}", err);
442 })
443}
444
445#[cfg(test)]
446mod tests {
447 use regex::Regex;
448
449 use crate::{
450 events::evaluate::like_to_regex, BaseEventType, DefaultTypeTree, Event, ParsedContentFilter,
451 };
452 use opcua_types::{
453 AttributeId, ByteString, ContentFilter, ContentFilterElement, DateTime, FilterOperator,
454 LocalizedText, NodeClass, NodeId, NumericRange, ObjectTypeId, Operand,
455 };
456
457 fn compare_regex(r1: Regex, r2: Regex) {
458 assert_eq!(r1.as_str(), r2.as_str());
459 }
460
461 #[test]
462 fn like_to_regex_tests() {
463 compare_regex(like_to_regex("").unwrap(), Regex::new("^$").unwrap());
464 compare_regex(like_to_regex("^$").unwrap(), Regex::new(r"^\^\$$").unwrap());
465 compare_regex(like_to_regex("%").unwrap(), Regex::new("^.*$").unwrap());
466 compare_regex(like_to_regex("[%]").unwrap(), Regex::new("^[%]$").unwrap());
467 compare_regex(like_to_regex("[_]").unwrap(), Regex::new("^[_]$").unwrap());
468 compare_regex(
469 like_to_regex(r"[\]]").unwrap(),
470 Regex::new(r"^[\]]$").unwrap(),
471 );
472 compare_regex(
473 like_to_regex("[$().+*?]").unwrap(),
474 Regex::new(r"^[\$\(\)\.\+\*\?]$").unwrap(),
475 );
476 compare_regex(like_to_regex("_").unwrap(), Regex::new("^?$").unwrap());
477 compare_regex(
478 like_to_regex("[a-z]").unwrap(),
479 Regex::new("^[a-z]$").unwrap(),
480 );
481 compare_regex(
482 like_to_regex("[abc]").unwrap(),
483 Regex::new("^[abc]$").unwrap(),
484 );
485 compare_regex(
486 like_to_regex(r"\[\]").unwrap(),
487 Regex::new(r"^\[\]$").unwrap(),
488 );
489 compare_regex(
490 like_to_regex("[^0-9]").unwrap(),
491 Regex::new("^[^0-9]$").unwrap(),
492 );
493
494 let re = like_to_regex("Th[ia][ts]%").unwrap();
496 assert!(re.is_match("That is fine"));
497 assert!(re.is_match("This is fine"));
498 assert!(re.is_match("That as one"));
499 assert!(!re.is_match("Then at any")); let re = like_to_regex("%en%").unwrap();
502 assert!(re.is_match("entail"));
503 assert!(re.is_match("green"));
504 assert!(re.is_match("content"));
505
506 let re = like_to_regex("abc[13-68]").unwrap();
507 assert!(re.is_match("abc1"));
508 assert!(!re.is_match("abc2"));
509 assert!(re.is_match("abc3"));
510 assert!(re.is_match("abc4"));
511 assert!(re.is_match("abc5"));
512 assert!(re.is_match("abc6"));
513 assert!(!re.is_match("abc7"));
514 assert!(re.is_match("abc8"));
515
516 let re = like_to_regex("ABC[^13-5]").unwrap();
517 assert!(!re.is_match("ABC1"));
518 assert!(re.is_match("ABC2"));
519 assert!(!re.is_match("ABC3"));
520 assert!(!re.is_match("ABC4"));
521 assert!(!re.is_match("ABC5"));
522 }
523
524 mod opcua {
525 pub(super) use crate as nodes;
526 pub(super) use opcua_types as types;
527 }
528
529 #[derive(Event)]
530 #[opcua(identifier = "i=123", namespace = "my:namespace:uri")]
531 struct TestEvent {
532 base: BaseEventType,
533 own_namespace_index: u16,
534 field: i32,
535 }
536
537 impl TestEvent {
538 pub(super) fn new(
539 type_id: impl Into<NodeId>,
540 event_id: ByteString,
541 message: impl Into<LocalizedText>,
542 time: DateTime,
543 field: i32,
544 ) -> Self {
545 Self {
546 base: BaseEventType::new(type_id, event_id, message, time),
547 field,
548 own_namespace_index: 1,
549 }
550 }
551 }
552
553 fn type_tree() -> DefaultTypeTree {
554 let mut type_tree = DefaultTypeTree::new();
555
556 let event_type_id = NodeId::new(1, 123);
557 type_tree.add_type_node(
558 &event_type_id,
559 &ObjectTypeId::BaseEventType.into(),
560 NodeClass::ObjectType,
561 );
562 type_tree.add_type_property(
563 &NodeId::new(1, "field"),
564 &event_type_id,
565 &[&"Field".into()],
566 NodeClass::Variable,
567 );
568
569 type_tree
570 }
571
572 fn filter(
573 elements: Vec<ContentFilterElement>,
574 type_tree: &DefaultTypeTree,
575 ) -> ParsedContentFilter {
576 let (_, f) = ParsedContentFilter::parse(
577 ContentFilter {
578 elements: Some(elements),
579 },
580 type_tree,
581 false,
582 &[FilterOperator::InView, FilterOperator::RelatedTo],
583 );
584 f.unwrap()
585 }
586
587 fn filter_elem(operands: &[Operand], op: FilterOperator) -> ContentFilterElement {
588 ContentFilterElement {
589 filter_operator: op,
590 filter_operands: Some(operands.iter().map(|o| o.into()).collect()),
591 }
592 }
593
594 fn event(field: i32) -> TestEvent {
595 TestEvent::new(
596 NodeId::new(1, 123),
597 ByteString::null(),
598 "message",
599 DateTime::now(),
600 field,
601 )
602 }
603
604 #[test]
605 fn test_equality_filter() {
606 let type_tree = type_tree();
607 let f = filter(
608 vec![filter_elem(
609 &[Operand::literal(10), Operand::literal(9)],
610 FilterOperator::Equals,
611 )],
612 &type_tree,
613 );
614 let event = event(2);
615 assert!(!f.evaluate(&event as &dyn Event, &type_tree));
616 let f = filter(
617 vec![filter_elem(
618 &[
619 Operand::literal(2),
620 Operand::simple_attribute(
621 ObjectTypeId::BaseEventType,
622 "Field",
623 AttributeId::Value,
624 NumericRange::None,
625 ),
626 ],
627 FilterOperator::Equals,
628 )],
629 &type_tree,
630 );
631 assert!(f.evaluate(&event as &dyn Event, &type_tree));
632 }
633
634 #[test]
635 fn test_lt_filter() {
636 let type_tree = type_tree();
637 let f = filter(
638 vec![filter_elem(
639 &[Operand::literal(10), Operand::literal(9)],
640 FilterOperator::LessThan,
641 )],
642 &type_tree,
643 );
644 let event = event(2);
645 assert!(!f.evaluate(&event as &dyn Event, &type_tree));
646 let f = filter(
647 vec![filter_elem(
648 &[
649 Operand::literal(1),
650 Operand::simple_attribute(
651 ObjectTypeId::BaseEventType,
652 "Field",
653 AttributeId::Value,
654 NumericRange::None,
655 ),
656 ],
657 FilterOperator::LessThan,
658 )],
659 &type_tree,
660 );
661 assert!(f.evaluate(&event as &dyn Event, &type_tree));
662 let f = filter(
663 vec![filter_elem(
664 &[
665 Operand::literal(2),
666 Operand::simple_attribute(
667 ObjectTypeId::BaseEventType,
668 "Field",
669 AttributeId::Value,
670 NumericRange::None,
671 ),
672 ],
673 FilterOperator::LessThan,
674 )],
675 &type_tree,
676 );
677 assert!(!f.evaluate(&event as &dyn Event, &type_tree));
678 }
679
680 #[test]
681 fn test_lte_filter() {
682 let type_tree = type_tree();
683 let f = filter(
684 vec![filter_elem(
685 &[Operand::literal(10), Operand::literal(9)],
686 FilterOperator::LessThanOrEqual,
687 )],
688 &type_tree,
689 );
690 let event = event(2);
691 assert!(!f.evaluate(&event as &dyn Event, &type_tree));
692 let f = filter(
693 vec![filter_elem(
694 &[
695 Operand::literal(1),
696 Operand::simple_attribute(
697 ObjectTypeId::BaseEventType,
698 "Field",
699 AttributeId::Value,
700 NumericRange::None,
701 ),
702 ],
703 FilterOperator::LessThanOrEqual,
704 )],
705 &type_tree,
706 );
707 assert!(f.evaluate(&event as &dyn Event, &type_tree));
708 let f = filter(
709 vec![filter_elem(
710 &[
711 Operand::literal(2),
712 Operand::simple_attribute(
713 ObjectTypeId::BaseEventType,
714 "Field",
715 AttributeId::Value,
716 NumericRange::None,
717 ),
718 ],
719 FilterOperator::LessThanOrEqual,
720 )],
721 &type_tree,
722 );
723 assert!(f.evaluate(&event as &dyn Event, &type_tree));
724 }
725
726 #[test]
727 fn test_gt_filter() {
728 let type_tree = type_tree();
729 let f = filter(
730 vec![filter_elem(
731 &[Operand::literal(10), Operand::literal(9)],
732 FilterOperator::GreaterThan,
733 )],
734 &type_tree,
735 );
736 let event = event(2);
737 assert!(f.evaluate(&event as &dyn Event, &type_tree));
738 let f = filter(
739 vec![filter_elem(
740 &[
741 Operand::literal(3),
742 Operand::simple_attribute(
743 ObjectTypeId::BaseEventType,
744 "Field",
745 AttributeId::Value,
746 NumericRange::None,
747 ),
748 ],
749 FilterOperator::GreaterThan,
750 )],
751 &type_tree,
752 );
753 assert!(f.evaluate(&event as &dyn Event, &type_tree));
754 let f = filter(
755 vec![filter_elem(
756 &[
757 Operand::literal(2),
758 Operand::simple_attribute(
759 ObjectTypeId::BaseEventType,
760 "Field",
761 AttributeId::Value,
762 NumericRange::None,
763 ),
764 ],
765 FilterOperator::GreaterThan,
766 )],
767 &type_tree,
768 );
769 assert!(!f.evaluate(&event as &dyn Event, &type_tree));
770 }
771
772 #[test]
773 fn test_gte_filter() {
774 let type_tree = type_tree();
775 let f = filter(
776 vec![filter_elem(
777 &[Operand::literal(10), Operand::literal(9)],
778 FilterOperator::GreaterThanOrEqual,
779 )],
780 &type_tree,
781 );
782 let event = event(2);
783 assert!(f.evaluate(&event as &dyn Event, &type_tree));
784 let f = filter(
785 vec![filter_elem(
786 &[
787 Operand::literal(3),
788 Operand::simple_attribute(
789 ObjectTypeId::BaseEventType,
790 "Field",
791 AttributeId::Value,
792 NumericRange::None,
793 ),
794 ],
795 FilterOperator::GreaterThanOrEqual,
796 )],
797 &type_tree,
798 );
799 assert!(f.evaluate(&event as &dyn Event, &type_tree));
800 let f = filter(
801 vec![filter_elem(
802 &[
803 Operand::literal(2),
804 Operand::simple_attribute(
805 ObjectTypeId::BaseEventType,
806 "Field",
807 AttributeId::Value,
808 NumericRange::None,
809 ),
810 ],
811 FilterOperator::GreaterThanOrEqual,
812 )],
813 &type_tree,
814 );
815 assert!(f.evaluate(&event as &dyn Event, &type_tree));
816 }
817
818 #[test]
819 fn test_not_filter() {
820 let type_tree = type_tree();
821 let f = filter(
822 vec![filter_elem(&[Operand::literal(false)], FilterOperator::Not)],
823 &type_tree,
824 );
825 let evt = event(2);
826 assert!(f.evaluate(&evt as &dyn Event, &type_tree));
827
828 let f = filter(
829 vec![
830 filter_elem(&[Operand::element(1)], FilterOperator::Not),
831 filter_elem(
832 &[
833 Operand::simple_attribute(
834 ObjectTypeId::BaseEventType,
835 "Field",
836 AttributeId::Value,
837 NumericRange::None,
838 ),
839 Operand::literal(3),
840 ],
841 FilterOperator::Equals,
842 ),
843 ],
844 &type_tree,
845 );
846 assert!(f.evaluate(&evt as &dyn Event, &type_tree));
847 let evt = event(3);
848 assert!(!f.evaluate(&evt as &dyn Event, &type_tree));
849 }
850
851 #[test]
852 fn test_between_filter() {
853 let type_tree = type_tree();
854 let f = filter(
855 vec![filter_elem(
856 &[
857 Operand::literal(9),
858 Operand::literal(8),
859 Operand::literal(10),
860 ],
861 FilterOperator::Between,
862 )],
863 &type_tree,
864 );
865 let evt = event(2);
866 assert!(f.evaluate(&evt as &dyn Event, &type_tree));
867 let f = filter(
868 vec![filter_elem(
869 &[
870 Operand::simple_attribute(
871 ObjectTypeId::BaseEventType,
872 "Field",
873 AttributeId::Value,
874 NumericRange::None,
875 ),
876 Operand::literal(8),
877 Operand::literal(10),
878 ],
879 FilterOperator::Between,
880 )],
881 &type_tree,
882 );
883 assert!(!f.evaluate(&evt as &dyn Event, &type_tree));
884 let evt = event(9);
885 assert!(f.evaluate(&evt as &dyn Event, &type_tree));
886 let evt = event(10);
887 assert!(f.evaluate(&evt as &dyn Event, &type_tree));
888 let evt = event(8);
889 assert!(f.evaluate(&evt as &dyn Event, &type_tree));
890 let evt = event(11);
891 assert!(!f.evaluate(&evt as &dyn Event, &type_tree));
892 }
893
894 #[test]
895 fn test_and_filter() {
896 let type_tree = type_tree();
897 let f = filter(
898 vec![filter_elem(
899 &[Operand::literal(true), Operand::literal(false)],
900 FilterOperator::And,
901 )],
902 &type_tree,
903 );
904 let evt = event(2);
905 assert!(!f.evaluate(&evt as &dyn Event, &type_tree));
906 let f = filter(
907 vec![
908 filter_elem(
909 &[Operand::element(1), Operand::element(2)],
910 FilterOperator::And,
911 ),
912 filter_elem(
913 &[
914 Operand::simple_attribute(
915 ObjectTypeId::BaseEventType,
916 "Field",
917 AttributeId::Value,
918 NumericRange::None,
919 ),
920 Operand::literal(3),
921 ],
922 FilterOperator::Equals,
923 ),
924 filter_elem(
925 &[Operand::literal(3), Operand::literal(3)],
926 FilterOperator::Equals,
927 ),
928 ],
929 &type_tree,
930 );
931
932 assert!(!f.evaluate(&evt as &dyn Event, &type_tree));
933 let evt = event(3);
934 assert!(f.evaluate(&evt as &dyn Event, &type_tree));
935 }
936
937 #[test]
938 fn test_or_filter() {
939 let type_tree = type_tree();
940 let f = filter(
941 vec![filter_elem(
942 &[Operand::literal(true), Operand::literal(false)],
943 FilterOperator::Or,
944 )],
945 &type_tree,
946 );
947 let evt = event(2);
948 assert!(f.evaluate(&evt as &dyn Event, &type_tree));
949 let f = filter(
950 vec![
951 filter_elem(
952 &[Operand::element(1), Operand::element(2)],
953 FilterOperator::Or,
954 ),
955 filter_elem(
956 &[
957 Operand::simple_attribute(
958 ObjectTypeId::BaseEventType,
959 "Field",
960 AttributeId::Value,
961 NumericRange::None,
962 ),
963 Operand::literal(3),
964 ],
965 FilterOperator::Equals,
966 ),
967 filter_elem(
968 &[Operand::literal(3), Operand::literal(2)],
969 FilterOperator::Equals,
970 ),
971 ],
972 &type_tree,
973 );
974
975 assert!(!f.evaluate(&evt as &dyn Event, &type_tree));
976 let evt = event(3);
977 assert!(f.evaluate(&evt as &dyn Event, &type_tree));
978 }
979
980 #[test]
981 fn test_in_list() {
982 let type_tree = type_tree();
983 let f = filter(
984 vec![filter_elem(
985 &[
986 Operand::literal(1),
987 Operand::literal(2),
988 Operand::literal(3),
989 Operand::literal(1),
990 ],
991 FilterOperator::InList,
992 )],
993 &type_tree,
994 );
995 let evt = event(2);
996 assert!(f.evaluate(&evt as &dyn Event, &type_tree));
997 let f = filter(
998 vec![filter_elem(
999 &[
1000 Operand::simple_attribute(
1001 ObjectTypeId::BaseEventType,
1002 "Field",
1003 AttributeId::Value,
1004 NumericRange::None,
1005 ),
1006 Operand::literal(1),
1007 Operand::literal(2),
1008 Operand::literal(3),
1009 ],
1010 FilterOperator::InList,
1011 )],
1012 &type_tree,
1013 );
1014 assert!(f.evaluate(&evt as &dyn Event, &type_tree));
1015 let evt = event(4);
1016 assert!(!f.evaluate(&evt as &dyn Event, &type_tree));
1017 }
1018
1019 #[test]
1020 fn test_of_type() {
1021 let type_tree = type_tree();
1022 let f = filter(
1023 vec![filter_elem(
1024 &[Operand::literal(NodeId::new(1, 123))],
1025 FilterOperator::OfType,
1026 )],
1027 &type_tree,
1028 );
1029 let evt = event(2);
1030 assert!(f.evaluate(&evt as &dyn Event, &type_tree));
1031
1032 let f = filter(
1034 vec![filter_elem(
1035 &[Operand::literal(NodeId::new(1, 456))],
1036 FilterOperator::OfType,
1037 )],
1038 &type_tree,
1039 );
1040 let evt = event(2);
1041 assert!(!f.evaluate(&evt as &dyn Event, &type_tree));
1042
1043 let f = filter(
1045 vec![filter_elem(
1046 &[Operand::literal(ObjectTypeId::BaseEventType)],
1047 FilterOperator::OfType,
1048 )],
1049 &type_tree,
1050 );
1051 let evt = event(2);
1052 assert!(f.evaluate(&evt as &dyn Event, &type_tree));
1053 }
1054}