Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fixes GH-123: XML report must always produce a valid XML! Will reopen…
… if the issue happens again. For now, guard against invalid strings.
- Loading branch information
Showing
7 changed files
with
174 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
53 changes: 53 additions & 0 deletions
53
...rc/main/java/com/carrotsearch/ant/tasks/junit4/listeners/antxml/XmlStringTransformer.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
package com.carrotsearch.ant.tasks.junit4.listeners.antxml; | ||
|
||
import org.simpleframework.xml.transform.Transform; | ||
|
||
final class XmlStringTransformer implements Transform<String> { | ||
private final StringBuilder buffer = new StringBuilder(); | ||
|
||
@Override | ||
public String read(String value) throws Exception { | ||
return value; | ||
} | ||
|
||
@Override | ||
public String write(String value) throws Exception { | ||
if (!isMappableXmlText(value)) { | ||
return remap(value); | ||
} | ||
return value; | ||
} | ||
|
||
private String remap(CharSequence value) { | ||
buffer.setLength(0); | ||
final int length = value.length(); | ||
for (int i = 0; i < length; i = Character.offsetByCodePoints(value, i, 1)) { | ||
int cp = Character.codePointAt(value, i); | ||
if ((cp >= 0x20 && cp <= 0x00D7FF) || | ||
(cp < 0x20 && (cp == 0x09 || cp == 0x0A || cp == 0x0D)) || | ||
(cp >= 0xE000 && cp <= 0x00FFFD) || | ||
(cp >= 0x10000 && cp <= 0x10FFFF)) { | ||
buffer.appendCodePoint(cp); | ||
} else { | ||
buffer.append(/* Replacement char. */ "\ufffd"); | ||
} | ||
} | ||
return buffer.toString(); | ||
} | ||
|
||
private static boolean isMappableXmlText(CharSequence value) { | ||
final int length = value.length(); | ||
for (int i = 0; i < length; i = Character.offsetByCodePoints(value, i, 1)) { | ||
int cp = Character.codePointAt(value, i); | ||
if ((cp >= 0x20 && cp <= 0x00D7FF) || | ||
(cp < 0x20 && (cp == 0x09 || cp == 0x0A || cp == 0x0D)) || | ||
(cp >= 0xE000 && cp <= 0x00FFFD) || | ||
(cp >= 0x10000 && cp <= 0x10FFFF)) { | ||
// Ok, mappable XML character. | ||
} else { | ||
return false; | ||
} | ||
} | ||
return true; | ||
} | ||
} |
76 changes: 76 additions & 0 deletions
76
junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/TestXmlStringsRoundtrip.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
package com.carrotsearch.ant.tasks.junit4; | ||
|
||
import java.io.ByteArrayInputStream; | ||
import java.io.ByteArrayOutputStream; | ||
import java.util.Arrays; | ||
import java.util.Random; | ||
|
||
import javax.xml.parsers.DocumentBuilder; | ||
import javax.xml.parsers.DocumentBuilderFactory; | ||
|
||
import org.junit.Test; | ||
import org.simpleframework.xml.Attribute; | ||
import org.simpleframework.xml.Element; | ||
import org.simpleframework.xml.Root; | ||
import org.simpleframework.xml.core.Persister; | ||
import org.simpleframework.xml.transform.RegistryMatcher; | ||
import org.xml.sax.SAXParseException; | ||
|
||
import com.carrotsearch.ant.tasks.junit4.listeners.antxml.XmlStringTransformerAccess; | ||
import com.carrotsearch.randomizedtesting.RandomizedTest; | ||
import com.carrotsearch.randomizedtesting.annotations.Repeat; | ||
import com.google.common.base.Charsets; | ||
|
||
public class TestXmlStringsRoundtrip extends RandomizedTest { | ||
@Test | ||
@Repeat(iterations = 100) | ||
public void testRoundTrip() throws Exception { | ||
char[] chars = new char[randomIntBetween(0, 1024)]; | ||
Random random = getRandom(); | ||
for (int i = 0; i < chars.length; i++) { | ||
chars[i] = (char) random.nextInt(); | ||
} | ||
|
||
check(chars); | ||
} | ||
|
||
@Test | ||
public void testBoundary() throws Exception { | ||
check(new char [] {'a', 0x0000, 'z'}); | ||
check(new char [] {'a', 0x0001, 'z'}); | ||
} | ||
|
||
@Root | ||
public static class Model { | ||
@Attribute | ||
public String attribute; | ||
|
||
@Element(name = "system-out", data = true, required = true) | ||
public String contents = ""; | ||
|
||
public Model() {} | ||
|
||
public Model(String s) { | ||
attribute = contents = s; | ||
} | ||
} | ||
|
||
private void check(char[] chars) throws Exception { | ||
ByteArrayOutputStream baos = new ByteArrayOutputStream(); | ||
|
||
RegistryMatcher rm = new RegistryMatcher(); | ||
rm.bind(String.class, XmlStringTransformerAccess.getInstance()); | ||
Persister persister = new Persister(rm); | ||
persister.write(new Model(new String(chars)), baos); | ||
|
||
DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance(); | ||
DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder(); | ||
try { | ||
docBuilder.parse(new ByteArrayInputStream(baos.toByteArray())); | ||
} catch (SAXParseException e) { | ||
System.out.println("Input: " + Arrays.toString(chars)); | ||
System.out.println("XML: " + new String(baos.toByteArray(), Charsets.UTF_8)); | ||
throw e; | ||
} | ||
} | ||
} |
19 changes: 15 additions & 4 deletions
19
junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestAntXmlReport.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,19 +1,30 @@ | ||
package com.carrotsearch.ant.tasks.junit4.it; | ||
|
||
|
||
import java.io.File; | ||
|
||
import javax.xml.parsers.DocumentBuilder; | ||
import javax.xml.parsers.DocumentBuilderFactory; | ||
|
||
import org.junit.Assert; | ||
import org.junit.Test; | ||
|
||
|
||
public class TestAntXmlReport extends JUnit4XmlTestBase { | ||
|
||
@Test | ||
public void antxml() { | ||
public void antxml() throws Exception { | ||
super.executeTarget("antxml"); | ||
|
||
// Simple check for existence. | ||
Assert.assertTrue( | ||
new File(getProject().getBaseDir(), "ant-xmls/TEST-com.carrotsearch.ant.tasks.junit4.tests.TestBeforeClassError.xml").length() > 0); | ||
|
||
// Attempt to read and parse. | ||
File basedir = new File(getProject().getBaseDir(), "ant-xmls"); | ||
for (File f : basedir.listFiles()) { | ||
if (f.isFile() && f.getName().endsWith(".xml")) { | ||
DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance(); | ||
DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder(); | ||
docBuilder.parse(f); | ||
} | ||
} | ||
} | ||
} |
7 changes: 7 additions & 0 deletions
7
...t/java/com/carrotsearch/ant/tasks/junit4/listeners/antxml/XmlStringTransformerAccess.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
package com.carrotsearch.ant.tasks.junit4.listeners.antxml; | ||
|
||
public class XmlStringTransformerAccess { | ||
public static XmlStringTransformer getInstance() { | ||
return new XmlStringTransformer(); | ||
} | ||
} |
13 changes: 13 additions & 0 deletions
13
...t4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/TestInvalidUtfCharacter.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
package com.carrotsearch.ant.tasks.junit4.tests; | ||
|
||
import org.junit.Test; | ||
|
||
public class TestInvalidUtfCharacter { | ||
@Test | ||
public void emitInvalidCharacter() throws Exception { | ||
String msg = "Invalid char: >\u0002< >\u0000<"; | ||
System.out.println(msg); | ||
System.out.flush(); | ||
throw new Exception(msg); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters