From ab78f80f9d50823df2cfd6a00e6a2cc41a303da2 Mon Sep 17 00:00:00 2001 From: Jeroen van den Bos Date: Fri, 22 Jul 2016 17:36:07 +0200 Subject: [PATCH 01/17] #78: Test utility classes for good practices. --- .../java/io/parsingdata/metal/Shorthand.java | 4 +- .../main/java/io/parsingdata/metal/Util.java | 5 +- .../parsingdata/metal/UtilityClassTest.java | 52 +++++++++++++++++++ 3 files changed, 59 insertions(+), 2 deletions(-) create mode 100644 core/src/test/java/io/parsingdata/metal/UtilityClassTest.java diff --git a/core/src/main/java/io/parsingdata/metal/Shorthand.java b/core/src/main/java/io/parsingdata/metal/Shorthand.java index c398ceff..69fc689b 100644 --- a/core/src/main/java/io/parsingdata/metal/Shorthand.java +++ b/core/src/main/java/io/parsingdata/metal/Shorthand.java @@ -29,7 +29,9 @@ import io.parsingdata.metal.expression.value.reference.*; import io.parsingdata.metal.token.*; -public class Shorthand { +public final class Shorthand { + + private Shorthand() {} public static Token def(final String name, final ValueExpression size, final Expression predicate, final Encoding encoding) { return new Def(name, size, predicate, encoding); } public static Token def(final String name, final ValueExpression size, final Expression predicate) { return def(name, size, predicate, null); } diff --git a/core/src/main/java/io/parsingdata/metal/Util.java b/core/src/main/java/io/parsingdata/metal/Util.java index 34a7e58d..65a48ef3 100644 --- a/core/src/main/java/io/parsingdata/metal/Util.java +++ b/core/src/main/java/io/parsingdata/metal/Util.java @@ -18,7 +18,10 @@ import io.parsingdata.metal.token.Token; -public class Util { +public final class Util { + + private Util() {} + final private static char[] HEX_ARRAY = "0123456789ABCDEF".toCharArray(); public static T checkNotNull(final T argument, final String name) { diff --git a/core/src/test/java/io/parsingdata/metal/UtilityClassTest.java b/core/src/test/java/io/parsingdata/metal/UtilityClassTest.java new file mode 100644 index 00000000..d6703b6b --- /dev/null +++ b/core/src/test/java/io/parsingdata/metal/UtilityClassTest.java @@ -0,0 +1,52 @@ +/* + * Copyright 2013-2016 Netherlands Forensic Institute + * + * Licensed 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 io.parsingdata.metal; + +import org.junit.Test; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +public class UtilityClassTest { + + private void checkUtilityClass(Class c) throws ReflectiveOperationException { + assertTrue(Modifier.isFinal(c.getModifiers())); + final Constructor[] cons = c.getDeclaredConstructors(); + assertEquals(1, cons.length); + assertTrue(Modifier.isPrivate(cons[0].getModifiers())); + cons[0].setAccessible(true); + cons[0].newInstance(); + for (Method m : c.getDeclaredMethods()) { + assertTrue(Modifier.isStatic(m.getModifiers())); + } + } + + @Test + public void shorthand() throws ReflectiveOperationException { + checkUtilityClass(Shorthand.class); + } + + @Test + public void util() throws ReflectiveOperationException { + checkUtilityClass(Util.class); + } + +} From b14f09dd2f73c7b4e2782667093850650196ce12 Mon Sep 17 00:00:00 2001 From: Jeroen van den Bos Date: Fri, 22 Jul 2016 18:03:13 +0200 Subject: [PATCH 02/17] #78: Util.tokensToString() and Reversal utility class. --- .../metal/data/transformation/Reversal.java | 4 +++- .../io/parsingdata/metal/UtilityClassTest.java | 18 ++++++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/core/src/main/java/io/parsingdata/metal/data/transformation/Reversal.java b/core/src/main/java/io/parsingdata/metal/data/transformation/Reversal.java index 69314ecd..cbae973d 100644 --- a/core/src/main/java/io/parsingdata/metal/data/transformation/Reversal.java +++ b/core/src/main/java/io/parsingdata/metal/data/transformation/Reversal.java @@ -19,7 +19,9 @@ import io.parsingdata.metal.data.ParseGraph; import io.parsingdata.metal.data.ParseItem; -public class Reversal { +public final class Reversal { + + private Reversal() {} public static ParseGraph reverse(ParseGraph oldGraph, ParseGraph newGraph) { if (oldGraph.isEmpty()) { return newGraph; } diff --git a/core/src/test/java/io/parsingdata/metal/UtilityClassTest.java b/core/src/test/java/io/parsingdata/metal/UtilityClassTest.java index d6703b6b..5b82bc5b 100644 --- a/core/src/test/java/io/parsingdata/metal/UtilityClassTest.java +++ b/core/src/test/java/io/parsingdata/metal/UtilityClassTest.java @@ -16,17 +16,22 @@ package io.parsingdata.metal; +import io.parsingdata.metal.data.transformation.Reversal; +import io.parsingdata.metal.token.Token; import org.junit.Test; import java.lang.reflect.Constructor; import java.lang.reflect.Method; import java.lang.reflect.Modifier; +import static io.parsingdata.metal.Util.tokensToString; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; public class UtilityClassTest { + // Check that a class is final, has a single private constructor and that all + // its declared methods are static. private void checkUtilityClass(Class c) throws ReflectiveOperationException { assertTrue(Modifier.isFinal(c.getModifiers())); final Constructor[] cons = c.getDeclaredConstructors(); @@ -49,4 +54,17 @@ public void util() throws ReflectiveOperationException { checkUtilityClass(Util.class); } + @Test + public void reversal() throws ReflectiveOperationException { + checkUtilityClass(Reversal.class); + } + + // The method is used to print tokens for composing Tokens' toString() + // implementation. Since they all require a non-zero amount of tokens, this + // method must be explicitly tested. + @Test + public void zeroTokensToString() { + assertEquals("", tokensToString(new Token[] {})); + } + } From cf4a9b60cbb584c5343af4c3610ebdd84f1a1f1e Mon Sep 17 00:00:00 2001 From: Jeroen van den Bos Date: Fri, 22 Jul 2016 23:02:04 +0200 Subject: [PATCH 03/17] #78: Added more utility classes. --- .../parsingdata/metal/data/selection/ByItem.java | 5 ++++- .../parsingdata/metal/data/selection/ByName.java | 4 +++- .../metal/data/selection/ByOffset.java | 4 +++- .../metal/data/selection/ByToken.java | 2 +- .../parsingdata/metal/data/selection/ByType.java | 4 +++- .../io/parsingdata/metal/UtilityClassTest.java | 16 +++++++--------- 6 files changed, 21 insertions(+), 14 deletions(-) diff --git a/core/src/main/java/io/parsingdata/metal/data/selection/ByItem.java b/core/src/main/java/io/parsingdata/metal/data/selection/ByItem.java index 62d8062b..7614d6bd 100644 --- a/core/src/main/java/io/parsingdata/metal/data/selection/ByItem.java +++ b/core/src/main/java/io/parsingdata/metal/data/selection/ByItem.java @@ -22,7 +22,10 @@ import static io.parsingdata.metal.Util.checkNotNull; import static io.parsingdata.metal.data.ParseGraph.EMPTY; -public class ByItem { +public final class ByItem { + + private ByItem() {} + /** * @param graph The graph to search * @param lastHead The first item (bottom-up) to be excluded diff --git a/core/src/main/java/io/parsingdata/metal/data/selection/ByName.java b/core/src/main/java/io/parsingdata/metal/data/selection/ByName.java index 372c9db6..151b729b 100644 --- a/core/src/main/java/io/parsingdata/metal/data/selection/ByName.java +++ b/core/src/main/java/io/parsingdata/metal/data/selection/ByName.java @@ -23,7 +23,9 @@ import static io.parsingdata.metal.Util.checkNotNull; -public class ByName { +public final class ByName { + + private ByName() {} /** * @param graph The graph to search diff --git a/core/src/main/java/io/parsingdata/metal/data/selection/ByOffset.java b/core/src/main/java/io/parsingdata/metal/data/selection/ByOffset.java index 41bdf3c9..9dac8284 100644 --- a/core/src/main/java/io/parsingdata/metal/data/selection/ByOffset.java +++ b/core/src/main/java/io/parsingdata/metal/data/selection/ByOffset.java @@ -23,7 +23,9 @@ import static io.parsingdata.metal.Util.checkNotNull; -public class ByOffset { +public final class ByOffset { + + private ByOffset() {} public static boolean hasGraphAtRef(final ParseGraph graph, final long ref) { return findRef(ByType.getGraphs(graph), ref) != null; diff --git a/core/src/main/java/io/parsingdata/metal/data/selection/ByToken.java b/core/src/main/java/io/parsingdata/metal/data/selection/ByToken.java index 51a30a96..f584becb 100644 --- a/core/src/main/java/io/parsingdata/metal/data/selection/ByToken.java +++ b/core/src/main/java/io/parsingdata/metal/data/selection/ByToken.java @@ -24,7 +24,7 @@ import static io.parsingdata.metal.Util.checkNotNull; -public class ByToken { +public final class ByToken { private ByToken() {} diff --git a/core/src/main/java/io/parsingdata/metal/data/selection/ByType.java b/core/src/main/java/io/parsingdata/metal/data/selection/ByType.java index 5078a026..33c89893 100644 --- a/core/src/main/java/io/parsingdata/metal/data/selection/ByType.java +++ b/core/src/main/java/io/parsingdata/metal/data/selection/ByType.java @@ -22,7 +22,9 @@ import static io.parsingdata.metal.Util.checkNotNull; -public class ByType { +public final class ByType { + + private ByType() {} public static ParseGraphList getRefs(final ParseGraph graph) { checkNotNull(graph, "graph"); diff --git a/core/src/test/java/io/parsingdata/metal/UtilityClassTest.java b/core/src/test/java/io/parsingdata/metal/UtilityClassTest.java index 5b82bc5b..69f5325c 100644 --- a/core/src/test/java/io/parsingdata/metal/UtilityClassTest.java +++ b/core/src/test/java/io/parsingdata/metal/UtilityClassTest.java @@ -16,6 +16,7 @@ package io.parsingdata.metal; +import io.parsingdata.metal.data.selection.*; import io.parsingdata.metal.data.transformation.Reversal; import io.parsingdata.metal.token.Token; import org.junit.Test; @@ -45,18 +46,15 @@ private void checkUtilityClass(Class c) throws ReflectiveOperationException { } @Test - public void shorthand() throws ReflectiveOperationException { + public void utilityClasses() throws ReflectiveOperationException { checkUtilityClass(Shorthand.class); - } - - @Test - public void util() throws ReflectiveOperationException { checkUtilityClass(Util.class); - } - - @Test - public void reversal() throws ReflectiveOperationException { checkUtilityClass(Reversal.class); + checkUtilityClass(ByItem.class); + checkUtilityClass(ByName.class); + checkUtilityClass(ByOffset.class); + checkUtilityClass(ByToken.class); + checkUtilityClass(ByType.class); } // The method is used to print tokens for composing Tokens' toString() From 17464eafcb07c8e698ef0438fa9cc8cacac73c3d Mon Sep 17 00:00:00 2001 From: Jeroen van den Bos Date: Fri, 22 Jul 2016 23:21:14 +0200 Subject: [PATCH 04/17] #78: Enums. --- .../io/parsingdata/metal/UtilityClassTest.java | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/core/src/test/java/io/parsingdata/metal/UtilityClassTest.java b/core/src/test/java/io/parsingdata/metal/UtilityClassTest.java index 69f5325c..7ebc3482 100644 --- a/core/src/test/java/io/parsingdata/metal/UtilityClassTest.java +++ b/core/src/test/java/io/parsingdata/metal/UtilityClassTest.java @@ -18,6 +18,8 @@ import io.parsingdata.metal.data.selection.*; import io.parsingdata.metal.data.transformation.Reversal; +import io.parsingdata.metal.encoding.ByteOrder; +import io.parsingdata.metal.encoding.Sign; import io.parsingdata.metal.token.Token; import org.junit.Test; @@ -65,4 +67,16 @@ public void zeroTokensToString() { assertEquals("", tokensToString(new Token[] {})); } + // Metal uses enums to prevent the use of difficult to understand boolean arguments. + // However, enums come with some inherited methods that are not of use internally. + @Test + public void inheritedEnumMethods() { + assertEquals(2, Sign.values().length); + assertEquals(Sign.SIGNED, Sign.valueOf("SIGNED")); + assertEquals(Sign.UNSIGNED, Sign.valueOf("UNSIGNED")); + assertEquals(2, ByteOrder.values().length); + assertEquals(ByteOrder.BIG_ENDIAN, ByteOrder.valueOf("BIG_ENDIAN")); + assertEquals(ByteOrder.LITTLE_ENDIAN, ByteOrder.valueOf("LITTLE_ENDIAN")); + } + } From 72833ff7cf16539faf26dbc120e3896308bffe0e Mon Sep 17 00:00:00 2001 From: Jeroen van den Bos Date: Fri, 22 Jul 2016 23:40:55 +0200 Subject: [PATCH 05/17] #78: More tests: Offset returns correct empty value when evaluated on a value that was not parsed. Testing toString() for two operand ComparisonExpression and Last in general. --- .../java/io/parsingdata/metal/ErrorsTest.java | 39 ++++++++++--------- .../io/parsingdata/metal/ToStringTest.java | 4 +- 2 files changed, 23 insertions(+), 20 deletions(-) diff --git a/core/src/test/java/io/parsingdata/metal/ErrorsTest.java b/core/src/test/java/io/parsingdata/metal/ErrorsTest.java index 367d3de1..ca335298 100644 --- a/core/src/test/java/io/parsingdata/metal/ErrorsTest.java +++ b/core/src/test/java/io/parsingdata/metal/ErrorsTest.java @@ -16,28 +16,23 @@ package io.parsingdata.metal; -import static org.junit.Assert.assertFalse; - -import static io.parsingdata.metal.Shorthand.con; -import static io.parsingdata.metal.Shorthand.def; -import static io.parsingdata.metal.Shorthand.div; -import static io.parsingdata.metal.Shorthand.ref; -import static io.parsingdata.metal.Shorthand.repn; -import static io.parsingdata.metal.Shorthand.seq; -import static io.parsingdata.metal.util.TokenDefinitions.any; -import static io.parsingdata.metal.util.EncodingFactory.enc; -import static io.parsingdata.metal.util.EnvironmentFactory.stream; - -import java.io.IOException; - -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; - import io.parsingdata.metal.data.ByteStream; import io.parsingdata.metal.data.Environment; +import io.parsingdata.metal.data.OptionalValueList; import io.parsingdata.metal.data.ParseResult; import io.parsingdata.metal.token.Token; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; + +import java.io.IOException; + +import static io.parsingdata.metal.Shorthand.*; +import static io.parsingdata.metal.util.EncodingFactory.enc; +import static io.parsingdata.metal.util.EnvironmentFactory.stream; +import static io.parsingdata.metal.util.TokenDefinitions.any; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; public class ErrorsTest { @@ -75,4 +70,12 @@ public void multiValueInRepN() throws IOException { assertFalse(parseResult.succeeded); } + @Test + public void definedValueHasNoOffset() { + final OptionalValueList offsetCon = offset(con(1)).eval(stream(), enc()); + assertFalse(offsetCon.isEmpty()); + assertEquals(1, offsetCon.size); + assertFalse(offsetCon.head.isPresent()); + } + } diff --git a/core/src/test/java/io/parsingdata/metal/ToStringTest.java b/core/src/test/java/io/parsingdata/metal/ToStringTest.java index c0ee781f..cf8b9965 100644 --- a/core/src/test/java/io/parsingdata/metal/ToStringTest.java +++ b/core/src/test/java/io/parsingdata/metal/ToStringTest.java @@ -41,7 +41,7 @@ public void before() { @Test public void validateToStringImplementation() { - final Expression e = not(and(eq(v()), or(eqNum(v()), and(eqStr(v()), or(gtNum(v()), ltNum(v())))))); + final Expression e = not(and(eq(v(), v()), or(eqNum(v()), and(eqStr(v()), or(gtNum(v()), ltNum(v())))))); final Token t = repn(sub(opt(pre(str("str", rep(cho(any(n()), seq(nod(v()), whl(def(n(), con(1), e), e))))), e)), v()), v()); final String output = t.toString(); for (int i = 0; i < count; i++) { @@ -56,7 +56,7 @@ private String n() { private Token t() { return any("a"); } private ValueExpression v() { - return neg(add(div(mod(mul(sub(ref(n()), first(ref(n()))), con(1)), cat(ref(n()), ref(t()))), add(self, add(offset(ref(n())), add(currentOffset, count(ref(n())))))), elvis(ref(n()), ref(n())))); + return neg(add(div(mod(mul(sub(last(ref(n())), first(ref(n()))), con(1)), cat(ref(n()), ref(t()))), add(self, add(offset(ref(n())), add(currentOffset, count(ref(n())))))), elvis(ref(n()), ref(n())))); } @Test From 96467e5d90d5fd6fe778dd93e4d138decd75af7e Mon Sep 17 00:00:00 2001 From: Jeroen van den Bos Date: Sat, 23 Jul 2016 13:12:34 +0200 Subject: [PATCH 06/17] #78: ByItem.getGraphAfter() on an empty graph, ByToken.getAll() with refs and ComparisonExpression with either operand as empty. --- .../ComparisonExpressionSemanticsTest.java | 37 +++++++--------- .../metal/data/selection/ByItemTest.java | 31 ++++++++++++++ .../metal/data/selection/ByTokenTest.java | 42 +++++++++++++------ 3 files changed, 74 insertions(+), 36 deletions(-) create mode 100644 core/src/test/java/io/parsingdata/metal/data/selection/ByItemTest.java diff --git a/core/src/test/java/io/parsingdata/metal/ComparisonExpressionSemanticsTest.java b/core/src/test/java/io/parsingdata/metal/ComparisonExpressionSemanticsTest.java index 4361bdc4..4b76bbe1 100644 --- a/core/src/test/java/io/parsingdata/metal/ComparisonExpressionSemanticsTest.java +++ b/core/src/test/java/io/parsingdata/metal/ComparisonExpressionSemanticsTest.java @@ -16,33 +16,22 @@ package io.parsingdata.metal; -import static io.parsingdata.metal.Shorthand.con; -import static io.parsingdata.metal.Shorthand.def; -import static io.parsingdata.metal.Shorthand.eq; -import static io.parsingdata.metal.Shorthand.eqNum; -import static io.parsingdata.metal.Shorthand.eqStr; -import static io.parsingdata.metal.Shorthand.expTrue; -import static io.parsingdata.metal.Shorthand.gtNum; -import static io.parsingdata.metal.Shorthand.ltNum; -import static io.parsingdata.metal.Shorthand.ref; -import static io.parsingdata.metal.Shorthand.self; -import static io.parsingdata.metal.Shorthand.seq; -import static io.parsingdata.metal.util.TokenDefinitions.any; -import static io.parsingdata.metal.util.EncodingFactory.enc; -import static io.parsingdata.metal.util.EnvironmentFactory.stream; - -import java.nio.charset.Charset; -import java.util.Arrays; -import java.util.Collection; - -import io.parsingdata.metal.expression.Expression; -import org.junit.runners.Parameterized.Parameters; - import io.parsingdata.metal.data.Environment; import io.parsingdata.metal.encoding.Encoding; +import io.parsingdata.metal.expression.Expression; import io.parsingdata.metal.expression.comparison.ComparisonExpression; import io.parsingdata.metal.token.Token; import io.parsingdata.metal.util.ParameterizedParse; +import org.junit.runners.Parameterized.Parameters; + +import java.nio.charset.Charset; +import java.util.Arrays; +import java.util.Collection; + +import static io.parsingdata.metal.Shorthand.*; +import static io.parsingdata.metal.util.EncodingFactory.enc; +import static io.parsingdata.metal.util.EnvironmentFactory.stream; +import static io.parsingdata.metal.util.TokenDefinitions.any; public class ComparisonExpressionSemanticsTest extends ParameterizedParse { @@ -66,7 +55,9 @@ public static Collection data() { { "1, 2 == 1", listCom(eq(ref("a"), ref("b")), expTrue()), stream(1, 2, 1, 2), enc(), false }, { "1, 2 == 1, 2", listCom(expTrue(), eq(ref("a"), ref("b"))), stream(1, 2, 1, 2), enc(), true }, { "1, 2 == 2, 2", listCom(expTrue(), eq(ref("a"), ref("b"))), stream(1, 2, 2, 2), enc(), false }, - { "1, 2 == 1, 3", listCom(expTrue(), eq(ref("a"), ref("b"))), stream(1, 2, 1, 3), enc(), false } + { "1, 2 == 1, 3", listCom(expTrue(), eq(ref("a"), ref("b"))), stream(1, 2, 1, 3), enc(), false }, + { "1, 2, 1 != 1/0", valCom(1, eqNum(con(1), div(con(1), con(0)))), stream(1, 2), enc(), false }, + { "1, 2, 1/0 != 1", valCom(1, eqNum(div(con(1), con(0)), con(1))), stream(1, 2), enc(), false } }); } diff --git a/core/src/test/java/io/parsingdata/metal/data/selection/ByItemTest.java b/core/src/test/java/io/parsingdata/metal/data/selection/ByItemTest.java new file mode 100644 index 00000000..b15bd473 --- /dev/null +++ b/core/src/test/java/io/parsingdata/metal/data/selection/ByItemTest.java @@ -0,0 +1,31 @@ +/* + * Copyright 2013-2016 Netherlands Forensic Institute + * + * Licensed 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 io.parsingdata.metal.data.selection; + +import io.parsingdata.metal.data.ParseGraph; +import org.junit.Test; + +import static org.junit.Assert.assertTrue; + +public class ByItemTest { + + @Test + public void empty() { + assertTrue(ByItem.getGraphAfter(ParseGraph.EMPTY, null).isEmpty()); + } + +} diff --git a/core/src/test/java/io/parsingdata/metal/data/selection/ByTokenTest.java b/core/src/test/java/io/parsingdata/metal/data/selection/ByTokenTest.java index 9cce31da..a0314db2 100644 --- a/core/src/test/java/io/parsingdata/metal/data/selection/ByTokenTest.java +++ b/core/src/test/java/io/parsingdata/metal/data/selection/ByTokenTest.java @@ -26,10 +26,13 @@ import java.io.IOException; import static io.parsingdata.metal.Shorthand.*; +import static io.parsingdata.metal.data.selection.ByToken.getAll; import static io.parsingdata.metal.util.EncodingFactory.enc; import static io.parsingdata.metal.util.EnvironmentFactory.stream; import static org.hamcrest.CoreMatchers.*; import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; public class ByTokenTest { @@ -103,13 +106,13 @@ public void getAllNullCheck() { thrown.expect(IllegalArgumentException.class); thrown.expectMessage("Argument definition may not be null"); - ByToken.getAll(parseResultGraph(stream(0, 1, 2), SIMPLE_SEQ), null); + getAll(parseResultGraph(stream(0, 1, 2), SIMPLE_SEQ), null); } @Test public void getAllUnusedToken() { final ParseGraph graph = parseResultGraph(stream(0), SEQ_REP); - final ParseItemList list = ByToken.getAll(graph, UNUSED_DEF); + final ParseItemList list = getAll(graph, UNUSED_DEF); assertThat(list.size, is(equalTo(0L))); } @@ -117,7 +120,7 @@ public void getAllUnusedToken() { @Test public void getAllNonePresent() { final ParseGraph graph = parseResultGraph(stream(0), SEQ_REP); - final ParseItemList list = ByToken.getAll(graph, DEF2); + final ParseItemList list = getAll(graph, DEF2); assertThat(list.size, is(equalTo(0L))); } @@ -125,7 +128,7 @@ public void getAllNonePresent() { @Test public void getAllSingleDef() { final ParseGraph graph = parseResultGraph(stream(0, 1, 2, 3, 4, 5), SEQ_REP); - final ParseItemList list = ByToken.getAll(graph, DEF1); + final ParseItemList list = getAll(graph, DEF1); assertThat(list.size, is(equalTo(1L))); assertThat(list.head.getDefinition(), is(equalTo(DEF1))); @@ -134,7 +137,7 @@ public void getAllSingleDef() { @Test public void getAllRepDef() { final ParseGraph graph = parseResultGraph(stream(0, 1, 2, 3, 4, 5), SEQ_REP); - final ParseItemList list = ByToken.getAll(graph, DEF2); + final ParseItemList list = getAll(graph, DEF2); assertThat(list.size, is(equalTo(5L))); assertThat(list.head.getDefinition(), is(equalTo(DEF2))); @@ -143,8 +146,8 @@ public void getAllRepDef() { @Test public void getAllRepSeq() { final ParseGraph graph = parseResultGraph(stream(0, 1, 2, 3, 4, 5), rep(SIMPLE_SEQ)); - final ParseItemList list1 = ByToken.getAll(graph, DEF1); - final ParseItemList list2 = ByToken.getAll(graph, DEF2); + final ParseItemList list1 = getAll(graph, DEF1); + final ParseItemList list2 = getAll(graph, DEF2); assertThat(list1.size, is(equalTo(3L))); assertThat(list2.size, is(equalTo(3L))); @@ -159,7 +162,7 @@ public void getAllRepSeq() { @Test public void getAllSub() { final ParseGraph graph = parseResultGraph(stream(4, 2, 2, 3, 4, 5), SEQ_SUB); - final ParseItemList list = ByToken.getAll(graph, TWO_BYTES); + final ParseItemList list = getAll(graph, TWO_BYTES); assertThat(list.size, is(equalTo(2L))); assertThat(list.head.getDefinition(), is(equalTo(TWO_BYTES))); @@ -170,10 +173,10 @@ public void getAllSub() { public void getAllMutualRecursive() { final ParseGraph graph = parseResultGraph(stream(0, 1, 2, 3, 4, 5), MUT_REC_1); - final ParseItemList repList = ByToken.getAll(graph, REPN_DEF2); + final ParseItemList repList = getAll(graph, REPN_DEF2); assertThat(repList.size, is(equalTo(4L))); - final ParseItemList recList = ByToken.getAll(graph, MUT_REC_1); + final ParseItemList recList = getAll(graph, MUT_REC_1); assertThat(recList.size, is(equalTo(4L))); } @@ -181,10 +184,10 @@ public void getAllMutualRecursive() { public void getAllMutualRecursiveWithStruct() { final ParseGraph graph = parseResultGraph(stream(0, 1, 2, 3, 4, 5), STR_MUT_REC_1); - final ParseItemList repList = ByToken.getAll(graph, REPN_DEF2); + final ParseItemList repList = getAll(graph, REPN_DEF2); assertThat(repList.size, is(equalTo(4L))); - final ParseItemList recList = ByToken.getAll(graph, STR_MUT_REC_1); + final ParseItemList recList = getAll(graph, STR_MUT_REC_1); assertThat(recList.size, is(equalTo(2L))); } @@ -193,7 +196,7 @@ public void compareGetAllNameWithGetAllToken() { final ParseGraph graph = parseResultGraph(stream(0, 1, 2, 3, 4, 5), SEQ_REP); ParseValueList valueList = ByName.getAllValues(graph, "value2"); - ParseItemList itemList = ByToken.getAll(graph, DEF2); + ParseItemList itemList = getAll(graph, DEF2); while (valueList.head != null) { assertThat(valueList.head, is(equalTo(itemList.head.asValue()))); @@ -212,4 +215,17 @@ private ParseGraph parseResultGraph(final Environment env, final Token def) { } } + @Test + public void getSubRef() throws IOException { + final Token smallSub1 = sub(DEF2, last(ref("value1"))); + final Token smallSub2 = sub(DEF2, last(ref("value1"))); + final Token composition = seq(DEF1, smallSub1, smallSub2); + final ParseResult result = composition.parse(stream(0), enc()); + assertTrue(result.succeeded); + final ParseItemList refs = ByToken.getAll(result.environment.order, smallSub1); + assertEquals(2, refs.size); + assertTrue(refs.head.isRef()); + assertTrue(refs.tail.head.isGraph()); + } + } From 1b02973af7261663c5bb69b4c66ff12fe7afb935 Mon Sep 17 00:00:00 2001 From: Jeroen van den Bos Date: Sat, 23 Jul 2016 17:57:01 +0200 Subject: [PATCH 07/17] #78: Classes in formats have also been correctly defined as final classes with a private constructor. Also added relevant tests for it. --- core/pom.xml | 1 + .../parsingdata/metal/UtilityClassTest.java | 2 +- .../io/parsingdata/metal/format/Callback.java | 14 +++---- .../io/parsingdata/metal/format/JPEG.java | 4 +- .../java/io/parsingdata/metal/format/PNG.java | 4 +- .../java/io/parsingdata/metal/format/ZIP.java | 4 +- .../metal/DescriptionClassTest.java | 37 +++++++++++++++++++ 7 files changed, 54 insertions(+), 12 deletions(-) create mode 100644 formats/src/test/java/io/parsingdata/metal/DescriptionClassTest.java diff --git a/core/pom.xml b/core/pom.xml index 80238616..8d247584 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -33,6 +33,7 @@ **/util/** + **/UtilityClassTest.class diff --git a/core/src/test/java/io/parsingdata/metal/UtilityClassTest.java b/core/src/test/java/io/parsingdata/metal/UtilityClassTest.java index 7ebc3482..f21042a8 100644 --- a/core/src/test/java/io/parsingdata/metal/UtilityClassTest.java +++ b/core/src/test/java/io/parsingdata/metal/UtilityClassTest.java @@ -35,7 +35,7 @@ public class UtilityClassTest { // Check that a class is final, has a single private constructor and that all // its declared methods are static. - private void checkUtilityClass(Class c) throws ReflectiveOperationException { + public static void checkUtilityClass(Class c) throws ReflectiveOperationException { assertTrue(Modifier.isFinal(c.getModifiers())); final Constructor[] cons = c.getDeclaredConstructors(); assertEquals(1, cons.length); diff --git a/formats/src/main/java/io/parsingdata/metal/format/Callback.java b/formats/src/main/java/io/parsingdata/metal/format/Callback.java index 110992b3..efd5617b 100644 --- a/formats/src/main/java/io/parsingdata/metal/format/Callback.java +++ b/formats/src/main/java/io/parsingdata/metal/format/Callback.java @@ -16,21 +16,19 @@ package io.parsingdata.metal.format; +import io.parsingdata.metal.data.Environment; +import io.parsingdata.metal.encoding.Encoding; +import io.parsingdata.metal.expression.value.*; + import java.io.ByteArrayOutputStream; import java.io.IOException; import java.util.zip.CRC32; import java.util.zip.Inflater; import java.util.zip.InflaterOutputStream; -import io.parsingdata.metal.data.Environment; -import io.parsingdata.metal.encoding.Encoding; -import io.parsingdata.metal.expression.value.OptionalValue; -import io.parsingdata.metal.expression.value.UnaryValueExpression; -import io.parsingdata.metal.expression.value.Value; -import io.parsingdata.metal.expression.value.ValueExpression; -import io.parsingdata.metal.expression.value.ValueOperation; +public final class Callback { -public class Callback { + private Callback() {} public static ValueExpression crc32(final ValueExpression target) { return new UnaryValueExpression(target) { diff --git a/formats/src/main/java/io/parsingdata/metal/format/JPEG.java b/formats/src/main/java/io/parsingdata/metal/format/JPEG.java index 90909da1..20b513f8 100644 --- a/formats/src/main/java/io/parsingdata/metal/format/JPEG.java +++ b/formats/src/main/java/io/parsingdata/metal/format/JPEG.java @@ -24,7 +24,9 @@ * Since nearly every byte of the scan data is individually matched, this * approach will lead to stack overflow on files of realistic size. */ -public class JPEG { +public final class JPEG { + + private JPEG() {} private static final Token HEADER = seq("start of image", diff --git a/formats/src/main/java/io/parsingdata/metal/format/PNG.java b/formats/src/main/java/io/parsingdata/metal/format/PNG.java index a2d1d55f..aa0def3b 100644 --- a/formats/src/main/java/io/parsingdata/metal/format/PNG.java +++ b/formats/src/main/java/io/parsingdata/metal/format/PNG.java @@ -22,7 +22,9 @@ import static io.parsingdata.metal.Shorthand.*; import static io.parsingdata.metal.format.Callback.crc32; -public class PNG { +public final class PNG { + + private PNG() {} private static final Token HEADER = seq("signature", diff --git a/formats/src/main/java/io/parsingdata/metal/format/ZIP.java b/formats/src/main/java/io/parsingdata/metal/format/ZIP.java index 6b215b35..be6333d8 100644 --- a/formats/src/main/java/io/parsingdata/metal/format/ZIP.java +++ b/formats/src/main/java/io/parsingdata/metal/format/ZIP.java @@ -30,7 +30,9 @@ * - Only single-part files. * - Only Store and Deflate compression schemes. */ -public class ZIP { +public final class ZIP { + + private ZIP() {} private static Token localFileBody(final String name, final int cm, final Expression crc, final Expression cs, final Expression usp) { return diff --git a/formats/src/test/java/io/parsingdata/metal/DescriptionClassTest.java b/formats/src/test/java/io/parsingdata/metal/DescriptionClassTest.java new file mode 100644 index 00000000..e8ab6877 --- /dev/null +++ b/formats/src/test/java/io/parsingdata/metal/DescriptionClassTest.java @@ -0,0 +1,37 @@ +/* + * Copyright 2013-2016 Netherlands Forensic Institute + * + * Licensed 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 io.parsingdata.metal; + +import io.parsingdata.metal.format.Callback; +import io.parsingdata.metal.format.JPEG; +import io.parsingdata.metal.format.PNG; +import io.parsingdata.metal.format.ZIP; +import org.junit.Test; + +import static io.parsingdata.metal.UtilityClassTest.checkUtilityClass; + +public class DescriptionClassTest { + + @Test + public void utilityClasses() throws ReflectiveOperationException { + checkUtilityClass(Callback.class); + checkUtilityClass(JPEG.class); + checkUtilityClass(PNG.class); + checkUtilityClass(ZIP.class); + } + +} From 670300ba7558464d9c812caaddd2aeb6b4f33f1b Mon Sep 17 00:00:00 2001 From: Jeroen van den Bos Date: Sun, 24 Jul 2016 10:36:02 +0200 Subject: [PATCH 08/17] #78: Refactoring. --- core/pom.xml | 1 - .../parsingdata/metal/UtilityClassTest.java | 21 +--------- .../metal/util/ClassDefinition.java | 42 +++++++++++++++++++ .../metal/DescriptionClassTest.java | 3 +- 4 files changed, 46 insertions(+), 21 deletions(-) create mode 100644 core/src/test/java/io/parsingdata/metal/util/ClassDefinition.java diff --git a/core/pom.xml b/core/pom.xml index 8d247584..80238616 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -33,7 +33,6 @@ **/util/** - **/UtilityClassTest.class diff --git a/core/src/test/java/io/parsingdata/metal/UtilityClassTest.java b/core/src/test/java/io/parsingdata/metal/UtilityClassTest.java index f21042a8..65affa2d 100644 --- a/core/src/test/java/io/parsingdata/metal/UtilityClassTest.java +++ b/core/src/test/java/io/parsingdata/metal/UtilityClassTest.java @@ -23,30 +23,13 @@ import io.parsingdata.metal.token.Token; import org.junit.Test; -import java.lang.reflect.Constructor; -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; - import static io.parsingdata.metal.Util.tokensToString; +import static io.parsingdata.metal.util.ClassDefinition.checkUtilityClass; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; public class UtilityClassTest { - // Check that a class is final, has a single private constructor and that all - // its declared methods are static. - public static void checkUtilityClass(Class c) throws ReflectiveOperationException { - assertTrue(Modifier.isFinal(c.getModifiers())); - final Constructor[] cons = c.getDeclaredConstructors(); - assertEquals(1, cons.length); - assertTrue(Modifier.isPrivate(cons[0].getModifiers())); - cons[0].setAccessible(true); - cons[0].newInstance(); - for (Method m : c.getDeclaredMethods()) { - assertTrue(Modifier.isStatic(m.getModifiers())); - } - } - + // Check that utility classes are well-formed. @Test public void utilityClasses() throws ReflectiveOperationException { checkUtilityClass(Shorthand.class); diff --git a/core/src/test/java/io/parsingdata/metal/util/ClassDefinition.java b/core/src/test/java/io/parsingdata/metal/util/ClassDefinition.java new file mode 100644 index 00000000..106bfa8d --- /dev/null +++ b/core/src/test/java/io/parsingdata/metal/util/ClassDefinition.java @@ -0,0 +1,42 @@ +/* + * Copyright 2013-2016 Netherlands Forensic Institute + * + * Licensed 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 io.parsingdata.metal.util; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +public class ClassDefinition { + + // Check that a class is final, has a single private constructor and that all + // its declared methods are static. + public static void checkUtilityClass(Class c) throws ReflectiveOperationException { + assertTrue(Modifier.isFinal(c.getModifiers())); + final Constructor[] cons = c.getDeclaredConstructors(); + assertEquals(1, cons.length); + assertTrue(Modifier.isPrivate(cons[0].getModifiers())); + cons[0].setAccessible(true); + cons[0].newInstance(); + for (Method m : c.getDeclaredMethods()) { + assertTrue(Modifier.isStatic(m.getModifiers())); + } + } + +} diff --git a/formats/src/test/java/io/parsingdata/metal/DescriptionClassTest.java b/formats/src/test/java/io/parsingdata/metal/DescriptionClassTest.java index e8ab6877..67d44dfc 100644 --- a/formats/src/test/java/io/parsingdata/metal/DescriptionClassTest.java +++ b/formats/src/test/java/io/parsingdata/metal/DescriptionClassTest.java @@ -22,10 +22,11 @@ import io.parsingdata.metal.format.ZIP; import org.junit.Test; -import static io.parsingdata.metal.UtilityClassTest.checkUtilityClass; +import static io.parsingdata.metal.util.ClassDefinition.checkUtilityClass; public class DescriptionClassTest { + // Check that description and callback classes are well-formed. @Test public void utilityClasses() throws ReflectiveOperationException { checkUtilityClass(Callback.class); From c4f2dfb597daa24b65a0e60dc28f4be9ef236c63 Mon Sep 17 00:00:00 2001 From: Jeroen van den Bos Date: Sun, 24 Jul 2016 22:06:56 +0200 Subject: [PATCH 09/17] #78: Formats at 100% coverage. --- .../io/parsingdata/metal/format/Callback.java | 22 +++++---- .../io/parsingdata/metal/CallbackTest.java | 46 +++++++++++++++++++ 2 files changed, 58 insertions(+), 10 deletions(-) create mode 100644 formats/src/test/java/io/parsingdata/metal/CallbackTest.java diff --git a/formats/src/main/java/io/parsingdata/metal/format/Callback.java b/formats/src/main/java/io/parsingdata/metal/format/Callback.java index efd5617b..ea9579d4 100644 --- a/formats/src/main/java/io/parsingdata/metal/format/Callback.java +++ b/formats/src/main/java/io/parsingdata/metal/format/Callback.java @@ -21,10 +21,9 @@ import io.parsingdata.metal.expression.value.*; import java.io.ByteArrayOutputStream; -import java.io.IOException; import java.util.zip.CRC32; +import java.util.zip.DataFormatException; import java.util.zip.Inflater; -import java.util.zip.InflaterOutputStream; public final class Callback { @@ -58,15 +57,18 @@ public OptionalValue eval(final Value v, final Environment env, final Encoding e @Override public OptionalValue execute(final Value value) { final Inflater inf = new Inflater(true); - final ByteArrayOutputStream bos = new ByteArrayOutputStream(); - final InflaterOutputStream ios = new InflaterOutputStream(bos, inf); - try { - ios.write(value.getValue()); - ios.close(); - return OptionalValue.of(new Value(bos.toByteArray(), enc)); - } catch (final IOException e) { - return OptionalValue.empty(); + inf.setInput(value.getValue()); + final byte[] dataReceiver = new byte[512]; + final ByteArrayOutputStream out = new ByteArrayOutputStream(); + while(!inf.finished()) { + try { + final int processed = inf.inflate(dataReceiver); + out.write(dataReceiver, 0, processed); + } catch (DataFormatException e) { + return OptionalValue.empty(); + } } + return OptionalValue.of(new Value(out.toByteArray(), enc)); } }); } diff --git a/formats/src/test/java/io/parsingdata/metal/CallbackTest.java b/formats/src/test/java/io/parsingdata/metal/CallbackTest.java new file mode 100644 index 00000000..9afd2106 --- /dev/null +++ b/formats/src/test/java/io/parsingdata/metal/CallbackTest.java @@ -0,0 +1,46 @@ +/* + * Copyright 2013-2016 Netherlands Forensic Institute + * + * Licensed 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 io.parsingdata.metal; + +import io.parsingdata.metal.data.OptionalValueList; +import org.junit.Test; + +import static io.parsingdata.metal.Shorthand.con; +import static io.parsingdata.metal.format.Callback.crc32; +import static io.parsingdata.metal.format.Callback.inflate; +import static io.parsingdata.metal.util.EncodingFactory.enc; +import static io.parsingdata.metal.util.EnvironmentFactory.stream; +import static org.junit.Assert.*; + +public class CallbackTest { + + @Test + public void crc32Good() { + final OptionalValueList result = crc32(con(0x01020304)).eval(stream(), enc()); + assertEquals(1, result.size); + assertTrue(result.head.isPresent()); + assertArrayEquals(new byte[] { -74, 60, -5, -51 }, result.head.get().getValue()); + } + + @Test + public void inflateDataFormatError() { + final OptionalValueList result = inflate(con(0xffffffff)).eval(stream(), enc()); + assertEquals(1, result.size); + assertFalse(result.head.isPresent()); + } + +} From a43fe8c07b4a01efea50c07684029cde32b0c834 Mon Sep 17 00:00:00 2001 From: Jeroen van den Bos Date: Mon, 25 Jul 2016 10:47:28 +0200 Subject: [PATCH 10/17] #78: Encoding package to 100%. --- .../ComparisonExpressionSemanticsTest.java | 6 ++++-- .../java/io/parsingdata/metal/ToStringTest.java | 17 ++++++++++++++--- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/core/src/test/java/io/parsingdata/metal/ComparisonExpressionSemanticsTest.java b/core/src/test/java/io/parsingdata/metal/ComparisonExpressionSemanticsTest.java index 4b76bbe1..da646427 100644 --- a/core/src/test/java/io/parsingdata/metal/ComparisonExpressionSemanticsTest.java +++ b/core/src/test/java/io/parsingdata/metal/ComparisonExpressionSemanticsTest.java @@ -35,6 +35,8 @@ public class ComparisonExpressionSemanticsTest extends ParameterizedParse { + public static final Charset ASCII = Charset.forName("ISO646-US"); + @Parameters(name="{0} ({4})") public static Collection data() { return Arrays.asList(new Object[][] { @@ -46,8 +48,8 @@ public static Collection data() { { "1 < 1", numCom(1, ltNum(ref("a"))), stream(1, 1), enc(), false }, { "2 < 1", numCom(1, ltNum(ref("a"))), stream(1, 2), enc(), false }, { "1 < 2", numCom(1, ltNum(ref("a"))), stream(2, 1), enc(), true }, - { "\"abc\" == \"abc\"", strCom(3, eqStr(ref("a"))), stream("abcabc", Charset.forName("ISO646-US")), enc(), true }, - { "\"abd\" == \"abc\"", strCom(3, eqStr(ref("a"))), stream("abcabd", Charset.forName("ISO646-US")), enc(), false }, + { "\"abc\" == \"abc\"", strCom(3, eqStr(ref("a"))), stream("abcabc", ASCII), new Encoding(ASCII), true }, + { "\"abd\" == \"abc\"", strCom(3, eqStr(ref("a"))), stream("abcabd", ASCII), new Encoding(ASCII), false }, { "1 == 1(eq)", valCom(1, eq(ref("a"))), stream(1, 1), enc(), true }, { "2 == 1(eq)", valCom(1, eq(ref("a"))), stream(1, 2), enc(), false }, { "1 == 1 with self", valCom(1, eq(self, ref("a"))), stream(1, 1), enc(), true }, diff --git a/core/src/test/java/io/parsingdata/metal/ToStringTest.java b/core/src/test/java/io/parsingdata/metal/ToStringTest.java index cf8b9965..fdcb1129 100644 --- a/core/src/test/java/io/parsingdata/metal/ToStringTest.java +++ b/core/src/test/java/io/parsingdata/metal/ToStringTest.java @@ -16,19 +16,22 @@ package io.parsingdata.metal; +import io.parsingdata.metal.encoding.ByteOrder; +import io.parsingdata.metal.encoding.Encoding; +import io.parsingdata.metal.encoding.Sign; import io.parsingdata.metal.expression.Expression; import io.parsingdata.metal.expression.value.ValueExpression; import io.parsingdata.metal.token.Token; import org.junit.Assert; import org.junit.Before; import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; + +import java.nio.charset.Charset; import static io.parsingdata.metal.Shorthand.*; import static io.parsingdata.metal.util.TokenDefinitions.any; +import static org.junit.Assert.assertEquals; -@RunWith(JUnit4.class) public class ToStringTest { private static final String prefix = "prefix"; @@ -77,4 +80,12 @@ private void checkToken(final Token t) { Assert.assertTrue(s1s.contains("_name_c_")); } + @Test + public void encoding() { + assertEquals("Encoding(UNSIGNED,US-ASCII,BIG_ENDIAN)", new Encoding().toString()); + assertEquals("Encoding(SIGNED,US-ASCII,BIG_ENDIAN)", new Encoding(Sign.SIGNED).toString()); + assertEquals("Encoding(UNSIGNED,UTF-8,BIG_ENDIAN)", new Encoding(Charset.forName("UTF-8")).toString()); + assertEquals("Encoding(UNSIGNED,US-ASCII,LITTLE_ENDIAN)", new Encoding(ByteOrder.LITTLE_ENDIAN).toString()); + } + } From 3d19018f68bd3b57d35b540656ab06f7c067af17 Mon Sep 17 00:00:00 2001 From: Jeroen van den Bos Date: Mon, 25 Jul 2016 13:19:52 +0200 Subject: [PATCH 11/17] #78: Tests related to list semantics edge cases for Sub, Nod and Def. --- .../io/parsingdata/metal/DefSizeTest.java | 29 +++++++++++------ .../io/parsingdata/metal/SubStructTest.java | 13 ++++++++ .../io/parsingdata/metal/token/NodTest.java | 31 +++++++++---------- .../metal/util/TokenDefinitions.java | 3 ++ 4 files changed, 50 insertions(+), 26 deletions(-) diff --git a/core/src/test/java/io/parsingdata/metal/DefSizeTest.java b/core/src/test/java/io/parsingdata/metal/DefSizeTest.java index d3b26ebe..eb682cde 100644 --- a/core/src/test/java/io/parsingdata/metal/DefSizeTest.java +++ b/core/src/test/java/io/parsingdata/metal/DefSizeTest.java @@ -16,16 +16,6 @@ package io.parsingdata.metal; -import static io.parsingdata.metal.Shorthand.con; -import static io.parsingdata.metal.Shorthand.def; -import static io.parsingdata.metal.Shorthand.ref; -import static io.parsingdata.metal.Shorthand.seq; - -import java.io.IOException; - -import org.junit.Assert; -import org.junit.Test; - import io.parsingdata.metal.data.ByteStream; import io.parsingdata.metal.data.Environment; import io.parsingdata.metal.data.ParseGraph; @@ -33,6 +23,17 @@ import io.parsingdata.metal.encoding.Encoding; import io.parsingdata.metal.token.Token; import io.parsingdata.metal.util.InMemoryByteStream; +import org.junit.Assert; +import org.junit.Test; + +import java.io.IOException; + +import static io.parsingdata.metal.Shorthand.*; +import static io.parsingdata.metal.util.EncodingFactory.enc; +import static io.parsingdata.metal.util.EnvironmentFactory.stream; +import static io.parsingdata.metal.util.TokenDefinitions.EMPTY_VE; +import static io.parsingdata.metal.util.TokenDefinitions.any; +import static org.junit.Assert.assertFalse; public class DefSizeTest { public static final Token FORMAT = @@ -68,4 +69,12 @@ public void testInvalidLength() throws IOException { // The top-level Token (Seq) has failed, so no values are recorded in the ParseGraph. Assert.assertEquals(ParseGraph.EMPTY, result.environment.order); } + + @Test + public void testEmptyLengthInList() throws IOException { + assertFalse(def("a", EMPTY_VE).parse(stream(1, 2, 3, 4), enc()).succeeded); + final Token aList = seq(any("a"), any("a")); + assertFalse(seq(aList, def("b", ref("a"))).parse(stream(1, 2, 3, 4), enc()).succeeded); + } + } diff --git a/core/src/test/java/io/parsingdata/metal/SubStructTest.java b/core/src/test/java/io/parsingdata/metal/SubStructTest.java index 48022e8e..418bcc5b 100644 --- a/core/src/test/java/io/parsingdata/metal/SubStructTest.java +++ b/core/src/test/java/io/parsingdata/metal/SubStructTest.java @@ -27,6 +27,9 @@ import static io.parsingdata.metal.Shorthand.*; import static io.parsingdata.metal.util.EncodingFactory.enc; import static io.parsingdata.metal.util.EnvironmentFactory.stream; +import static io.parsingdata.metal.util.TokenDefinitions.EMPTY_VE; +import static io.parsingdata.metal.util.TokenDefinitions.any; +import static junit.framework.TestCase.assertFalse; public class SubStructTest { @@ -128,4 +131,14 @@ private void checkValue(final ParseItem item, final int value, final int offset) Assert.assertEquals(offset, item.asValue().getOffset()); } + @Test + public void errorEmptyAddressList() throws IOException { + assertFalse(sub(any("a"), ref("b")).parse(stream(1, 2, 3, 4), enc()).succeeded); + } + + @Test + public void errorEmptyAddressInList() throws IOException { + assertFalse(sub(any("a"), cat(con(0), EMPTY_VE)).parse(stream(1, 2, 3, 4), enc()).succeeded); + } + } diff --git a/core/src/test/java/io/parsingdata/metal/token/NodTest.java b/core/src/test/java/io/parsingdata/metal/token/NodTest.java index 71279350..8cec32db 100644 --- a/core/src/test/java/io/parsingdata/metal/token/NodTest.java +++ b/core/src/test/java/io/parsingdata/metal/token/NodTest.java @@ -16,26 +16,20 @@ package io.parsingdata.metal.token; -import static org.hamcrest.CoreMatchers.is; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; +import io.parsingdata.metal.data.ParseResult; +import org.junit.Test; -import static io.parsingdata.metal.Shorthand.con; -import static io.parsingdata.metal.Shorthand.def; -import static io.parsingdata.metal.Shorthand.eq; -import static io.parsingdata.metal.Shorthand.nod; -import static io.parsingdata.metal.Shorthand.ref; -import static io.parsingdata.metal.Shorthand.seq; +import java.io.IOException; + +import static io.parsingdata.metal.Shorthand.*; import static io.parsingdata.metal.util.EncodingFactory.enc; import static io.parsingdata.metal.util.EncodingFactory.signed; import static io.parsingdata.metal.util.EnvironmentFactory.stream; - -import java.io.IOException; - -import org.junit.Test; - -import io.parsingdata.metal.data.ParseResult; +import static io.parsingdata.metal.util.TokenDefinitions.EMPTY_VE; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; public class NodTest { @@ -93,4 +87,9 @@ public void nodWithSizeZero() throws IOException { assertThat(parseResult.environment.offset, is(2L)); } + @Test + public void nodWithEmpty() throws IOException { + assertFalse(nod(EMPTY_VE).parse(stream(1, 2, 3, 4), enc()).succeeded); + } + } diff --git a/core/src/test/java/io/parsingdata/metal/util/TokenDefinitions.java b/core/src/test/java/io/parsingdata/metal/util/TokenDefinitions.java index 983b9d97..8425d179 100644 --- a/core/src/test/java/io/parsingdata/metal/util/TokenDefinitions.java +++ b/core/src/test/java/io/parsingdata/metal/util/TokenDefinitions.java @@ -18,6 +18,7 @@ import io.parsingdata.metal.Shorthand; import io.parsingdata.metal.encoding.Encoding; +import io.parsingdata.metal.expression.value.ValueExpression; import io.parsingdata.metal.token.Token; import static io.parsingdata.metal.Shorthand.*; @@ -26,6 +27,8 @@ public class TokenDefinitions { private TokenDefinitions() {} + public static final ValueExpression EMPTY_VE = div(con(1), con(0)); // division by zero to create empty value + public static Token any(final String name) { return def(name, con(1)); } From 53592aeb4d780db587dc4d879eddb4c5fb4b3335 Mon Sep 17 00:00:00 2001 From: Jeroen van den Bos Date: Mon, 25 Jul 2016 14:09:45 +0200 Subject: [PATCH 12/17] #78: Token package to 100%. --- .../io/parsingdata/metal/ShorthandsTest.java | 75 ++++++++++++++++--- .../io/parsingdata/metal/ToStringTest.java | 11 ++- 2 files changed, 75 insertions(+), 11 deletions(-) diff --git a/core/src/test/java/io/parsingdata/metal/ShorthandsTest.java b/core/src/test/java/io/parsingdata/metal/ShorthandsTest.java index 2b04c760..608617af 100644 --- a/core/src/test/java/io/parsingdata/metal/ShorthandsTest.java +++ b/core/src/test/java/io/parsingdata/metal/ShorthandsTest.java @@ -19,12 +19,12 @@ import io.parsingdata.metal.data.Environment; import io.parsingdata.metal.data.OptionalValueList; import io.parsingdata.metal.data.ParseResult; -import io.parsingdata.metal.expression.value.OptionalValue; -import io.parsingdata.metal.expression.value.ValueExpression; +import io.parsingdata.metal.token.Cho; +import io.parsingdata.metal.token.Seq; import io.parsingdata.metal.token.Token; +import org.junit.Rule; import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; +import org.junit.rules.ExpectedException; import java.io.IOException; @@ -38,9 +38,10 @@ public class ShorthandsTest { - private static final Token multiSequence = seq(def("a", con(1), eq(con(1))), - def("b", con(1), eq(con(2))), - def("c", con(1), eq(con(3)))); + private static final Token multiSequence = + seq(def("a", con(1), eq(con(1))), + def("b", con(1), eq(con(2))), + def("c", con(1), eq(con(3)))); @Test public void sequenceMultiMatch() throws IOException { @@ -52,9 +53,10 @@ public void sequenceMultiNoMatch() throws IOException { assertFalse(multiSequence.parse(stream(1, 2, 2), enc()).succeeded); } - private static final Token multiChoice = cho(def("a", con(1), gtNum(con(2))), - def("b", con(1), gtNum(con(1))), - def("c", con(1), gtNum(con(0)))); + private static final Token multiChoice = + cho(def("a", con(1), gtNum(con(2))), + def("b", con(1), gtNum(con(1))), + def("c", con(1), gtNum(con(0)))); @Test public void choiceMultiMatchA() throws IOException { @@ -128,4 +130,57 @@ private void checkNameAndValue(final String name, final int value, final Environ assertEquals(value, refList.head.get().asNumeric().intValue()); } + @Rule + public ExpectedException thrown = ExpectedException.none(); + + @Test + public void choSingle() { + setUpArgumentException(); + cho(any("a")); + } + + @Test + public void choEmpty() { + setUpArgumentException(); + cho(); + } + + @Test + public void seqSingle() { + setUpArgumentException(); + seq(any("a")); + } + + @Test + public void seqEmpty() { + setUpArgumentException(); + seq(); + } + + private void setUpArgumentException() { + thrown.expect(IllegalArgumentException.class); + thrown.expectMessage("At least two Tokens are required."); + } + + public static final Token DEFA = any("a"); + public static final Token DEFB = any("b"); + + @Test + public void checkChoTokens() { + final Token choToken = cho(DEFA, DEFB); + final Cho cho = (Cho)choToken; + assertEquals(2, cho.tokens().length); + assertEquals(DEFA, cho.tokens()[0]); + assertEquals(DEFB, cho.tokens()[1]); + } + + @Test + public void checkSeqTokens() { + final Token seqToken = seq(DEFA, DEFB); + final Seq seq = (Seq)seqToken; + assertEquals(2, seq.tokens().length); + assertEquals(DEFA, seq.tokens()[0]); + assertEquals(DEFB, seq.tokens()[1]); + } + } diff --git a/core/src/test/java/io/parsingdata/metal/ToStringTest.java b/core/src/test/java/io/parsingdata/metal/ToStringTest.java index fdcb1129..07091200 100644 --- a/core/src/test/java/io/parsingdata/metal/ToStringTest.java +++ b/core/src/test/java/io/parsingdata/metal/ToStringTest.java @@ -16,11 +16,14 @@ package io.parsingdata.metal; +import io.parsingdata.metal.data.Environment; +import io.parsingdata.metal.data.ParseGraph; import io.parsingdata.metal.encoding.ByteOrder; import io.parsingdata.metal.encoding.Encoding; import io.parsingdata.metal.encoding.Sign; import io.parsingdata.metal.expression.Expression; import io.parsingdata.metal.expression.value.ValueExpression; +import io.parsingdata.metal.token.StructSink; import io.parsingdata.metal.token.Token; import org.junit.Assert; import org.junit.Before; @@ -37,6 +40,12 @@ public class ToStringTest { private static final String prefix = "prefix"; private int count; + private static final StructSink sink = new StructSink() { + @Override + public void handleStruct(String scopeName, Environment env, Encoding enc, ParseGraph struct) { + } + }; + @Before public void before() { count = 0; @@ -45,7 +54,7 @@ public void before() { @Test public void validateToStringImplementation() { final Expression e = not(and(eq(v(), v()), or(eqNum(v()), and(eqStr(v()), or(gtNum(v()), ltNum(v())))))); - final Token t = repn(sub(opt(pre(str("str", rep(cho(any(n()), seq(nod(v()), whl(def(n(), con(1), e), e))))), e)), v()), v()); + final Token t = repn(sub(opt(pre(str("str", rep(cho(str("str", any(n())), seq(nod(v()), whl(def(n(), con(1), e), e)))), sink), e)), v()), v()); final String output = t.toString(); for (int i = 0; i < count; i++) { Assert.assertTrue(output.contains(prefix + i)); From 7b8a83722acc5bd196f897cc4ec8b96f45983a35 Mon Sep 17 00:00:00 2001 From: Jeroen van den Bos Date: Mon, 25 Jul 2016 16:09:15 +0200 Subject: [PATCH 13/17] #78: Review comments. --- .../main/java/io/parsingdata/metal/encoding/Encoding.java | 3 ++- .../metal/ComparisonExpressionSemanticsTest.java | 8 +++----- .../io/parsingdata/metal/data/selection/ByTokenTest.java | 1 + .../java/io/parsingdata/metal/util/ClassDefinition.java | 2 +- .../main/java/io/parsingdata/metal/format/Callback.java | 2 +- .../src/test/java/io/parsingdata/metal/CallbackTest.java | 8 ++++++++ 6 files changed, 16 insertions(+), 8 deletions(-) diff --git a/core/src/main/java/io/parsingdata/metal/encoding/Encoding.java b/core/src/main/java/io/parsingdata/metal/encoding/Encoding.java index 132a9c78..25444caf 100644 --- a/core/src/main/java/io/parsingdata/metal/encoding/Encoding.java +++ b/core/src/main/java/io/parsingdata/metal/encoding/Encoding.java @@ -17,11 +17,12 @@ package io.parsingdata.metal.encoding; import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; public class Encoding { private static final Sign DEFAULT_SIGNED = Sign.UNSIGNED; - private static final Charset DEFAULT_CHARSET = Charset.forName("ISO646-US"); + private static final Charset DEFAULT_CHARSET = StandardCharsets.US_ASCII; private static final ByteOrder DEFAULT_BYTE_ORDER = ByteOrder.BIG_ENDIAN; private final Sign _sign; diff --git a/core/src/test/java/io/parsingdata/metal/ComparisonExpressionSemanticsTest.java b/core/src/test/java/io/parsingdata/metal/ComparisonExpressionSemanticsTest.java index da646427..7a2333ed 100644 --- a/core/src/test/java/io/parsingdata/metal/ComparisonExpressionSemanticsTest.java +++ b/core/src/test/java/io/parsingdata/metal/ComparisonExpressionSemanticsTest.java @@ -24,7 +24,6 @@ import io.parsingdata.metal.util.ParameterizedParse; import org.junit.runners.Parameterized.Parameters; -import java.nio.charset.Charset; import java.util.Arrays; import java.util.Collection; @@ -32,11 +31,10 @@ import static io.parsingdata.metal.util.EncodingFactory.enc; import static io.parsingdata.metal.util.EnvironmentFactory.stream; import static io.parsingdata.metal.util.TokenDefinitions.any; +import static java.nio.charset.StandardCharsets.US_ASCII; public class ComparisonExpressionSemanticsTest extends ParameterizedParse { - public static final Charset ASCII = Charset.forName("ISO646-US"); - @Parameters(name="{0} ({4})") public static Collection data() { return Arrays.asList(new Object[][] { @@ -48,8 +46,8 @@ public static Collection data() { { "1 < 1", numCom(1, ltNum(ref("a"))), stream(1, 1), enc(), false }, { "2 < 1", numCom(1, ltNum(ref("a"))), stream(1, 2), enc(), false }, { "1 < 2", numCom(1, ltNum(ref("a"))), stream(2, 1), enc(), true }, - { "\"abc\" == \"abc\"", strCom(3, eqStr(ref("a"))), stream("abcabc", ASCII), new Encoding(ASCII), true }, - { "\"abd\" == \"abc\"", strCom(3, eqStr(ref("a"))), stream("abcabd", ASCII), new Encoding(ASCII), false }, + { "\"abc\" == \"abc\"", strCom(3, eqStr(ref("a"))), stream("abcabc", US_ASCII), new Encoding(US_ASCII), true }, + { "\"abd\" == \"abc\"", strCom(3, eqStr(ref("a"))), stream("abcabd", US_ASCII), new Encoding(US_ASCII), false }, { "1 == 1(eq)", valCom(1, eq(ref("a"))), stream(1, 1), enc(), true }, { "2 == 1(eq)", valCom(1, eq(ref("a"))), stream(1, 2), enc(), false }, { "1 == 1 with self", valCom(1, eq(self, ref("a"))), stream(1, 1), enc(), true }, diff --git a/core/src/test/java/io/parsingdata/metal/data/selection/ByTokenTest.java b/core/src/test/java/io/parsingdata/metal/data/selection/ByTokenTest.java index a0314db2..2223ad04 100644 --- a/core/src/test/java/io/parsingdata/metal/data/selection/ByTokenTest.java +++ b/core/src/test/java/io/parsingdata/metal/data/selection/ByTokenTest.java @@ -223,6 +223,7 @@ public void getSubRef() throws IOException { final ParseResult result = composition.parse(stream(0), enc()); assertTrue(result.succeeded); final ParseItemList refs = ByToken.getAll(result.environment.order, smallSub1); + // should return the ParseGraph created by the Sub and the ParseRef that refers to the existing ParseItem assertEquals(2, refs.size); assertTrue(refs.head.isRef()); assertTrue(refs.tail.head.isGraph()); diff --git a/core/src/test/java/io/parsingdata/metal/util/ClassDefinition.java b/core/src/test/java/io/parsingdata/metal/util/ClassDefinition.java index 106bfa8d..c0676aba 100644 --- a/core/src/test/java/io/parsingdata/metal/util/ClassDefinition.java +++ b/core/src/test/java/io/parsingdata/metal/util/ClassDefinition.java @@ -34,7 +34,7 @@ public static void checkUtilityClass(Class c) throws ReflectiveOperationExcep assertTrue(Modifier.isPrivate(cons[0].getModifiers())); cons[0].setAccessible(true); cons[0].newInstance(); - for (Method m : c.getDeclaredMethods()) { + for (final Method m : c.getDeclaredMethods()) { assertTrue(Modifier.isStatic(m.getModifiers())); } } diff --git a/formats/src/main/java/io/parsingdata/metal/format/Callback.java b/formats/src/main/java/io/parsingdata/metal/format/Callback.java index ea9579d4..54f5a442 100644 --- a/formats/src/main/java/io/parsingdata/metal/format/Callback.java +++ b/formats/src/main/java/io/parsingdata/metal/format/Callback.java @@ -64,7 +64,7 @@ public OptionalValue execute(final Value value) { try { final int processed = inf.inflate(dataReceiver); out.write(dataReceiver, 0, processed); - } catch (DataFormatException e) { + } catch (final DataFormatException e) { return OptionalValue.empty(); } } diff --git a/formats/src/test/java/io/parsingdata/metal/CallbackTest.java b/formats/src/test/java/io/parsingdata/metal/CallbackTest.java index 9afd2106..d73261da 100644 --- a/formats/src/test/java/io/parsingdata/metal/CallbackTest.java +++ b/formats/src/test/java/io/parsingdata/metal/CallbackTest.java @@ -36,6 +36,14 @@ public void crc32Good() { assertArrayEquals(new byte[] { -74, 60, -5, -51 }, result.head.get().getValue()); } + @Test + public void inflateGood() { + final OptionalValueList result = inflate(con(0xcb, 0x4d, 0x2d, 0x49, 0xcc, 0x01, 0x00)).eval(stream(), enc()); + assertEquals(1, result.size); + assertTrue(result.head.isPresent()); + assertEquals("metal", result.head.get().asString()); + } + @Test public void inflateDataFormatError() { final OptionalValueList result = inflate(con(0xffffffff)).eval(stream(), enc()); From 49c37a3d0269293c2be9a314da44d921a4ede62c Mon Sep 17 00:00:00 2001 From: Jeroen van den Bos Date: Tue, 26 Jul 2016 00:13:41 +0200 Subject: [PATCH 14/17] 78: Edge case testing in the data package. --- .../io/parsingdata/metal/ParseGraphTest.java | 92 ++++++++++++++----- .../io/parsingdata/metal/ToStringTest.java | 16 ++++ .../metal/data/OptionalValueListTest.java | 34 +++++++ 3 files changed, 120 insertions(+), 22 deletions(-) create mode 100644 core/src/test/java/io/parsingdata/metal/data/OptionalValueListTest.java diff --git a/core/src/test/java/io/parsingdata/metal/ParseGraphTest.java b/core/src/test/java/io/parsingdata/metal/ParseGraphTest.java index f287a9b5..1269c82f 100644 --- a/core/src/test/java/io/parsingdata/metal/ParseGraphTest.java +++ b/core/src/test/java/io/parsingdata/metal/ParseGraphTest.java @@ -19,12 +19,21 @@ import io.parsingdata.metal.data.*; import io.parsingdata.metal.token.Token; import org.junit.Assert; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.ExpectedException; + +import java.io.IOException; import static io.parsingdata.metal.Shorthand.*; +import static io.parsingdata.metal.data.ParseGraph.EMPTY; +import static io.parsingdata.metal.data.ParseGraph.NONE; import static io.parsingdata.metal.util.EncodingFactory.enc; +import static io.parsingdata.metal.util.EnvironmentFactory.stream; import static io.parsingdata.metal.util.TokenDefinitions.any; +import static junit.framework.TestCase.assertNull; import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertThat; public class ParseGraphTest { @@ -81,23 +90,23 @@ private ParseGraph makeSimpleGraph() { @Test public void simple() { Assert.assertTrue(pg.head.isValue()); - Assert.assertEquals(h, pg.head); + assertEquals(h, pg.head); Assert.assertTrue(pg.tail.head.isValue()); - Assert.assertEquals(g, pg.tail.head); + assertEquals(g, pg.tail.head); Assert.assertTrue(pg.tail.tail.head.isGraph()); Assert.assertTrue(pg.tail.tail.head.asGraph().head.isValue()); - Assert.assertEquals(f, pg.tail.tail.head.asGraph().head); + assertEquals(f, pg.tail.tail.head.asGraph().head); Assert.assertTrue(pg.tail.tail.head.asGraph().tail.head.isGraph()); Assert.assertTrue(pg.tail.tail.head.asGraph().tail.head.asGraph().head.isValue()); - Assert.assertEquals(e, pg.tail.tail.head.asGraph().tail.head.asGraph().head); + assertEquals(e, pg.tail.tail.head.asGraph().tail.head.asGraph().head); Assert.assertTrue(pg.tail.tail.head.asGraph().tail.head.asGraph().tail.head.isValue()); - Assert.assertEquals(d, pg.tail.tail.head.asGraph().tail.head.asGraph().tail.head); + assertEquals(d, pg.tail.tail.head.asGraph().tail.head.asGraph().tail.head); Assert.assertTrue(pg.tail.tail.head.asGraph().tail.tail.head.isValue()); - Assert.assertEquals(c, pg.tail.tail.head.asGraph().tail.tail.head); + assertEquals(c, pg.tail.tail.head.asGraph().tail.tail.head); Assert.assertTrue(pg.tail.tail.tail.head.isValue()); - Assert.assertEquals(b, pg.tail.tail.tail.head); + assertEquals(b, pg.tail.tail.tail.head); Assert.assertTrue(pg.tail.tail.tail.tail.head.isValue()); - Assert.assertEquals(a, pg.tail.tail.tail.tail.head); + assertEquals(a, pg.tail.tail.tail.tail.head); } private ParseGraph makeCycleGraph() { @@ -112,14 +121,14 @@ private ParseGraph makeCycleGraph() { @Test public void cycle() { - Assert.assertEquals(2, pgc.size); + assertEquals(2, pgc.size); Assert.assertTrue(pgc.head.isGraph()); Assert.assertTrue(pgc.head.asGraph().head.isRef()); - Assert.assertEquals(pgc, pgc.head.asGraph().head.asRef().resolve(pgc)); + assertEquals(pgc, pgc.head.asGraph().head.asRef().resolve(pgc)); Assert.assertTrue(pgc.head.asGraph().tail.head.isValue()); - Assert.assertEquals(b, pgc.head.asGraph().tail.head); + assertEquals(b, pgc.head.asGraph().tail.head); Assert.assertTrue(pgc.tail.head.isValue()); - Assert.assertEquals(a, pgc.tail.head); + assertEquals(a, pgc.tail.head); } private ParseGraph makeLongGraph() { @@ -146,17 +155,17 @@ private ParseGraph makeLongGraph() { @Test public void listGraphs() { final ParseGraphList list = pgl.getGraphs(); - Assert.assertEquals(6, list.size); + assertEquals(6, list.size); } @Test public void firstValue() { Assert.assertTrue(pgl.containsValue()); - Assert.assertEquals(a, pgl.getLowestOffsetValue()); - Assert.assertEquals(f, pgl.head.asGraph().getLowestOffsetValue()); - Assert.assertEquals(a, pg.getLowestOffsetValue()); - Assert.assertEquals(c, pg.tail.tail.head.asGraph().getLowestOffsetValue()); - Assert.assertEquals(d, pg.tail.tail.head.asGraph().tail.head.asGraph().getLowestOffsetValue()); + assertEquals(a, pgl.getLowestOffsetValue()); + assertEquals(f, pgl.head.asGraph().getLowestOffsetValue()); + assertEquals(a, pg.getLowestOffsetValue()); + assertEquals(c, pg.tail.tail.head.asGraph().getLowestOffsetValue()); + assertEquals(d, pg.tail.tail.head.asGraph().tail.head.asGraph().getLowestOffsetValue()); } @Test @@ -164,15 +173,15 @@ public void testSimpleGetGraphAfter() { final ParseGraph graph = makeSimpleGraph(); final ParseItem itemB = graph.tail.tail.tail.head; Assert.assertTrue(itemB.isValue()); - Assert.assertEquals(b, itemB); + assertEquals(b, itemB); final ParseGraph subGraph = graph.getGraphAfter(itemB); Assert.assertTrue(subGraph.head.isValue()); - Assert.assertEquals(h, subGraph.head); + assertEquals(h, subGraph.head); Assert.assertTrue(subGraph.tail.head.isValue()); - Assert.assertEquals(g, subGraph.tail.head); + assertEquals(g, subGraph.tail.head); Assert.assertTrue(subGraph.tail.tail.head.isGraph()); Assert.assertTrue(subGraph.tail.tail.head.asGraph().head.isValue()); - Assert.assertEquals(f, subGraph.tail.tail.head.asGraph().head); + assertEquals(f, subGraph.tail.tail.head.asGraph().head); } @Test @@ -190,4 +199,43 @@ public void testLongToString() { assertThat(pgl.toString(), is("graph(graph(f(0x66), graph(terminator:Def), false), graph(e(0x65), graph(graph(graph(d(0x64), graph(terminator:Def), false), graph(c(0x63), graph(graph(terminator:Def), graph(graph(b(0x62), graph(terminator:Def), false), graph(terminator:Def), false), false), false), false), graph(a(0x61), graph(EMPTY), false), false), false), false)")); } + @Rule + public ExpectedException thrown = ExpectedException.none(); + + @Test + public void testNone() throws IOException { + assertEquals("None", NONE.toString()); + thrown.expect(IllegalStateException.class); + thrown.expectMessage("This placeholder may not be invoked."); + NONE.parse(stream(), enc()); + } + + @Test + public void testCloseNotBranched() { + thrown.expect(IllegalStateException.class); + thrown.expectMessage("Cannot close branch that is not open."); + EMPTY.closeBranch(); + } + + @Test + public void testAsValue() { + thrown.expect(UnsupportedOperationException.class); + thrown.expectMessage("Cannot convert ParseGraph to ParseValue."); + EMPTY.asValue(); + } + + @Test + public void testAsRef() { + thrown.expect(UnsupportedOperationException.class); + thrown.expectMessage("Cannot convert ParseGraph to ParseRef."); + EMPTY.asRef(); + } + + @Test + public void testCurrent() { + assertNull(EMPTY.current()); + assertNull(EMPTY.add(new ParseRef(0, NONE)).current()); + assertNull(EMPTY.addBranch(NONE).current()); + } + } diff --git a/core/src/test/java/io/parsingdata/metal/ToStringTest.java b/core/src/test/java/io/parsingdata/metal/ToStringTest.java index 07091200..aa5aed45 100644 --- a/core/src/test/java/io/parsingdata/metal/ToStringTest.java +++ b/core/src/test/java/io/parsingdata/metal/ToStringTest.java @@ -17,11 +17,15 @@ package io.parsingdata.metal; import io.parsingdata.metal.data.Environment; +import io.parsingdata.metal.data.OptionalValueList; import io.parsingdata.metal.data.ParseGraph; +import io.parsingdata.metal.data.ParseValue; import io.parsingdata.metal.encoding.ByteOrder; import io.parsingdata.metal.encoding.Encoding; import io.parsingdata.metal.encoding.Sign; import io.parsingdata.metal.expression.Expression; +import io.parsingdata.metal.expression.value.OptionalValue; +import io.parsingdata.metal.expression.value.Value; import io.parsingdata.metal.expression.value.ValueExpression; import io.parsingdata.metal.token.StructSink; import io.parsingdata.metal.token.Token; @@ -32,6 +36,10 @@ import java.nio.charset.Charset; import static io.parsingdata.metal.Shorthand.*; +import static io.parsingdata.metal.data.OptionalValueList.EMPTY; +import static io.parsingdata.metal.data.ParseGraph.NONE; +import static io.parsingdata.metal.util.EncodingFactory.enc; +import static io.parsingdata.metal.util.EnvironmentFactory.stream; import static io.parsingdata.metal.util.TokenDefinitions.any; import static org.junit.Assert.assertEquals; @@ -97,4 +105,12 @@ public void encoding() { assertEquals("Encoding(UNSIGNED,US-ASCII,LITTLE_ENDIAN)", new Encoding(ByteOrder.LITTLE_ENDIAN).toString()); } + @Test + public void data() { + assertEquals("stream: InMemoryByteStream(2); offset: 0; order: graph(EMPTY)", stream(1, 2).toString()); + final OptionalValue ov1 = OptionalValue.of(new ParseValue("name", NONE, 0, new byte[] { 1, 2 }, enc())); + final OptionalValue ov2 = OptionalValue.of(new Value(new byte[] { 3 }, enc())); + assertEquals(">OptionalValue(0x03)>OptionalValue(name(0x0102))", EMPTY.add(ov1).add(ov2).toString()); + } + } diff --git a/core/src/test/java/io/parsingdata/metal/data/OptionalValueListTest.java b/core/src/test/java/io/parsingdata/metal/data/OptionalValueListTest.java new file mode 100644 index 00000000..7c687d38 --- /dev/null +++ b/core/src/test/java/io/parsingdata/metal/data/OptionalValueListTest.java @@ -0,0 +1,34 @@ +/* + * Copyright 2013-2016 Netherlands Forensic Institute + * + * Licensed 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 io.parsingdata.metal.data; + +import io.parsingdata.metal.expression.value.OptionalValue; +import io.parsingdata.metal.expression.value.Value; +import org.junit.Test; + +import static io.parsingdata.metal.data.OptionalValueList.EMPTY; +import static io.parsingdata.metal.util.EncodingFactory.enc; +import static junit.framework.TestCase.assertTrue; + +public class OptionalValueListTest { + + @Test + public void containsEmptyInTail() { + assertTrue(EMPTY.add(OptionalValue.empty()).add(OptionalValue.of(new Value(new byte[] { 1, 2 }, enc()))).containsEmpty()); + } + +} \ No newline at end of file From 751e9594edccbcd6351c543d2f07c3746fce1bf0 Mon Sep 17 00:00:00 2001 From: Roel van Dijk Date: Tue, 26 Jul 2016 08:07:32 +0200 Subject: [PATCH 15/17] #78: Add some tests for expression.value package. --- .../expression/value/ConstantFactory.java | 4 +- .../parsingdata/metal/UtilityClassTest.java | 2 + .../expression/value/OptionalValueTest.java | 56 +++++++++++++++++++ .../metal/util/ClassDefinition.java | 26 ++++++--- 4 files changed, 78 insertions(+), 10 deletions(-) create mode 100644 core/src/test/java/io/parsingdata/metal/expression/value/OptionalValueTest.java diff --git a/core/src/main/java/io/parsingdata/metal/expression/value/ConstantFactory.java b/core/src/main/java/io/parsingdata/metal/expression/value/ConstantFactory.java index 1daa1338..c9380b2b 100644 --- a/core/src/main/java/io/parsingdata/metal/expression/value/ConstantFactory.java +++ b/core/src/main/java/io/parsingdata/metal/expression/value/ConstantFactory.java @@ -22,7 +22,9 @@ import java.math.BigInteger; import java.util.BitSet; -public class ConstantFactory { +public final class ConstantFactory { + + private ConstantFactory() {} public static Value createFromNumeric(final BigInteger value, final Encoding enc) { return new Value(compact(value.toByteArray(), enc.isSigned()), setToBE(enc)); diff --git a/core/src/test/java/io/parsingdata/metal/UtilityClassTest.java b/core/src/test/java/io/parsingdata/metal/UtilityClassTest.java index 65affa2d..bb561d75 100644 --- a/core/src/test/java/io/parsingdata/metal/UtilityClassTest.java +++ b/core/src/test/java/io/parsingdata/metal/UtilityClassTest.java @@ -20,6 +20,7 @@ import io.parsingdata.metal.data.transformation.Reversal; import io.parsingdata.metal.encoding.ByteOrder; import io.parsingdata.metal.encoding.Sign; +import io.parsingdata.metal.expression.value.ConstantFactory; import io.parsingdata.metal.token.Token; import org.junit.Test; @@ -40,6 +41,7 @@ public void utilityClasses() throws ReflectiveOperationException { checkUtilityClass(ByOffset.class); checkUtilityClass(ByToken.class); checkUtilityClass(ByType.class); + checkUtilityClass(ConstantFactory.class); } // The method is used to print tokens for composing Tokens' toString() diff --git a/core/src/test/java/io/parsingdata/metal/expression/value/OptionalValueTest.java b/core/src/test/java/io/parsingdata/metal/expression/value/OptionalValueTest.java new file mode 100644 index 00000000..47e600f9 --- /dev/null +++ b/core/src/test/java/io/parsingdata/metal/expression/value/OptionalValueTest.java @@ -0,0 +1,56 @@ +/* + * Copyright 2013-2016 Netherlands Forensic Institute + * + * Licensed 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 io.parsingdata.metal.expression.value; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; + +import java.util.NoSuchElementException; + +import static io.parsingdata.metal.util.EncodingFactory.enc; +import static junit.framework.TestCase.assertFalse; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +public class OptionalValueTest { + + private static final Value VALUE = new Value(new byte[] { 1 }, enc()); + private static final OptionalValue OPTIONAL_VALUE = OptionalValue.of(VALUE); + private static final OptionalValue EMPTY = OptionalValue.empty(); + + @Rule + public ExpectedException thrown = ExpectedException.none(); + + @Test + public void withValue() { + assertTrue(OPTIONAL_VALUE.isPresent()); + assertEquals("OptionalValue(0x01)", OPTIONAL_VALUE.toString()); + assertEquals(OPTIONAL_VALUE.get(), VALUE); + } + + @Test + public void withoutValue() { + assertFalse(EMPTY.isPresent()); + assertEquals("OptionalValue(empty)", EMPTY.toString()); + + thrown.expectMessage("OptionalValue instance is empty."); + thrown.expect(NoSuchElementException.class); + EMPTY.get(); + } + +} \ No newline at end of file diff --git a/core/src/test/java/io/parsingdata/metal/util/ClassDefinition.java b/core/src/test/java/io/parsingdata/metal/util/ClassDefinition.java index c0676aba..5699f5d9 100644 --- a/core/src/test/java/io/parsingdata/metal/util/ClassDefinition.java +++ b/core/src/test/java/io/parsingdata/metal/util/ClassDefinition.java @@ -16,26 +16,34 @@ package io.parsingdata.metal.util; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + import java.lang.reflect.Constructor; import java.lang.reflect.Method; import java.lang.reflect.Modifier; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - public class ClassDefinition { - // Check that a class is final, has a single private constructor and that all - // its declared methods are static. public static void checkUtilityClass(Class c) throws ReflectiveOperationException { - assertTrue(Modifier.isFinal(c.getModifiers())); + final String simpleName = c.getSimpleName(); + // class is final + assertTrue(simpleName + " should be final", Modifier.isFinal(c.getModifiers())); + + // has one constructor final Constructor[] cons = c.getDeclaredConstructors(); - assertEquals(1, cons.length); - assertTrue(Modifier.isPrivate(cons[0].getModifiers())); + assertEquals(simpleName + " should have exactly 1 constructor", 1, cons.length); + + // which is private + assertTrue(simpleName + " should have a private constructor", Modifier.isPrivate(cons[0].getModifiers())); + + // call it for coverage cons[0].setAccessible(true); cons[0].newInstance(); + + // check that all declared methods are static for (final Method m : c.getDeclaredMethods()) { - assertTrue(Modifier.isStatic(m.getModifiers())); + assertTrue("method '" + m.getName() + "' in " + simpleName + " should be static", Modifier.isStatic(m.getModifiers())); } } From 624c0e18fb3dd6cb46b4c09bbcf9a56ac49d0532 Mon Sep 17 00:00:00 2001 From: Jeroen van den Bos Date: Tue, 26 Jul 2016 11:11:54 +0200 Subject: [PATCH 16/17] #78: Data package at 100%. --- .../io/parsingdata/metal/data/ParseGraph.java | 1 - .../io/parsingdata/metal/ToStringTest.java | 25 +++++++++------ .../metal/data/ParseValueListTest.java | 31 +++++++++++++++++++ 3 files changed, 47 insertions(+), 10 deletions(-) create mode 100644 core/src/test/java/io/parsingdata/metal/data/ParseValueListTest.java diff --git a/core/src/main/java/io/parsingdata/metal/data/ParseGraph.java b/core/src/main/java/io/parsingdata/metal/data/ParseGraph.java index 408b355e..cbc91ec8 100644 --- a/core/src/main/java/io/parsingdata/metal/data/ParseGraph.java +++ b/core/src/main/java/io/parsingdata/metal/data/ParseGraph.java @@ -50,7 +50,6 @@ private ParseGraph(final Token definition) { private ParseGraph(final ParseItem head, final ParseGraph tail, final Token definition, final boolean branched) { this.head = checkNotNull(head, "head"); - if (head.isValue() && branched) { throw new IllegalArgumentException("Argument branch cannot be true when head contains a ParseValue."); } this.tail = checkNotNull(tail, "tail"); this.branched = branched; this.definition = checkNotNull(definition, "definition"); diff --git a/core/src/test/java/io/parsingdata/metal/ToStringTest.java b/core/src/test/java/io/parsingdata/metal/ToStringTest.java index aa5aed45..34030ebf 100644 --- a/core/src/test/java/io/parsingdata/metal/ToStringTest.java +++ b/core/src/test/java/io/parsingdata/metal/ToStringTest.java @@ -16,10 +16,7 @@ package io.parsingdata.metal; -import io.parsingdata.metal.data.Environment; -import io.parsingdata.metal.data.OptionalValueList; -import io.parsingdata.metal.data.ParseGraph; -import io.parsingdata.metal.data.ParseValue; +import io.parsingdata.metal.data.*; import io.parsingdata.metal.encoding.ByteOrder; import io.parsingdata.metal.encoding.Encoding; import io.parsingdata.metal.encoding.Sign; @@ -33,7 +30,7 @@ import org.junit.Before; import org.junit.Test; -import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; import static io.parsingdata.metal.Shorthand.*; import static io.parsingdata.metal.data.OptionalValueList.EMPTY; @@ -101,16 +98,26 @@ private void checkToken(final Token t) { public void encoding() { assertEquals("Encoding(UNSIGNED,US-ASCII,BIG_ENDIAN)", new Encoding().toString()); assertEquals("Encoding(SIGNED,US-ASCII,BIG_ENDIAN)", new Encoding(Sign.SIGNED).toString()); - assertEquals("Encoding(UNSIGNED,UTF-8,BIG_ENDIAN)", new Encoding(Charset.forName("UTF-8")).toString()); + assertEquals("Encoding(UNSIGNED,UTF-8,BIG_ENDIAN)", new Encoding(StandardCharsets.UTF_8).toString()); assertEquals("Encoding(UNSIGNED,US-ASCII,LITTLE_ENDIAN)", new Encoding(ByteOrder.LITTLE_ENDIAN).toString()); } @Test public void data() { - assertEquals("stream: InMemoryByteStream(2); offset: 0; order: graph(EMPTY)", stream(1, 2).toString()); - final OptionalValue ov1 = OptionalValue.of(new ParseValue("name", NONE, 0, new byte[] { 1, 2 }, enc())); + final Environment environment = stream(1, 2); + final String envString = "stream: InMemoryByteStream(2); offset: 0; order: graph(EMPTY)"; + assertEquals(envString, environment.toString()); + final ParseResult result = new ParseResult(true, environment); + assertEquals("ParseResult(true, " + environment + ")", result.toString()); + final ParseValue pv1 = new ParseValue("name", NONE, 0, new byte[] { 1, 2 }, enc()); + final String pv1String = "name(0x0102)"; + final OptionalValue ov1 = OptionalValue.of(pv1); final OptionalValue ov2 = OptionalValue.of(new Value(new byte[] { 3 }, enc())); - assertEquals(">OptionalValue(0x03)>OptionalValue(name(0x0102))", EMPTY.add(ov1).add(ov2).toString()); + assertEquals(">OptionalValue(0x03)>OptionalValue(" + pv1String + ")", EMPTY.add(ov1).add(ov2).toString()); + final ParseValue pv2 = new ParseValue("two", NONE, 0, new byte[] { 3, 4 }, enc()); + final String pv2String = "two(0x0304)"; + assertEquals(">" + pv2String + ">" + pv1String, ParseItemList.create(pv1).add(pv2).toString()); + assertEquals(">" + pv2String + ">" + pv1String, ParseValueList.create(pv1).add(pv2).toString()); } } diff --git a/core/src/test/java/io/parsingdata/metal/data/ParseValueListTest.java b/core/src/test/java/io/parsingdata/metal/data/ParseValueListTest.java new file mode 100644 index 00000000..6c4a270b --- /dev/null +++ b/core/src/test/java/io/parsingdata/metal/data/ParseValueListTest.java @@ -0,0 +1,31 @@ +/* + * Copyright 2013-2016 Netherlands Forensic Institute + * + * Licensed 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 io.parsingdata.metal.data; + +import org.junit.Test; + +import static io.parsingdata.metal.data.ParseValueList.EMPTY; +import static org.junit.Assert.assertEquals; + +public class ParseValueListTest { + + @Test + public void getValuesSincePrefixOnEmpty() { + assertEquals(EMPTY, EMPTY.getValuesSincePrefix(null)); + } + +} \ No newline at end of file From 6fe1b0445754b0d8c21ebbb9bc24b8c3976edc31 Mon Sep 17 00:00:00 2001 From: Jeroen van den Bos Date: Tue, 26 Jul 2016 13:57:40 +0200 Subject: [PATCH 17/17] #78: Data.selection package at 100%. --- .../metal/data/selection/ByNameTest.java | 36 +++++++++++++++++ .../metal/data/selection/ByOffsetTest.java | 38 ++++++++++++++++++ .../metal/data/selection/ByTypeTest.java | 40 +++++++++++++++++++ 3 files changed, 114 insertions(+) create mode 100644 core/src/test/java/io/parsingdata/metal/data/selection/ByNameTest.java create mode 100644 core/src/test/java/io/parsingdata/metal/data/selection/ByOffsetTest.java create mode 100644 core/src/test/java/io/parsingdata/metal/data/selection/ByTypeTest.java diff --git a/core/src/test/java/io/parsingdata/metal/data/selection/ByNameTest.java b/core/src/test/java/io/parsingdata/metal/data/selection/ByNameTest.java new file mode 100644 index 00000000..32db5ff9 --- /dev/null +++ b/core/src/test/java/io/parsingdata/metal/data/selection/ByNameTest.java @@ -0,0 +1,36 @@ +/* + * Copyright 2013-2016 Netherlands Forensic Institute + * + * Licensed 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 io.parsingdata.metal.data.selection; + +import io.parsingdata.metal.data.ParseGraph; +import org.junit.Test; + +import static junit.framework.TestCase.assertNull; + +public class ByNameTest { + + @Test + public void getValueOnEmpty() { + assertNull(ByName.getValue(ParseGraph.EMPTY, "name")); + } + + @Test + public void getValueOnBranchedEmpty() { + assertNull(ByName.getValue(ParseGraph.EMPTY.addBranch(ParseGraph.NONE), "name")); + } + +} diff --git a/core/src/test/java/io/parsingdata/metal/data/selection/ByOffsetTest.java b/core/src/test/java/io/parsingdata/metal/data/selection/ByOffsetTest.java new file mode 100644 index 00000000..d8bee34b --- /dev/null +++ b/core/src/test/java/io/parsingdata/metal/data/selection/ByOffsetTest.java @@ -0,0 +1,38 @@ +/* + * Copyright 2013-2016 Netherlands Forensic Institute + * + * Licensed 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 io.parsingdata.metal.data.selection; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; + +import static io.parsingdata.metal.data.ParseGraph.EMPTY; +import static io.parsingdata.metal.data.selection.ByOffset.getLowestOffsetValue; + +public class ByOffsetTest { + + @Rule + public ExpectedException thrown = ExpectedException.none(); + + @Test + public void getLowestOffsetWithoutValue() { + thrown.expect(IllegalStateException.class); + thrown.expectMessage("Cannot determine lowest offset if graph does not contain a value."); + getLowestOffsetValue(EMPTY); + } + +} diff --git a/core/src/test/java/io/parsingdata/metal/data/selection/ByTypeTest.java b/core/src/test/java/io/parsingdata/metal/data/selection/ByTypeTest.java new file mode 100644 index 00000000..b1966397 --- /dev/null +++ b/core/src/test/java/io/parsingdata/metal/data/selection/ByTypeTest.java @@ -0,0 +1,40 @@ +/* + * Copyright 2013-2016 Netherlands Forensic Institute + * + * Licensed 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 io.parsingdata.metal.data.selection; + +import io.parsingdata.metal.data.ParseRef; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; + +import static io.parsingdata.metal.data.ParseGraph.EMPTY; +import static io.parsingdata.metal.data.ParseGraph.NONE; +import static io.parsingdata.metal.data.selection.ByType.getRefs; + +public class ByTypeTest { + + @Rule + public ExpectedException thrown = ExpectedException.none(); + + @Test + public void unresolvableRef() { + thrown.expect(IllegalStateException.class); + thrown.expectMessage("A ref must point to an existing graph."); + getRefs(EMPTY.add(new ParseRef(0, NONE))); + } + +}