use regexsolver::Term;
use regexsolver::error::EngineError;
use regexsolver::execution_profile::ExecutionProfileBuilder;
use regexsolver::fast_automaton::{GenerationOptions, PathOrder};
#[test]
fn readme_automaton_building_example() -> Result<(), EngineError> {
use regexsolver::CharRange;
use regexsolver::fast_automaton::FastAutomaton;
use regexsolver::regex_charclass::char::Char;
let mut automaton = FastAutomaton::new_empty();
let s1 = automaton.new_state();
automaton.accept(s1);
let a_to_c = CharRange::new_from_range(Char::new('a')..=Char::new('c'));
let digits = CharRange::new_from_range(Char::new('0')..=Char::new('9'));
automaton.add_transition_from_range(0, s1, &a_to_c)?;
automaton.add_transition_from_range(s1, s1, &digits)?;
assert!(automaton.is_match("b42"));
assert!(!automaton.is_match("4b"));
assert_eq!(automaton.to_regex()?.to_string(), "[a-c][0-9]*");
Ok(())
}
#[test]
fn readme_hero_example() -> Result<(), EngineError> {
let a: Term = "(ab|xy){2}".parse()?;
let b: Term = ".*xy".parse()?;
let both = a.intersection([&b])?;
assert_eq!(both.to_pattern()?, "(ab|xy)xy");
assert!(both.matches("abxy")?);
assert_eq!(
both.generate_strings(2, 0, PathOrder::Sweep)?,
["xyxy", "abxy"]
);
Ok(())
}
#[test]
fn readme_regular_expression_example() -> Result<(), EngineError> {
use regexsolver::regex::RegularExpression;
let pattern = RegularExpression::new("ORD-20[0-9]{2}-[0-9]{4,6}")?;
assert_eq!(pattern.length(), (Some(13), Some(15)));
fn has_unbounded_repetition(regex: &RegularExpression) -> bool {
match regex {
RegularExpression::Character(_) => false,
RegularExpression::Repetition(inner, _, max) => {
max.is_none() || has_unbounded_repetition(inner)
}
RegularExpression::Concat(parts) => parts.iter().any(has_unbounded_repetition),
RegularExpression::Alternation(parts) => parts.iter().any(has_unbounded_repetition),
}
}
assert!(!has_unbounded_repetition(&pattern));
assert!(has_unbounded_repetition(&RegularExpression::new(
".*@example\\.com"
)?));
Ok(())
}
#[test]
fn readme_time_bounded_execution_example() -> Result<(), EngineError> {
let term = Term::from_pattern(".*abc.*cdef.*sqdsqf.*")?;
let execution_profile = ExecutionProfileBuilder::new()
.execution_timeout(50) .build();
execution_profile.run(|| {
assert_eq!(
EngineError::OperationTimeOutError,
term.generate_strings(100_000_000, 0, GenerationOptions::new())
.unwrap_err()
);
});
Ok(())
}
#[test]
fn readme_state_limited_execution_example() -> Result<(), EngineError> {
let term1 = Term::from_pattern(".*abcdef.*")?;
let term2 = Term::from_pattern(".*defabc.*")?;
let execution_profile = ExecutionProfileBuilder::new()
.max_number_of_states(5) .build();
execution_profile.run(|| {
assert_eq!(
EngineError::AutomatonHasTooManyStates,
term1.intersection(&[term2]).unwrap_err()
);
});
Ok(())
}
#[test]
fn readme_disabling_implicit_determinization_example() -> Result<(), EngineError> {
let nfa = Term::from_pattern(".*abc")?.to_automaton()?.into_owned();
assert!(!nfa.is_deterministic());
let execution_profile = ExecutionProfileBuilder::new()
.implicit_determinization(false) .build();
execution_profile.run(|| {
let mut cannot_minimize = nfa.clone();
assert_eq!(
EngineError::DeterministicAutomatonRequired,
cannot_minimize.minimize().unwrap_err()
);
let mut dfa = nfa.determinize().unwrap().into_owned();
assert!(dfa.minimize().is_ok());
});
Ok(())
}