git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@1556001 13f79535-47bb-0310-9956-ffa450edef68master
| @@ -91,6 +91,10 @@ Other changes: | |||
| * <sql> has a new outputencoding attribute. | |||
| Bugzilla Report 39541 | |||
| * changes to JUnitTestRunner and PlainJUnitResultFormatter to make | |||
| OutOfMemoryErrors less likely. | |||
| Bugzilla Report 45536 | |||
| Changes from Ant 1.9.2 TO Ant 1.9.3 | |||
| =================================== | |||
| @@ -558,8 +558,18 @@ public class JUnitTestRunner implements TestListener, JUnitTaskMirror.JUnitTestR | |||
| systemOut.close(); | |||
| systemOut = null; | |||
| if (startTestSuiteSuccess) { | |||
| sendOutAndErr(new String(outStrm.toByteArray()), | |||
| new String(errStrm.toByteArray())); | |||
| String out, err; | |||
| try { | |||
| out = new String(outStrm.toByteArray()); | |||
| } catch (OutOfMemoryError ex) { | |||
| out = "out of memory on output stream"; | |||
| } | |||
| try { | |||
| err = new String(errStrm.toByteArray()); | |||
| } catch (OutOfMemoryError ex) { | |||
| err = "out of memory on error stream"; | |||
| } | |||
| sendOutAndErr(out, err); | |||
| } | |||
| } | |||
| fireEndTestSuite(); | |||
| @@ -117,6 +117,7 @@ public class PlainJUnitResultFormatter implements JUnitResultFormatter, IgnoredT | |||
| * @throws BuildException if unable to write the output | |||
| */ | |||
| public void endTestSuite(JUnitTest suite) throws BuildException { | |||
| try { | |||
| StringBuffer sb = new StringBuffer("Tests run: "); | |||
| sb.append(suite.runCount()); | |||
| sb.append(", Failures: "); | |||
| @@ -129,40 +130,49 @@ public class PlainJUnitResultFormatter implements JUnitResultFormatter, IgnoredT | |||
| sb.append(nf.format(suite.getRunTime() / ONE_SECOND)); | |||
| sb.append(" sec"); | |||
| sb.append(StringUtils.LINE_SEP); | |||
| write(sb.toString()); | |||
| // append the err and output streams to the log | |||
| // write the err and output streams to the log | |||
| if (systemOutput != null && systemOutput.length() > 0) { | |||
| sb.append("------------- Standard Output ---------------") | |||
| .append(StringUtils.LINE_SEP) | |||
| .append(systemOutput) | |||
| .append("------------- ---------------- ---------------") | |||
| .append(StringUtils.LINE_SEP); | |||
| write("------------- Standard Output ---------------"); | |||
| write(StringUtils.LINE_SEP); | |||
| write(systemOutput); | |||
| write("------------- ---------------- ---------------"); | |||
| write(StringUtils.LINE_SEP); | |||
| } | |||
| if (systemError != null && systemError.length() > 0) { | |||
| sb.append("------------- Standard Error -----------------") | |||
| .append(StringUtils.LINE_SEP) | |||
| .append(systemError) | |||
| .append("------------- ---------------- ---------------") | |||
| .append(StringUtils.LINE_SEP); | |||
| write("------------- Standard Error -----------------"); | |||
| write(StringUtils.LINE_SEP); | |||
| write(systemError); | |||
| write("------------- ---------------- ---------------"); | |||
| write(StringUtils.LINE_SEP); | |||
| } | |||
| sb.append(StringUtils.LINE_SEP); | |||
| write(StringUtils.LINE_SEP); | |||
| if (out != null) { | |||
| try { | |||
| wri.flush(); | |||
| write(inner.toString()); | |||
| } catch (IOException ioex) { | |||
| throw new BuildException("Unable to write output", ioex); | |||
| } | |||
| } | |||
| } finally { | |||
| if (out != null) { | |||
| try { | |||
| out.write(sb.toString().getBytes()); | |||
| wri.close(); | |||
| out.write(inner.toString().getBytes()); | |||
| out.flush(); | |||
| } catch (IOException ioex) { | |||
| throw new BuildException("Unable to write output", ioex); | |||
| throw new BuildException("Unable to flush output", ioex); | |||
| } finally { | |||
| if (out != System.out && out != System.err) { | |||
| FileUtils.close(out); | |||
| } | |||
| wri = null; | |||
| out = null; | |||
| } | |||
| } | |||
| } | |||
| } | |||
| /** | |||
| @@ -286,4 +296,22 @@ public class PlainJUnitResultFormatter implements JUnitResultFormatter, IgnoredT | |||
| public void testAssumptionFailure(Test test, Throwable throwable) { | |||
| formatSkip(test, throwable.getMessage()); | |||
| } | |||
| /** | |||
| * Print out some text, and flush the output stream; encoding in the platform | |||
| * local default encoding. | |||
| * @param text text to write. | |||
| * @throws BuildException on IO Problems. | |||
| */ | |||
| private void write(String text) { | |||
| if (out == null) { | |||
| return; | |||
| } | |||
| try { | |||
| out.write(text.getBytes()); | |||
| out.flush(); | |||
| } catch (IOException ex) { | |||
| throw new BuildException("Unable to write output " + ex, ex); | |||
| } | |||
| } | |||
| } // PlainJUnitResultFormatter | |||
| @@ -21,6 +21,7 @@ package org.apache.tools.ant.util; | |||
| import java.io.IOException; | |||
| import java.io.OutputStream; | |||
| import java.io.OutputStreamWriter; | |||
| import java.io.StringWriter; | |||
| import java.io.Writer; | |||
| import java.util.ArrayList; | |||
| import java.util.HashMap; | |||
| @@ -233,7 +234,7 @@ public class DOMElementWriter { | |||
| case Node.CDATA_SECTION_NODE: | |||
| out.write("<![CDATA["); | |||
| out.write(encodedata(((Text) child).getData())); | |||
| encodedata(out, ((Text) child).getData()); | |||
| out.write("]]>"); | |||
| break; | |||
| @@ -486,19 +487,59 @@ public class DOMElementWriter { | |||
| * href="http://www.w3.org/TR/1998/REC-xml-19980210#sec-cdata-sect">http://www.w3.org/TR/1998/REC-xml-19980210#sec-cdata-sect</a>.</p> | |||
| * @param value the value to be encoded. | |||
| * @return the encoded value. | |||
| */ | |||
| public String encodedata(final String value) { | |||
| final StringWriter out = new StringWriter(); | |||
| try { | |||
| encodedata(out, value); | |||
| } catch (IOException ex) { | |||
| throw new RuntimeException(ex); | |||
| } | |||
| return out.toString(); | |||
| } | |||
| /** | |||
| * Drop characters that are illegal in XML documents and write the | |||
| * rest to the given writer. | |||
| * | |||
| * <p>Also ensure that we are not including an <code>]]></code> | |||
| * marker by replacing that sequence with | |||
| * <code>&#x5d;&#x5d;&gt;</code>.</p> | |||
| * | |||
| * <p>See XML 1.0 2.2 <a | |||
| * href="http://www.w3.org/TR/1998/REC-xml-19980210#charsets"> | |||
| * http://www.w3.org/TR/1998/REC-xml-19980210#charsets</a> and | |||
| * 2.7 <a | |||
| * href="http://www.w3.org/TR/1998/REC-xml-19980210#sec-cdata-sect">http://www.w3.org/TR/1998/REC-xml-19980210#sec-cdata-sect</a>.</p> | |||
| * @param value the value to be encoded. | |||
| * @param out where to write the encoded data to. | |||
| */ | |||
| public void encodedata(final Writer out, final String value) throws IOException { | |||
| final int len = value.length(); | |||
| StringBuffer sb = new StringBuffer(len); | |||
| for (int i = 0; i < len; ++i) { | |||
| final char c = value.charAt(i); | |||
| if (isLegalCharacter(c)) { | |||
| sb.append(c); | |||
| int prevEnd = 0, cdataEndPos = value.indexOf("]]>"); | |||
| while (prevEnd < len) { | |||
| final int end = (cdataEndPos < 0 ? len : cdataEndPos); | |||
| // Write out stretches of legal characters in the range [prevEnd, end). | |||
| for (int prevLegalCharPos = prevEnd; prevLegalCharPos < end; /*empty*/) { | |||
| int illegalCharPos; | |||
| for (illegalCharPos = prevLegalCharPos; true; ++illegalCharPos) { | |||
| if (illegalCharPos >= end | |||
| || !isLegalCharacter(value.charAt(illegalCharPos))) { | |||
| break; | |||
| } | |||
| } | |||
| out.write(value, prevLegalCharPos, illegalCharPos - prevLegalCharPos); | |||
| prevLegalCharPos = illegalCharPos + 1; | |||
| } | |||
| } | |||
| return sb.substring(0).replace("]]>", "]]]]><![CDATA[>"); | |||
| if (cdataEndPos >= 0) { | |||
| out.write("]]]]><![CDATA[>"); | |||
| prevEnd = cdataEndPos + 3; | |||
| cdataEndPos = value.indexOf("]]>", prevEnd); | |||
| } else { | |||
| prevEnd = end; | |||
| } | |||
| } | |||
| } | |||
| /** | |||