package pl.edu.amu.wmi.daut.base;
import junit.framework.TestCase;
/**
* Test klasy NondeterministicAutomatonByThompsonApproach.
*/
public class TestNondeterministicAutomatonByThompsonApproach extends TestCase {
/**
* Pierwszy test (przykładowy prosty automat).
*/
public final void testSimpleAutomaton() {
final AutomatonSpecification spec = new NaiveAutomatonSpecification();
State q0a = spec.addState();
State q1a = spec.addState();
State q2a = spec.addState();
State q3a = spec.addState();
State q4a = spec.addState();
State q5a = spec.addState();
spec.addTransition(q0a, q1a, new CharTransitionLabel('a'));
spec.addTransition(q0a, q2a, new CharTransitionLabel('b'));
spec.addTransition(q0a, q5a, new CharTransitionLabel('b'));
spec.addTransition(q1a, q2a, new CharTransitionLabel('c'));
spec.addTransition(q1a, q3a, new CharTransitionLabel('c'));
spec.addTransition(q1a, q4a, new CharTransitionLabel('b'));
spec.addTransition(q2a, q4a, new CharTransitionLabel('a'));
spec.addTransition(q2a, q5a, new CharTransitionLabel('a'));
spec.addTransition(q3a, q5a, new CharTransitionLabel('b'));
spec.addTransition(q4a, q3a, new CharTransitionLabel('c'));
spec.addTransition(q4a, q5a, new CharTransitionLabel('a'));
spec.addTransition(q5a, q0a, new CharTransitionLabel('a'));
spec.addLoop(q5a, new CharTransitionLabel('a'));
spec.markAsInitial(q0a);
spec.markAsFinal(q3a);
spec.markAsFinal(q4a);
spec.markAsFinal(q5a);
final NondeterministicAutomatonByThompsonApproach automaton =
new NondeterministicAutomatonByThompsonApproach(spec);
assertTrue(automaton.accepts("abc"));
assertTrue(automaton.accepts("ba"));
assertTrue(automaton.accepts("ac"));
assertTrue(automaton.accepts("baaaaaaaaa"));
assertTrue(automaton.accepts("b"));
assertFalse(automaton.accepts("cccccccccabbbbbbc"));
assertFalse(automaton.accepts("aaaaaaaaaaa"));
assertFalse(automaton.accepts("bcccccc"));
assertFalse(automaton.accepts("z"));
}
/**
* Drugi test (tylko epsilon-przejścia).
*/
public final void testOnlyEpsilonTransitionLabel() {
final AutomatonSpecification spec = new NaiveAutomatonSpecification();
State q0a = spec.addState();
State q1a = spec.addState();
State q2a = spec.addState();
State q3a = spec.addState();
spec.addTransition(q0a, q1a, new EpsilonTransitionLabel());
spec.addTransition(q0a, q2a, new EpsilonTransitionLabel());
spec.addTransition(q1a, q3a, new EpsilonTransitionLabel());
spec.addTransition(q2a, q3a, new EpsilonTransitionLabel());
spec.markAsInitial(q0a);
spec.markAsFinal(q3a);
final NondeterministicAutomatonByThompsonApproach automaton =
new NondeterministicAutomatonByThompsonApproach(spec);
assertTrue(automaton.accepts(""));
assertFalse(automaton.accepts("uam"));
}
/**
* Trzeci test (pusty automat).
*/
public final void testEmptyAutomaton() {
final AutomatonSpecification spec = new NaiveAutomatonSpecification();
final NondeterministicAutomatonByThompsonApproach automaton =
new NondeterministicAutomatonByThompsonApproach(spec);
assertFalse(automaton.accepts("cccccccccabbbbbbc"));
assertFalse(automaton.accepts("aaaaaaaaaaa"));
assertFalse(automaton.accepts("bcccccc"));
assertFalse(automaton.accepts("z"));
}
/**
* Czwarty test (Od stanu początkowego odchodzą 3 epsilon-przejścia do
* trzech różnych stanów. Dopiero od owych trzech stanów występują
* "normalne" przejścia - tj. po znaku).
*/
public final void testOnlyEpsilonTransitionLabelFromInitialState() {
final AutomatonSpecification spec = new NaiveAutomatonSpecification();
State q0a = spec.addState();
State q1a = spec.addState();
State q2a = spec.addState();
State q3a = spec.addState();
State q4a = spec.addState();
State q5a = spec.addState();
State q6a = spec.addState();
State q7a = spec.addState();
spec.addTransition(q0a, q1a, new EpsilonTransitionLabel());
spec.addTransition(q0a, q2a, new EpsilonTransitionLabel());
spec.addTransition(q0a, q3a, new EpsilonTransitionLabel());
spec.addTransition(q1a, q4a, new CharTransitionLabel('a'));
spec.addTransition(q1a, q5a, new CharTransitionLabel('a'));
spec.addTransition(q2a, q5a, new CharTransitionLabel('b'));
spec.addTransition(q3a, q5a, new CharTransitionLabel('c'));
spec.addTransition(q3a, q6a, new CharTransitionLabel('a'));
spec.addTransition(q3a, q6a, new CharTransitionLabel('b'));
spec.addTransition(q4a, q5a, new CharTransitionLabel('b'));
spec.addTransition(q4a, q7a, new CharTransitionLabel('b'));
spec.addTransition(q5a, q7a, new CharTransitionLabel('a'));
spec.addTransition(q5a, q6a, new CharTransitionLabel('a'));
spec.addTransition(q6a, q7a, new CharTransitionLabel('c'));
spec.addTransition(q6a, q5a, new CharTransitionLabel('b'));
spec.addLoop(q3a, new CharTransitionLabel('c'));
spec.addLoop(q6a, new CharTransitionLabel('c'));
spec.addLoop(q7a, new CharTransitionLabel('a'));
spec.addLoop(q7a, new CharTransitionLabel('b'));
spec.addLoop(q7a, new CharTransitionLabel('c'));
spec.markAsInitial(q0a);
spec.markAsFinal(q7a);
final NondeterministicAutomatonByThompsonApproach automaton =
new NondeterministicAutomatonByThompsonApproach(spec);
assertTrue(automaton.accepts("abc"));
assertTrue(automaton.accepts("ac"));
assertTrue(automaton.accepts("baaaaaaa"));
assertTrue(automaton.accepts("ccccccca"));
assertFalse(automaton.accepts("ccc"));
assertFalse(automaton.accepts(""));
assertFalse(automaton.accepts("uam"));
}
/**
* Piąty test (Do stanu końcowego prowadzą tylko epsilon przejścia.
* Występują pętle epsilon).
*/
public final void testOnlyEpsilonTransitionLabelToFinalState() {
final AutomatonSpecification spec = new NaiveAutomatonSpecification();
State q0a = spec.addState();
State q1a = spec.addState();
State q2a = spec.addState();
State q3a = spec.addState();
State q4a = spec.addState();
spec.addTransition(q1a, q4a, new EpsilonTransitionLabel());
spec.addTransition(q2a, q4a, new EpsilonTransitionLabel());
spec.addTransition(q3a, q4a, new EpsilonTransitionLabel());
spec.addTransition(q0a, q1a, new CharTransitionLabel('a'));
spec.addTransition(q0a, q2a, new CharTransitionLabel('b'));
spec.addTransition(q0a, q3a, new CharTransitionLabel('b'));
spec.addTransition(q1a, q2a, new CharTransitionLabel('a'));
spec.addTransition(q2a, q0a, new CharTransitionLabel('b'));
spec.addTransition(q3a, q2a, new CharTransitionLabel('c'));
spec.addLoop(q1a, new CharTransitionLabel('c'));
spec.addLoop(q3a, new CharTransitionLabel('a'));
spec.addLoop(q2a, new CharTransitionLabel('b'));
spec.addLoop(q1a, new EpsilonTransitionLabel());
spec.addLoop(q3a, new EpsilonTransitionLabel());
spec.markAsInitial(q0a);
spec.markAsFinal(q4a);
final NondeterministicAutomatonByThompsonApproach automaton =
new NondeterministicAutomatonByThompsonApproach(spec);
assertTrue(automaton.accepts("b"));
assertFalse(automaton.accepts("uam"));
}
/**
* Szósty test (tylko jeden stan, brak przejść).
*/
public final void testOneState() {
final AutomatonSpecification spec = new NaiveAutomatonSpecification();
State q0a = spec.addState();
final NondeterministicAutomatonByThompsonApproach automaton =
new NondeterministicAutomatonByThompsonApproach(spec);
spec.markAsInitial(q0a);
spec.markAsFinal(q0a);
assertTrue(automaton.accepts(""));
assertFalse(automaton.accepts("cccccccccabbbbbbc"));
assertFalse(automaton.accepts("aaaaaaaaaaa"));
assertFalse(automaton.accepts("bcccccc"));
assertFalse(automaton.accepts("z"));
}
/**
* Siódmy test (dwa stany, epsilon-przejście pomiędzy nimi).
*/
public final void testTwoStatesOneEpsilonTrasitionLabel() {
final AutomatonSpecification spec = new NaiveAutomatonSpecification();
State q0a = spec.addState();
State q1a = spec.addState();
spec.addTransition(q0a, q1a, new EpsilonTransitionLabel());
final NondeterministicAutomatonByThompsonApproach automaton =
new NondeterministicAutomatonByThompsonApproach(spec);
spec.markAsInitial(q0a);
spec.markAsFinal(q1a);
assertTrue(automaton.accepts(""));
assertFalse(automaton.accepts("cccccccccabbbbbbc"));
assertFalse(automaton.accepts("aaaaaaaaaaa"));
assertFalse(automaton.accepts("bcccccc"));
assertFalse(automaton.accepts("z"));
}
/**
* Ósmy test (automat akceptuje starego typu tablice
* rejestracyjne tj. 3 litery i 4 cyfry)
*/
public final void testOldFashionRegistationPlates() {
final AutomatonSpecification spec = new NaiveAutomatonSpecification();
State q0a = spec.addState();
State q1a = spec.addState();
State q2a = spec.addState();
State q3a = spec.addState();
State q4a = spec.addState();
State q5a = spec.addState();
State q6a = spec.addState();
State q7a = spec.addState();
TransitionLabel letterLabel = new CharRangeTransitionLabel('A', 'Z');
TransitionLabel digitLabel = new CharRangeTransitionLabel('0', '9');
spec.addTransition(q0a, q1a, letterLabel);
spec.addTransition(q1a, q2a, letterLabel);
spec.addTransition(q2a, q3a, letterLabel);
spec.addTransition(q3a, q4a, digitLabel);
spec.addTransition(q4a, q5a, digitLabel);
spec.addTransition(q5a, q6a, digitLabel);
spec.addTransition(q6a, q7a, digitLabel);
spec.markAsInitial(q0a);
spec.markAsFinal(q7a);
final NondeterministicAutomatonByThompsonApproach automaton =
new NondeterministicAutomatonByThompsonApproach(spec);
assertTrue(automaton.accepts("AAA9999"));
assertTrue(automaton.accepts("WXT5692"));
assertFalse(automaton.accepts(""));
assertFalse(automaton.accepts("AA99999"));
assertFalse(automaton.accepts("AAAA999"));
}
/**
* Dziewiąty test (automat akceptuje liczby nieujemne
* podzielne przez 3 i pomija nieznaczące zera).
*/
public final void testNonnegativeNumberDivisibleByThree() {
final AutomatonSpecification spec = new NaiveAutomatonSpecification();
State q0a = spec.addState();
State q1a = spec.addState();
State q2a = spec.addState();
State q3a = spec.addState();
spec.addTransition(q0a, q1a, new CharTransitionLabel('1'));
spec.addTransition(q0a, q1a, new CharTransitionLabel('4'));
spec.addTransition(q0a, q1a, new CharTransitionLabel('7'));
spec.addTransition(q0a, q2a, new CharTransitionLabel('2'));
spec.addTransition(q0a, q2a, new CharTransitionLabel('5'));
spec.addTransition(q0a, q2a, new CharTransitionLabel('8'));
spec.addTransition(q1a, q0a, new CharTransitionLabel('2'));
spec.addTransition(q1a, q0a, new CharTransitionLabel('5'));
spec.addTransition(q1a, q0a, new CharTransitionLabel('8'));
spec.addTransition(q1a, q2a, new CharTransitionLabel('1'));
spec.addTransition(q1a, q2a, new CharTransitionLabel('4'));
spec.addTransition(q1a, q2a, new CharTransitionLabel('7'));
spec.addTransition(q2a, q1a, new CharTransitionLabel('2'));
spec.addTransition(q2a, q1a, new CharTransitionLabel('5'));
spec.addTransition(q0a, q1a, new CharTransitionLabel('8'));
spec.addTransition(q2a, q0a, new CharTransitionLabel('1'));
spec.addTransition(q2a, q0a, new CharTransitionLabel('4'));
spec.addTransition(q2a, q0a, new CharTransitionLabel('7'));
spec.addTransition(q0a, q3a, new EpsilonTransitionLabel());
spec.addTransition(q0a, q3a, new CharTransitionLabel('-'));
spec.addLoop(q0a, new CharTransitionLabel('0'));
spec.addLoop(q0a, new CharTransitionLabel('3'));
spec.addLoop(q0a, new CharTransitionLabel('6'));
spec.addLoop(q0a, new CharTransitionLabel('9'));
spec.addLoop(q1a, new CharTransitionLabel('0'));
spec.addLoop(q1a, new CharTransitionLabel('3'));
spec.addLoop(q1a, new CharTransitionLabel('6'));
spec.addLoop(q1a, new CharTransitionLabel('9'));
spec.addLoop(q2a, new CharTransitionLabel('0'));
spec.addLoop(q2a, new CharTransitionLabel('3'));
spec.addLoop(q2a, new CharTransitionLabel('6'));
spec.addLoop(q2a, new CharTransitionLabel('9'));
spec.addLoop(q3a, new CharTransitionLabel('0'));
spec.addLoop(q3a, new CharTransitionLabel('1'));
spec.addLoop(q3a, new CharTransitionLabel('2'));
spec.addLoop(q3a, new CharTransitionLabel('3'));
spec.addLoop(q3a, new CharTransitionLabel('4'));
spec.addLoop(q3a, new CharTransitionLabel('5'));
spec.addLoop(q3a, new CharTransitionLabel('6'));
spec.addLoop(q3a, new CharTransitionLabel('7'));
spec.addLoop(q3a, new CharTransitionLabel('8'));
spec.addLoop(q3a, new CharTransitionLabel('9'));
spec.markAsInitial(q0a);
spec.markAsFinal(q0a);
final NondeterministicAutomatonByThompsonApproach automaton =
new NondeterministicAutomatonByThompsonApproach(spec);
assertTrue(automaton.accepts("0"));
assertTrue(automaton.accepts("003"));
assertTrue(automaton.accepts("12523212"));
assertTrue(automaton.accepts("111"));
assertFalse(automaton.accepts("-0301"));
assertFalse(automaton.accepts("-0302"));
}
/**
* Dziesiąty test (automat akceptuje poznańskie numery telefonów
* w postaci 61 XXX-XX-XX lub (61) XXX-XX-XX).
*/
public final void testPhoneNumbersPoznan() {
final AutomatonSpecification spec = new NaiveAutomatonSpecification();
State q0a = spec.addState();
State q1a = spec.addState();
State q2a = spec.addState();
State q3a = spec.addState();
State q4a = spec.addState();
State q5a = spec.addState();
State q6a = spec.addState();
State q7a = spec.addState();
State q8a = spec.addState();
State q9a = spec.addState();
State q10a = spec.addState();
State q11a = spec.addState();
State q12a = spec.addState();
State q13a = spec.addState();
State q14a = spec.addState();
State q15a = spec.addState();
TransitionLabel digitLabel = new CharRangeTransitionLabel('0', '9');
spec.addTransition(q0a, q1a, new CharTransitionLabel('('));
spec.addTransition(q1a, q2a, new CharTransitionLabel('6'));
spec.addTransition(q2a, q3a, new CharTransitionLabel('1'));
spec.addTransition(q3a, q4a, new CharTransitionLabel(')'));
spec.addTransition(q4a, q5a, new CharTransitionLabel(' '));
spec.addTransition(q0a, q6a, new CharTransitionLabel('6'));
spec.addTransition(q6a, q4a, new CharTransitionLabel('1'));
spec.addTransition(q4a, q5a, new CharTransitionLabel(' '));
spec.addTransition(q5a, q7a, digitLabel);
spec.addTransition(q7a, q8a, digitLabel);
spec.addTransition(q8a, q9a, digitLabel);
spec.addTransition(q9a, q10a, new CharTransitionLabel('-'));
spec.addTransition(q10a, q11a, digitLabel);
spec.addTransition(q11a, q12a, digitLabel);
spec.addTransition(q12a, q13a, new CharTransitionLabel('-'));
spec.addTransition(q13a, q14a, digitLabel);
spec.addTransition(q14a, q15a, digitLabel);
spec.markAsInitial(q0a);
spec.markAsFinal(q15a);
final NondeterministicAutomatonByThompsonApproach automaton =
new NondeterministicAutomatonByThompsonApproach(spec);
assertTrue(automaton.accepts("(61) 123-45-78"));
assertTrue(automaton.accepts("(61) 682-45-79"));
assertTrue(automaton.accepts("(61) 183-45-68"));
assertTrue(automaton.accepts("(61) 898-58-98"));
assertTrue(automaton.accepts("61 055-55-88"));
assertTrue(automaton.accepts("61 155-55-88"));
assertTrue(automaton.accepts("61 255-55-88"));
assertTrue(automaton.accepts("61 455-55-88"));
assertTrue(automaton.accepts("61 655-55-88"));
assertTrue(automaton.accepts("61 565-55-88"));
assertFalse(automaton.accepts("61 4857856"));
assertFalse(automaton.accepts("(61)666-88-88"));
assertFalse(automaton.accepts("61-555-55-55"));
assertFalse(automaton.accepts("615555555"));
assertFalse(automaton.accepts("615-555-555"));
}
/**
* Automat przyjmujący pola szachownicy.
*/
public final void testChessFields() {
final AutomatonSpecification spec = new NaiveAutomatonSpecification();
State q0a = spec.addState();
State q1a = spec.addState();
State q2a = spec.addState();
spec.addTransition(q0a, q1a, new CharRangeTransitionLabel('a', 'h'));
spec.addTransition(q1a, q2a, new CharRangeTransitionLabel('1', '8'));
spec.markAsInitial(q0a);
spec.markAsFinal(q2a);
final NondeterministicAutomatonByThompsonApproach automaton =
new NondeterministicAutomatonByThompsonApproach(spec);
assertFalse(automaton.accepts("1b"));
assertTrue(automaton.accepts("a2"));
assertTrue(automaton.accepts("c4"));
assertFalse(automaton.accepts("a"));
}
/**
* Automat akceptujący napisy typu "NOOOOOOO!!!", gdzie "O" występuje
* conajmniej 5 razy, wykrzyknik przynajmniej raz.
*/
public final void testAutomaton() {
final AutomatonSpecification spec = new NaiveAutomatonSpecification();
State q0 = spec.addState();
State q1 = spec.addState();
State q2 = spec.addState();
State q3 = spec.addState();
State q4 = spec.addState();
State q5 = spec.addState();
State q6 = spec.addState();
State q7 = spec.addState();
spec.addTransition(q0, q1, new CharTransitionLabel('N'));
spec.addTransition(q1, q2, new CharTransitionLabel('O'));
spec.addTransition(q2, q3, new CharTransitionLabel('O'));
spec.addTransition(q3, q4, new CharTransitionLabel('O'));
spec.addTransition(q4, q5, new CharTransitionLabel('O'));
spec.addTransition(q5, q6, new CharTransitionLabel('O'));
spec.addTransition(q6, q7, new CharTransitionLabel('!'));
spec.addLoop(q6, new CharTransitionLabel('O'));
spec.addLoop(q7, new CharTransitionLabel('!'));
spec.markAsInitial(q0);
spec.markAsFinal(q7);
final NondeterministicAutomatonByThompsonApproach automaton =
new NondeterministicAutomatonByThompsonApproach(spec);
assertFalse(automaton.accepts("N"));
assertFalse(automaton.accepts("NO"));
assertFalse(automaton.accepts("NOO"));
assertFalse(automaton.accepts("NOOO"));
assertFalse(automaton.accepts("NOOOO"));
assertFalse(automaton.accepts("NOOOOO"));
assertFalse(automaton.accepts("NOOOO!"));
assertTrue(automaton.accepts("NOOOOO!"));
assertTrue(automaton.accepts("NOOOOOO!"));
assertTrue(automaton.accepts("NOOOOO!!"));
assertTrue(automaton.accepts("NOOOOOOO!!!"));
}
/**
* Ósmy test (automat z przynajmniej jednym epsilon-przejściem
* akceptujący wszystkie napisy złożone z napisu "abcd"
* powielonego dowolną liczbę razy przynajmniej raz).
*/
public final void testNondeterministicAutomatonWithEpsilonTransition() {
final AutomatonSpecification spec = new NaiveAutomatonSpecification();
State q0 = spec.addState();
State q1 = spec.addState();
State q2 = spec.addState();
State q3 = spec.addState();
State q4 = spec.addState();
spec.addTransition(q0, q1, new CharTransitionLabel('a'));
spec.addTransition(q1, q2, new CharTransitionLabel('b'));
spec.addTransition(q2, q3, new CharTransitionLabel('c'));
spec.addTransition(q3, q4, new CharTransitionLabel('d'));
spec.addTransition(q4, q0, new EpsilonTransitionLabel());
spec.addTransition(q4, q1, new CharTransitionLabel('a'));
spec.markAsInitial(q0);
spec.markAsFinal(q4);
final NondeterministicAutomatonByThompsonApproach automaton =
new NondeterministicAutomatonByThompsonApproach(spec);
assertTrue(automaton.accepts("abcd"));
assertTrue(automaton.accepts("abcdabcd"));
assertTrue(automaton.accepts("abcdabcdabcd"));
assertTrue(automaton.accepts("abcdabcdabcdabcd"));
assertTrue(automaton.accepts("abcdabcdabcdabcdabcd"));
assertFalse(automaton.accepts("aabcd"));
assertFalse(automaton.accepts("abbcd"));
assertFalse(automaton.accepts("abccd"));
assertFalse(automaton.accepts("abcdd"));
assertFalse(automaton.accepts("aabbccdd"));
assertFalse(automaton.accepts(" "));
assertFalse(automaton.accepts("abc"));
assertFalse(automaton.accepts("+"));
assertFalse(automaton.accepts("1234"));
assertFalse(automaton.accepts("fghi"));
assertFalse(automaton.accepts("dddd"));
assertFalse(automaton.accepts("a123"));
assertFalse(automaton.accepts("a"));
assertFalse(automaton.accepts("b"));
assertFalse(automaton.accepts("c"));
assertFalse(automaton.accepts("d"));
}
}