use super::*;
#[test]
fn test_regex_rule_with_metacharacters_matches() {
let rule = MagicRule {
offset: OffsetSpec::Absolute(0),
typ: TypeKind::Regex {
flags: crate::parser::ast::RegexFlags::default(),
count: crate::parser::ast::RegexCount::Default,
},
op: Operator::Equal,
value: Value::String("[0-9]+".to_string()),
message: "has digits".to_string(),
children: vec![],
level: 0,
strength_modifier: None,
value_transform: None,
};
let mut context = EvaluationContext::new(EvaluationConfig::default());
let matches = evaluate_single_rule(&rule, b"abc123def", &mut context).unwrap();
assert_eq!(matches.len(), 1);
assert_eq!(matches[0].message, "has digits");
}
#[test]
fn test_regex_rule_with_metacharacters_no_match() {
let rule = MagicRule {
offset: OffsetSpec::Absolute(0),
typ: TypeKind::Regex {
flags: crate::parser::ast::RegexFlags::default(),
count: crate::parser::ast::RegexCount::Default,
},
op: Operator::Equal,
value: Value::String("[0-9]+".to_string()),
message: "has digits".to_string(),
children: vec![],
level: 0,
strength_modifier: None,
value_transform: None,
};
let mut context = EvaluationContext::new(EvaluationConfig::default());
let matches = evaluate_single_rule(&rule, b"abcdef", &mut context).unwrap();
assert!(matches.is_empty());
}
#[test]
fn test_search_rule_not_equal_succeeds_when_pattern_absent() {
let rule = MagicRule {
offset: OffsetSpec::Absolute(0),
typ: TypeKind::Search {
range: ::std::num::NonZeroUsize::new(64),
flags: SearchFlags::default(),
},
op: Operator::NotEqual,
value: Value::String("needle".to_string()),
message: "no needle".to_string(),
children: vec![],
level: 0,
strength_modifier: None,
value_transform: None,
};
let mut context = EvaluationContext::new(EvaluationConfig::default());
let matches = evaluate_single_rule(&rule, b"plain haystack", &mut context).unwrap();
assert_eq!(matches.len(), 1);
}
#[test]
fn test_regex_rule_with_ordering_operator_is_rejected() {
let rule = MagicRule {
offset: OffsetSpec::Absolute(0),
typ: TypeKind::Regex {
flags: crate::parser::ast::RegexFlags::default(),
count: crate::parser::ast::RegexCount::Default,
},
op: Operator::GreaterThan,
value: Value::String("[0-9]+".to_string()),
message: "bogus".to_string(),
children: vec![],
level: 0,
strength_modifier: None,
value_transform: None,
};
let mut context = EvaluationContext::new(EvaluationConfig::default());
let result = evaluate_single_rule(&rule, b"abcdef", &mut context);
match result {
Err(LibmagicError::EvaluationError(_)) => {}
other => panic!("expected EvaluationError for ordering operator on regex, got {other:?}"),
}
}
#[test]
fn test_search_rule_with_bitwise_operator_is_rejected() {
let rule = MagicRule {
offset: OffsetSpec::Absolute(0),
typ: TypeKind::Search {
range: ::std::num::NonZeroUsize::new(32),
flags: SearchFlags::default(),
},
op: Operator::BitwiseAnd,
value: Value::String("needle".to_string()),
message: "bogus".to_string(),
children: vec![],
level: 0,
strength_modifier: None,
value_transform: None,
};
let mut context = EvaluationContext::new(EvaluationConfig::default());
let result = evaluate_single_rule(&rule, b"plain haystack", &mut context);
assert!(
matches!(result, Err(LibmagicError::EvaluationError(_))),
"expected EvaluationError for bitwise operator on search"
);
}
#[test]
fn test_regex_parent_advances_anchor_for_relative_child() {
let child = MagicRule {
offset: OffsetSpec::Relative(0),
typ: TypeKind::Byte { signed: false },
op: Operator::Equal,
value: Value::Uint(u64::from(b'1')),
message: "first digit".to_string(),
children: vec![],
level: 1,
strength_modifier: None,
value_transform: None,
};
let parent = MagicRule {
offset: OffsetSpec::Absolute(0),
typ: TypeKind::Regex {
flags: crate::parser::ast::RegexFlags::default(),
count: crate::parser::ast::RegexCount::Default,
},
op: Operator::Equal,
value: Value::String("abc".to_string()),
message: "abc prefix".to_string(),
children: vec![child],
level: 0,
strength_modifier: None,
value_transform: None,
};
let mut context = EvaluationContext::new(EvaluationConfig::default());
let matches = evaluate_rules(&[parent], b"abc123X", &mut context).unwrap();
assert_eq!(
matches.len(),
2,
"expected parent + child match, got {}: {matches:?}",
matches.len()
);
assert_eq!(matches[0].message, "abc prefix");
assert_eq!(matches[1].message, "first digit");
}