You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@plc4x.apache.org by sr...@apache.org on 2019/12/06 15:07:59 UTC
[plc4x] 02/07: added some tests for expression parser and WIP for
MFL and MFP
This is an automated email from the ASF dual-hosted git repository.
sruehl pushed a commit to branch feature/ams_ads_mpsec
in repository https://gitbox.apache.org/repos/asf/plc4x.git
commit c76ff54090f8b8385a9c75f172398977b5241ee8
Author: Sebastian Rühl <sr...@apache.org>
AuthorDate: Fri Nov 29 11:33:36 2019 +0100
added some tests for expression parser and WIP for MFL and MFP
---
build-utils/protocol-base-mspec/pom.xml | 36 +++++
.../mspec/parser/MessageFormatListener.java | 16 +-
.../language/mspec/parser/MessageFormatParser.java | 54 +++++--
.../expression/ExpressionStringParserTest.java | 178 +++++++++++++++++++++
.../mspec/parser/MessageFormatListenerTest.java | 162 +++++++++++++++++++
.../mspec/parser/MessageFormatParserTest.java | 88 ++++++++++
6 files changed, 517 insertions(+), 17 deletions(-)
diff --git a/build-utils/protocol-base-mspec/pom.xml b/build-utils/protocol-base-mspec/pom.xml
index db361a8..a9096c2 100644
--- a/build-utils/protocol-base-mspec/pom.xml
+++ b/build-utils/protocol-base-mspec/pom.xml
@@ -64,6 +64,42 @@
<groupId>org.antlr</groupId>
<artifactId>antlr4-runtime</artifactId>
</dependency>
+
+ <!-- Testing -->
+ <dependency>
+ <groupId>org.junit.jupiter</groupId>
+ <artifactId>junit-jupiter-api</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.junit.jupiter</groupId>
+ <artifactId>junit-jupiter-params</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.junit.jupiter</groupId>
+ <artifactId>junit-jupiter-engine</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.junit.vintage</groupId>
+ <artifactId>junit-vintage-engine</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-core</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-junit-jupiter</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.hamcrest</groupId>
+ <artifactId>hamcrest-library</artifactId>
+ </dependency>
</dependencies>
</project>
\ No newline at end of file
diff --git a/build-utils/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/parser/MessageFormatListener.java b/build-utils/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/parser/MessageFormatListener.java
index 74ff1cf..42c3ce3 100644
--- a/build-utils/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/parser/MessageFormatListener.java
+++ b/build-utils/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/parser/MessageFormatListener.java
@@ -55,6 +55,14 @@ public class MessageFormatListener extends MSpecBaseListener {
private Map<String, TypeDefinition> types;
+ public Deque<List<Field>> getParserContexts() {
+ return parserContexts;
+ }
+
+ public Deque<List<EnumValue>> getEnumContexts() {
+ return enumContexts;
+ }
+
public Map<String, TypeDefinition> getTypes() {
return types;
}
@@ -458,12 +466,4 @@ public class MessageFormatListener extends MSpecBaseListener {
return quotedString;
}
- public static void main(String[] args) {
- //Term term = new ExpressionStringParser().parse(IOUtils.toInputStream("CAST(CAST(parameter,S7ParameterUserData).items(hurz)[0],S7ParameterUserDataItemCPUFunctions).cpuFunctionType", Charset.defaultCharset()));
- //Term term = new ExpressionStringParser().parse(IOUtils.toInputStream("CAST(parameter,S7ParameterUserData).items(hurz)[0]", Charset.defaultCharset()));
- Term term = new ExpressionStringParser().parse(IOUtils.toInputStream("payload.lengthInBytes+4", Charset.defaultCharset()));
-
- System.out.println(term);
- }
-
}
diff --git a/build-utils/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/parser/MessageFormatParser.java b/build-utils/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/parser/MessageFormatParser.java
index bdd99fb..a134666 100644
--- a/build-utils/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/parser/MessageFormatParser.java
+++ b/build-utils/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/parser/MessageFormatParser.java
@@ -19,6 +19,7 @@
package org.apache.plc4x.plugins.codegenerator.language.mspec.parser;
+import org.antlr.v4.runtime.CharStream;
import org.antlr.v4.runtime.CharStreams;
import org.antlr.v4.runtime.CommonTokenStream;
import org.antlr.v4.runtime.tree.ParseTree;
@@ -27,24 +28,59 @@ import org.apache.plc4x.plugins.codegenerator.language.mspec.MSpecLexer;
import org.apache.plc4x.plugins.codegenerator.language.mspec.MSpecParser;
import org.apache.plc4x.plugins.codegenerator.types.definitions.TypeDefinition;
+import java.io.IOException;
import java.io.InputStream;
import java.util.Map;
+import java.util.function.Function;
+import java.util.function.Supplier;
public class MessageFormatParser {
+ // TODO: can be used a instance once thread safety is asserted
+ private Function<CharStream, MSpecLexer> lexerBuilder;
+
+ // TODO: can be used a instance once thread safety is asserted
+ private Function<MSpecLexer, CommonTokenStream> commonTokenStreamBuilder;
+
+ // TODO: can be used a instance once thread safety is asserted
+ private Function<CommonTokenStream, MSpecParser> commonTokenStreamMSpecParserBuilder;
+
+ // TODO: can be used a instance once thread safety is asserted
+ private Supplier<ParseTreeWalker> voidParseTreeWalkerBuilder;
+
+ // TODO: can be used a instance once thread safety is asserted
+ private Supplier<MessageFormatListener> messageFormatListenerBuilder;
+
+ public MessageFormatParser() {
+ lexerBuilder = MSpecLexer::new;
+ commonTokenStreamBuilder = CommonTokenStream::new;
+ commonTokenStreamMSpecParserBuilder = MSpecParser::new;
+ voidParseTreeWalkerBuilder = ParseTreeWalker::new;
+ messageFormatListenerBuilder = MessageFormatListener::new;
+ }
+
+ MessageFormatParser(Function<CharStream, MSpecLexer> lexerBuilder, Function<MSpecLexer, CommonTokenStream> commonTokenStreamBuilder, Function<CommonTokenStream, MSpecParser> commonTokenStreamMSpecParserBuilder, Supplier<ParseTreeWalker> voidParseTreeWalkerBuilder, Supplier<MessageFormatListener> messageFormatListenerBuilder) {
+ this.lexerBuilder = lexerBuilder;
+ this.commonTokenStreamBuilder = commonTokenStreamBuilder;
+ this.commonTokenStreamMSpecParserBuilder = commonTokenStreamMSpecParserBuilder;
+ this.voidParseTreeWalkerBuilder = voidParseTreeWalkerBuilder;
+ this.messageFormatListenerBuilder = messageFormatListenerBuilder;
+ }
+
public Map<String, TypeDefinition> parse(InputStream source) {
+ MSpecLexer lexer;
try {
- MSpecLexer lexer = new MSpecLexer(CharStreams.fromStream(source));
- CommonTokenStream tokens = new CommonTokenStream(lexer);
- MSpecParser parser = new MSpecParser(tokens);
- ParseTree tree = parser.file();
- ParseTreeWalker walker = new ParseTreeWalker();
- MessageFormatListener listener = new MessageFormatListener();
- walker.walk(listener, tree);
- return listener.getTypes();
- } catch (Exception e) {
+ lexer = lexerBuilder.apply(CharStreams.fromStream(source));
+ } catch (IOException e) {
throw new RuntimeException(e);
}
+ CommonTokenStream tokens = commonTokenStreamBuilder.apply(lexer);
+ MSpecParser parser = commonTokenStreamMSpecParserBuilder.apply(tokens);
+ ParseTree tree = parser.file();
+ ParseTreeWalker walker = voidParseTreeWalkerBuilder.get();
+ MessageFormatListener listener = messageFormatListenerBuilder.get();
+ walker.walk(listener, tree);
+ return listener.getTypes();
}
}
diff --git a/build-utils/protocol-base-mspec/src/test/java/org/apache/plc4x/plugins/codegenerator/language/mspec/expression/ExpressionStringParserTest.java b/build-utils/protocol-base-mspec/src/test/java/org/apache/plc4x/plugins/codegenerator/language/mspec/expression/ExpressionStringParserTest.java
new file mode 100644
index 0000000..71c0222
--- /dev/null
+++ b/build-utils/protocol-base-mspec/src/test/java/org/apache/plc4x/plugins/codegenerator/language/mspec/expression/ExpressionStringParserTest.java
@@ -0,0 +1,178 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+ */
+
+package org.apache.plc4x.plugins.codegenerator.language.mspec.expression;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.plc4x.plugins.codegenerator.types.terms.BinaryTerm;
+import org.apache.plc4x.plugins.codegenerator.types.terms.NumericLiteral;
+import org.apache.plc4x.plugins.codegenerator.types.terms.Term;
+import org.apache.plc4x.plugins.codegenerator.types.terms.VariableLiteral;
+import org.junit.jupiter.api.Test;
+
+import java.nio.charset.Charset;
+import java.util.List;
+import java.util.function.Consumer;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.*;
+
+class ExpressionStringParserTest {
+
+ ExpressionStringParser SUT = new ExpressionStringParser();
+
+ @Test
+ void parseSimple() {
+ Term term = SUT.parse(IOUtils.toInputStream("payload.lengthInBytes+4", Charset.defaultCharset()));
+ assertThat(term, not(nullValue()));
+ assertThat(term, instanceOf(BinaryTerm.class));
+ BinaryTerm binaryTerm = (BinaryTerm) term;
+ assertVariableLiteral(
+ binaryTerm.getA(),
+ "payload",
+ null,
+ lengthInBytesVariableLiteral -> assertVariableLiteral(
+ lengthInBytesVariableLiteral,
+ "lengthInBytes"
+ )
+ );
+ assertNumericLiteral(binaryTerm.getB(), 4L);
+ assertThat(binaryTerm.getOperation(), is("+"));
+ }
+
+
+ @Test
+ void parseDoubleCast() {
+ Term term = SUT.parse(IOUtils.toInputStream("CAST(CAST(parameter,S7ParameterUserData).items(hurz)[0],S7ParameterUserDataItemCPUFunctions).cpuFunctionType", Charset.defaultCharset()));
+ assertVariableLiteral(
+ term,
+ "CAST",
+ outerCast -> {
+ assertThat(outerCast, hasSize(2));
+ assertVariableLiteral(
+ outerCast.get(0),
+ "CAST",
+ innerCast -> {
+ assertThat(innerCast, hasSize(2));
+ assertVariableLiteral(
+ innerCast.get(0),
+ "parameter"
+ );
+ assertVariableLiteral(
+ innerCast.get(1),
+ "S7ParameterUserData"
+ );
+ },
+ items -> {
+ assertVariableLiteral(
+ items,
+ "items",
+ hurzes -> {
+ assertThat(hurzes, hasSize(1));
+ assertVariableLiteral(
+ hurzes.get(0),
+ "hurz"
+ );
+ },
+ null,
+ 0
+ );
+ });
+ assertVariableLiteral(
+ outerCast.get(1),
+ "S7ParameterUserDataItemCPUFunctions"
+ );
+ }, variableLiteral -> {
+ assertVariableLiteral(
+ variableLiteral,
+ "cpuFunctionType"
+ );
+ }
+ );
+ }
+
+ @Test
+ void parseCast() {
+ Term term = SUT.parse(IOUtils.toInputStream("CAST(parameter,S7ParameterUserData).items(hurz)[0]", Charset.defaultCharset()));
+ assertVariableLiteral(
+ term,
+ "CAST",
+ terms -> {
+ assertThat(terms, hasSize(2));
+ assertVariableLiteral(
+ terms.get(0),
+ "parameter"
+ );
+ assertVariableLiteral(
+ terms.get(1),
+ "S7ParameterUserData"
+ );
+ }, variableLiteral -> {
+ assertVariableLiteral(
+ variableLiteral,
+ "items",
+ terms -> {
+ assertThat(terms, hasSize(1));
+ assertVariableLiteral(
+ terms.get(0),
+ "hurz"
+ );
+ },
+ null,
+ 0
+ );
+ }
+ );
+ }
+
+ void assertNumericLiteral(Term term, Number number) {
+ assertThat(term, not(nullValue()));
+ assertThat(term, instanceOf(NumericLiteral.class));
+ NumericLiteral numericLiteral = (NumericLiteral) term;
+ assertThat(numericLiteral.getNumber(), is(number));
+ }
+
+ void assertVariableLiteral(Term term, String name) {
+ assertVariableLiteral(term, name, null, null, -1);
+ }
+
+ void assertVariableLiteral(Term term, String name, Consumer<List<Term>> argsAsserter, Consumer<VariableLiteral> childAsserter) {
+ assertVariableLiteral(term, name, argsAsserter, childAsserter, -1);
+ }
+
+ void assertVariableLiteral(Term term, String name, Consumer<List<Term>> argsAsserter, Consumer<VariableLiteral> childAsserter, int index) {
+ assertThat(term, not(nullValue()));
+ assertThat(term, instanceOf(VariableLiteral.class));
+ VariableLiteral variableLiteral = (VariableLiteral) term;
+ assertThat(variableLiteral.getName(), is(name));
+ assertThat(variableLiteral.getIndex(), is(index));
+ if (argsAsserter != null) {
+ argsAsserter.accept(variableLiteral.getArgs());
+ } else {
+ assertThat(variableLiteral.getArgs(), nullValue());
+ }
+ if (childAsserter != null) {
+ childAsserter.accept(variableLiteral.getChild());
+ } else {
+ assertThat(variableLiteral.getChild(), nullValue());
+ }
+ }
+
+
+}
\ No newline at end of file
diff --git a/build-utils/protocol-base-mspec/src/test/java/org/apache/plc4x/plugins/codegenerator/language/mspec/parser/MessageFormatListenerTest.java b/build-utils/protocol-base-mspec/src/test/java/org/apache/plc4x/plugins/codegenerator/language/mspec/parser/MessageFormatListenerTest.java
new file mode 100644
index 0000000..3d9f4c4
--- /dev/null
+++ b/build-utils/protocol-base-mspec/src/test/java/org/apache/plc4x/plugins/codegenerator/language/mspec/parser/MessageFormatListenerTest.java
@@ -0,0 +1,162 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+ */
+
+package org.apache.plc4x.plugins.codegenerator.language.mspec.parser;
+
+import org.antlr.v4.runtime.CommonToken;
+import org.apache.plc4x.plugins.codegenerator.language.mspec.MSpecParser;
+import org.apache.plc4x.plugins.codegenerator.types.definitions.TypeDefinition;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+import java.util.Map;
+
+import static org.hamcrest.CoreMatchers.not;
+import static org.hamcrest.CoreMatchers.nullValue;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.hasSize;
+
+// TODO: implement me
+@ExtendWith(MockitoExtension.class)
+class MessageFormatListenerTest {
+
+ MessageFormatListener SUT;
+
+ @BeforeEach
+ void setUp() {
+ SUT = new MessageFormatListener();
+ }
+
+ @Test
+ void getTypes() {
+ Map<String, TypeDefinition> types = SUT.getTypes();
+ assertThat(types, nullValue());
+ }
+
+ @Test
+ void enterFile() {
+ assertThat(SUT.getParserContexts(), nullValue());
+ assertThat(SUT.getEnumContexts(), nullValue());
+ assertThat(SUT.getTypes(), nullValue());
+ SUT.enterFile(null);
+ assertThat(SUT.getParserContexts(), not(nullValue()));
+ assertThat(SUT.getEnumContexts(), not(nullValue()));
+ assertThat(SUT.getTypes(), not(nullValue()));
+ }
+
+ @Test
+ void enterComplexType() {
+ assertThat(SUT.getParserContexts(), nullValue());
+ assertThat(SUT.getEnumContexts(), nullValue());
+ assertThat(SUT.getTypes(), nullValue());
+ SUT.enterFile(null);
+ MSpecParser.ComplexTypeContext complexTypeContext = new MSpecParser.ComplexTypeContext(null, 0);
+ SUT.enterComplexType(complexTypeContext);
+ assertThat(SUT.getParserContexts(), hasSize(1));
+ assertThat(SUT.getEnumContexts(), hasSize(0));
+ assertThat(SUT.getTypes().values(), hasSize(0));
+ complexTypeContext.enumValues = new MSpecParser.EnumValueDefinitionContext(null, 0);
+ SUT.enterComplexType(complexTypeContext);
+ assertThat(SUT.getParserContexts(), hasSize(1));
+ assertThat(SUT.getEnumContexts(), hasSize(1));
+ assertThat(SUT.getTypes().values(), hasSize(0));
+ }
+
+ @Test
+ void exitComplexType() {
+ MSpecParser.ComplexTypeContext complexTypeContext = new MSpecParser.ComplexTypeContext(null, 0);
+ complexTypeContext.name = new MSpecParser.IdExpressionContext(null, 0);
+ complexTypeContext.name.id = new CommonToken(0);
+ SUT.exitComplexType(complexTypeContext);
+ }
+
+ @Test
+ void enterArrayField() {
+ }
+
+ @Test
+ void enterChecksumField() {
+ }
+
+ @Test
+ void enterConstField() {
+ }
+
+ @Test
+ void enterDiscriminatorField() {
+ }
+
+ @Test
+ void enterEnumField() {
+ }
+
+ @Test
+ void enterImplicitField() {
+ }
+
+ @Test
+ void enterManualArrayField() {
+ }
+
+ @Test
+ void enterManualField() {
+ }
+
+ @Test
+ void enterOptionalField() {
+ }
+
+ @Test
+ void enterPaddingField() {
+ }
+
+ @Test
+ void enterReservedField() {
+ }
+
+ @Test
+ void enterSimpleField() {
+ }
+
+ @Test
+ void enterTypeSwitchField() {
+ }
+
+ @Test
+ void enterVirtualField() {
+ }
+
+ @Test
+ void enterCaseStatement() {
+ }
+
+ @Test
+ void exitCaseStatement() {
+ }
+
+ @Test
+ void enterEnumValueDefinition() {
+ }
+
+ @Test
+ void main() {
+ }
+}
\ No newline at end of file
diff --git a/build-utils/protocol-base-mspec/src/test/java/org/apache/plc4x/plugins/codegenerator/language/mspec/parser/MessageFormatParserTest.java b/build-utils/protocol-base-mspec/src/test/java/org/apache/plc4x/plugins/codegenerator/language/mspec/parser/MessageFormatParserTest.java
new file mode 100644
index 0000000..7aa47d2
--- /dev/null
+++ b/build-utils/protocol-base-mspec/src/test/java/org/apache/plc4x/plugins/codegenerator/language/mspec/parser/MessageFormatParserTest.java
@@ -0,0 +1,88 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+ */
+
+package org.apache.plc4x.plugins.codegenerator.language.mspec.parser;
+
+import org.antlr.v4.runtime.CommonTokenStream;
+import org.antlr.v4.runtime.tree.ParseTreeWalker;
+import org.apache.commons.io.IOUtils;
+import org.apache.plc4x.plugins.codegenerator.language.mspec.MSpecLexer;
+import org.apache.plc4x.plugins.codegenerator.language.mspec.MSpecParser;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Disabled;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.Mock;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.mockito.Mockito.mock;
+
+// TODO: implement me
+@ExtendWith(MockitoExtension.class)
+class MessageFormatParserTest {
+
+ //@InjectMocks
+ MessageFormatParser SUT;
+
+ @Mock
+ MSpecLexer mSpecLexer;
+
+ @Mock
+ CommonTokenStream commonTokenStream;
+
+ @Mock
+ MSpecParser mSpecParser;
+
+ @Mock
+ ParseTreeWalker parseTreeWalker;
+
+ @Mock
+ MessageFormatListener messageFormatListener;
+
+ @BeforeEach
+ void setUp() {
+ SUT = new MessageFormatParser(
+ (_ignore) -> mSpecLexer,
+ (_ignore) -> commonTokenStream,
+ (_ignore) -> mSpecParser,
+ () -> parseTreeWalker,
+ () -> messageFormatListener
+ );
+ }
+
+ @Test
+ void parseNull() {
+ assertThrows(NullPointerException.class, () -> SUT.parse(null));
+ }
+
+ @Disabled("mockito broken because of NPE in REAL code")
+ @Test
+ void parseSomething() {
+ // TODO: seems like mockito is broken somehow...
+ MSpecParser mSpecParser = mock(MSpecParser.class);
+ // TODO: ... because this throws a NPE... (somehow call ends up in real code)
+ mSpecParser.file();
+ InputStream is = IOUtils.toInputStream("test", StandardCharsets.UTF_8);
+ SUT.parse(is);
+ }
+}
\ No newline at end of file