diff --git a/serialization/aut/src/main/java/net/automatalib/serialization/aut/InternalAUTParser.java b/serialization/aut/src/main/java/net/automatalib/serialization/aut/InternalAUTParser.java index bb92fc5c72..c37bfea758 100644 --- a/serialization/aut/src/main/java/net/automatalib/serialization/aut/InternalAUTParser.java +++ b/serialization/aut/src/main/java/net/automatalib/serialization/aut/InternalAUTParser.java @@ -38,6 +38,7 @@ class InternalAUTParser { private int initialState; + private int numStates; private final Set alphabetSymbols = new HashSet<>(); private final Map> transitionMap = new HashMap<>(); @@ -63,9 +64,9 @@ public InputModelData> parse(Function inputMap = Maps.asMap(alphabetSymbols, inputTransformer::apply); final Alphabet alphabet = Alphabets.fromCollection(inputMap.values()); - final CompactNFA result = new CompactNFA<>(alphabet, transitionMap.size()); + final CompactNFA result = new CompactNFA<>(alphabet, numStates); - for (int i = 0; i < transitionMap.size(); i++) { + for (int i = 0; i < numStates; i++) { result.addState(); } @@ -98,9 +99,12 @@ private void parseHeader(BufferedReader reader) throws IOException { verifyLBracketAndShift(); initialState = parseNumberAndShift(); verifyCommaAndShift(); - parseNumberAndShift(); // ignore number of states - verifyCommaAndShift(); parseNumberAndShift(); // ignore number of transitions + verifyCommaAndShift(); + numStates = parseNumberAndShift(); // store number of states + if (numStates < 1) { + throw new IllegalArgumentException("Number of states must be >= 1"); + } verifyRBracketAndShift(); } @@ -194,6 +198,10 @@ private int parseNumberAndShift() { sym = currentLineContent[currentPos]; } + if (sb.length() == 0){ + throw new IllegalArgumentException(buildErrorMessage("Expected a positive number")); + } + // forward pointer shiftToNextNonWhitespace(); return Integer.parseInt(sb.toString()); diff --git a/serialization/aut/src/test/java/net/automatalib/serialization/aut/AUTSerializationTest.java b/serialization/aut/src/test/java/net/automatalib/serialization/aut/AUTSerializationTest.java index 19d951d65c..0f043b5ef1 100644 --- a/serialization/aut/src/test/java/net/automatalib/serialization/aut/AUTSerializationTest.java +++ b/serialization/aut/src/test/java/net/automatalib/serialization/aut/AUTSerializationTest.java @@ -34,6 +34,7 @@ import net.automatalib.util.automata.random.RandomAutomata; import net.automatalib.words.Alphabet; import net.automatalib.words.impl.Alphabets; +import net.automatalib.words.impl.ArrayAlphabet; import org.testng.Assert; import org.testng.annotations.Test; @@ -65,6 +66,28 @@ public void quotationLabelTest() throws Exception { } } + @Test + public void sinkStateTest() throws Exception { + try (InputStream is = AUTSerializationTest.class.getResourceAsStream("/sinkStateTest.aut")) { + final SimpleAutomaton automaton = AUTParser.readAutomaton(is).model; + Assert.assertEquals(3, automaton.size()); + + final Alphabet alphabet = new ArrayAlphabet("input", "output"); + + final Set s0 = automaton.getInitialStates(); + final Set t1 = automaton.getSuccessors(s0, Collections.singletonList("input")); + final Set t2 = automaton.getSuccessors(s0, Collections.singletonList("output")); + final Set t3 = automaton.getSuccessors(s0, Arrays.asList("input", "output")); + final Set t4 = automaton.getSuccessors(s0, Arrays.asList("input", "output", "output")); + + Assert.assertEquals(Collections.singleton(0), s0); + Assert.assertEquals(Collections.singleton(1), t1); + Assert.assertEquals(Collections.singleton(2), t2); + Assert.assertEquals(Collections.singleton(0), t3); + Assert.assertEquals(Collections.singleton(2), t4); + } + } + @Test public void serializationTest() throws Exception { final Alphabet alphabet = Alphabets.integers(0, 2); @@ -92,10 +115,14 @@ private void equalityTest(SimpleAutomaton src, SimpleAutomaton AUTParser.readAutomaton(e1)); Assert.assertThrows(() -> AUTParser.readAutomaton(e2)); Assert.assertThrows(() -> AUTParser.readAutomaton(e3)); + Assert.assertThrows(() -> AUTParser.readAutomaton(e4)); + Assert.assertThrows(() -> AUTParser.readAutomaton(e5)); } } diff --git a/serialization/aut/src/test/resources/error4.aut b/serialization/aut/src/test/resources/error4.aut new file mode 100644 index 0000000000..73898677ff --- /dev/null +++ b/serialization/aut/src/test/resources/error4.aut @@ -0,0 +1,4 @@ +des(0, 3, 0) +(0, a, 1) +(1, b, 0) +(1, c, 1) \ No newline at end of file diff --git a/serialization/aut/src/test/resources/error5.aut b/serialization/aut/src/test/resources/error5.aut new file mode 100644 index 0000000000..34be5ec16c --- /dev/null +++ b/serialization/aut/src/test/resources/error5.aut @@ -0,0 +1,2 @@ +des(0, 1, 1) +(1, z , -2) \ No newline at end of file diff --git a/serialization/aut/src/test/resources/sinkStateTest.aut b/serialization/aut/src/test/resources/sinkStateTest.aut new file mode 100644 index 0000000000..15794c0505 --- /dev/null +++ b/serialization/aut/src/test/resources/sinkStateTest.aut @@ -0,0 +1,5 @@ +des(0,4,3) +(0,input,1) +(0,output,2) +(1,input,2) +(1,output,0) \ No newline at end of file