You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@ant.apache.org by bo...@apache.org on 2014/01/06 20:54:30 UTC

svn commit: r1556001 - in /ant/core/trunk: ./ src/main/org/apache/tools/ant/taskdefs/optional/junit/ src/main/org/apache/tools/ant/util/

Author: bodewig
Date: Mon Jan  6 19:54:30 2014
New Revision: 1556001

URL: http://svn.apache.org/r1556001
Log:
try to make OOM in <junit> less likely.  PR 45536.  Submitted by Steve Loughran who decided not to commit it himself :-)

Modified:
    ant/core/trunk/WHATSNEW
    ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTestRunner.java
    ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/optional/junit/PlainJUnitResultFormatter.java
    ant/core/trunk/src/main/org/apache/tools/ant/util/DOMElementWriter.java

Modified: ant/core/trunk/WHATSNEW
URL: http://svn.apache.org/viewvc/ant/core/trunk/WHATSNEW?rev=1556001&r1=1556000&r2=1556001&view=diff
==============================================================================
--- ant/core/trunk/WHATSNEW (original)
+++ ant/core/trunk/WHATSNEW Mon Jan  6 19:54:30 2014
@@ -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
 ===================================
 

Modified: ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTestRunner.java
URL: http://svn.apache.org/viewvc/ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTestRunner.java?rev=1556001&r1=1556000&r2=1556001&view=diff
==============================================================================
--- ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTestRunner.java (original)
+++ ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTestRunner.java Mon Jan  6 19:54:30 2014
@@ -558,8 +558,18 @@ public class JUnitTestRunner implements 
             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();

Modified: ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/optional/junit/PlainJUnitResultFormatter.java
URL: http://svn.apache.org/viewvc/ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/optional/junit/PlainJUnitResultFormatter.java?rev=1556001&r1=1556000&r2=1556001&view=diff
==============================================================================
--- ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/optional/junit/PlainJUnitResultFormatter.java (original)
+++ ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/optional/junit/PlainJUnitResultFormatter.java Mon Jan  6 19:54:30 2014
@@ -117,6 +117,7 @@ public class PlainJUnitResultFormatter i
      * @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 i
         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 i
     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

Modified: ant/core/trunk/src/main/org/apache/tools/ant/util/DOMElementWriter.java
URL: http://svn.apache.org/viewvc/ant/core/trunk/src/main/org/apache/tools/ant/util/DOMElementWriter.java?rev=1556001&r1=1556000&r2=1556001&view=diff
==============================================================================
--- ant/core/trunk/src/main/org/apache/tools/ant/util/DOMElementWriter.java (original)
+++ ant/core/trunk/src/main/org/apache/tools/ant/util/DOMElementWriter.java Mon Jan  6 19:54:30 2014
@@ -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>]]&gt;</code>
+     * marker by replacing that sequence with
+     * <code>&amp;#x5d;&amp;#x5d;&amp;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;
+            }
+        }
     }
 
     /**