use super::engine::requires_resharp;
struct Case {
pattern: &'static str,
expected: bool,
}
fn run_case(case: &Case) {
let actual = requires_resharp(case.pattern);
assert_eq!(
actual, case.expected,
"requires_resharp({:?}) = {} but expected {}",
case.pattern, actual, case.expected
);
}
#[test]
fn set_algebra_amp_triggers() {
run_case(&Case { pattern: "foo&bar", expected: true });
}
#[test]
fn set_algebra_complement_triggers() {
run_case(&Case { pattern: "~(foo)", expected: true });
}
#[test]
fn escaped_amp_does_not_trigger() {
run_case(&Case { pattern: r"foo\&bar", expected: false });
}
#[test]
fn in_class_amp_does_not_trigger() {
run_case(&Case { pattern: "[&a-z]+", expected: false });
}
#[test]
fn lookahead_triggers() {
run_case(&Case { pattern: "foo(?=bar)", expected: true });
}
#[test]
fn negative_lookahead_triggers() {
run_case(&Case { pattern: "foo(?!bar)", expected: true });
}
#[test]
fn lookbehind_triggers() {
run_case(&Case { pattern: "(?<=foo)bar", expected: true });
}
#[test]
fn negative_lookbehind_triggers() {
run_case(&Case { pattern: "(?<!foo)bar", expected: true });
}
#[test]
fn non_capturing_group_does_not_trigger() {
run_case(&Case { pattern: "(?:foo)bar", expected: false });
}
#[test]
fn named_capture_angle_does_not_trigger() {
run_case(&Case { pattern: "(?<name>foo)bar", expected: false });
}
#[test]
fn named_capture_p_does_not_trigger() {
run_case(&Case { pattern: "(?P<name>foo)bar", expected: false });
}
#[test]
fn inline_flags_do_not_trigger() {
run_case(&Case { pattern: "(?i)foo", expected: false });
}
#[test]
fn escaped_lookahead_does_not_trigger() {
run_case(&Case { pattern: r"\(?=foo\)", expected: false });
}
#[test]
fn in_class_lookalike_does_not_trigger() {
run_case(&Case { pattern: "[(?=]", expected: false });
}
#[test]
fn prose_em_dash_pattern_triggers() {
run_case(&Case { pattern: "(?<=[a-z]) -- (?=[a-z])", expected: true });
}
#[test]
fn plain_literal_does_not_trigger() {
run_case(&Case { pattern: "AKIA1234567890ABCDEF", expected: false });
}
#[test]
fn plain_regex_no_lookaround_does_not_trigger() {
run_case(&Case { pattern: r"hvb\.[\w-]{138,300}", expected: false });
}
use super::engine::lookaround_in_complement;
fn assert_rejected(pattern: &str, expect_substr: &str) {
let actual = lookaround_in_complement(pattern);
match actual {
Some(msg) => assert!(
msg.contains(expect_substr),
"lookaround_in_complement({:?}) returned message that did not contain {:?}: {}",
pattern, expect_substr, msg
),
None => panic!(
"lookaround_in_complement({:?}) returned None; expected Some(_) containing {:?}",
pattern, expect_substr
),
}
}
fn assert_accepted(pattern: &str) {
let actual = lookaround_in_complement(pattern);
assert!(
actual.is_none(),
"lookaround_in_complement({:?}) = {:?}; expected None",
pattern, actual
);
}
#[test]
fn complement_with_word_boundary_rejected() {
assert_rejected(r"em&~(.*\bword\b.*)", r"\b");
}
#[test]
fn complement_with_not_word_boundary_rejected() {
assert_rejected(r"em&~(.*\B.*)", r"\B");
}
#[test]
fn complement_with_caret_rejected() {
assert_rejected(r"em&~(^foo$)", "^");
}
#[test]
fn complement_with_dollar_rejected() {
assert_rejected(r"em&~(foo$)", "$");
}
#[test]
fn complement_with_explicit_lookahead_rejected() {
assert_rejected(r"em&~((?=foo).*)", "lookahead");
}
#[test]
fn complement_with_explicit_neg_lookahead_rejected() {
assert_rejected(r"em&~((?!foo).*)", "lookahead");
}
#[test]
fn complement_with_explicit_lookbehind_rejected() {
assert_rejected(r"em&~((?<=foo).*)", "lookbehind");
}
#[test]
fn complement_with_explicit_neg_lookbehind_rejected() {
assert_rejected(r"em&~((?<!foo).*)", "lookbehind");
}
#[test]
fn second_of_two_complements_rejected() {
assert_rejected(r"em&~(.*foo.*)&~(.*\bword\b.*)", r"\b");
}
#[test]
fn nested_group_inside_complement_with_boundary_rejected() {
assert_rejected(r"em&~((?:foo|\bword\b).*)", r"\b");
}
#[test]
fn boundary_outside_any_complement_accepted() {
assert_accepted(r"\bem\b&_*&~(.*foo.*)");
}
#[test]
fn text_anchors_inside_complement_accepted() {
assert_accepted(r"em&~(\Afoo\z)");
}
#[test]
fn caret_in_class_inside_complement_accepted() {
assert_accepted(r"em&~([^abc].*)");
}
#[test]
fn dollar_in_class_inside_complement_accepted() {
assert_accepted(r"em&~([$].*)");
}
#[test]
fn escaped_backslash_b_inside_complement_accepted() {
assert_accepted(r"em&~(\\b.*)");
}
#[test]
fn plain_set_algebra_without_triggers_accepted() {
assert_accepted(r"BUILD_[0-9]{6}&~(BUILD_000000)");
}
#[test]
fn rule_without_complement_accepted_even_with_lookaround() {
assert_accepted(r"(?<=[a-z]) -- (?=[a-z])");
}
#[test]
fn plain_literal_accepted() {
assert_accepted("AKIA1234567890ABCDEF");
}