#![allow(clippy::doc_markdown, clippy::uninlined_format_args)]
use fuzzy_regex::{FuzzyRegex, FuzzyRegexBuilder};
#[test]
fn test_empty_pattern_matches_empty_string() {
let re = FuzzyRegex::new("").unwrap();
assert!(re.is_match(""));
}
#[test]
fn test_empty_pattern_matches_at_start() {
let re = FuzzyRegex::new("").unwrap();
let m = re.find("hello").unwrap();
assert_eq!(m.start(), 0);
assert_eq!(m.end(), 0);
}
#[test]
fn test_optional_pattern_matches_empty() {
let re = FuzzyRegex::new("a?").unwrap();
assert!(re.is_match(""));
assert!(re.is_match("a"));
assert!(re.is_match("b")); }
#[test]
fn test_star_quantifier_matches_empty() {
let re = FuzzyRegex::new("a*").unwrap();
assert!(re.is_match(""));
assert!(re.is_match("aaa"));
assert!(re.is_match("bbb")); }
#[test]
fn test_empty_alternation_branch() {
let re = FuzzyRegex::new("(?:a|)").unwrap();
assert!(re.is_match(""));
assert!(re.is_match("a"));
assert!(re.is_match("b")); }
#[test]
fn test_multiple_empty_alternations() {
let re = FuzzyRegex::new("(?:|)").unwrap();
assert!(re.is_match(""));
assert!(re.is_match("anything"));
}
#[test]
fn test_anchored_empty_pattern() {
let re = FuzzyRegex::new("^$").unwrap();
assert!(re.is_match(""));
}
#[test]
fn test_nested_star_quantifiers() {
let re = FuzzyRegex::new("(?:a*)*").unwrap();
assert!(re.is_match(""));
assert!(re.is_match("a"));
assert!(re.is_match("aaaaaa"));
}
#[test]
fn test_nested_plus_in_group() {
let re = FuzzyRegex::new("(?:a+)+").unwrap();
assert!(!re.is_match(""));
assert!(re.is_match("a"));
assert!(re.is_match("aaaaaa"));
}
#[test]
fn test_quantifier_on_group_with_alternation() {
let re = FuzzyRegex::new("(?:ab|cd)+").unwrap();
assert!(re.is_match("ab"));
assert!(re.is_match("cd"));
assert!(re.is_match("abcd"));
assert!(re.is_match("cdab"));
assert!(re.is_match("ababab"));
}
#[test]
fn test_lazy_vs_greedy_quantifier() {
let greedy = FuzzyRegex::new("a.*b").unwrap();
let m = greedy.find("aXXbYYb");
assert!(m.is_some());
assert_eq!(m.unwrap().as_str(), "aXXbYYb");
let lazy = FuzzyRegex::new("a.*?b").unwrap();
let m = lazy.find("aXXbYYb");
assert!(m.is_some());
assert_eq!(m.unwrap().as_str(), "aXXb");
}
#[test]
fn test_lazy_plus_quantifier() {
let greedy = FuzzyRegex::new("a+").unwrap();
assert_eq!(greedy.find("aaaa").unwrap().as_str(), "aaaa");
let lazy = FuzzyRegex::new("a+?").unwrap();
assert_eq!(lazy.find("aaaa").unwrap().as_str(), "a");
}
#[test]
fn test_lazy_star_quantifier() {
let greedy = FuzzyRegex::new("a*").unwrap();
assert_eq!(greedy.find("aaaa").unwrap().as_str(), "aaaa");
let lazy = FuzzyRegex::new("a*?").unwrap();
assert_eq!(lazy.find("aaaa").unwrap().as_str(), "");
}
#[test]
fn test_lazy_with_html_tag_pattern() {
let lazy = FuzzyRegex::new("<.*?>").unwrap();
let text = "<tag>content</tag>";
let m = lazy.find(text).unwrap();
assert_eq!(m.as_str(), "<tag>");
}
#[test]
fn test_possessive_quantifier_style() {
let result = FuzzyRegex::new("a++b");
if let Ok(re) = result {
assert!(re.is_match("aab"));
}
}
#[test]
fn test_zero_or_more_of_optional() {
let re = FuzzyRegex::new("(?:a?)*").unwrap();
assert!(re.is_match(""));
assert!(re.is_match("a"));
assert!(re.is_match("aaa"));
}
#[test]
fn test_exact_repetition() {
let re = FuzzyRegex::new("a{3}").unwrap();
assert!(!re.is_match("aa"));
assert!(re.is_match("aaa"));
assert!(re.is_match("aaaa")); }
#[test]
fn test_range_repetition() {
let re = FuzzyRegex::new("^a{2,4}$").unwrap();
assert!(!re.is_match("a"));
assert!(re.is_match("aa"));
assert!(re.is_match("aaa"));
assert!(re.is_match("aaaa"));
assert!(!re.is_match("aaaaa"));
}
#[test]
fn test_min_repetition_unbounded() {
let re = FuzzyRegex::new("^a{2,}$").unwrap();
assert!(!re.is_match("a"));
assert!(re.is_match("aa"));
assert!(re.is_match("aaaaaaaaaa"));
}
#[test]
fn test_char_class_with_hyphen_at_start() {
let re = FuzzyRegex::new("[-abc]").unwrap();
assert!(re.is_match("-"));
assert!(re.is_match("a"));
assert!(re.is_match("b"));
assert!(re.is_match("c"));
assert!(!re.is_match("d"));
}
#[test]
fn test_char_class_with_hyphen_at_end() {
let re = FuzzyRegex::new(r"[abc\-]").unwrap();
assert!(re.is_match("-"));
assert!(re.is_match("a"));
}
#[test]
fn test_char_class_with_caret_not_at_start() {
let re = FuzzyRegex::new("[a^b]").unwrap();
assert!(re.is_match("^"));
assert!(re.is_match("a"));
assert!(re.is_match("b"));
}
#[test]
fn test_char_class_with_bracket() {
let re = FuzzyRegex::new(r"\[").unwrap();
assert!(re.is_match("["));
let re2 = FuzzyRegex::new(r"\]").unwrap();
assert!(re2.is_match("]"));
}
#[test]
fn test_nested_char_class_posix_style() {
let re = FuzzyRegex::new("[a-zA-Z]").unwrap();
assert!(re.is_match("a"));
assert!(re.is_match("Z"));
assert!(!re.is_match("5"));
}
#[test]
fn test_negated_char_class() {
let re = FuzzyRegex::new("[^abc]").unwrap();
assert!(!re.is_match("a"));
assert!(!re.is_match("b"));
assert!(!re.is_match("c"));
assert!(re.is_match("d"));
assert!(re.is_match("1"));
}
#[test]
fn test_char_class_intersection_style() {
let re = FuzzyRegex::new("[a-z0-9_]").unwrap();
assert!(re.is_match("a"));
assert!(re.is_match("z"));
assert!(re.is_match("0"));
assert!(re.is_match("9"));
assert!(re.is_match("_"));
assert!(!re.is_match("A"));
}
#[test]
fn test_caret_in_middle_is_literal_without_multiline() {
let re = FuzzyRegex::new("a^b").unwrap();
assert!(!re.is_match("a^b"));
assert!(!re.is_match("a\nb"));
}
#[test]
fn test_multiple_anchors() {
let re = FuzzyRegex::new("^^$").unwrap();
assert!(re.is_match(""));
}
#[test]
fn test_anchor_with_alternation() {
let re = FuzzyRegex::new("^(?:a|b)$").unwrap();
assert!(re.is_match("a"));
assert!(re.is_match("b"));
assert!(!re.is_match("ab"));
assert!(!re.is_match("c"));
}
#[test]
fn test_multiline_caret() {
let re = FuzzyRegex::new("(?m)^abc").unwrap();
assert!(re.is_match("abc"));
assert!(re.is_match("xyz\nabc"));
assert!(re.is_match("line1\nabc\nline3"));
}
#[test]
fn test_multiline_dollar() {
let re = FuzzyRegex::new("(?m)abc$").unwrap();
assert!(re.is_match("abc"));
assert!(re.is_match("abc\nxyz"));
assert!(re.is_match("line1\nabc\nline3"));
}
#[test]
fn test_word_boundary_basic() {
let re = FuzzyRegex::new(r"\bword\b").unwrap();
assert!(re.is_match("word"));
assert!(re.is_match("a word here"));
}
#[test]
fn test_word_boundary_at_string_edges() {
let re = FuzzyRegex::new(r"\btest\b").unwrap();
assert!(re.is_match("test"));
assert!(re.is_match("test case"));
assert!(re.is_match("a test"));
}
#[test]
fn test_non_word_boundary() {
let result = FuzzyRegex::new(r"\Bword");
if let Ok(re) = result {
assert!(re.is_match("sword")); }
}
#[test]
fn test_word_boundary_with_numbers() {
let re = FuzzyRegex::new(r"\b\d+\b").unwrap();
assert!(re.is_match("123"));
assert!(re.is_match("test 456 here"));
}
#[test]
fn test_unicode_basic_multilingual_plane() {
let re = FuzzyRegex::new("café").unwrap();
assert!(re.is_match("café"));
assert!(!re.is_match("cafe"));
}
#[test]
fn test_unicode_cyrillic() {
let re = FuzzyRegex::new("привет").unwrap();
assert!(re.is_match("привет"));
assert!(re.is_match("слово привет мир"));
}
#[test]
fn test_unicode_chinese() {
let re = FuzzyRegex::new("你好").unwrap();
assert!(re.is_match("你好"));
assert!(re.is_match("说你好世界"));
}
#[test]
fn test_unicode_mixed_scripts() {
let re = FuzzyRegex::new("hello世界").unwrap();
assert!(re.is_match("hello世界"));
}
#[test]
fn test_unicode_emoji_basic() {
let result = FuzzyRegex::new("🎉");
if let Ok(re) = result {
assert!(re.is_match("🎉"));
assert!(re.is_match("party 🎉 time"));
}
}
#[test]
fn test_unicode_case_folding() {
let re = FuzzyRegex::new("(?i)CAFE").unwrap();
assert!(re.is_match("cafe"));
assert!(re.is_match("CAFE"));
assert!(re.is_match("Cafe"));
}
#[test]
fn test_unicode_in_char_class() {
let re = FuzzyRegex::new("[а-я]").unwrap(); assert!(re.is_match("а"));
assert!(re.is_match("я"));
assert!(re.is_match("привет"));
assert!(!re.is_match("ABC"));
}
#[test]
fn test_escaped_metacharacters() {
let re = FuzzyRegex::new(r"\.\*\+\?\[\]\{\}\(\)\|\^\$\\").unwrap();
assert!(re.is_match(".*+?[]{}()|^$\\"));
}
#[test]
fn test_escaped_backslash() {
let re = FuzzyRegex::new(r"\\").unwrap();
assert!(re.is_match("\\"));
assert!(re.is_match("path\\to\\file"));
}
#[test]
fn test_hex_escape_sequences() {
let re = FuzzyRegex::new(r"\x41\x42\x43").unwrap();
assert!(re.is_match("ABC"));
}
#[test]
fn test_unicode_escape_sequences() {
let re = FuzzyRegex::new(r"\x41\x42").unwrap();
assert!(re.is_match("AB"));
}
#[test]
fn test_alternation_order_matters_for_greedy() {
let re = FuzzyRegex::new("a|ab").unwrap();
let m = re.find("ab");
assert!(m.is_some());
assert_eq!(m.unwrap().as_str(), "ab");
}
#[test]
fn test_alternation_with_different_lengths() {
let re = FuzzyRegex::new("(?:abc|ab|a)").unwrap();
assert!(re.is_match("a"));
assert!(re.is_match("ab"));
assert!(re.is_match("abc"));
}
#[test]
fn test_alternation_in_middle_of_pattern() {
let re = FuzzyRegex::new("x(?:a|b|c)y").unwrap();
assert!(re.is_match("xay"));
assert!(re.is_match("xby"));
assert!(re.is_match("xcy"));
assert!(!re.is_match("xdy"));
}
#[test]
fn test_nested_alternation() {
let re = FuzzyRegex::new("(?:(?:a|b)|(?:c|d))").unwrap();
assert!(re.is_match("a"));
assert!(re.is_match("b"));
assert!(re.is_match("c"));
assert!(re.is_match("d"));
}
#[test]
fn test_dot_does_not_match_newline_by_default() {
let re = FuzzyRegex::new("a.b").unwrap();
assert!(re.is_match("aXb"));
assert!(!re.is_match("a\nb"));
}
#[test]
fn test_dot_matches_newline_with_dotall() {
let re = FuzzyRegex::new("(?s)a.b").unwrap();
assert!(re.is_match("aXb"));
assert!(re.is_match("a\nb"));
}
#[test]
fn test_dot_matches_unicode() {
let re = FuzzyRegex::new("a.b").unwrap();
assert!(re.is_match("aXb"));
assert!(re.is_match("aйb")); assert!(re.is_match("a中b")); }
#[test]
fn test_fuzzy_empty_pattern() {
let re = FuzzyRegex::new("(?:a){e<=1}").unwrap();
assert!(re.is_match("a"));
assert!(re.is_match("b")); assert!(re.is_match("")); }
#[test]
fn test_fuzzy_with_alternation() {
let re = FuzzyRegex::new("(?:hello|world){e<=1}").unwrap();
assert!(re.is_match("hello"));
assert!(re.is_match("hallo")); assert!(re.is_match("world"));
assert!(re.is_match("wrld")); }
#[test]
fn test_fuzzy_with_unicode() {
let re = FuzzyRegex::new("(?:привет){e<=1}").unwrap();
assert!(re.is_match("привет"));
assert!(re.is_match("превет")); assert!(re.is_match("приве")); }
#[test]
fn test_unicode_flag_word_class() {
use fuzzy_regex::FuzzyRegexBuilder;
let re1 = FuzzyRegexBuilder::new(r"\w+").build().unwrap();
assert!(re1.is_match("hello"));
assert!(!re1.is_match("привет"));
let re2 = FuzzyRegexBuilder::new(r"(?u)\w+").build().unwrap();
assert!(re2.is_match("hello"));
assert!(re2.is_match("привет"));
let re3 = FuzzyRegexBuilder::new(r"\w+")
.unicode(true)
.build()
.unwrap();
assert!(re3.is_match("привет"));
}
#[test]
fn test_unicode_flag_digit_class() {
let re = FuzzyRegex::new("(?u)\\d+").unwrap();
assert!(re.is_match("123"));
assert!(re.is_match("\u{0660}\u{0661}")); }
#[test]
fn test_unicode_flag_whitespace_class() {
let re = FuzzyRegex::new("(?u)\\s+").unwrap();
assert!(re.is_match(" "));
assert!(re.is_match("\t\n"));
assert!(re.is_match("\u{00A0}")); }
#[test]
fn test_unicode_flag_mixed() {
let re = FuzzyRegex::new("(?u)\\w+:\\d+").unwrap();
assert!(re.is_match("abc:123"));
assert!(re.is_match("привет:456"));
let re2 = FuzzyRegex::new("\\w+:\\d+").unwrap();
assert!(re2.is_match("abc:123"));
assert!(!re2.is_match("привет:456")); }
#[test]
fn test_unicode_flag_in_fuzzy() {
let re = FuzzyRegex::new("(?u)(?:привет){e<=1}").unwrap();
assert!(re.is_match("привет")); assert!(re.is_match("превет")); assert!(re.is_match("привят")); }
#[test]
fn test_fuzzy_single_char() {
let re = FuzzyRegex::new("(?:x){e<=1}").unwrap();
assert!(re.is_match("x"));
assert!(re.is_match("y")); assert!(re.is_match("")); assert!(re.is_match("xx")); }
#[test]
fn test_fuzzy_with_char_class() {
let re = FuzzyRegex::new(r"(?:\d{3}){e<=1}").unwrap();
assert!(re.is_match("123"));
assert!(re.is_match("12")); assert!(re.is_match("1234")); assert!(re.is_match("1X3")); }
#[test]
fn test_fuzzy_anchored() {
let re = FuzzyRegex::new("^(?:test){e<=1}$").unwrap();
assert!(re.is_match("test"));
assert!(re.is_match("tst")); assert!(re.is_match("testt")); assert!(re.is_match("tXst")); assert!(!re.is_match("tt")); }
#[test]
fn test_fuzzy_with_plus_quantifier() {
let re = FuzzyRegex::new("(?:ab+c){e<=1}").unwrap();
assert!(re.is_match("abc"));
assert!(re.is_match("abbc"));
assert!(re.is_match("ac"));
assert!(re.is_match("aXc"));
assert!(!re.is_match("a")); }
#[test]
fn test_fuzzy_with_star_quantifier() {
let re = FuzzyRegex::new("(?:ab*c){e<=1}").unwrap();
assert!(re.is_match("ac")); assert!(re.is_match("abc")); assert!(re.is_match("abbc"));
assert!(re.is_match("aXc")); }
#[test]
fn test_fuzzy_with_optional_quantifier() {
let re = FuzzyRegex::new("(?:ab?c){e<=1}").unwrap();
assert!(re.is_match("ac"));
assert!(re.is_match("abc"));
assert!(re.is_match("aXc")); }
#[test]
fn test_fuzzy_backreference_in_group() {
let re = FuzzyRegex::new(r"(?:(abc)\1){e<=1}").unwrap();
assert!(re.is_match("abcabc"));
assert!(re.is_match("abcabX")); assert!(re.is_match("abcab"));
assert!(!re.is_match("abcXXX")); }
#[test]
fn test_explicit_fuzzy_backreference() {
let re = FuzzyRegex::new(r"(abc)\1{e<=1}").unwrap();
assert!(re.is_match("abcabc")); assert!(re.is_match("abcabX")); assert!(!re.is_match("abcXXX")); }
#[test]
fn test_fuzzy_capture_with_exact_backref() {
let re = FuzzyRegex::new(r"((?:abc){e<=1})\1").unwrap();
assert!(re.is_match("abcabc"));
assert!(re.is_match("abXabX"));
assert!(!re.is_match("abXabc"));
assert!(!re.is_match("abcabX"));
}
#[test]
fn test_fuzzy_capture_with_fuzzy_backref() {
let re = FuzzyRegex::new(r"((?:abc){e<=1})\1{e<=1}").unwrap();
assert!(re.is_match("abcabc"));
assert!(re.is_match("abXabX"));
assert!(re.is_match("abcabX"));
assert!(re.is_match("abXabc"));
}
#[test]
fn test_simple_backreference() {
let re = FuzzyRegex::new(r"(abc)\1").unwrap();
assert!(re.is_match("abcabc"));
assert!(!re.is_match("abcdef"));
assert!(!re.is_match("abcabX"));
}
#[test]
fn test_backreference_captures() {
let re = FuzzyRegex::new(r"(abc)\1").unwrap();
let caps = re.captures("abcabc").unwrap();
assert_eq!(caps.get(0).unwrap().as_str(), "abcabc");
assert_eq!(caps.get(1).unwrap().as_str(), "abc");
}
#[test]
fn test_multiple_backreferences() {
let re = FuzzyRegex::new(r"(a)(b)\1\2").unwrap();
assert!(re.is_match("abab"));
assert!(!re.is_match("abba"));
assert!(!re.is_match("abcd"));
}
#[test]
fn test_backreference_with_quantifier() {
let re = FuzzyRegex::new(r"(ab)\1+").unwrap();
assert!(re.is_match("abab")); assert!(re.is_match("ababab")); assert!(!re.is_match("ab")); }
#[test]
fn test_email_like_pattern() {
let re = FuzzyRegex::new(r"[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}").unwrap();
assert!(re.is_match("test@example.com"));
assert!(re.is_match("user.name+tag@sub.domain.org"));
assert!(!re.is_match("invalid"));
assert!(!re.is_match("@example.com"));
}
#[test]
fn test_url_like_pattern() {
let re = FuzzyRegex::new(r"https?://[a-zA-Z0-9.-]+(?:/[a-zA-Z0-9./_-]*)?").unwrap();
assert!(re.is_match("http://example.com"));
assert!(re.is_match("https://example.com/path/to/page"));
assert!(re.is_match("https://sub.domain.org/file.html"));
}
#[test]
fn test_ip_address_pattern() {
let re = FuzzyRegex::new(r"\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}").unwrap();
assert!(re.is_match("192.168.1.1"));
assert!(re.is_match("10.0.0.1"));
assert!(re.is_match("255.255.255.255"));
}
#[test]
fn test_phone_number_pattern() {
let re = FuzzyRegex::new(r"^\(?\d{3}\)?[-.\s]?\d{3}[-.\s]?\d{4}$").unwrap();
assert!(re.is_match("(123) 456-7890"));
assert!(re.is_match("123-456-7890"));
assert!(re.is_match("123.456.7890"));
assert!(re.is_match("1234567890"));
}
#[test]
fn test_date_pattern() {
let re = FuzzyRegex::new(r"\d{4}-\d{2}-\d{2}").unwrap();
assert!(re.is_match("2024-01-15"));
assert!(re.is_match("1999-12-31"));
}
#[test]
fn test_catastrophic_backtracking_protection() {
let re = FuzzyRegex::new("(?:a+)+b").unwrap();
let input = "a".repeat(20);
assert!(!re.is_match(&input)); }
#[test]
fn test_long_alternation() {
let re = FuzzyRegex::new("(?:a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z)").unwrap();
assert!(re.is_match("a"));
assert!(re.is_match("z"));
assert!(re.is_match("m"));
assert!(!re.is_match("1"));
}
#[test]
fn test_deeply_nested_groups() {
let re = FuzzyRegex::new("(?:(?:(?:(?:a))))").unwrap();
assert!(re.is_match("a"));
}
#[test]
fn test_very_long_literal() {
let long_pattern = "abcdefghijklmnopqrstuvwxyz".repeat(10);
let re = FuzzyRegex::new(&long_pattern).unwrap();
assert!(re.is_match(&long_pattern));
assert!(!re.is_match("abc"));
}
#[test]
fn test_nested_quantifiers() {
let re = FuzzyRegex::new("(a+)+").unwrap();
assert!(re.is_match("aaaa"));
let re2 = FuzzyRegex::new("(a*)*").unwrap();
assert!(re2.is_match("aaaa"));
let re3 = FuzzyRegex::new("(a?)?").unwrap();
assert!(re3.is_match(""));
assert!(re3.is_match("a"));
}
#[test]
fn test_empty_group_with_quantifier() {
let re = FuzzyRegex::new("()*").unwrap();
assert!(re.is_match(""));
let re2 = FuzzyRegex::new("()+").unwrap();
assert!(re2.is_match(""));
let re3 = FuzzyRegex::new("(|a)*").unwrap();
assert!(re3.is_match("aaa"));
}
#[test]
fn test_specific_repetition_counts() {
let re = FuzzyRegex::new("a{3}").unwrap();
assert!(re.is_match("aaa"));
assert!(!re.is_match("aa"));
assert!(re.is_match("aaaa"));
let re2 = FuzzyRegex::new("a{2,4}").unwrap();
assert!(re2.is_match("aaa"));
let re3 = FuzzyRegex::new("a{2,}").unwrap();
assert!(re3.is_match("aaaaa"));
}
#[test]
fn test_zero_repetition() {
let re = FuzzyRegex::new("a{0}").unwrap();
assert!(re.is_match("b"));
let re2 = FuzzyRegex::new("a{0,3}").unwrap();
assert!(re2.is_match(""));
assert!(re2.is_match("aa"));
}
#[test]
fn test_large_repetition() {
let re = FuzzyRegex::new("a{100}").unwrap();
assert!(re.is_match(&"a".repeat(100)));
let re2 = FuzzyRegex::new("a{50,}").unwrap();
assert!(re2.is_match(&"a".repeat(100)));
}
#[test]
fn test_group_repetition() {
let re = FuzzyRegex::new("(ab){2}").unwrap();
assert!(re.is_match("abab"));
assert!(!re.is_match("ab"));
}
#[test]
fn test_special_escapes() {
let re_tab = FuzzyRegex::new(r"\t").unwrap();
assert!(re_tab.is_match("\t"));
let re_newline = FuzzyRegex::new(r"\n").unwrap();
assert!(re_newline.is_match("\n"));
let re_cr = FuzzyRegex::new(r"\r").unwrap();
assert!(re_cr.is_match("\r"));
}
#[test]
fn test_escaped_metacharacters_comprehensive() {
let re = FuzzyRegex::new(r"\.").unwrap();
assert!(re.is_match("."));
assert!(!re.is_match("a"));
let re2 = FuzzyRegex::new(r"\*").unwrap();
assert!(re2.is_match("*"));
let re3 = FuzzyRegex::new(r"\+").unwrap();
assert!(re3.is_match("+"));
let re4 = FuzzyRegex::new(r"\?").unwrap();
assert!(re4.is_match("?"));
let re5 = FuzzyRegex::new(r"\|").unwrap();
assert!(re5.is_match("|"));
let re6 = FuzzyRegex::new(r"\\").unwrap();
assert!(re6.is_match("\\"));
}
#[test]
fn test_metachar_in_char_class() {
let re = FuzzyRegex::new("[a.b]").unwrap();
assert!(re.is_match("."));
let re2 = FuzzyRegex::new("[a*b]").unwrap();
assert!(re2.is_match("*"));
let re3 = FuzzyRegex::new("[a$b]").unwrap();
assert!(re3.is_match("$"));
}
#[test]
fn test_lookahead() {
let re = FuzzyRegex::new("a(?=b)").unwrap();
assert!(re.is_match("ab"));
assert!(!re.is_match("ac"));
let re2 = FuzzyRegex::new("a(?!b)").unwrap();
assert!(re2.is_match("ac"));
assert!(!re2.is_match("ab"));
}
#[test]
fn test_lookbehind() {
let re = FuzzyRegex::new("(?<=hello) world").unwrap();
assert!(re.is_match("hello world"));
assert!(!re.is_match("bye world"));
let m = re.find("say hello world here").unwrap();
assert_eq!(m.start(), 9);
assert_eq!(m.end(), 15);
let re2 = FuzzyRegex::new("(?<!hello) world").unwrap();
assert!(re2.is_match("bye world"));
assert!(!re2.is_match("hello world"));
}
#[test]
fn test_lookbehind_fuzzy() {
let re = FuzzyRegex::new("(?<=(?:hello){e<=1}) world").unwrap();
assert!(re.is_match("hello world")); assert!(re.is_match("hallo world")); assert!(re.is_match("helo world")); assert!(re.is_match("helllo world")); assert!(!re.is_match("goodbye world")); }
#[test]
fn test_fuzzy_with_special_chars() {
let re = FuzzyRegex::new(r"(?:a.b){e<=1}").unwrap();
assert!(re.is_match("axb"));
assert!(re.is_match("ab"));
let re2 = FuzzyRegex::new(r"^(?:abc){e<=1}$").unwrap();
assert!(re2.is_match("abd")); assert!(re2.is_match("abcd")); }
#[test]
fn test_fuzzy_with_char_class_edge() {
let re = FuzzyRegex::new(r"(?:[a-z]{3}){e<=1}").unwrap();
assert!(re.is_match("ab")); assert!(re.is_match("ab1")); }
#[test]
fn test_multiple_fuzzy_groups() {
let re = FuzzyRegex::new(r"(?:ab){e<=1}(?:cd){e<=1}").unwrap();
assert!(re.is_match("abcd"));
assert!(re.is_match("xbcy")); }
#[test]
fn test_pathological_no_backtrack() {
let long_a = "a".repeat(30);
let re = FuzzyRegex::new("(a+)+b").unwrap();
assert!(re.is_match(&format!("{}b", long_a)));
assert!(!re.is_match(&long_a));
let re2 = FuzzyRegex::new("(a*)*b").unwrap();
assert!(re2.is_match(&format!("{}b", long_a)));
}
#[test]
fn test_overlapping_capture_groups() {
let re = FuzzyRegex::new("(a+)(a+)").unwrap();
let m = re.find("aaaa").unwrap();
assert_eq!(m.as_str(), "aaaa");
}
#[test]
fn test_prefix_empty_suffix() {
let re = FuzzyRegex::new("x()*y").unwrap();
assert!(re.is_match("xy"));
let re2 = FuzzyRegex::new("x(a*)y").unwrap();
assert!(re2.is_match("xy"));
}
#[test]
fn test_emoji_zwj_sequence() {
let re = FuzzyRegex::new("👨👩👧").unwrap();
assert!(re.is_match("👨👩👧"));
}
#[test]
fn test_unicode_cyrillic_range() {
let re = FuzzyRegex::new("[а-я]").unwrap();
assert!(re.is_match("м"));
assert!(!re.is_match("a")); }
#[test]
fn test_fuzzy_substitution_hallo() {
let re = FuzzyRegex::new("(?:hello){e<=1}").unwrap();
let m = re.find("hallo world").unwrap();
assert_eq!(m.as_str(), "hallo");
}
#[test]
fn test_fuzzy_substitution_hxllo() {
let re = FuzzyRegex::new("(?:hello){e<=1}").unwrap();
let m = re.find("hxllo world").unwrap();
assert_eq!(m.as_str(), "hxllo");
}
#[test]
fn test_fuzzy_substitution_quack() {
let re = FuzzyRegex::new("(?:quick){e<=1}").unwrap();
let m = re.find("The quack brown fox").unwrap();
assert_eq!(m.as_str(), "quack");
}
#[test]
fn test_fuzzy_insertion_heello() {
let re = FuzzyRegex::new("(?:hello){e<=1}").unwrap();
assert!(re.is_match("heello world"));
}
#[test]
fn test_fuzzy_insertion_caat() {
let re = FuzzyRegex::new("(?:cat){e<=1}").unwrap();
assert!(re.is_match("caat sitting"));
}
#[test]
fn test_fuzzy_deletion_helo() {
let re = FuzzyRegex::new("(?:hello){e<=2}").unwrap();
let m = re.find("helo world").unwrap();
assert_eq!(m.as_str(), "helo");
}
#[test]
fn test_fuzzy_deletion_wrld() {
let re = FuzzyRegex::new("(?:world){e<=1}").unwrap();
let m = re.find("wrld end").unwrap();
assert_eq!(m.as_str(), "wrld");
}
#[test]
fn test_fuzzy_no_match_xyzzy() {
let re = FuzzyRegex::new("(?:xyzzy){e<=1}").unwrap();
assert!(!re.is_match("The quick brown fox"));
}
#[test]
fn test_fuzzy_no_match_abcdef() {
let re = FuzzyRegex::new("(?:abcdef){e<=1}").unwrap();
assert!(!re.is_match("nothing matches here"));
}
#[test]
fn test_fuzzy_dna_acgt() {
let dna: String = (0..100)
.map(|i| match i % 4 {
0 => 'A',
1 => 'C',
2 => 'G',
_ => 'T',
})
.collect();
let re = FuzzyRegex::new("(?:ACGT){e<=1}").unwrap();
let m = re.find(&dna).unwrap();
assert_eq!(m.as_str(), "ACGT");
}
#[test]
fn test_fuzzy_dna_long_sequence() {
let dna: String = (0..100)
.map(|i| match i % 4 {
0 => 'A',
1 => 'C',
2 => 'G',
_ => 'T',
})
.collect();
let re = FuzzyRegex::new("(?:ACGTACGT){e<=2}").unwrap();
let m = re.find(&dna).unwrap();
assert_eq!(m.as_str(), "ACGTACGT");
}
#[test]
fn test_fuzzy_dna_no_match_gggg() {
let dna: String = (0..100)
.map(|i| match i % 4 {
0 => 'A',
1 => 'C',
2 => 'G',
_ => 'T',
})
.collect();
let re = FuzzyRegex::new("(?:GGGG){e<=1}").unwrap();
assert!(!re.is_match(&dna)); }
#[test]
fn test_fuzzy_single_char_exact() {
let re = FuzzyRegex::new("(?:a){e<=1}").unwrap();
let m = re.find("a").unwrap();
assert_eq!(m.as_str(), "a");
}
#[test]
fn test_fuzzy_single_char_substitution() {
let re = FuzzyRegex::new("(?:a){e<=1}").unwrap();
let m = re.find("b").unwrap();
assert_eq!(m.as_str(), "b"); }
#[test]
fn test_fuzzy_deletion_from_pattern() {
let re = FuzzyRegex::new("(?:ab){e<=1}").unwrap();
let m = re.find("a").unwrap();
assert_eq!(m.as_str(), "a"); }
#[test]
fn test_fuzzy_case_sensitivity_one_sub() {
let re = FuzzyRegex::new("(?:Hello){e<=1}").unwrap();
let m = re.find("hello world").unwrap();
assert_eq!(m.as_str(), "hello"); }
#[test]
fn test_fuzzy_case_sensitivity_too_many_errors() {
let re = FuzzyRegex::new("(?:HELLO){e<=2}").unwrap();
assert!(!re.is_match("hello world")); }
#[test]
fn test_fuzzy_multiple_potential_matches() {
let re = FuzzyRegex::new("(?:the){e<=1}").unwrap();
let m = re.find("the them then").unwrap();
assert_eq!(m.as_str(), "the");
}
#[test]
fn test_fuzzy_multiple_exact_matches() {
let re = FuzzyRegex::new("(?:cat){e<=1}").unwrap();
let m = re.find("cat bat rat cat").unwrap();
assert_eq!(m.as_str(), "cat");
}
#[test]
fn test_fuzzy_long_text() {
let long_text = "Lorem ipsum ".repeat(100);
let re = FuzzyRegex::new("(?:Lorem){e<=2}").unwrap();
let m = re.find(&long_text).unwrap();
assert_eq!(m.as_str(), "Lorem");
}
#[test]
fn test_fuzzy_unicode_cafe() {
let re = FuzzyRegex::new("(?:café){e<=1}").unwrap();
let m = re.find("I love café au lait").unwrap();
assert_eq!(m.as_str(), "café");
}
#[test]
fn test_fuzzy_unicode_naive() {
let re = FuzzyRegex::new("(?:naïve){e<=1}").unwrap();
assert!(re.is_match("Don't be naïve"));
}
#[test]
fn test_fuzzy_pattern_with_context() {
let re = FuzzyRegex::new("The (?:quick){e<=1} brown").unwrap();
let m = re.find("The quack brown fox").unwrap();
assert_eq!(m.as_str(), "The quack brown");
}
#[test]
fn test_fuzzy_pattern_followed_by_literal() {
let re = FuzzyRegex::new("(?:hello){e<=1} world").unwrap();
let m = re.find("hallo world!").unwrap();
assert_eq!(m.as_str(), "hallo world");
}
#[test]
fn test_char_restriction_substitution_allowed() {
let re = FuzzyRegex::new(r"(?:hello){s<=1:[a-z]}").unwrap();
let m = re.find("hallo").unwrap();
assert_eq!(m.as_str(), "hallo");
}
#[test]
fn test_char_restriction_substitution_rejected() {
let re = FuzzyRegex::new(r"(?:hello){s<=1:[a-z]}").unwrap();
assert!(!re.is_match("h3llo"));
}
#[test]
fn test_char_restriction_insertion_allowed() {
let re = FuzzyRegex::new(r"^(?:hell){i<=1:[a-z]}$").unwrap();
let m = re.find("hello").unwrap();
assert_eq!(m.as_str(), "hello");
}
#[test]
fn test_char_restriction_insertion_rejected() {
let re = FuzzyRegex::new(r"^(?:hell){i<=1:[a-z]}$").unwrap();
assert!(!re.is_match("hell1"));
}
#[test]
fn test_char_restriction_general_error_allowed() {
let re = FuzzyRegex::new(r"(?:hello){e<=1:[a-z]}").unwrap();
let m = re.find("hallo").unwrap();
assert_eq!(m.as_str(), "hallo");
}
#[test]
fn test_char_restriction_general_error_rejected() {
let re = FuzzyRegex::new(r"(?:hello){e<=1:[a-z]}").unwrap();
assert!(!re.is_match("h3llo"));
}
#[test]
fn test_char_restriction_digit_allowed() {
let re = FuzzyRegex::new(r"(?:test){e<=1:\d}").unwrap();
let m = re.find("t3st").unwrap();
assert_eq!(m.as_str(), "t3st");
}
#[test]
fn test_char_restriction_digit_rejected() {
let re = FuzzyRegex::new(r"(?:test){e<=1:\d}").unwrap();
assert!(!re.is_match("tast"));
}
#[test]
fn test_char_restriction_exact_match_bypasses() {
let re = FuzzyRegex::new(r"(?:hello){e<=1:[a-z]}").unwrap();
let m = re.find("hello").unwrap();
assert_eq!(m.as_str(), "hello");
}
#[test]
fn test_char_restriction_deletion() {
let re = FuzzyRegex::new(r"(?:hello){d<=1:[a-z]}").unwrap();
let m = re.find("hllo").unwrap();
assert_eq!(m.as_str(), "hllo");
}
#[test]
fn test_char_restriction_transposition() {
let re = FuzzyRegex::new(r"(?:the){e<=1:[a-z]}").unwrap();
let m = re.find("teh").unwrap();
assert_eq!(m.as_str(), "teh");
}
#[test]
fn test_word_boundary_in_middle() {
let re = FuzzyRegex::new(r"\bword\b").unwrap();
assert!(re.is_match("a word here"));
}
#[test]
fn test_word_boundary_exact() {
let re = FuzzyRegex::new(r"\bword\b").unwrap();
assert!(re.is_match("word"));
}
#[test]
fn test_word_boundary_with_suffix_rejected() {
let re = FuzzyRegex::new(r"\bword\b").unwrap();
assert!(!re.is_match("words"));
}
#[test]
fn test_word_boundary_with_prefix_rejected() {
let re = FuzzyRegex::new(r"\bword\b").unwrap();
assert!(!re.is_match("sword"));
}
#[test]
fn test_word_boundary_both_rejected() {
let re = FuzzyRegex::new(r"\bword\b").unwrap();
assert!(!re.is_match("swords"));
}
#[test]
fn test_word_boundary_start_only() {
let re = FuzzyRegex::new(r"\bword").unwrap();
assert!(re.is_match("word!"));
}
#[test]
fn test_word_boundary_end_only() {
let re = FuzzyRegex::new(r"word\b").unwrap();
assert!(re.is_match("a word"));
}
#[test]
fn test_word_boundary_digits() {
let re = FuzzyRegex::new(r"\b\d+\b").unwrap();
assert!(re.is_match("test 123 here"));
assert!(!re.is_match("test123"));
}
#[test]
fn test_word_boundary_quis() {
let re = FuzzyRegex::new(r"\bquis\b").unwrap();
assert!(re.is_match("quis nostrud"));
assert!(!re.is_match("aliquis")); }
#[test]
fn test_non_word_boundary_embedded() {
let re = FuzzyRegex::new(r"\Bword\B").unwrap();
assert!(re.is_match("swordsmith"));
assert!(!re.is_match("word")); assert!(!re.is_match("sword")); }
#[test]
fn test_non_word_boundary_not_at_start() {
let re = FuzzyRegex::new(r"\Bword").unwrap();
assert!(re.is_match("swords"));
}
#[test]
fn test_non_word_boundary_not_at_end() {
let re = FuzzyRegex::new(r"word\B").unwrap();
assert!(re.is_match("words"));
}
#[test]
fn test_non_word_boundary_digits_embedded() {
let re = FuzzyRegex::new(r"\B\d+\B").unwrap();
assert!(re.is_match("abc123def"));
}
#[test]
fn test_non_word_boundary_before_non_word() {
let re = FuzzyRegex::new(r"\B!").unwrap();
assert!(re.is_match("!"));
}
#[test]
fn test_non_word_boundary_after_non_word() {
let re = FuzzyRegex::new(r"!\B").unwrap();
assert!(re.is_match("!"));
}
#[test]
fn test_word_boundary_in_empty_string() {
let re = FuzzyRegex::new(r"\b").unwrap();
assert!(!re.is_match(""));
}
#[test]
fn test_non_word_boundary_with_space_start() {
let re = FuzzyRegex::new(r"\B ").unwrap();
assert!(re.is_match(" "));
}
#[test]
fn test_non_word_boundary_with_space_end() {
let re = FuzzyRegex::new(r" \B").unwrap();
assert!(re.is_match(" "));
}
#[test]
fn test_word_boundary_find_multiple() {
let re = FuzzyRegex::new(r"\b\w+\b").unwrap();
let matches: Vec<_> = re.find_iter("hello world test").collect();
assert_eq!(matches.len(), 3);
assert_eq!(matches[0].as_str(), "hello");
assert_eq!(matches[1].as_str(), "world");
assert_eq!(matches[2].as_str(), "test");
}
#[test]
fn test_transposition_limit_matches() {
let re = FuzzyRegex::new("(?:ab){t<=1}").unwrap();
assert!(re.is_match("ab")); assert!(re.is_match("ba")); }
#[test]
fn test_transposition_limit_combined() {
let re = FuzzyRegex::new("(?:ab){e<=1,t<=1}").unwrap();
assert!(re.is_match("ab")); assert!(re.is_match("ba")); }
#[test]
fn test_transposition_with_total_edits() {
let re = FuzzyRegex::new("(?:hello){t<=1,e<=2}").unwrap();
assert!(re.is_match("hello")); assert!(re.is_match("ehllo")); assert!(re.is_match("hallo")); }
#[test]
fn test_cost_syntax_basic() {
let re = FuzzyRegex::new("(?:hello){c<=2}").unwrap();
assert!(re.is_match("hello")); assert!(re.is_match("hallo")); assert!(re.is_match("helo")); }
#[test]
fn test_cost_constraint_rejects_over_limit() {
let re = FuzzyRegex::new("(?:hi){c<=1}").unwrap();
assert!(re.is_match("hi")); assert!(re.is_match("ho")); assert!(!re.is_match("xy"));
}
#[test]
fn test_weighted_cost_constraint() {
let re = FuzzyRegex::new("(?:ab){2i+1d+1s<=3}").unwrap();
assert!(re.is_match("ab")); assert!(re.is_match("a")); assert!(re.is_match("abcd")); }
#[test]
fn test_greedy_first_basic() {
let re = FuzzyRegexBuilder::new("(?:hello){e<=1}")
.greedy_first(true)
.build()
.unwrap();
assert!(re.is_match("hello world"));
let m = re.find("hello world").unwrap();
assert_eq!(m.as_str(), "hello");
}
#[test]
fn test_greedy_first_finds_first_match() {
let re = FuzzyRegexBuilder::new("(?:cat){e<=1}")
.greedy_first(true)
.build()
.unwrap();
let m = re.find("cat bat cat").unwrap();
assert_eq!(m.start(), 0);
assert_eq!(m.end(), 3);
}
#[test]
fn test_greedy_first_vs_best_match() {
let re_best = FuzzyRegexBuilder::new("(?:hello){e<=2}").build().unwrap();
let re_greedy = FuzzyRegexBuilder::new("(?:hello){e<=2}")
.greedy_first(true)
.build()
.unwrap();
let text = "hello hello";
let best = re_best.find(text);
let greedy = re_greedy.find(text);
assert!(best.is_some());
assert!(greedy.is_some());
}
#[test]
fn test_greedy_first_no_match() {
let re = FuzzyRegexBuilder::new("(?:xyz){e<=1}")
.greedy_first(true)
.build()
.unwrap();
assert!(!re.is_match("abc"));
}
#[test]
fn test_greedy_first_case_insensitive() {
let re = FuzzyRegexBuilder::new("(?:hello){e<=1}")
.case_insensitive(true)
.greedy_first(true)
.build()
.unwrap();
assert!(re.is_match("HELLO"));
}
#[test]
fn test_find_rev_basic() {
let re = FuzzyRegex::new("world").unwrap();
let m = re.find_rev("hello world world").unwrap();
assert_eq!(m.start(), 12);
assert_eq!(m.end(), 17);
}
#[test]
fn test_find_rev_no_match() {
let re = FuzzyRegex::new("xyz").unwrap();
assert!(re.find_rev("hello world").is_none());
}
#[test]
fn test_find_rev_single_match() {
let re = FuzzyRegex::new("hello").unwrap();
let m = re.find_rev("say hello to the world").unwrap();
assert_eq!(m.as_str(), "hello");
}
#[test]
fn test_find_rev_iter() {
let re = FuzzyRegex::new("(?:cat|dog){e<=1}").unwrap();
let matches = re.find_iter_rev("cat dog cat");
assert_eq!(matches.len(), 3);
}
#[test]
fn test_find_at_basic() {
let re = FuzzyRegex::new("hello").unwrap();
let m = re.find_at("say hello world", 4).unwrap();
assert_eq!(m.as_str(), "hello");
}
#[test]
fn test_find_at_no_match() {
let re = FuzzyRegex::new("hello").unwrap();
assert!(re.find_at("say hello world", 10).is_none());
}
#[test]
fn test_find_at_start_of_match() {
let re = FuzzyRegex::new("(?:hello){e<=1}").unwrap();
let m = re.find_at("hello world", 0).unwrap();
assert!(m.as_str().starts_with("hell"));
}
#[test]
fn test_find_from_basic() {
let re = FuzzyRegex::new("world").unwrap();
let m = re.find_from("hello world", 6).unwrap();
assert_eq!(m.as_str(), "world");
}
#[test]
fn test_fullmatch_basic() {
let re = FuzzyRegex::new("hello").unwrap();
let m = re.fullmatch("hello").unwrap();
assert_eq!(m.as_str(), "hello");
}
#[test]
fn test_fullmatch_no_match() {
let re = FuzzyRegex::new("hello").unwrap();
assert!(re.fullmatch("hello world").is_none());
}
#[test]
fn test_fullmatch_fuzzy() {
let re = FuzzyRegex::new("(?:hello){e<=1}").unwrap();
let m = re.fullmatch("helo").unwrap();
assert_eq!(m.as_str(), "helo");
}
#[test]
fn test_fullmatch_at() {
let re = FuzzyRegex::new("hello").unwrap();
let m = re.fullmatch_at("ahello", 1).unwrap();
assert_eq!(m.as_str(), "hello");
}
#[test]
fn test_fullmatch_at_no_match() {
let re = FuzzyRegex::new("hello").unwrap();
assert!(re.fullmatch_at("hello world", 0).is_none());
}
#[test]
fn test_split_basic() {
let re = FuzzyRegex::new(",").unwrap();
let parts: Vec<&str> = re.split("a,b,c").collect();
assert_eq!(parts, vec!["a", "b", "c"]);
}
#[test]
fn test_split_no_match() {
let re = FuzzyRegex::new(",").unwrap();
let parts: Vec<&str> = re.split("abc").collect();
assert_eq!(parts, vec!["abc"]);
}
#[test]
fn test_split_empty_parts() {
let re = FuzzyRegex::new(",").unwrap();
let parts: Vec<&str> = re.split("a,,b").collect();
assert_eq!(parts, vec!["a", "", "b"]);
}
#[test]
fn test_split_fuzzy() {
let re = FuzzyRegex::new("(?:,){e<=1}").unwrap();
let parts: Vec<&str> = re.split("a;b;c").collect();
assert!(parts.len() >= 2);
}
#[test]
fn test_splitn_basic() {
let re = FuzzyRegex::new(",").unwrap();
let parts = re.splitn("a,b,c,d", 2);
assert_eq!(parts, vec!["a", "b,c,d"]);
}
#[test]
fn test_splitn_all() {
let re = FuzzyRegex::new(",").unwrap();
let parts = re.splitn("a,b,c", 10);
assert_eq!(parts, vec!["a", "b", "c"]);
}
#[test]
fn test_replace_basic() {
let re = FuzzyRegex::new("world").unwrap();
let result = re.replace("hello world", "there");
assert_eq!(result, "hello there");
}
#[test]
fn test_replace_all() {
let re = FuzzyRegex::new("o").unwrap();
let result = re.replace_all("hello world", "x");
assert_eq!(result, "hellx wxrld");
}
#[test]
fn test_replace_fuzzy() {
let re = FuzzyRegex::new("(?:hello){e<=1}").unwrap();
let result = re.replace("say helo there", "hi");
assert!(result.contains("hi"));
}
#[test]
fn test_replace_no_match() {
let re = FuzzyRegex::new("xyz").unwrap();
let result = re.replace("hello world", "replaced");
assert_eq!(result, "hello world");
}
#[test]
fn test_replace_with_closure() {
let re = FuzzyRegex::new(r"(\d+)").unwrap();
let result = re.replace_all_with("price: 100 amount: 200", |caps| {
let num: i32 = caps.get(1).unwrap().as_str().parse().unwrap();
format!("${}", num)
});
assert_eq!(result, "price: $100 amount: $200");
}
#[test]
fn test_builder_ungreedy() {
let re = FuzzyRegexBuilder::new("<.+>")
.ungreedy(true)
.build()
.unwrap();
let m = re.find("<a> <b>").unwrap();
assert!(m.as_str().starts_with("<a"));
}
#[test]
fn test_builder_verbose() {
let re = FuzzyRegexBuilder::new("(?x) hello world")
.verbose(true)
.build()
.unwrap();
assert!(re.is_match("helloworld"));
let re2 = FuzzyRegexBuilder::new("(?x) hello \\s world")
.verbose(true)
.build()
.unwrap();
assert!(re2.is_match("hello world"));
}
#[test]
fn test_builder_dot_all() {
let re = FuzzyRegexBuilder::new("a.b").dot_all(true).build().unwrap();
assert!(re.is_match("a\nb"));
}
#[test]
fn test_builder_multi_line() {
let re = FuzzyRegexBuilder::new("^hello")
.multi_line(true)
.build()
.unwrap();
assert!(re.is_match("foo\nhello"));
}
#[test]
fn test_builder_max_threads() {
let re = FuzzyRegexBuilder::new("hello")
.max_threads(100)
.build()
.unwrap();
assert!(re.is_match("hello world"));
}
#[test]
fn test_builder_timeout() {
use std::time::Duration;
let re = FuzzyRegexBuilder::new("hello")
.timeout(Duration::from_secs(1))
.build()
.unwrap();
assert!(re.is_match("hello"));
}
#[test]
fn test_match_flags_best_match() {
let re = FuzzyRegexBuilder::new("(?:hello){e<=2}").build().unwrap();
let m = re.find("heallo hallo").unwrap();
assert_eq!(m.as_str(), "heallo");
}
#[test]
fn test_match_flags_enhance_match() {
let re = FuzzyRegexBuilder::new("(?:hello){e<=2}").build().unwrap();
let m = re.find("helo").unwrap();
assert_eq!(m.as_str(), "helo");
}
#[test]
fn test_is_match_at() {
let re = FuzzyRegex::new("hello").unwrap();
assert!(re.is_match_at("say hello world", 4));
assert!(!re.is_match_at("say hello world", 10));
}
#[test]
fn test_is_match_at_fuzzy() {
let re = FuzzyRegex::new("(?:hello){e<=1}").unwrap();
assert!(re.is_match_at("ahello", 1));
}
#[test]
fn test_is_match_bytes() {
let re = FuzzyRegex::new("hello").unwrap();
assert!(re.is_match_bytes(b"hello world"));
}
#[test]
fn test_find_bytes() {
let re = FuzzyRegex::new("hello").unwrap();
let m = re.find_bytes(b"hello world").unwrap();
assert_eq!(m.start(), 0);
assert_eq!(m.end(), 5);
}
#[test]
fn test_find_bytes_fuzzy() {
let re = FuzzyRegex::new("(?:hello){e<=1}").unwrap();
let m = re.find_bytes(b"helo world").unwrap();
assert_eq!(&b"helo world"[m.start()..m.end()], b"helo");
}
#[test]
fn test_find_iter_bytes() {
let re = FuzzyRegex::new("o").unwrap();
let matches: Vec<_> = re.find_iter_bytes(b"hello world").collect();
assert_eq!(matches.len(), 2);
}
#[test]
fn test_cost_with_transposition() {
let re = FuzzyRegex::new("(?:ab){1i+1d+1s+2t<=3}").unwrap();
assert!(re.is_match("ab")); assert!(re.is_match("ba")); assert!(re.is_match("ac")); }
#[test]
fn test_weighted_cost_high_insertion_cost() {
let re = FuzzyRegex::new("(?:ab){3i+1d+1s+1t<=3}").unwrap();
assert!(re.is_match("ab")); assert!(re.is_match("abc")); assert!(re.is_match("a")); assert!(re.is_match("cb")); }
#[test]
fn test_cost_exclusive_bound() {
let re = FuzzyRegex::new("(?:ab){c<3}").unwrap();
assert!(re.is_match("ab")); assert!(re.is_match("ac")); assert!(re.is_match("cb")); }
#[test]
fn test_cost_zero_cost_operation() {
let re = FuzzyRegex::new("(?:ab){0i+1d+1s<=2}").unwrap();
assert!(re.is_match("ab")); assert!(re.is_match("abc")); assert!(re.is_match("abcd")); assert!(re.is_match("a")); }