use rsigma_parser::{SigmaParserError, parse_condition, parse_field_spec, parse_sigma_yaml};
#[test]
fn field_spec_empty_field_name_with_modifier() {
let spec = parse_field_spec("|contains").unwrap();
assert!(spec.name.is_none());
assert_eq!(spec.modifiers.len(), 1);
}
#[test]
fn field_spec_double_pipe_produces_unknown_modifier() {
let err = parse_field_spec("field||contains").unwrap_err();
assert!(
matches!(err, SigmaParserError::UnknownModifier(ref s) if s.is_empty()),
"expected UnknownModifier for empty modifier string, got: {err}"
);
}
#[test]
fn field_spec_trailing_pipe_produces_unknown_modifier() {
let err = parse_field_spec("field|").unwrap_err();
assert!(
matches!(err, SigmaParserError::UnknownModifier(ref s) if s.is_empty()),
"expected UnknownModifier for trailing pipe, got: {err}"
);
}
#[test]
fn condition_trailing_operator_fails_with_location() {
let err = parse_condition("selection and").unwrap_err();
assert!(
matches!(err, SigmaParserError::Condition(_, _)),
"expected Condition error, got: {err}"
);
}
#[test]
fn condition_unmatched_parens_fails() {
let err = parse_condition("(selection and filter").unwrap_err();
assert!(
matches!(err, SigmaParserError::Condition(_, _)),
"expected Condition error for unmatched paren, got: {err}"
);
}
#[test]
fn condition_double_operator_fails() {
let err = parse_condition("selection and or filter").unwrap_err();
assert!(
matches!(err, SigmaParserError::Condition(_, _)),
"expected Condition error for 'and or', got: {err}"
);
}
#[test]
fn multi_doc_mixed_valid_and_invalid_collects_both() {
let yaml = r#"
title: Valid Rule
logsource:
product: windows
detection:
selection:
CommandLine|contains: test
condition: selection
level: low
---
logsource:
product: windows
detection:
selection:
CommandLine|contains: test
condition: selection
level: low
"#;
let collection = parse_sigma_yaml(yaml).unwrap();
assert_eq!(
collection.rules.len(),
1,
"first valid rule should be collected"
);
assert!(
!collection.errors.is_empty(),
"second doc's error should be reported"
);
}
#[test]
fn correlation_missing_type_reports_clear_error() {
let yaml = r#"
title: Bad Correlation
correlation:
rules:
- some-rule
timespan: 60s
condition:
gte: 3
level: high
"#;
let collection = parse_sigma_yaml(yaml).unwrap();
assert!(
!collection.errors.is_empty(),
"missing correlation type should produce an error"
);
assert!(
collection.errors[0].contains("type"),
"error message should mention 'type', got: {}",
collection.errors[0]
);
}
#[test]
fn correlation_missing_timespan_reports_clear_error() {
let yaml = r#"
title: Bad Correlation
correlation:
type: event_count
rules:
- some-rule
condition:
gte: 3
level: high
"#;
let collection = parse_sigma_yaml(yaml).unwrap();
assert!(
!collection.errors.is_empty(),
"missing timespan should produce an error"
);
let err = &collection.errors[0];
assert!(
err.contains("timespan") || err.contains("timeframe"),
"error should mention timespan/timeframe, got: {err}"
);
}