Skip to content
Permalink
Browse files

Fix JENKINS-17521, JENKINS-44527

  • Loading branch information...
slide committed Jun 1, 2017
1 parent 1c680b0 commit 66d639066e5463302844be20e11b9d1176052f7a
@@ -11,6 +11,7 @@
<packaging>hpi</packaging>
<version>0.21-SNAPSHOT</version>
<name>Jenkins NUnit plugin</name>
<description>Allows handling NUnit results similar to how JUnit results are handled</description>
<url>http://wiki.jenkins-ci.org/display/JENKINS/NUnit+Plugin</url>

<properties>
@@ -105,14 +106,14 @@
<repositories>
<repository>
<id>repo.jenkins-ci.org</id>
<url>http://repo.jenkins-ci.org/public/</url>
<url>https://repo.jenkins-ci.org/public/</url>
</repository>
</repositories>

<pluginRepositories>
<pluginRepository>
<id>repo.jenkins-ci.org</id>
<url>http://repo.jenkins-ci.org/public/</url>
<url>https://repo.jenkins-ci.org/public/</url>
</pluginRepository>
</pluginRepositories>
</project>
@@ -0,0 +1,72 @@
package hudson.plugins.nunit;

import org.apache.commons.io.input.ProxyInputStream;

import java.io.IOException;
import java.io.InputStream;

/**
* Created by acearl on 6/1/2017.
*/
public class InvalidXmlInputStream extends ProxyInputStream {
private final byte replacement;

/**
* Constructs a new ProxyInputStream.
*
* @param delegate the InputStream to delegate to
*/
public InvalidXmlInputStream(InputStream delegate, char replacement) {
super(delegate);
this.replacement = (byte)replacement;
}

private boolean isValid(int input) {
return ((input == 0x9) || (input == 0xA) || (input == 0xD) ||
((input >= 0x20) && (input <= 0xD7FF)) ||
((input >= 0xE000) && (input <= 0xFFFD)) ||
((input >= 0x10000) && (input <= 0x10FFFF)));
}

/**
* Invokes the delegate's <code>read()</code> method, detecting and skipping invalid xml characters
*
* @return the byte read (excluding invalid xml characters) or -1 if the end of stream
* @throws IOException if an I/O error occurs
*/
@Override
public int read() throws IOException {
int read = super.read();
if(read >= 0 && !isValid(read)) {
return (int)replacement;
}
return read;
}

/**
* Invokes the delegate's <code>read(byte[], int, int)</code> method, detecting and skipping invalid xml.
*
* @param cbuf the buffer to read the bytes into
* @param off The start offset
* @param len The number of bytes to read
* @return the number of bytes read or -1 if the end of stream
* @throws IOException if an I/O error occurs
*/
@Override
public int read(byte[] cbuf, int off, int len) throws IOException {
int read = super.read(cbuf, off, len);

if (read == -1) {
return -1;
}

int pos = off - 1;
for (int readPos = off; readPos < off + read; readPos++) {
if (!isValid(cbuf[readPos])) {
cbuf[readPos] = replacement;
}
pos++;
}
return pos - off + 1;
}
}
@@ -19,6 +19,8 @@
import javax.xml.transform.stream.StreamSource;

import org.apache.commons.io.input.BOMInputStream;
import hudson.Functions;
import org.apache.commons.lang.StringUtils;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
@@ -40,6 +42,7 @@
public static final String JUNIT_FILE_POSTFIX = ".xml";
public static final String JUNIT_FILE_PREFIX = "TEST-";

private static final int MAX_PATH_WINDOWS = 260;
private static final String TEMP_JUNIT_FILE_STR = "temp-junit.xml";
public static final String NUNIT_TO_JUNIT_XSLFILE_STR = "nunit-to-junit.xsl";

@@ -67,7 +70,7 @@ public void transform(InputStream nunitFileStream, File junitOutputPath) throws
File junitTargetFile = new File(junitOutputPath, TEMP_JUNIT_FILE_STR);
FileOutputStream fileOutputStream = new FileOutputStream(junitTargetFile);
try {
BOMInputStream is = new BOMInputStream(nunitFileStream);
InputStream is = new InvalidXmlInputStream(new BOMInputStream(nunitFileStream), '?');
nunitTransformer.transform(new StreamSource(is), new StreamResult(fileOutputStream));
} finally {
fileOutputStream.close();
@@ -109,8 +112,16 @@ private void splitJUnitFile(File junitFile, File junitOutputPath) throws SAXExce
for (int i = 0; i < elementsByTagName.getLength(); i++) {
Element element = (Element) elementsByTagName.item(i);
DOMSource source = new DOMSource(element);
String filename = JUNIT_FILE_PREFIX + element.getAttribute("name").replaceAll(ILLEGAL_FILE_CHARS_REGEX, "_") + "_" + transformCount + "_" + i + JUNIT_FILE_POSTFIX;
String fileNamePostfix = "_" + transformCount + "_" + i + JUNIT_FILE_POSTFIX;
String filename = JUNIT_FILE_PREFIX + element.getAttribute("name").replaceAll(ILLEGAL_FILE_CHARS_REGEX, "_") + fileNamePostfix;
File junitOutputFile = new File(junitOutputPath, filename);

// check for really long file names
if(junitOutputFile.toString().length() >= MAX_PATH_WINDOWS && Functions.isWindows()) {
int maxMiddleLength = MAX_PATH_WINDOWS - JUNIT_FILE_PREFIX.length() - fileNamePostfix.length() - junitOutputPath.toString().length();
filename = JUNIT_FILE_PREFIX + StringUtils.left(element.getAttribute("name").replaceAll(ILLEGAL_FILE_CHARS_REGEX, "_"), maxMiddleLength) + fileNamePostfix;
junitOutputFile = new File(junitOutputPath, filename);
}
FileOutputStream fileOutputStream = new FileOutputStream(junitOutputFile);
try {
StreamResult result = new StreamResult(fileOutputStream);
@@ -85,7 +85,6 @@ STACK TRACE:
</testcase>
</xsl:for-each>
</testsuite>
<!-- </redirect:write>-->
</xsl:for-each>
</xsl:for-each>
</testsuites>
@@ -57,12 +57,26 @@ public void testFilenameDoesNotContainInvalidChars() throws Exception {
assertJunitFiles(3);
}

@Issue("JENKINS-44315")
@Test
public void testIssue44315() throws Exception {
transformer.transform(getClass().getResourceAsStream("NUnit-issue44315.xml"), tempFilePath);
assertJunitFiles(195);
}

@Issue("JENKINS-44527")
@Test
public void testIssue44527() throws Exception {
transformer.transform(getClass().getResourceAsStream("NUnit-issue44527.xml"), tempFilePath);
assertJunitFiles(144);
}

private void assertJunitFiles(int expectedJunitFilesCount) throws DocumentException {
File[] listFiles = tempFilePath.listFiles(this);
Assert.assertEquals("The number of junit files are incorrect.", expectedJunitFilesCount, listFiles.length);
for (File file : listFiles) {
Document result = new SAXReader().read(file);
Assert.assertNotNull("The XML wasnt parsed", result);
Assert.assertNotNull("The XML wasn't parsed", result);
org.dom4j.Element root = result.getRootElement();
Assert.assertNotNull("There is no root in the XML", root);
Assert.assertEquals("The name is not correct", "testsuite", root.getName());
@@ -76,6 +90,13 @@ public void testXmlWithBOM() throws Exception {
assertJunitFiles(2);
}

@Issue("JENKINS-17521")
@Test
public void testInvalidXmlCharacters() throws Exception {
transformer.transform(getClass().getResourceAsStream("NUnit-issue17521.xml"), tempFilePath);
assertJunitFiles(2);
}

public boolean accept(File dir, String name) {
return name.startsWith(NUnitReportTransformer.JUNIT_FILE_PREFIX);
}
Binary file not shown.

0 comments on commit 66d6390

Please sign in to comment.
You can’t perform that action at this time.