package pl.edu.amu.wmi.daut.base;
import junit.framework.TestCase;
import java.util.List;
/**
* Przykładowe testy przykładowej klasy NaiveAutomatonSpecification.
*/
public class TestNaiveAutomatonSpecification extends TestCase {
/**
* Test prostego automatu o trzech stanach.
*/
public final void testSimpleAutomaton() {
NaiveAutomatonSpecification spec = new NaiveAutomatonSpecification();
// budowanie
State s0 = spec.addState();
State s1 = spec.addState();
spec.addTransition(s0, s1, new CharTransitionLabel('a'));
State s2 = spec.addState();
spec.addTransition(s0, s2, new CharTransitionLabel('b'));
spec.addTransition(s1, s2, new CharTransitionLabel('c'));
spec.markAsInitial(s0);
spec.markAsFinal(s2);
// testowanie
State r0 = spec.getInitialState();
List<OutgoingTransition> r0Outs = spec.allOutgoingTransitions(r0);
// w ten sposób w JUnicie wyrażamy oczekiwanie, że liczba
// przejść wychodzących z początkowego stanu powinna być równa 2
assertEquals(r0Outs.size(), 2);
assertFalse(spec.isFinal(r0));
State r1;
State r2;
if (((CharTransitionLabel) r0Outs.get(0).getTransitionLabel()).getChar() == 'a') {
r1 = r0Outs.get(0).getTargetState();
r2 = r0Outs.get(1).getTargetState();
assertEquals(((CharTransitionLabel) r0Outs.get(1).getTransitionLabel()).getChar(), 'b');
assertTrue(
((CharTransitionLabel) r0Outs.get(1).getTransitionLabel()).canAcceptCharacter('b'));
assertFalse(
((CharTransitionLabel) r0Outs.get(1).getTransitionLabel()).canAcceptCharacter('c'));
assertFalse(((CharTransitionLabel) r0Outs.get(1).getTransitionLabel()).canBeEpsilon());
} else {
// kolejność może być odwrócona
r1 = r0Outs.get(1).getTargetState();
r2 = r0Outs.get(0).getTargetState();
assertEquals(((CharTransitionLabel) r0Outs.get(0).getTransitionLabel()).getChar(), 'b');
}
assertFalse(spec.isFinal(r1));
assertTrue(spec.isFinal(r2));
assertSame(r0, spec.getInitialState());
assertNotSame(r0, r1);
assertNotSame(r0, r2);
assertNotSame(r1, r2);
List<State> states = spec.allStates();
assertEquals(states.size(), 3);
}
/**
* Prosty test wyznaczania przecięcia.
*/
public final void testIntersections() {
CharTransitionLabel tA1 = new CharTransitionLabel('a');
CharTransitionLabel tA2 = new CharTransitionLabel('a');
CharTransitionLabel tB = new CharTransitionLabel('b');
EmptyTransitionLabel emptyTransition = new EmptyTransitionLabel();
TransitionLabel intersectedA = tA1.intersect(tA2);
assertFalse(intersectedA.isEmpty());
assertTrue(intersectedA.canAcceptCharacter('a'));
assertFalse(intersectedA.canAcceptCharacter('b'));
assertTrue(tA1.intersect(tB).isEmpty());
assertTrue(tB.intersect(tA1).isEmpty());
assertTrue(emptyTransition.intersect(tA1).isEmpty());
assertTrue(tA1.intersect(emptyTransition).isEmpty());
assertTrue(emptyTransition.intersect(emptyTransition).isEmpty());
}
/**
* Test metody dodającej pętlę.
*/
public final void testAddLoop() {
NaiveAutomatonSpecification spec = new NaiveAutomatonSpecification();
//budowanie
State s0 = spec.addState();
spec.addLoop(s0, new CharTransitionLabel('a'));
spec.markAsInitial(s0);
spec.markAsFinal(s0);
//testowanie
State r0 = spec.getInitialState();
List<OutgoingTransition> r0Outs = spec.allOutgoingTransitions(r0);
assertEquals(r0Outs.size(), 1);
assertTrue(spec.isFinal(r0));
if (((CharTransitionLabel) r0Outs.get(0).getTransitionLabel()).getChar() == 'a') {
assertEquals(
((CharTransitionLabel) r0Outs.get(0).getTransitionLabel()).getChar(), 'a');
assertTrue(
((CharTransitionLabel) r0Outs.get(0).getTransitionLabel()).canAcceptCharacter('a'));
assertFalse(
((CharTransitionLabel) r0Outs.get(0).getTransitionLabel()).canBeEpsilon());
}
assertTrue(spec.isFinal(r0));
assertSame(r0, spec.getInitialState());
List<State> states = spec.allStates();
assertEquals(states.size(), 1);
}
/**
* Test metody tworzącej prosty automat.
*/
public final void testmakeOneLoopAutomaton(char c) {
AutomatonSpecification spec = new NaiveAutomatonSpecification();
//budowanie
spec = spec.makeOneLoopAutomaton(c);
//testowanie
State r0 = spec.getInitialState();
List<OutgoingTransition> r0Outs = spec.allOutgoingTransitions(r0);
assertEquals(r0Outs.size(), 1);
assertTrue(spec.isFinal(r0));
State r1;
if (((CharTransitionLabel) r0Outs.get(0).getTransitionLabel()).getChar() == 'c') {
r1 = r0Outs.get(0).getTargetState();
assertEquals(
((CharTransitionLabel) r0Outs.get(0).getTransitionLabel()).getChar(), 'c');
assertTrue(
((CharTransitionLabel) r0Outs.get(0).getTransitionLabel()).canAcceptCharacter('c'));
assertFalse(
((CharTransitionLabel) r0Outs.get(0).getTransitionLabel()).canBeEpsilon());
}
assertTrue(spec.isFinal(r0));
assertSame(r0, spec.getInitialState());
List<State> states = spec.allStates();
assertEquals(states.size(), 1);
}
/**
* Test metody dopełniającej automat.
*/
public final void testMakeFull() {
NaiveAutomatonSpecification spec = new NaiveAutomatonSpecification();
NaiveAutomatonSpecification spec2 = new NaiveAutomatonSpecification();
NaiveAutomatonSpecification spec3 = new NaiveAutomatonSpecification();
assertFalse(spec.isFull("abc"));
spec.makeFull("abc");
assertTrue(spec.isFull("abc"));
assertEquals(spec.countStates(), 1);
State s = spec2.addState();
assertFalse(spec2.isFull("abc"));
spec2.makeFull("abc");
assertTrue(spec2.isFull("abc"));
assertEquals(spec2.countStates(), 2);
State s0 = spec3.addState();
State s1 = spec3.addState();
State s2 = spec3.addState();
spec3.addTransition(s0, s1, new CharTransitionLabel('a'));
assertFalse(spec3.isFull("abc"));
spec3.makeFull("abc");
assertTrue(spec3.isFull("abc"));
assertEquals(spec3.countStates(), 4);
}
/**
* Test metody dopełniającej automat na automacie, który jest już pełny.
*/
public final void testMakeFullAlreadyFull() {
NaiveAutomatonSpecification spec = new NaiveAutomatonSpecification();
State s0 = spec.addState();
State s1 = spec.addState();
State s2 = spec.addState();
spec.addTransition(s0, s1, new CharTransitionLabel('b'));
spec.addTransition(s0, s1, new CharTransitionLabel('a'));
spec.addLoop(s1, new CharTransitionLabel('a'));
spec.addLoop(s1, new CharTransitionLabel('b'));
spec.addLoop(s2, new CharTransitionLabel('a'));
spec.addLoop(s2, new CharTransitionLabel('b'));
spec.makeFull("ab");
assertTrue(spec.isFull("ab"));
assertEquals(spec.countStates(), 3);
}
/**
* Test metody dopełniającej automat na automacie, któremu brakuje jednego przejścia.
*/
public final void testMakeFullAlmostFull() {
NaiveAutomatonSpecification spec = new NaiveAutomatonSpecification();
State s0 = spec.addState();
State s1 = spec.addState();
State s2 = spec.addState();
spec.addTransition(s0, s1, new CharTransitionLabel('a'));
spec.addLoop(s1, new CharTransitionLabel('a'));
spec.addLoop(s1, new CharTransitionLabel('b'));
spec.addLoop(s2, new CharTransitionLabel('a'));
spec.addLoop(s2, new CharTransitionLabel('b'));
spec.makeFull("ab");
assertEquals(spec.countStates(), 4);
assertTrue(spec.isFull("ab"));
}
/**
* Test metody tworzącej prosty automat.
*/
public final void testmakeOneTransitionAutomaton(char c) {
AutomatonSpecification spec = new NaiveAutomatonSpecification();
spec.makeOneTransitionAutomaton(c);
//testowanie
State r0 = spec.getInitialState();
List<OutgoingTransition> r0Outs = spec.allOutgoingTransitions(r0);
assertEquals(r0Outs.size(), 1);
assertFalse(spec.isFinal(r0));
State r1 = r0Outs.get(0).getTargetState();
if (((CharTransitionLabel) r0Outs.get(0).getTransitionLabel()).getChar() == 'c') {
assertEquals(
((CharTransitionLabel) r0Outs.get(0).getTransitionLabel()).getChar(), 'c');
assertTrue(
((CharTransitionLabel) r0Outs.get(0).getTransitionLabel()).canAcceptCharacter('c'));
assertFalse(
((CharTransitionLabel) r0Outs.get(0).getTransitionLabel()).canBeEpsilon());
}
assertTrue(spec.isFinal(r1));
assertSame(r0, spec.getInitialState());
List<State> states = spec.allStates();
assertEquals(states.size(), 2);
}
/**
* Test metody tworzącej automat akceptujący wszystkie napisy nad zadanym językiem.
*/
public final void testMakeAllStringsAutomaton() {
final AutomatonSpecification spec = new NaiveAutomatonSpecification();
spec.makeAllStringsAutomaton("abc");
assertTrue(spec.acceptEmptyWord());
AutomatonByRecursion automaton = new AutomatonByRecursion(spec);
assertFalse(automaton.accepts("defffadegbc"));
assertFalse(automaton.accepts("abecadlo"));
assertTrue(automaton.accepts("abcbcabbbaaa"));
assertTrue(automaton.accepts("bbccaabcbabab"));
assertTrue(automaton.accepts("cacacacbbccccc"));
}
/**
* Testuje działanie metody makeAllNonEmptyStringsAutomaton().
*/
public final void testMakeAllNonEmptyStringsAutomaton() {
//Buduję automat na 2 stanach korzystając z testowanej metody
final AutomatonSpecification spec = new NaiveAutomatonSpecification();
spec.makeAllNonEmptyStringsAutomaton("ab");
AutomatonByRecursion automaton = new AutomatonByRecursion(spec);
//Sprawdzam czy automat akceptuje losowe słowa i czy odrzuca słowo puste
assertFalse(spec.acceptEmptyWord());
assertTrue(automaton.accepts("abbabbabbabbaaa"));
assertFalse(automaton.accepts("caba"));
assertTrue(automaton.accepts("a"));
assertTrue(automaton.accepts("b"));
assertTrue(automaton.accepts("aaaa"));
assertTrue(automaton.accepts("bbbb"));
}
/**
* Test metody sprawdzającej, czy akceptowany język jest nieskończony dla
* automatu z kilkoma pętlami zarówno w stanach pojedyńczych, jak i z wieloma
* stanami.
*/
public final void testInfiniteForManyLoops() {
NaiveAutomatonSpecification automat = new NaiveAutomatonSpecification();
State s0 = automat.addState();
State s1 = automat.addState();
State s2 = automat.addState();
State s3 = automat.addState();
State s4 = automat.addState();
automat.addTransition(s0, s1, new CharTransitionLabel('a'));
automat.addLoop(s1, new CharTransitionLabel('b'));
automat.addLoop(s2, new CharTransitionLabel('b'));
automat.addTransition(s1, s2, new CharTransitionLabel('a'));
automat.addTransition(s2, s1, new CharTransitionLabel('a'));
automat.addTransition(s2, s0, new CharTransitionLabel('c'));
automat.addTransition(s2, s3, new CharTransitionLabel('c'));
automat.addTransition(s3, s4, new CharTransitionLabel('a'));
automat.addLoop(s4, new CharTransitionLabel('b'));
automat.markAsFinal(s2);
automat.markAsFinal(s1);
automat.markAsInitial(s0);
automat.markAsFinal(s4);
assertTrue(automat.isInfinite());
}
/**
* Test metody sprawdzającej, czy akceptowany język jest nieskończony przy
* automacie z pętlą rozpoczynającą się zaraz po przejściu ze stanu początkowego.
*/
public final void testInfiniteForLoopStartingAfterState0() {
NaiveAutomatonSpecification automat = new NaiveAutomatonSpecification();
State s0 = automat.addState();
State s1 = automat.addState();
State s2 = automat.addState();
State s3 = automat.addState();
automat.addTransition(s0, s1, new CharTransitionLabel('a'));
automat.addTransition(s1, s2, new CharTransitionLabel('a'));
automat.addTransition(s2, s3, new CharTransitionLabel('a'));
automat.addTransition(s3, s1, new CharTransitionLabel('a'));
automat.markAsInitial(s0);
automat.markAsFinal(s2);
assertTrue(automat.isInfinite());
}
/**
* Test metody sprawdzającej, czy akceptowany język jest nieskończony dla
* automatu, w którym z pętli zawierającej stan końcowy da się wyjść do
* innego stanu końcowego.
*/
public final void testInfiniteForStateAfterLoop() {
NaiveAutomatonSpecification automat = new NaiveAutomatonSpecification();
State s0 = automat.addState();
State s1 = automat.addState();
State s2 = automat.addState();
State s3 = automat.addState();
State s4 = automat.addState();
automat.addTransition(s0, s1, new CharTransitionLabel('a'));
automat.addTransition(s1, s2, new CharTransitionLabel('a'));
automat.addTransition(s2, s3, new CharTransitionLabel('a'));
automat.addTransition(s3, s1, new CharTransitionLabel('a'));
automat.addTransition(s3, s4, new CharTransitionLabel('b'));
automat.markAsInitial(s0);
automat.markAsFinal(s2);
automat.markAsFinal(s1);
automat.markAsFinal(s4);
assertTrue(automat.isInfinite());
}
/**
* Test metody sprawdzającej, czy akceptowany język jest nieskończony dla
* automatu, w którym z pętli zawierającej stan końcowy da sie wyjść do innej
* pętli.
*/
public final void testInfiniteForLoopAfterLoop() {
NaiveAutomatonSpecification automat = new NaiveAutomatonSpecification();
State s0 = automat.addState();
State s1 = automat.addState();
State s2 = automat.addState();
State s3 = automat.addState();
State s4 = automat.addState();
State s5 = automat.addState();
automat.addTransition(s0, s1, new CharTransitionLabel('a'));
automat.addTransition(s1, s2, new CharTransitionLabel('a'));
automat.addTransition(s2, s3, new CharTransitionLabel('a'));
automat.addTransition(s3, s2, new CharTransitionLabel('b'));
automat.addTransition(s3, s1, new CharTransitionLabel('a'));
automat.addTransition(s3, s4, new CharTransitionLabel('b'));
automat.addTransition(s4, s5, new CharTransitionLabel('a'));
automat.addTransition(s5, s4, new CharTransitionLabel('a'));
automat.markAsInitial(s0);
automat.markAsFinal(s1);
assertTrue(automat.isInfinite());
}
/**
* Test metody sprawdzającej, czy akceptowany język jest nieskończony dla
* automatu, w którym stan końcowy jest zawarty po pętli.
*/
public final void testInfiniteForFinalAfterLoop() {
NaiveAutomatonSpecification automat = new NaiveAutomatonSpecification();
State s0 = automat.addState();
State s1 = automat.addState();
State s2 = automat.addState();
State s3 = automat.addState();
State s4 = automat.addState();
automat.addTransition(s0, s1, new CharTransitionLabel('a'));
automat.addTransition(s1, s2, new CharTransitionLabel('a'));
automat.addTransition(s2, s3, new CharTransitionLabel('a'));
automat.addTransition(s3, s1, new CharTransitionLabel('a'));
automat.addTransition(s3, s4, new CharTransitionLabel('b'));
automat.markAsInitial(s0);
automat.markAsFinal(s4);
assertTrue(automat.isInfinite());
}
/**
* Test metody sprawdzającej, czy akceptowany język jest nieskończony dla
* automatu, w którym mamy zwykłą ścieżkę ze stanu s0 do stanu s4 bez żadnych
* pętli.
*/
public final void testInfiniteForSimpleRoute() {
NaiveAutomatonSpecification automat = new NaiveAutomatonSpecification();
State s0 = automat.addState();
State s1 = automat.addState();
State s2 = automat.addState();
State s3 = automat.addState();
State s4 = automat.addState();
automat.addTransition(s0, s1, new CharTransitionLabel('a'));
automat.addTransition(s1, s2, new CharTransitionLabel('a'));
automat.addTransition(s2, s3, new CharTransitionLabel('a'));
automat.addTransition(s3, s4, new CharTransitionLabel('a'));
automat.markAsInitial(s0);
automat.markAsFinal(s3);
assertFalse(automat.isInfinite());
}
/**
* Test metody sprawdzającej, czy akceptowany język jest nieskończony dla
* automatu z jedną pętlą i dwoma stanami końcowymi w niej.
*/
public final void testInfiniteForOneLoopAndTwoFinalStates() {
NaiveAutomatonSpecification automat = new NaiveAutomatonSpecification();
State s0 = automat.addState();
State s1 = automat.addState();
State s2 = automat.addState();
State s3 = automat.addState();
automat.addTransition(s1, s2, new CharTransitionLabel('a'));
automat.addTransition(s2, s3, new CharTransitionLabel('a'));
automat.addTransition(s3, s1, new CharTransitionLabel('a'));
automat.markAsInitial(s0);
automat.markAsFinal(s2);
automat.markAsFinal(s1);
assertFalse(automat.isInfinite());
}
/**
* Test metody sprawdzającej, czy akceptowany język jest nieskończony dla
* automatu zawierającego jeden stan zawierający pętlę do samego siebie.
*/
public final void testInfiniteForOneState() {
NaiveAutomatonSpecification automat = new NaiveAutomatonSpecification();
State s0 = automat.addState();
automat.addLoop(s0, new CharTransitionLabel('a'));
automat.markAsInitial(s0);
automat.markAsFinal(s0);
assertTrue(automat.isInfinite());
}
/**
* Test metody sprawdzającej, czy akceptowany język jest nieskończony z pętlą
* złożoną z 2 stanów dla sytuacji, kiedy stanem końcowym jest stan początkowy.
*/
public final void testInfiniteFinalState0() {
NaiveAutomatonSpecification automat = new NaiveAutomatonSpecification();
State s0 = automat.addState();
State s1 = automat.addState();
automat.addTransition(s0, s1, new CharTransitionLabel('a'));
automat.addTransition(s1, s0, new CharTransitionLabel('a'));
automat.markAsInitial(s0);
automat.markAsFinal(s0);
assertTrue(automat.isInfinite());
}
/**
* Test metody sprawdzającej, czy akceptowany język jest nieskończony dla
* automatu, w którym jeden ze stanów końcowych jest zawarty przed pętlą.
*/
public final void testInfiniteForFinalUntilLoop() {
NaiveAutomatonSpecification automat = new NaiveAutomatonSpecification();
State s0 = automat.addState();
State s1 = automat.addState();
State s2 = automat.addState();
State s3 = automat.addState();
automat.addTransition(s0, s1, new CharTransitionLabel('a'));
automat.addTransition(s1, s2, new CharTransitionLabel('b'));
automat.addTransition(s2, s3, new CharTransitionLabel('b'));
automat.addTransition(s3, s2, new CharTransitionLabel('c'));
automat.markAsFinal(s1);
automat.markAsFinal(s3);
automat.markAsInitial(s0);
assertTrue(automat.isInfinite());
}
/**
* Test ze "ślepą uliczką".
*/
public final void testInfiniteDeadEnd() {
NaiveAutomatonSpecification automat = new NaiveAutomatonSpecification();
State s0 = automat.addState();
State sA1 = automat.addState();
State sA2 = automat.addState();
State sA3 = automat.addState();
State sB1 = automat.addState();
State sB2 = automat.addState();
State sB3 = automat.addState();
automat.addTransition(s0, sA1, new CharTransitionLabel('a'));
automat.addTransition(s0, sB1, new CharTransitionLabel('b'));
automat.markAsInitial(s0);
automat.markAsFinal(sA1);
automat.markAsFinal(sB1);
assertFalse(automat.isInfinite());
automat.addTransition(sA1, sA2, new AnyTransitionLabel());
automat.addTransition(sA2, sA3, new CharTransitionLabel('a'));
automat.addTransition(sA3, sA2, new CharTransitionLabel('b'));
automat.addTransition(sB1, sB2, new AnyTransitionLabel());
automat.addTransition(sB2, sB3, new CharTransitionLabel('a'));
automat.addTransition(sB3, sB2, new CharTransitionLabel('x'));
assertFalse(automat.isInfinite());
automat.markAsFinal(sB2);
assertTrue(automat.isInfinite());
}
/**
* Test metody sprawdzającej czy podany język jest nieskończony dla
* automatu z pojedynczym stanem bez pętli.
*/
public final void testInfiniteForOneStateWithoutLoop() {
NaiveAutomatonSpecification automat = new NaiveAutomatonSpecification();
State s0 = automat.addState();
automat.markAsInitial(s0);
automat.markAsFinal(s0);
assertFalse(automat.isInfinite());
}
/**
* Test metody sprawdzającej czy podany język jest nieskończony dla
* automatu ze stanem niefinalnym po pętli.
*/
public final void testInfiniteForNotFinalStateAfterLoop() {
NaiveAutomatonSpecification automat = new NaiveAutomatonSpecification();
State s0 = automat.addState();
State s1 = automat.addState();
automat.markAsInitial(s0);
automat.addLoop(s0, new CharTransitionLabel('c'));
automat.addTransition(s0, s1, new CharTransitionLabel('b'));
assertFalse(automat.isInfinite());
}
/**
* Test metody sprawdzającej, czy akceptowany język jest nieskończony dla
* automatu z epsilon-przejściami.
*/
public final void testInfiniteForEpsilons() {
NaiveAutomatonSpecification automat = new NaiveAutomatonSpecification();
State q0 = automat.addState();
State q1 = automat.addState();
State q2 = automat.addState();
State q3 = automat.addState();
State q4 = automat.addState();
automat.addTransition(q0, q1, new CharTransitionLabel('a'));
automat.addTransition(q1, q2, new EpsilonTransitionLabel());
automat.addTransition(q2, q3, new CharTransitionLabel('b'));
automat.markAsFinal(q3);
automat.markAsInitial(q0);
assertFalse(automat.isInfinite());
automat.addTransition(q3, q4, new EpsilonTransitionLabel());
automat.addTransition(q4, q2, new CharTransitionLabel('a'));
assertTrue(automat.isInfinite());
}
/**
* Test metody testUnmark.
*/
public final void testUnmark() {
final AutomatonSpecification spec = new NaiveAutomatonSpecification();
//Test 1
State q0a = spec.addState();
State q1a = spec.addState();
spec.addTransition(q1a, q0a, new CharTransitionLabel(' '));
spec.markAsFinal(q1a);
spec.markAsInitial(q0a);
spec.unmarkAsFinalState(q1a);
assertFalse(spec.isFinal(q1a));
//test 2
State q0b = spec.addState();
State q1b = spec.addState();
spec.addTransition(q1b, q0b, new CharTransitionLabel(' '));
spec.markAsFinal(q0b);
spec.markAsInitial(q1b);
spec.unmarkAsFinalState(q1b);
assertTrue(spec.isFinal(q0b));
//test 3
State q0c = spec.addState();
State q1c = spec.addState();
State q2c = spec.addState();
State q3c = spec.addState();
State q4c = spec.addState();
State q5c = spec.addState();
spec.addTransition(q0c, q2c, new CharTransitionLabel('a'));
spec.addTransition(q3c, q4c, new CharTransitionLabel('a'));
spec.addTransition(q1c, q5c, new CharTransitionLabel('a'));
spec.markAsFinal(q5c);
spec.markAsInitial(q0c);
spec.unmarkAsFinalState(q5c);
assertFalse(spec.isFinal(q0c));
spec.markAsFinal(q1c);
spec.markAsInitial(q3c);
spec.unmarkAsFinalState(q3c);
assertTrue(spec.isFinal(q1c));
}
}