use super::escape_literal;
use forbidden_regex::RegexSet;
fn compiled(literal: &str) -> RegexSet {
let pattern = escape_literal(literal);
return RegexSet::new(std::slice::from_ref(&pattern)).expect("escaped literal must compile")
}
fn assert_round_trips(literal: &str) {
let set = compiled(literal);
assert!(set.is_match(literal.as_bytes()), "did not match literal {literal:?}");
let embedded = format!("xy{literal}z9");
assert!(set.is_match(embedded.as_bytes()), "did not match embedded {literal:?}");
}
#[test]
fn metacharacter_literals_round_trip() {
for literal in [
"a.b", "a*b", "a+b", "a?b", "a|b", "a^b", "a$b", "a[b", "a]b", "a(b", "a)b", "a{b",
"a}b", "a&b", "a~b", "a-b", "a/b", "(?:group)", "[class]", "{2,5}", ".*+?", "a.b.c",
] {
assert_round_trips(literal);
}
}
#[test]
fn dot_is_literal_not_wildcard() {
let set = compiled("a.c");
assert!(set.is_match(b"a.c"));
assert!(!set.is_match(b"axc"));
}
#[test]
fn quantifiers_are_literal() {
let star = compiled("a*b");
assert!(star.is_match(b"a*b"));
assert!(!star.is_match(b"b"));
assert!(!star.is_match(b"aaab"));
let plus = compiled("a+b");
assert!(plus.is_match(b"a+b"));
assert!(!plus.is_match(b"aaab"));
let opt = compiled("ab?c");
assert!(opt.is_match(b"ab?c"));
assert!(!opt.is_match(b"ac"));
}
#[test]
fn class_brackets_are_literal() {
let set = compiled("[abc]");
assert!(set.is_match(b"[abc]"));
assert!(!set.is_match(b"a"));
assert!(!set.is_match(b"b"));
}
#[test]
fn pipe_is_literal_not_alternation() {
let set = compiled("a|b");
assert!(set.is_match(b"a|b"));
assert!(!set.is_match(b"a"));
assert!(!set.is_match(b"b"));
}
#[test]
fn backslash_shorthand_is_two_literal_bytes() {
let digit = compiled("\\d");
assert!(digit.is_match(b"\\d"));
assert!(!digit.is_match(b"5"));
let word = compiled("\\w+");
assert!(word.is_match(b"\\w+"));
assert!(!word.is_match(b"abc"));
}
#[test]
fn whitespace_is_preserved() {
let space = compiled("foo bar");
assert!(space.is_match(b"foo bar"));
assert!(!space.is_match(b"foobar"));
let tab = compiled("a\tb");
assert!(tab.is_match(b"a\tb"));
assert!(!tab.is_match(b"ab"));
}
#[test]
fn hash_is_literal_even_leading() {
let lead = compiled("#nocomment");
assert!(lead.is_match(b"#nocomment"));
let mid = compiled("a#b");
assert!(mid.is_match(b"a#b"));
assert!(!mid.is_match(b"ab"));
}
#[test]
fn embedded_newline_round_trips() {
let set = compiled("a\nb");
assert!(set.is_match(b"a\nb"));
assert!(!set.is_match(b"ab"));
assert!(escape_literal("x\ny").as_bytes().contains(&b'\n'));
}
#[test]
fn quotes_and_punctuation_pass_through() {
for literal in ["key=\"value\"", "it's", "a,b;c:d", "<tag>", "@user", "a`b`c", "50%off"] {
assert_round_trips(literal);
}
}
#[test]
fn secret_shaped_literal_round_trips() {
let secret = "AKIA1234567890ABCDE\x50";
let set = compiled(secret);
assert!(set.is_match(secret.as_bytes()));
assert!(!set.is_match(b"AKIA"));
}