#[cfg(test)]
use super::{NFAChar, TransitionLabelChar, NFA};
#[test]
fn test_nfa_char_new() {
let nfa = NFAChar::new();
assert_eq!(nfa.num_states(), 1);
assert_eq!(nfa.num_transitions(), 0);
assert_eq!(nfa.start(), 0);
assert!(!nfa.is_final(0));
}
#[test]
fn test_nfa_char_add_state() {
let mut nfa = NFAChar::new();
let q1 = nfa.add_state(false);
let q2 = nfa.add_state(true);
assert_eq!(q1, 1);
assert_eq!(q2, 2);
assert_eq!(nfa.num_states(), 3);
assert!(!nfa.is_final(q1));
assert!(nfa.is_final(q2));
}
#[test]
fn test_nfa_char_simple_accept() {
let mut nfa = NFAChar::new();
let q0 = nfa.start();
let q1 = nfa.add_state(true);
nfa.add_transition_char(q0, 'a', q1);
assert!(nfa.accepts("a"));
assert!(!nfa.accepts("b"));
assert!(!nfa.accepts(""));
assert!(!nfa.accepts("aa"));
}
#[test]
fn test_nfa_char_epsilon_closure() {
let mut nfa = NFAChar::new();
let q0 = nfa.start();
let q1 = nfa.add_state(false);
let q2 = nfa.add_state(true);
nfa.add_epsilon(q0, q1);
nfa.add_epsilon(q1, q2);
let closure = nfa.epsilon_closure_single(q0);
assert!(closure.contains(&q0));
assert!(closure.contains(&q1));
assert!(closure.contains(&q2));
assert_eq!(closure.len(), 3);
}
#[test]
fn test_nfa_char_accepts_with_epsilon() {
let mut nfa = NFAChar::new();
let q0 = nfa.start();
let q1 = nfa.add_state(false);
let q2 = nfa.add_state(true);
nfa.add_epsilon(q0, q1);
nfa.add_transition_char(q1, 'x', q2);
assert!(nfa.accepts("x"));
assert!(!nfa.accepts("y"));
}
#[test]
fn test_nfa_char_union() {
let mut nfa_a = NFAChar::new();
let q0 = nfa_a.start();
let q1 = nfa_a.add_state(true);
nfa_a.add_transition_char(q0, 'a', q1);
let mut nfa_b = NFAChar::new();
let q0 = nfa_b.start();
let q1 = nfa_b.add_state(true);
nfa_b.add_transition_char(q0, 'b', q1);
let union = nfa_a.union(nfa_b);
assert!(union.accepts("a"));
assert!(union.accepts("b"));
assert!(!union.accepts("c"));
assert!(!union.accepts("ab"));
assert!(!union.accepts(""));
}
#[test]
fn test_nfa_char_concatenate() {
let mut nfa_a = NFAChar::new();
let q0 = nfa_a.start();
let q1 = nfa_a.add_state(true);
nfa_a.add_transition_char(q0, 'a', q1);
let mut nfa_b = NFAChar::new();
let q0 = nfa_b.start();
let q1 = nfa_b.add_state(true);
nfa_b.add_transition_char(q0, 'b', q1);
let concat = nfa_a.concatenate(nfa_b);
assert!(concat.accepts("ab"));
assert!(!concat.accepts("a"));
assert!(!concat.accepts("b"));
assert!(!concat.accepts("ba"));
assert!(!concat.accepts(""));
}
#[test]
fn test_nfa_char_kleene_star() {
let mut nfa_a = NFAChar::new();
let q0 = nfa_a.start();
let q1 = nfa_a.add_state(true);
nfa_a.add_transition_char(q0, 'a', q1);
let star = nfa_a.kleene_star();
assert!(star.accepts(""));
assert!(star.accepts("a"));
assert!(star.accepts("aa"));
assert!(star.accepts("aaa"));
assert!(!star.accepts("b"));
assert!(!star.accepts("ab"));
}
#[test]
fn test_nfa_char_kleene_plus() {
let mut nfa_a = NFAChar::new();
let q0 = nfa_a.start();
let q1 = nfa_a.add_state(true);
nfa_a.add_transition_char(q0, 'a', q1);
let plus = nfa_a.kleene_plus();
assert!(!plus.accepts(""));
assert!(plus.accepts("a"));
assert!(plus.accepts("aa"));
assert!(plus.accepts("aaa"));
assert!(!plus.accepts("b"));
}
#[test]
fn test_nfa_char_optional() {
let mut nfa_a = NFAChar::new();
let q0 = nfa_a.start();
let q1 = nfa_a.add_state(true);
nfa_a.add_transition_char(q0, 'a', q1);
let opt = nfa_a.optional();
assert!(opt.accepts(""));
assert!(opt.accepts("a"));
assert!(!opt.accepts("aa"));
assert!(!opt.accepts("b"));
}
#[test]
fn test_nfa_byte_simple() {
let mut nfa = NFA::new();
let q0 = nfa.start();
let q1 = nfa.add_state(true);
nfa.add_transition_byte(q0, b'a', q1);
assert!(nfa.accepts(b"a"));
assert!(nfa.accepts_str("a"));
assert!(!nfa.accepts(b"b"));
assert!(!nfa.accepts(b""));
}
#[test]
fn test_nfa_byte_union() {
let mut nfa_a = NFA::new();
let q0 = nfa_a.start();
let q1 = nfa_a.add_state(true);
nfa_a.add_transition_byte(q0, b'a', q1);
let mut nfa_b = NFA::new();
let q0 = nfa_b.start();
let q1 = nfa_b.add_state(true);
nfa_b.add_transition_byte(q0, b'b', q1);
let union = nfa_a.union(nfa_b);
assert!(union.accepts_str("a"));
assert!(union.accepts_str("b"));
assert!(!union.accepts_str("c"));
}
#[test]
fn test_nfa_byte_concatenate() {
let mut nfa_a = NFA::new();
let q0 = nfa_a.start();
let q1 = nfa_a.add_state(true);
nfa_a.add_transition_byte(q0, b'a', q1);
let mut nfa_b = NFA::new();
let q0 = nfa_b.start();
let q1 = nfa_b.add_state(true);
nfa_b.add_transition_byte(q0, b'b', q1);
let concat = nfa_a.concatenate(nfa_b);
assert!(concat.accepts_str("ab"));
assert!(!concat.accepts_str("a"));
assert!(!concat.accepts_str("b"));
}
#[test]
fn test_nfa_char_complex_pattern() {
let mut nfa_a = NFAChar::new();
let q0 = nfa_a.start();
let q1 = nfa_a.add_state(true);
nfa_a.add_transition_char(q0, 'a', q1);
let mut nfa_b = NFAChar::new();
let q0 = nfa_b.start();
let q1 = nfa_b.add_state(true);
nfa_b.add_transition_char(q0, 'b', q1);
let mut nfa_c = NFAChar::new();
let q0 = nfa_c.start();
let q1 = nfa_c.add_state(true);
nfa_c.add_transition_char(q0, 'c', q1);
let union = nfa_a.union(nfa_b);
let star = union.kleene_star();
let pattern = star.concatenate(nfa_c);
assert!(pattern.accepts("c"));
assert!(pattern.accepts("ac"));
assert!(pattern.accepts("bc"));
assert!(pattern.accepts("aac"));
assert!(pattern.accepts("abc"));
assert!(pattern.accepts("bac"));
assert!(pattern.accepts("aabc"));
assert!(!pattern.accepts(""));
assert!(!pattern.accepts("a"));
assert!(!pattern.accepts("b"));
assert!(!pattern.accepts("ca"));
}
#[test]
fn test_nfa_char_start_of_line_anchor() {
let mut nfa = NFAChar::new();
let q0 = nfa.start();
let q1 = nfa.add_state(false);
let q2 = nfa.add_state(false);
let q3 = nfa.add_state(false);
let q4 = nfa.add_state(false);
let q5 = nfa.add_state(false);
let q6 = nfa.add_state(true);
nfa.add_transition(q0, TransitionLabelChar::StartOfLine, q1);
nfa.add_transition_char(q1, 'h', q2);
nfa.add_transition_char(q2, 'e', q3);
nfa.add_transition_char(q3, 'l', q4);
nfa.add_transition_char(q4, 'l', q5);
nfa.add_transition_char(q5, 'o', q6);
assert!(nfa.accepts("hello"));
assert!(!nfa.accepts("xhello"));
}
#[test]
fn test_nfa_char_end_of_line_anchor() {
let mut nfa = NFAChar::new();
let q0 = nfa.start();
let q1 = nfa.add_state(false);
let q2 = nfa.add_state(false);
let q3 = nfa.add_state(false);
let q4 = nfa.add_state(false);
let q5 = nfa.add_state(false);
let q6 = nfa.add_state(true);
nfa.add_transition_char(q0, 'h', q1);
nfa.add_transition_char(q1, 'e', q2);
nfa.add_transition_char(q2, 'l', q3);
nfa.add_transition_char(q3, 'l', q4);
nfa.add_transition_char(q4, 'o', q5);
nfa.add_transition(q5, TransitionLabelChar::EndOfLine, q6);
assert!(nfa.accepts("hello"));
}
#[test]
fn test_nfa_char_anchored_pattern() {
let mut nfa = NFAChar::new();
let q0 = nfa.start();
let q1 = nfa.add_state(false);
let q2 = nfa.add_state(false);
let q3 = nfa.add_state(false);
let q4 = nfa.add_state(false);
let q5 = nfa.add_state(false);
let q6 = nfa.add_state(false);
let q7 = nfa.add_state(true);
nfa.add_transition(q0, TransitionLabelChar::StartOfLine, q1);
nfa.add_transition_char(q1, 'h', q2);
nfa.add_transition_char(q2, 'e', q3);
nfa.add_transition_char(q3, 'l', q4);
nfa.add_transition_char(q4, 'l', q5);
nfa.add_transition_char(q5, 'o', q6);
nfa.add_transition(q6, TransitionLabelChar::EndOfLine, q7);
assert!(nfa.accepts("hello"));
assert!(!nfa.accepts("xhello"));
}
#[test]
fn test_nfa_char_multiline_start_of_line() {
let mut nfa = NFAChar::new();
let q0 = nfa.start();
let q1 = nfa.add_state(false);
let q2 = nfa.add_state(false);
let q3 = nfa.add_state(false);
let q4 = nfa.add_state(false);
let q5 = nfa.add_state(true);
nfa.add_transition(q0, TransitionLabelChar::StartOfLine, q1);
nfa.add_transition_char(q1, 'l', q2);
nfa.add_transition_char(q2, 'i', q3);
nfa.add_transition_char(q3, 'n', q4);
nfa.add_transition_char(q4, 'e', q5);
assert!(nfa.accepts_with_flags("line", false, false));
}
#[test]
fn test_nfa_char_start_of_input_anchor() {
let mut nfa = NFAChar::new();
let q0 = nfa.start();
let q1 = nfa.add_state(false);
let q2 = nfa.add_state(false);
let q3 = nfa.add_state(false);
let q4 = nfa.add_state(false);
let q5 = nfa.add_state(false);
let q6 = nfa.add_state(true);
nfa.add_transition(q0, TransitionLabelChar::StartOfInput, q1);
nfa.add_transition_char(q1, 'h', q2);
nfa.add_transition_char(q2, 'e', q3);
nfa.add_transition_char(q3, 'l', q4);
nfa.add_transition_char(q4, 'l', q5);
nfa.add_transition_char(q5, 'o', q6);
assert!(nfa.accepts_with_flags("hello", true, false));
}
#[test]
fn test_nfa_char_end_of_input_anchor() {
let mut nfa = NFAChar::new();
let q0 = nfa.start();
let q1 = nfa.add_state(false);
let q2 = nfa.add_state(false);
let q3 = nfa.add_state(false);
let q4 = nfa.add_state(false);
let q5 = nfa.add_state(false);
let q6 = nfa.add_state(true);
nfa.add_transition_char(q0, 'h', q1);
nfa.add_transition_char(q1, 'e', q2);
nfa.add_transition_char(q2, 'l', q3);
nfa.add_transition_char(q3, 'l', q4);
nfa.add_transition_char(q4, 'o', q5);
nfa.add_transition(q5, TransitionLabelChar::EndOfInput, q6);
assert!(nfa.accepts("hello"));
assert!(nfa.accepts("hello\n"));
}
#[test]
fn test_nfa_char_strict_end_of_input_anchor() {
let mut nfa = NFAChar::new();
let q0 = nfa.start();
let q1 = nfa.add_state(false);
let q2 = nfa.add_state(false);
let q3 = nfa.add_state(false);
let q4 = nfa.add_state(false);
let q5 = nfa.add_state(false);
let q6 = nfa.add_state(true);
nfa.add_transition_char(q0, 'h', q1);
nfa.add_transition_char(q1, 'e', q2);
nfa.add_transition_char(q2, 'l', q3);
nfa.add_transition_char(q3, 'l', q4);
nfa.add_transition_char(q4, 'o', q5);
nfa.add_transition(q5, TransitionLabelChar::EndOfInputStrict, q6);
assert!(nfa.accepts("hello"));
assert!(!nfa.accepts("hello\n")); }