diff --git a/metamorph/build.gradle b/metamorph/build.gradle index ed537f1a5..5fd1c5121 100644 --- a/metamorph/build.gradle +++ b/metamorph/build.gradle @@ -25,6 +25,9 @@ dependencies { implementation project(':metafacture-mangling') implementation project(':metafacture-javaintegration') implementation 'org.slf4j:slf4j-api:1.7.21' + testImplementation project(':metafacture-io') + testImplementation project(':metafacture-json') + testImplementation project(':metafacture-strings') testImplementation 'junit:junit:4.12' testImplementation 'org.mockito:mockito-core:2.5.5' testRuntimeOnly 'org.slf4j:slf4j-simple:1.7.21' @@ -45,4 +48,6 @@ test { showStandardStreams = true exceptionFormat = 'full' } + + systemProperties System.properties } diff --git a/metamorph/src/test/java/org/metafacture/metamorph/Issue366Test.java b/metamorph/src/test/java/org/metafacture/metamorph/Issue366Test.java new file mode 100644 index 000000000..bed96a453 --- /dev/null +++ b/metamorph/src/test/java/org/metafacture/metamorph/Issue366Test.java @@ -0,0 +1,96 @@ +package org.metafacture.metamorph; + +import org.metafacture.io.LineReader; +import org.metafacture.io.ObjectJavaIoWriter; +import org.metafacture.json.JsonDecoder; +import org.metafacture.json.JsonEncoder; +import org.metafacture.strings.StringReader; + +import org.junit.Assert; +import org.junit.Test; + +import java.io.StringWriter; +import java.io.Writer; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.atomic.LongAdder; +import java.util.stream.IntStream; + +public final class Issue366Test { + + private static final String INPUT = "{\"10012\":{\"a\":\"V\"}}"; + + private static final String[] OUTPUT = new String[]{ + "{\"r\":{\"k\":\"K\",\"v\":\"V\"}}\n", + "{\"r\":{\"v\":\"V\",\"k\":\"K\"}}\n", + "{\"r\":{\"k\":\"K\",\"v\":\"V\"}}\n", + "{\"r\":{\"k\":\"K\",\"v\":\"V\"}}\n" + }; + + private static final String MORPH = "" + + "\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + ""; + + private static final int OPTION = Integer.valueOf(System.getProperty("issue366.option", "0")); + + private static final int ITER = Integer.valueOf(System.getProperty("issue366.iter", "10")); + + private final Map outcome = new HashMap<>(); + + private final Object[] args = new String[]{".a", "?2", "??"}; + // Either one of these replacements avoids the issue: + private final Object[] opts = new String[]{"", "??", "?2"}; + + @Test + public void testTransform() { + if (OPTION > args.length) { + throw new RuntimeException("Invalid option: " + OPTION); + } + else if (OPTION > 0) { + args[OPTION - 1] = opts[OPTION - 1]; + } + + final String morph = String.format(MORPH, args); + System.out.println(morph); + + IntStream.range(0, ITER).forEach(i -> transform(morph)); + outcome.forEach((k, v) -> System.err.print(v.sum() + "/" + ITER + ": " + k)); + + Assert.assertEquals(1, outcome.size()); + Assert.assertEquals(OUTPUT[OPTION], outcome.keySet().iterator().next()); + } + + private void transform(final String morph) { + final StringReader reader = new StringReader(); + final Writer writer = new StringWriter(); + + reader + .setReceiver(new LineReader()) + .setReceiver(new JsonDecoder()) + .setReceiver(new Metamorph(new java.io.StringReader(morph))) + .setReceiver(new JsonEncoder()) + // ObjectJavaIoWriter in org.metafacture.io has been deprecated + .setReceiver(new ObjectJavaIoWriter<>(writer)); + + try { + reader.process(INPUT); + reader.closeStream(); + + outcome.computeIfAbsent(writer.toString(), k -> new LongAdder()).increment(); + } + catch (Exception e) { + throw new RuntimeException(e); + } + } + +}