Source Code Cross Referenced for JUnitTask.java in  » Build » ANT » org » apache » tools » ant » taskdefs » optional » junit » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Build » ANT » org.apache.tools.ant.taskdefs.optional.junit 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         *  Licensed to the Apache Software Foundation (ASF) under one or more
0003:         *  contributor license agreements.  See the NOTICE file distributed with
0004:         *  this work for additional information regarding copyright ownership.
0005:         *  The ASF licenses this file to You under the Apache License, Version 2.0
0006:         *  (the "License"); you may not use this file except in compliance with
0007:         *  the License.  You may obtain a copy of the License at
0008:         *
0009:         *      http://www.apache.org/licenses/LICENSE-2.0
0010:         *
0011:         *  Unless required by applicable law or agreed to in writing, software
0012:         *  distributed under the License is distributed on an "AS IS" BASIS,
0013:         *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0014:         *  See the License for the specific language governing permissions and
0015:         *  limitations under the License.
0016:         *
0017:         */
0018:
0019:        package org.apache.tools.ant.taskdefs.optional.junit;
0020:
0021:        import java.io.BufferedReader;
0022:        import java.io.BufferedWriter;
0023:        import java.io.File;
0024:        import java.io.FileOutputStream;
0025:        import java.io.FileReader;
0026:        import java.io.FileWriter;
0027:        import java.io.IOException;
0028:        import java.io.OutputStream;
0029:        import java.io.PrintWriter;
0030:        import java.lang.reflect.Constructor;
0031:        import java.util.ArrayList;
0032:        import java.util.Collection;
0033:        import java.util.Enumeration;
0034:        import java.util.HashMap;
0035:        import java.util.Hashtable;
0036:        import java.util.Iterator;
0037:        import java.util.List;
0038:        import java.util.Map;
0039:        import java.util.Properties;
0040:        import java.util.Vector;
0041:
0042:        import org.apache.tools.ant.AntClassLoader;
0043:        import org.apache.tools.ant.BuildException;
0044:        import org.apache.tools.ant.Project;
0045:        import org.apache.tools.ant.Task;
0046:        import org.apache.tools.ant.taskdefs.Execute;
0047:        import org.apache.tools.ant.taskdefs.ExecuteWatchdog;
0048:        import org.apache.tools.ant.taskdefs.LogOutputStream;
0049:        import org.apache.tools.ant.taskdefs.PumpStreamHandler;
0050:        import org.apache.tools.ant.types.Assertions;
0051:        import org.apache.tools.ant.types.Commandline;
0052:        import org.apache.tools.ant.types.CommandlineJava;
0053:        import org.apache.tools.ant.types.EnumeratedAttribute;
0054:        import org.apache.tools.ant.types.Environment;
0055:        import org.apache.tools.ant.types.Path;
0056:        import org.apache.tools.ant.types.Permissions;
0057:        import org.apache.tools.ant.types.PropertySet;
0058:        import org.apache.tools.ant.util.FileUtils;
0059:        import org.apache.tools.ant.util.LoaderUtils;
0060:
0061:        /**
0062:         * Runs JUnit tests.
0063:         *
0064:         * <p> JUnit is a framework to create unit tests. It has been initially
0065:         * created by Erich Gamma and Kent Beck.  JUnit can be found at <a
0066:         * href="http://www.junit.org">http://www.junit.org</a>.
0067:         *
0068:         * <p> <code>JUnitTask</code> can run a single specific
0069:         * <code>JUnitTest</code> using the <code>test</code> element.</p>
0070:         * For example, the following target <code><pre>
0071:         *   &lt;target name="test-int-chars" depends="jar-test"&gt;
0072:         *       &lt;echo message="testing international characters"/&gt;
0073:         *       &lt;junit printsummary="no" haltonfailure="yes" fork="false"&gt;
0074:         *           &lt;classpath refid="classpath"/&gt;
0075:         *           &lt;formatter type="plain" usefile="false" /&gt;
0076:         *           &lt;test name="org.apache.ecs.InternationalCharTest" /&gt;
0077:         *       &lt;/junit&gt;
0078:         *   &lt;/target&gt;
0079:         * </pre></code>
0080:         * <p>runs a single junit test
0081:         * (<code>org.apache.ecs.InternationalCharTest</code>) in the current
0082:         * VM using the path with id <code>classpath</code> as classpath and
0083:         * presents the results formatted using the standard
0084:         * <code>plain</code> formatter on the command line.</p>
0085:         *
0086:         * <p> This task can also run batches of tests.  The
0087:         * <code>batchtest</code> element creates a <code>BatchTest</code>
0088:         * based on a fileset.  This allows, for example, all classes found in
0089:         * directory to be run as testcases.</p>
0090:         *
0091:         * <p>For example,</p><code><pre>
0092:         * &lt;target name="run-tests" depends="dump-info,compile-tests" if="junit.present"&gt;
0093:         *   &lt;junit printsummary="no" haltonfailure="yes" fork="${junit.fork}"&gt;
0094:         *     &lt;jvmarg value="-classic"/&gt;
0095:         *     &lt;classpath refid="tests-classpath"/&gt;
0096:         *     &lt;sysproperty key="build.tests" value="${build.tests}"/&gt;
0097:         *     &lt;formatter type="brief" usefile="false" /&gt;
0098:         *     &lt;batchtest&gt;
0099:         *       &lt;fileset dir="${tests.dir}"&gt;
0100:         *         &lt;include name="**&#047;*Test*" /&gt;
0101:         *       &lt;/fileset&gt;
0102:         *     &lt;/batchtest&gt;
0103:         *   &lt;/junit&gt;
0104:         * &lt;/target&gt;
0105:         * </pre></code>
0106:         * <p>this target finds any classes with a <code>test</code> directory
0107:         * anywhere in their path (under the top <code>${tests.dir}</code>, of
0108:         * course) and creates <code>JUnitTest</code>'s for each one.</p>
0109:         *
0110:         * <p> Of course, <code>&lt;junit&gt;</code> and
0111:         * <code>&lt;batch&gt;</code> elements can be combined for more
0112:         * complex tests. For an example, see the ant <code>build.xml</code>
0113:         * target <code>run-tests</code> (the second example is an edited
0114:         * version).</p>
0115:         *
0116:         * <p> To spawn a new Java VM to prevent interferences between
0117:         * different testcases, you need to enable <code>fork</code>.  A
0118:         * number of attributes and elements allow you to set up how this JVM
0119:         * runs.
0120:         *
0121:         *
0122:         * @since Ant 1.2
0123:         *
0124:         * @see JUnitTest
0125:         * @see BatchTest
0126:         */
0127:        public class JUnitTask extends Task {
0128:
0129:            private static final String CLASSPATH = "CLASSPATH=";
0130:            private CommandlineJava commandline;
0131:            private Vector tests = new Vector();
0132:            private Vector batchTests = new Vector();
0133:            private Vector formatters = new Vector();
0134:            private File dir = null;
0135:
0136:            private Integer timeout = null;
0137:            private boolean summary = false;
0138:            private boolean reloading = true;
0139:            private String summaryValue = "";
0140:            private JUnitTaskMirror.JUnitTestRunnerMirror runner = null;
0141:
0142:            private boolean newEnvironment = false;
0143:            private Environment env = new Environment();
0144:
0145:            private boolean includeAntRuntime = true;
0146:            private Path antRuntimeClasses = null;
0147:
0148:            // Do we send output to System.out/.err in addition to the formatters?
0149:            private boolean showOutput = false;
0150:
0151:            // Do we send output to the formatters ?
0152:            private boolean outputToFormatters = true;
0153:
0154:            private File tmpDir;
0155:            private AntClassLoader classLoader = null;
0156:            private Permissions perm = null;
0157:            private ForkMode forkMode = new ForkMode("perTest");
0158:
0159:            private boolean splitJunit = false;
0160:            private JUnitTaskMirror delegate;
0161:
0162:            //   Attributes for basetest
0163:            private boolean haltOnError = false;
0164:            private boolean haltOnFail = false;
0165:            private boolean filterTrace = true;
0166:            private boolean fork = false;
0167:            private String failureProperty;
0168:            private String errorProperty;
0169:
0170:            private static final int STRING_BUFFER_SIZE = 128;
0171:            /**
0172:             * @since Ant 1.7
0173:             */
0174:            public static final String TESTLISTENER_PREFIX = "junit.framework.TestListener: ";
0175:
0176:            private static final FileUtils FILE_UTILS = FileUtils
0177:                    .getFileUtils();
0178:
0179:            /**
0180:             * If true, force ant to re-classload all classes for each JUnit TestCase
0181:             *
0182:             * @param value force class reloading for each test case
0183:             */
0184:            public void setReloading(boolean value) {
0185:                reloading = value;
0186:            }
0187:
0188:            /**
0189:             * If true, smartly filter the stack frames of
0190:             * JUnit errors and failures before reporting them.
0191:             *
0192:             * <p>This property is applied on all BatchTest (batchtest) and
0193:             * JUnitTest (test) however it can possibly be overridden by their
0194:             * own properties.</p>
0195:             * @param value <tt>false</tt> if it should not filter, otherwise
0196:             * <tt>true<tt>
0197:             *
0198:             * @since Ant 1.5
0199:             */
0200:            public void setFiltertrace(boolean value) {
0201:                this .filterTrace = value;
0202:            }
0203:
0204:            /**
0205:             * If true, stop the build process when there is an error in a test.
0206:             * This property is applied on all BatchTest (batchtest) and JUnitTest
0207:             * (test) however it can possibly be overridden by their own
0208:             * properties.
0209:             * @param value <tt>true</tt> if it should halt, otherwise
0210:             * <tt>false</tt>
0211:             *
0212:             * @since Ant 1.2
0213:             */
0214:            public void setHaltonerror(boolean value) {
0215:                this .haltOnError = value;
0216:            }
0217:
0218:            /**
0219:             * Property to set to "true" if there is a error in a test.
0220:             *
0221:             * <p>This property is applied on all BatchTest (batchtest) and
0222:             * JUnitTest (test), however, it can possibly be overriden by
0223:             * their own properties.</p>
0224:             * @param propertyName the name of the property to set in the
0225:             * event of an error.
0226:             *
0227:             * @since Ant 1.4
0228:             */
0229:            public void setErrorProperty(String propertyName) {
0230:                this .errorProperty = propertyName;
0231:            }
0232:
0233:            /**
0234:             * If true, stop the build process if a test fails
0235:             * (errors are considered failures as well).
0236:             * This property is applied on all BatchTest (batchtest) and
0237:             * JUnitTest (test) however it can possibly be overridden by their
0238:             * own properties.
0239:             * @param value <tt>true</tt> if it should halt, otherwise
0240:             * <tt>false</tt>
0241:             *
0242:             * @since Ant 1.2
0243:             */
0244:            public void setHaltonfailure(boolean value) {
0245:                this .haltOnFail = value;
0246:            }
0247:
0248:            /**
0249:             * Property to set to "true" if there is a failure in a test.
0250:             *
0251:             * <p>This property is applied on all BatchTest (batchtest) and
0252:             * JUnitTest (test), however, it can possibly be overriden by
0253:             * their own properties.</p>
0254:             * @param propertyName the name of the property to set in the
0255:             * event of an failure.
0256:             *
0257:             * @since Ant 1.4
0258:             */
0259:            public void setFailureProperty(String propertyName) {
0260:                this .failureProperty = propertyName;
0261:            }
0262:
0263:            /**
0264:             * If true, JVM should be forked for each test.
0265:             *
0266:             * <p>It avoids interference between testcases and possibly avoids
0267:             * hanging the build.  this property is applied on all BatchTest
0268:             * (batchtest) and JUnitTest (test) however it can possibly be
0269:             * overridden by their own properties.</p>
0270:             * @param value <tt>true</tt> if a JVM should be forked, otherwise
0271:             * <tt>false</tt>
0272:             * @see #setTimeout
0273:             *
0274:             * @since Ant 1.2
0275:             */
0276:            public void setFork(boolean value) {
0277:                this .fork = value;
0278:            }
0279:
0280:            /**
0281:             * Set the behavior when {@link #setFork fork} fork has been enabled.
0282:             *
0283:             * <p>Possible values are "once", "perTest" and "perBatch".  If
0284:             * set to "once", only a single Java VM will be forked for all
0285:             * tests, with "perTest" (the default) each test will run in a
0286:             * fresh Java VM and "perBatch" will run all tests from the same
0287:             * &lt;batchtest&gt; in the same Java VM.</p>
0288:             *
0289:             * <p>This attribute will be ignored if tests run in the same VM
0290:             * as Ant.</p>
0291:             *
0292:             * <p>Only tests with the same configuration of haltonerror,
0293:             * haltonfailure, errorproperty, failureproperty and filtertrace
0294:             * can share a forked Java VM, so even if you set the value to
0295:             * "once", Ant may need to fork mutliple VMs.</p>
0296:             * @param mode the mode to use.
0297:             * @since Ant 1.6.2
0298:             */
0299:            public void setForkMode(ForkMode mode) {
0300:                this .forkMode = mode;
0301:            }
0302:
0303:            /**
0304:             * If true, print one-line statistics for each test, or "withOutAndErr"
0305:             * to also show standard output and error.
0306:             *
0307:             * Can take the values on, off, and withOutAndErr.
0308:             * @param value <tt>true</tt> to print a summary,
0309:             * <tt>withOutAndErr</tt> to include the test&apos;s output as
0310:             * well, <tt>false</tt> otherwise.
0311:             * @see SummaryJUnitResultFormatter
0312:             *
0313:             * @since Ant 1.2
0314:             */
0315:            public void setPrintsummary(SummaryAttribute value) {
0316:                summaryValue = value.getValue();
0317:                summary = value.asBoolean();
0318:            }
0319:
0320:            /**
0321:             * Print summary enumeration values.
0322:             */
0323:            public static class SummaryAttribute extends EnumeratedAttribute {
0324:                /**
0325:                 * list the possible values
0326:                 * @return  array of allowed values
0327:                 */
0328:                public String[] getValues() {
0329:                    return new String[] { "true", "yes", "false", "no", "on",
0330:                            "off", "withOutAndErr" };
0331:                }
0332:
0333:                /**
0334:                 * gives the boolean equivalent of the authorized values
0335:                 * @return boolean equivalent of the value
0336:                 */
0337:                public boolean asBoolean() {
0338:                    String v = getValue();
0339:                    return "true".equals(v) || "on".equals(v)
0340:                            || "yes".equals(v) || "withOutAndErr".equals(v);
0341:                }
0342:            }
0343:
0344:            /**
0345:             * Set the timeout value (in milliseconds).
0346:             *
0347:             * <p>If the test is running for more than this value, the test
0348:             * will be canceled. (works only when in 'fork' mode).</p>
0349:             * @param value the maximum time (in milliseconds) allowed before
0350:             * declaring the test as 'timed-out'
0351:             * @see #setFork(boolean)
0352:             *
0353:             * @since Ant 1.2
0354:             */
0355:            public void setTimeout(Integer value) {
0356:                timeout = value;
0357:            }
0358:
0359:            /**
0360:             * Set the maximum memory to be used by all forked JVMs.
0361:             * @param   max     the value as defined by <tt>-mx</tt> or <tt>-Xmx</tt>
0362:             *                  in the java command line options.
0363:             *
0364:             * @since Ant 1.2
0365:             */
0366:            public void setMaxmemory(String max) {
0367:                getCommandline().setMaxmemory(max);
0368:            }
0369:
0370:            /**
0371:             * The command used to invoke the Java Virtual Machine,
0372:             * default is 'java'. The command is resolved by
0373:             * java.lang.Runtime.exec(). Ignored if fork is disabled.
0374:             *
0375:             * @param   value   the new VM to use instead of <tt>java</tt>
0376:             * @see #setFork(boolean)
0377:             *
0378:             * @since Ant 1.2
0379:             */
0380:            public void setJvm(String value) {
0381:                getCommandline().setVm(value);
0382:            }
0383:
0384:            /**
0385:             * Adds a JVM argument; ignored if not forking.
0386:             *
0387:             * @return create a new JVM argument so that any argument can be
0388:             * passed to the JVM.
0389:             * @see #setFork(boolean)
0390:             *
0391:             * @since Ant 1.2
0392:             */
0393:            public Commandline.Argument createJvmarg() {
0394:                return getCommandline().createVmArgument();
0395:            }
0396:
0397:            /**
0398:             * The directory to invoke the VM in. Ignored if no JVM is forked.
0399:             * @param   dir     the directory to invoke the JVM from.
0400:             * @see #setFork(boolean)
0401:             *
0402:             * @since Ant 1.2
0403:             */
0404:            public void setDir(File dir) {
0405:                this .dir = dir;
0406:            }
0407:
0408:            /**
0409:             * Adds a system property that tests can access.
0410:             * This might be useful to tranfer Ant properties to the
0411:             * testcases when JVM forking is not enabled.
0412:             *
0413:             * @since Ant 1.3
0414:             * @deprecated since ant 1.6
0415:             * @param sysp environment variable to add
0416:             */
0417:            public void addSysproperty(Environment.Variable sysp) {
0418:
0419:                getCommandline().addSysproperty(sysp);
0420:            }
0421:
0422:            /**
0423:             * Adds a system property that tests can access.
0424:             * This might be useful to tranfer Ant properties to the
0425:             * testcases when JVM forking is not enabled.
0426:             * @param sysp new environment variable to add
0427:             * @since Ant 1.6
0428:             */
0429:            public void addConfiguredSysproperty(Environment.Variable sysp) {
0430:                // get a build exception if there is a missing key or value
0431:                // see bugzilla report 21684
0432:                String testString = sysp.getContent();
0433:                getProject().log("sysproperty added : " + testString,
0434:                        Project.MSG_DEBUG);
0435:                getCommandline().addSysproperty(sysp);
0436:            }
0437:
0438:            /**
0439:             * Adds a set of properties that will be used as system properties
0440:             * that tests can access.
0441:             *
0442:             * This might be useful to tranfer Ant properties to the
0443:             * testcases when JVM forking is not enabled.
0444:             *
0445:             * @param sysp set of properties to be added
0446:             * @since Ant 1.6
0447:             */
0448:            public void addSyspropertyset(PropertySet sysp) {
0449:                getCommandline().addSyspropertyset(sysp);
0450:            }
0451:
0452:            /**
0453:             * Adds path to classpath used for tests.
0454:             *
0455:             * @return reference to the classpath in the embedded java command line
0456:             * @since Ant 1.2
0457:             */
0458:            public Path createClasspath() {
0459:                return getCommandline().createClasspath(getProject())
0460:                        .createPath();
0461:            }
0462:
0463:            /**
0464:             * Adds a path to the bootclasspath.
0465:             * @return reference to the bootclasspath in the embedded java command line
0466:             * @since Ant 1.6
0467:             */
0468:            public Path createBootclasspath() {
0469:                return getCommandline().createBootclasspath(getProject())
0470:                        .createPath();
0471:            }
0472:
0473:            /**
0474:             * Adds an environment variable; used when forking.
0475:             *
0476:             * <p>Will be ignored if we are not forking a new VM.</p>
0477:             * @param var environment variable to be added
0478:             * @since Ant 1.5
0479:             */
0480:            public void addEnv(Environment.Variable var) {
0481:                env.addVariable(var);
0482:            }
0483:
0484:            /**
0485:             * If true, use a new environment when forked.
0486:             *
0487:             * <p>Will be ignored if we are not forking a new VM.</p>
0488:             *
0489:             * @param newenv boolean indicating if setting a new environment is wished
0490:             * @since Ant 1.5
0491:             */
0492:            public void setNewenvironment(boolean newenv) {
0493:                newEnvironment = newenv;
0494:            }
0495:
0496:            /**
0497:             * Preset the attributes of the test
0498:             * before configuration in the build
0499:             * script.
0500:             * This allows attributes in the <junit> task
0501:             * be be defaults for the tests, but allows
0502:             * individual tests to override the defaults.
0503:             */
0504:            private void preConfigure(BaseTest test) {
0505:                test.setFiltertrace(filterTrace);
0506:                test.setHaltonerror(haltOnError);
0507:                if (errorProperty != null) {
0508:                    test.setErrorProperty(errorProperty);
0509:                }
0510:                test.setHaltonfailure(haltOnFail);
0511:                if (failureProperty != null) {
0512:                    test.setFailureProperty(failureProperty);
0513:                }
0514:                test.setFork(fork);
0515:            }
0516:
0517:            /**
0518:             * Add a new single testcase.
0519:             * @param   test    a new single testcase
0520:             * @see JUnitTest
0521:             *
0522:             * @since Ant 1.2
0523:             */
0524:            public void addTest(JUnitTest test) {
0525:                tests.addElement(test);
0526:                preConfigure(test);
0527:            }
0528:
0529:            /**
0530:             * Adds a set of tests based on pattern matching.
0531:             *
0532:             * @return  a new instance of a batch test.
0533:             * @see BatchTest
0534:             *
0535:             * @since Ant 1.2
0536:             */
0537:            public BatchTest createBatchTest() {
0538:                BatchTest test = new BatchTest(getProject());
0539:                batchTests.addElement(test);
0540:                preConfigure(test);
0541:                return test;
0542:            }
0543:
0544:            /**
0545:             * Add a new formatter to all tests of this task.
0546:             *
0547:             * @param fe formatter element
0548:             * @since Ant 1.2
0549:             */
0550:            public void addFormatter(FormatterElement fe) {
0551:                formatters.addElement(fe);
0552:            }
0553:
0554:            /**
0555:             * If true, include ant.jar, optional.jar and junit.jar in the forked VM.
0556:             *
0557:             * @param b include ant run time yes or no
0558:             * @since Ant 1.5
0559:             */
0560:            public void setIncludeantruntime(boolean b) {
0561:                includeAntRuntime = b;
0562:            }
0563:
0564:            /**
0565:             * If true, send any output generated by tests to Ant's logging system
0566:             * as well as to the formatters.
0567:             * By default only the formatters receive the output.
0568:             *
0569:             * <p>Output will always be passed to the formatters and not by
0570:             * shown by default.  This option should for example be set for
0571:             * tests that are interactive and prompt the user to do
0572:             * something.</p>
0573:             *
0574:             * @param showOutput if true, send output to Ant's logging system too
0575:             * @since Ant 1.5
0576:             */
0577:            public void setShowOutput(boolean showOutput) {
0578:                this .showOutput = showOutput;
0579:            }
0580:
0581:            /**
0582:             * If true, send any output generated by tests to the formatters.
0583:             *
0584:             * @param outputToFormatters if true, send output to formatters (Default
0585:             *                           is true).
0586:             * @since Ant 1.7.0
0587:             */
0588:            public void setOutputToFormatters(boolean outputToFormatters) {
0589:                this .outputToFormatters = outputToFormatters;
0590:            }
0591:
0592:            /**
0593:             * Assertions to enable in this program (if fork=true)
0594:             * @since Ant 1.6
0595:             * @param asserts assertion set
0596:             */
0597:            public void addAssertions(Assertions asserts) {
0598:                if (getCommandline().getAssertions() != null) {
0599:                    throw new BuildException(
0600:                            "Only one assertion declaration is allowed");
0601:                }
0602:                getCommandline().setAssertions(asserts);
0603:            }
0604:
0605:            /**
0606:             * Sets the permissions for the application run inside the same JVM.
0607:             * @since Ant 1.6
0608:             * @return .
0609:             */
0610:            public Permissions createPermissions() {
0611:                if (perm == null) {
0612:                    perm = new Permissions();
0613:                }
0614:                return perm;
0615:            }
0616:
0617:            /**
0618:             * If set, system properties will be copied to the cloned VM - as
0619:             * well as the bootclasspath unless you have explicitly specified
0620:             * a bootclaspath.
0621:             *
0622:             * <p>Doesn't have any effect unless fork is true.</p>
0623:             * @param cloneVm a <code>boolean</code> value.
0624:             * @since Ant 1.7
0625:             */
0626:            public void setCloneVm(boolean cloneVm) {
0627:                getCommandline().setCloneVm(cloneVm);
0628:            }
0629:
0630:            /**
0631:             * Creates a new JUnitRunner and enables fork of a new Java VM.
0632:             *
0633:             * @throws Exception under ??? circumstances
0634:             * @since Ant 1.2
0635:             */
0636:            public JUnitTask() throws Exception {
0637:                getCommandline()
0638:                        .setClassname(
0639:                                "org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner");
0640:            }
0641:
0642:            /**
0643:             * Where Ant should place temporary files.
0644:             *
0645:             * @param tmpDir location where temporary files should go to
0646:             * @since Ant 1.6
0647:             */
0648:            public void setTempdir(File tmpDir) {
0649:                if (tmpDir != null) {
0650:                    if (!tmpDir.exists() || !tmpDir.isDirectory()) {
0651:                        throw new BuildException(tmpDir.toString()
0652:                                + " is not a valid temp directory");
0653:                    }
0654:                }
0655:                this .tmpDir = tmpDir;
0656:            }
0657:
0658:            /**
0659:             * Adds the jars or directories containing Ant, this task and
0660:             * JUnit to the classpath - this should make the forked JVM work
0661:             * without having to specify them directly.
0662:             *
0663:             * @since Ant 1.4
0664:             */
0665:            public void init() {
0666:                antRuntimeClasses = new Path(getProject());
0667:                splitJunit = !addClasspathEntry("/junit/framework/TestCase.class");
0668:                addClasspathEntry("/org/apache/tools/ant/launch/AntMain.class");
0669:                addClasspathEntry("/org/apache/tools/ant/Task.class");
0670:                addClasspathEntry("/org/apache/tools/ant/taskdefs/optional/junit/JUnitTestRunner.class");
0671:            }
0672:
0673:            private static JUnitTaskMirror createMirror(JUnitTask task,
0674:                    ClassLoader loader) {
0675:                try {
0676:                    loader.loadClass("junit.framework.Test"); // sanity check
0677:                } catch (ClassNotFoundException e) {
0678:                    throw new BuildException(
0679:                            "The <classpath> for <junit> must include junit.jar "
0680:                                    + "if not in Ant's own classpath", e, task
0681:                                    .getLocation());
0682:                }
0683:                try {
0684:                    Class c = loader.loadClass(JUnitTaskMirror.class.getName()
0685:                            + "Impl");
0686:                    if (c.getClassLoader() != loader) {
0687:                        throw new BuildException("Overdelegating loader", task
0688:                                .getLocation());
0689:                    }
0690:                    Constructor cons = c
0691:                            .getConstructor(new Class[] { JUnitTask.class });
0692:                    return (JUnitTaskMirror) cons
0693:                            .newInstance(new Object[] { task });
0694:                } catch (Exception e) {
0695:                    throw new BuildException(e, task.getLocation());
0696:                }
0697:            }
0698:
0699:            private final class SplitLoader extends AntClassLoader {
0700:
0701:                public SplitLoader(ClassLoader parent, Path path) {
0702:                    super (parent, getProject(), path, true);
0703:                }
0704:
0705:                // forceLoadClass is not convenient here since it would not
0706:                // properly deal with inner classes of these classes.
0707:                protected synchronized Class loadClass(String classname,
0708:                        boolean resolve) throws ClassNotFoundException {
0709:                    Class theClass = findLoadedClass(classname);
0710:                    if (theClass != null) {
0711:                        return theClass;
0712:                    }
0713:                    if (isSplit(classname)) {
0714:                        theClass = findClass(classname);
0715:                        if (resolve) {
0716:                            resolveClass(theClass);
0717:                        }
0718:                        return theClass;
0719:                    } else {
0720:                        return super .loadClass(classname, resolve);
0721:                    }
0722:                }
0723:
0724:                private final String[] splitClasses = {
0725:                        "BriefJUnitResultFormatter", "JUnitResultFormatter",
0726:                        "JUnitTaskMirrorImpl", "JUnitTestRunner",
0727:                        "JUnitVersionHelper",
0728:                        "OutErrSummaryJUnitResultFormatter",
0729:                        "PlainJUnitResultFormatter",
0730:                        "SummaryJUnitResultFormatter",
0731:                        "XMLJUnitResultFormatter", };
0732:
0733:                private boolean isSplit(String classname) {
0734:                    String simplename = classname.substring(classname
0735:                            .lastIndexOf('.') + 1);
0736:                    for (int i = 0; i < splitClasses.length; i++) {
0737:                        if (simplename.equals(splitClasses[i])
0738:                                || simplename.startsWith(splitClasses[i] + '$')) {
0739:                            return true;
0740:                        }
0741:                    }
0742:                    return false;
0743:                }
0744:
0745:            }
0746:
0747:            /**
0748:             * Runs the testcase.
0749:             *
0750:             * @throws BuildException in case of test failures or errors
0751:             * @since Ant 1.2
0752:             */
0753:            public void execute() throws BuildException {
0754:                ClassLoader myLoader = JUnitTask.class.getClassLoader();
0755:                ClassLoader mirrorLoader;
0756:                if (splitJunit) {
0757:                    Path path = new Path(getProject());
0758:                    path.add(antRuntimeClasses);
0759:                    path.add(getCommandline().getClasspath());
0760:                    mirrorLoader = new SplitLoader(myLoader, path);
0761:                } else {
0762:                    mirrorLoader = myLoader;
0763:                }
0764:                delegate = createMirror(this , mirrorLoader);
0765:
0766:                List testLists = new ArrayList();
0767:
0768:                boolean forkPerTest = forkMode.getValue().equals(
0769:                        ForkMode.PER_TEST);
0770:                if (forkPerTest || forkMode.getValue().equals(ForkMode.ONCE)) {
0771:                    testLists.addAll(executeOrQueue(getIndividualTests(),
0772:                            forkPerTest));
0773:                } else { /* forkMode.getValue().equals(ForkMode.PER_BATCH) */
0774:                    final int count = batchTests.size();
0775:                    for (int i = 0; i < count; i++) {
0776:                        BatchTest batchtest = (BatchTest) batchTests
0777:                                .elementAt(i);
0778:                        testLists.addAll(executeOrQueue(batchtest.elements(),
0779:                                false));
0780:                    }
0781:                    testLists.addAll(executeOrQueue(tests.elements(),
0782:                            forkPerTest));
0783:                }
0784:
0785:                try {
0786:                    Iterator iter = testLists.iterator();
0787:                    while (iter.hasNext()) {
0788:                        List l = (List) iter.next();
0789:                        if (l.size() == 1) {
0790:                            execute((JUnitTest) l.get(0));
0791:                        } else {
0792:                            execute(l);
0793:                        }
0794:                    }
0795:                } finally {
0796:                    deleteClassLoader();
0797:                    if (mirrorLoader instanceof  SplitLoader) {
0798:                        ((SplitLoader) mirrorLoader).cleanup();
0799:                    }
0800:                    delegate = null;
0801:                }
0802:            }
0803:
0804:            /**
0805:             * Run the tests.
0806:             * @param arg one JunitTest
0807:             * @throws BuildException in case of test failures or errors
0808:             */
0809:            protected void execute(JUnitTest arg) throws BuildException {
0810:                JUnitTest test = (JUnitTest) arg.clone();
0811:                // set the default values if not specified
0812:                //@todo should be moved to the test class instead.
0813:                if (test.getTodir() == null) {
0814:                    test.setTodir(getProject().resolveFile("."));
0815:                }
0816:
0817:                if (test.getOutfile() == null) {
0818:                    test.setOutfile("TEST-" + test.getName());
0819:                }
0820:
0821:                // execute the test and get the return code
0822:                TestResultHolder result = null;
0823:                if (!test.getFork()) {
0824:                    result = executeInVM(test);
0825:                } else {
0826:                    ExecuteWatchdog watchdog = createWatchdog();
0827:                    result = executeAsForked(test, watchdog, null);
0828:                    // null watchdog means no timeout, you'd better not check with null
0829:                }
0830:                actOnTestResult(result, test, "Test " + test.getName());
0831:            }
0832:
0833:            /**
0834:             * Execute a list of tests in a single forked Java VM.
0835:             * @param tests the list of tests to execute.
0836:             * @throws BuildException on error.
0837:             */
0838:            protected void execute(List tests) throws BuildException {
0839:                JUnitTest test = null;
0840:                // Create a temporary file to pass the test cases to run to
0841:                // the runner (one test case per line)
0842:                File casesFile = createTempPropertiesFile("junittestcases");
0843:                PrintWriter writer = null;
0844:                try {
0845:                    writer = new PrintWriter(new BufferedWriter(new FileWriter(
0846:                            casesFile)));
0847:                    Iterator iter = tests.iterator();
0848:                    while (iter.hasNext()) {
0849:                        test = (JUnitTest) iter.next();
0850:                        writer.print(test.getName());
0851:                        if (test.getTodir() == null) {
0852:                            writer.print("," + getProject().resolveFile("."));
0853:                        } else {
0854:                            writer.print("," + test.getTodir());
0855:                        }
0856:
0857:                        if (test.getOutfile() == null) {
0858:                            writer.println("," + "TEST-" + test.getName());
0859:                        } else {
0860:                            writer.println("," + test.getOutfile());
0861:                        }
0862:                    }
0863:                    writer.flush();
0864:                    writer.close();
0865:                    writer = null;
0866:
0867:                    // execute the test and get the return code
0868:                    ExecuteWatchdog watchdog = createWatchdog();
0869:                    TestResultHolder result = executeAsForked(test, watchdog,
0870:                            casesFile);
0871:                    actOnTestResult(result, test, "Tests");
0872:                } catch (IOException e) {
0873:                    log(e.toString(), Project.MSG_ERR);
0874:                    throw new BuildException(e);
0875:                } finally {
0876:                    if (writer != null) {
0877:                        writer.close();
0878:                    }
0879:
0880:                    try {
0881:                        casesFile.delete();
0882:                    } catch (Exception e) {
0883:                        log(e.toString(), Project.MSG_ERR);
0884:                    }
0885:                }
0886:            }
0887:
0888:            /**
0889:             * Execute a testcase by forking a new JVM. The command will block
0890:             * until it finishes. To know if the process was destroyed or not
0891:             * or whether the forked Java VM exited abnormally, use the
0892:             * attributes of the returned holder object.
0893:             * @param  test       the testcase to execute.
0894:             * @param  watchdog   the watchdog in charge of cancelling the test if it
0895:             * exceeds a certain amount of time. Can be <tt>null</tt>, in this case
0896:             * the test could probably hang forever.
0897:             * @param casesFile list of test cases to execute. Can be <tt>null</tt>,
0898:             * in this case only one test is executed.
0899:             * @throws BuildException in case of error creating a temporary property file,
0900:             * or if the junit process can not be forked
0901:             */
0902:            private TestResultHolder executeAsForked(JUnitTest test,
0903:                    ExecuteWatchdog watchdog, File casesFile)
0904:                    throws BuildException {
0905:
0906:                if (perm != null) {
0907:                    log("Permissions ignored when running in forked mode!",
0908:                            Project.MSG_WARN);
0909:                }
0910:
0911:                CommandlineJava cmd = null;
0912:                try {
0913:                    cmd = (CommandlineJava) (getCommandline().clone());
0914:                } catch (CloneNotSupportedException e) {
0915:                    throw new BuildException("This shouldn't happen", e,
0916:                            getLocation());
0917:                }
0918:                cmd
0919:                        .setClassname("org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner");
0920:                if (casesFile == null) {
0921:                    cmd.createArgument().setValue(test.getName());
0922:                } else {
0923:                    log("Running multiple tests in the same VM",
0924:                            Project.MSG_VERBOSE);
0925:                    cmd.createArgument().setValue(
0926:                            Constants.TESTSFILE + casesFile);
0927:                }
0928:
0929:                cmd.createArgument().setValue(
0930:                        Constants.FILTERTRACE + test.getFiltertrace());
0931:                cmd.createArgument().setValue(
0932:                        Constants.HALT_ON_ERROR + test.getHaltonerror());
0933:                cmd.createArgument().setValue(
0934:                        Constants.HALT_ON_FAILURE + test.getHaltonfailure());
0935:                if (includeAntRuntime) {
0936:                    Vector v = Execute.getProcEnvironment();
0937:                    Enumeration e = v.elements();
0938:                    while (e.hasMoreElements()) {
0939:                        String s = (String) e.nextElement();
0940:                        if (s.startsWith(CLASSPATH)) {
0941:                            cmd.createClasspath(getProject()).createPath()
0942:                                    .append(
0943:                                            new Path(getProject(), s
0944:                                                    .substring(CLASSPATH
0945:                                                            .length())));
0946:                        }
0947:                    }
0948:                    log("Implicitly adding " + antRuntimeClasses
0949:                            + " to CLASSPATH", Project.MSG_VERBOSE);
0950:                    cmd.createClasspath(getProject()).createPath().append(
0951:                            antRuntimeClasses);
0952:                }
0953:
0954:                if (summary) {
0955:                    String prefix = "";
0956:                    if ("withoutanderr".equalsIgnoreCase(summaryValue)) {
0957:                        prefix = "OutErr";
0958:                    }
0959:                    cmd
0960:                            .createArgument()
0961:                            .setValue(
0962:                                    Constants.FORMATTER
0963:                                            + "org.apache.tools.ant.taskdefs.optional.junit."
0964:                                            + prefix
0965:                                            + "SummaryJUnitResultFormatter");
0966:                }
0967:
0968:                cmd.createArgument().setValue(
0969:                        Constants.SHOWOUTPUT + String.valueOf(showOutput));
0970:                cmd.createArgument().setValue(
0971:                        Constants.OUTPUT_TO_FORMATTERS
0972:                                + String.valueOf(outputToFormatters));
0973:
0974:                cmd.createArgument().setValue(
0975:                        Constants.LOGTESTLISTENEREVENTS + "true"); // #31885
0976:
0977:                StringBuffer formatterArg = new StringBuffer(STRING_BUFFER_SIZE);
0978:                final FormatterElement[] feArray = mergeFormatters(test);
0979:                for (int i = 0; i < feArray.length; i++) {
0980:                    FormatterElement fe = feArray[i];
0981:                    if (fe.shouldUse(this )) {
0982:                        formatterArg.append(Constants.FORMATTER);
0983:                        formatterArg.append(fe.getClassname());
0984:                        File outFile = getOutput(fe, test);
0985:                        if (outFile != null) {
0986:                            formatterArg.append(",");
0987:                            formatterArg.append(outFile);
0988:                        }
0989:                        cmd.createArgument().setValue(formatterArg.toString());
0990:                        formatterArg = new StringBuffer();
0991:                    }
0992:                }
0993:
0994:                File vmWatcher = createTempPropertiesFile("junitvmwatcher");
0995:                cmd.createArgument().setValue(
0996:                        Constants.CRASHFILE + vmWatcher.getAbsolutePath());
0997:                File propsFile = createTempPropertiesFile("junit");
0998:                cmd.createArgument().setValue(
0999:                        Constants.PROPSFILE + propsFile.getAbsolutePath());
1000:                Hashtable p = getProject().getProperties();
1001:                Properties props = new Properties();
1002:                for (Enumeration e = p.keys(); e.hasMoreElements();) {
1003:                    Object key = e.nextElement();
1004:                    props.put(key, p.get(key));
1005:                }
1006:                try {
1007:                    FileOutputStream outstream = new FileOutputStream(propsFile);
1008:                    props.store(outstream,
1009:                            "Ant JUnitTask generated properties file");
1010:                    outstream.close();
1011:                } catch (java.io.IOException e) {
1012:                    propsFile.delete();
1013:                    throw new BuildException(
1014:                            "Error creating temporary properties " + "file.",
1015:                            e, getLocation());
1016:                }
1017:
1018:                Execute execute = new Execute(new JUnitLogStreamHandler(this ,
1019:                        Project.MSG_INFO, Project.MSG_WARN), watchdog);
1020:                execute.setCommandline(cmd.getCommandline());
1021:                execute.setAntRun(getProject());
1022:                if (dir != null) {
1023:                    execute.setWorkingDirectory(dir);
1024:                }
1025:
1026:                String[] environment = env.getVariables();
1027:                if (environment != null) {
1028:                    for (int i = 0; i < environment.length; i++) {
1029:                        log("Setting environment variable: " + environment[i],
1030:                                Project.MSG_VERBOSE);
1031:                    }
1032:                }
1033:                execute.setNewenvironment(newEnvironment);
1034:                execute.setEnvironment(environment);
1035:
1036:                log(cmd.describeCommand(), Project.MSG_VERBOSE);
1037:                TestResultHolder result = new TestResultHolder();
1038:                try {
1039:                    result.exitCode = execute.execute();
1040:                } catch (IOException e) {
1041:                    throw new BuildException("Process fork failed.", e,
1042:                            getLocation());
1043:                } finally {
1044:                    String vmCrashString = "unknown";
1045:                    BufferedReader br = null;
1046:                    try {
1047:                        br = new BufferedReader(new FileReader(vmWatcher));
1048:                        vmCrashString = br.readLine();
1049:                    } catch (Exception e) {
1050:                        e.printStackTrace();
1051:                        // ignored.
1052:                    } finally {
1053:                        FileUtils.close(br);
1054:                    }
1055:                    if (watchdog != null && watchdog.killedProcess()) {
1056:                        result.timedOut = true;
1057:                        logTimeout(feArray, test, vmCrashString);
1058:                    } else if (!Constants.TERMINATED_SUCCESSFULLY
1059:                            .equals(vmCrashString)) {
1060:                        result.crashed = true;
1061:                        logVmCrash(feArray, test, vmCrashString);
1062:                    }
1063:                    vmWatcher.delete();
1064:
1065:                    if (!propsFile.delete()) {
1066:                        throw new BuildException("Could not delete temporary "
1067:                                + "properties file.");
1068:                    }
1069:                }
1070:
1071:                return result;
1072:            }
1073:
1074:            /**
1075:             * Create a temporary file to pass the properties to a new process.
1076:             * Will auto-delete on (graceful) exit.
1077:             * The file will be in the project basedir unless tmpDir declares
1078:             * something else.
1079:             * @param prefix
1080:             * @return created file
1081:             */
1082:            private File createTempPropertiesFile(String prefix) {
1083:                File propsFile = FILE_UTILS.createTempFile(prefix,
1084:                        ".properties", tmpDir != null ? tmpDir : getProject()
1085:                                .getBaseDir(), true);
1086:                return propsFile;
1087:            }
1088:
1089:            /**
1090:             * Pass output sent to System.out to the TestRunner so it can
1091:             * collect ot for the formatters.
1092:             *
1093:             * @param output output coming from System.out
1094:             * @since Ant 1.5
1095:             */
1096:            protected void handleOutput(String output) {
1097:                if (output.startsWith(TESTLISTENER_PREFIX)) {
1098:                    log(output, Project.MSG_VERBOSE);
1099:                } else if (runner != null) {
1100:                    if (outputToFormatters) {
1101:                        runner.handleOutput(output);
1102:                    }
1103:                    if (showOutput) {
1104:                        super .handleOutput(output);
1105:                    }
1106:                } else {
1107:                    super .handleOutput(output);
1108:                }
1109:            }
1110:
1111:            /**
1112:             * Handle an input request by this task.
1113:             * @see Task#handleInput(byte[], int, int)
1114:             * This implementation delegates to a runner if it
1115:             * present.
1116:             * @param buffer the buffer into which data is to be read.
1117:             * @param offset the offset into the buffer at which data is stored.
1118:             * @param length the amount of data to read.
1119:             *
1120:             * @return the number of bytes read.
1121:             * @exception IOException if the data cannot be read.
1122:             *
1123:             * @since Ant 1.6
1124:             */
1125:            protected int handleInput(byte[] buffer, int offset, int length)
1126:                    throws IOException {
1127:                if (runner != null) {
1128:                    return runner.handleInput(buffer, offset, length);
1129:                } else {
1130:                    return super .handleInput(buffer, offset, length);
1131:                }
1132:            }
1133:
1134:            /**
1135:             * Pass output sent to System.out to the TestRunner so it can
1136:             * collect ot for the formatters.
1137:             *
1138:             * @param output output coming from System.out
1139:             * @since Ant 1.5.2
1140:             */
1141:            protected void handleFlush(String output) {
1142:                if (runner != null) {
1143:                    runner.handleFlush(output);
1144:                    if (showOutput) {
1145:                        super .handleFlush(output);
1146:                    }
1147:                } else {
1148:                    super .handleFlush(output);
1149:                }
1150:            }
1151:
1152:            /**
1153:             * Pass output sent to System.err to the TestRunner so it can
1154:             * collect it for the formatters.
1155:             *
1156:             * @param output output coming from System.err
1157:             * @since Ant 1.5
1158:             */
1159:            public void handleErrorOutput(String output) {
1160:                if (runner != null) {
1161:                    runner.handleErrorOutput(output);
1162:                    if (showOutput) {
1163:                        super .handleErrorOutput(output);
1164:                    }
1165:                } else {
1166:                    super .handleErrorOutput(output);
1167:                }
1168:            }
1169:
1170:            /**
1171:             * Pass output sent to System.err to the TestRunner so it can
1172:             * collect it for the formatters.
1173:             *
1174:             * @param output coming from System.err
1175:             * @since Ant 1.5.2
1176:             */
1177:            public void handleErrorFlush(String output) {
1178:                if (runner != null) {
1179:                    runner.handleErrorFlush(output);
1180:                    if (showOutput) {
1181:                        super .handleErrorFlush(output);
1182:                    }
1183:                } else {
1184:                    super .handleErrorFlush(output);
1185:                }
1186:            }
1187:
1188:            // in VM is not very nice since it could probably hang the
1189:            // whole build. IMHO this method should be avoided and it would be best
1190:            // to remove it in future versions. TBD. (SBa)
1191:
1192:            /**
1193:             * Execute inside VM.
1194:             * @param arg one JUnitTest
1195:             * @throws BuildException under unspecified circumstances
1196:             */
1197:            private TestResultHolder executeInVM(JUnitTest arg)
1198:                    throws BuildException {
1199:                JUnitTest test = (JUnitTest) arg.clone();
1200:                test.setProperties(getProject().getProperties());
1201:                if (dir != null) {
1202:                    log("dir attribute ignored if running in the same VM",
1203:                            Project.MSG_WARN);
1204:                }
1205:
1206:                if (newEnvironment || null != env.getVariables()) {
1207:                    log(
1208:                            "Changes to environment variables are ignored if running in "
1209:                                    + "the same VM.", Project.MSG_WARN);
1210:                }
1211:
1212:                if (getCommandline().getBootclasspath() != null) {
1213:                    log("bootclasspath is ignored if running in the same VM.",
1214:                            Project.MSG_WARN);
1215:                }
1216:
1217:                CommandlineJava.SysProperties sysProperties = getCommandline()
1218:                        .getSystemProperties();
1219:                if (sysProperties != null) {
1220:                    sysProperties.setSystem();
1221:                }
1222:
1223:                try {
1224:                    log("Using System properties " + System.getProperties(),
1225:                            Project.MSG_VERBOSE);
1226:                    if (splitJunit) {
1227:                        classLoader = (AntClassLoader) delegate.getClass()
1228:                                .getClassLoader();
1229:                    } else {
1230:                        createClassLoader();
1231:                    }
1232:                    if (classLoader != null) {
1233:                        classLoader.setThreadContextLoader();
1234:                    }
1235:                    runner = delegate.newJUnitTestRunner(test, test
1236:                            .getHaltonerror(), test.getFiltertrace(), test
1237:                            .getHaltonfailure(), false, true, classLoader);
1238:                    if (summary) {
1239:
1240:                        JUnitTaskMirror.SummaryJUnitResultFormatterMirror f = delegate
1241:                                .newSummaryJUnitResultFormatter();
1242:                        f.setWithOutAndErr("withoutanderr"
1243:                                .equalsIgnoreCase(summaryValue));
1244:                        f.setOutput(getDefaultOutput());
1245:                        runner.addFormatter(f);
1246:                    }
1247:
1248:                    runner.setPermissions(perm);
1249:
1250:                    final FormatterElement[] feArray = mergeFormatters(test);
1251:                    for (int i = 0; i < feArray.length; i++) {
1252:                        FormatterElement fe = feArray[i];
1253:                        if (fe.shouldUse(this )) {
1254:                            File outFile = getOutput(fe, test);
1255:                            if (outFile != null) {
1256:                                fe.setOutfile(outFile);
1257:                            } else {
1258:                                fe.setOutput(getDefaultOutput());
1259:                            }
1260:                            runner
1261:                                    .addFormatter(fe
1262:                                            .createFormatter(classLoader));
1263:                        }
1264:                    }
1265:
1266:                    runner.run();
1267:                    TestResultHolder result = new TestResultHolder();
1268:                    result.exitCode = runner.getRetCode();
1269:                    return result;
1270:                } finally {
1271:                    if (sysProperties != null) {
1272:                        sysProperties.restoreSystem();
1273:                    }
1274:                    if (classLoader != null) {
1275:                        classLoader.resetThreadContextLoader();
1276:                    }
1277:                }
1278:            }
1279:
1280:            /**
1281:             * @return <tt>null</tt> if there is a timeout value, otherwise the
1282:             * watchdog instance.
1283:             *
1284:             * @throws BuildException under unspecified circumstances
1285:             * @since Ant 1.2
1286:             */
1287:            protected ExecuteWatchdog createWatchdog() throws BuildException {
1288:                if (timeout == null) {
1289:                    return null;
1290:                }
1291:                return new ExecuteWatchdog((long) timeout.intValue());
1292:            }
1293:
1294:            /**
1295:             * Get the default output for a formatter.
1296:             *
1297:             * @return default output stream for a formatter
1298:             * @since Ant 1.3
1299:             */
1300:            protected OutputStream getDefaultOutput() {
1301:                return new LogOutputStream(this , Project.MSG_INFO);
1302:            }
1303:
1304:            /**
1305:             * Merge all individual tests from the batchtest with all individual tests
1306:             * and return an enumeration over all <tt>JUnitTest</tt>.
1307:             *
1308:             * @return enumeration over individual tests
1309:             * @since Ant 1.3
1310:             */
1311:            protected Enumeration getIndividualTests() {
1312:                final int count = batchTests.size();
1313:                final Enumeration[] enums = new Enumeration[count + 1];
1314:                for (int i = 0; i < count; i++) {
1315:                    BatchTest batchtest = (BatchTest) batchTests.elementAt(i);
1316:                    enums[i] = batchtest.elements();
1317:                }
1318:                enums[enums.length - 1] = tests.elements();
1319:                return Enumerations.fromCompound(enums);
1320:            }
1321:
1322:            /**
1323:             * return an enumeration listing each test, then each batchtest
1324:             * @return enumeration
1325:             * @since Ant 1.3
1326:             */
1327:            protected Enumeration allTests() {
1328:                Enumeration[] enums = { tests.elements(), batchTests.elements() };
1329:                return Enumerations.fromCompound(enums);
1330:            }
1331:
1332:            /**
1333:             * @param test junit test
1334:             * @return array of FormatterElement
1335:             * @since Ant 1.3
1336:             */
1337:            private FormatterElement[] mergeFormatters(JUnitTest test) {
1338:                Vector feVector = (Vector) formatters.clone();
1339:                test.addFormattersTo(feVector);
1340:                FormatterElement[] feArray = new FormatterElement[feVector
1341:                        .size()];
1342:                feVector.copyInto(feArray);
1343:                return feArray;
1344:            }
1345:
1346:            /**
1347:             * If the formatter sends output to a file, return that file.
1348:             * null otherwise.
1349:             * @param fe  formatter element
1350:             * @param test one JUnit test
1351:             * @return file reference
1352:             * @since Ant 1.3
1353:             */
1354:            protected File getOutput(FormatterElement fe, JUnitTest test) {
1355:                if (fe.getUseFile()) {
1356:                    String base = test.getOutfile();
1357:                    if (base == null) {
1358:                        base = JUnitTaskMirror.JUnitTestRunnerMirror.IGNORED_FILE_NAME;
1359:                    }
1360:                    String filename = base + fe.getExtension();
1361:                    File destFile = new File(test.getTodir(), filename);
1362:                    String absFilename = destFile.getAbsolutePath();
1363:                    return getProject().resolveFile(absFilename);
1364:                }
1365:                return null;
1366:            }
1367:
1368:            /**
1369:             * Search for the given resource and add the directory or archive
1370:             * that contains it to the classpath.
1371:             *
1372:             * <p>Doesn't work for archives in JDK 1.1 as the URL returned by
1373:             * getResource doesn't contain the name of the archive.</p>
1374:             *
1375:             * @param resource resource that one wants to lookup
1376:             * @return true if something was in fact added
1377:             * @since Ant 1.4
1378:             */
1379:            protected boolean addClasspathEntry(String resource) {
1380:                /*
1381:                 * pre Ant 1.6 this method used to call getClass().getResource
1382:                 * while Ant 1.6 will call ClassLoader.getResource().
1383:                 *
1384:                 * The difference is that Class.getResource expects a leading
1385:                 * slash for "absolute" resources and will strip it before
1386:                 * delegating to ClassLoader.getResource - so we now have to
1387:                 * emulate Class's behavior.
1388:                 */
1389:                if (resource.startsWith("/")) {
1390:                    resource = resource.substring(1);
1391:                } else {
1392:                    resource = "org/apache/tools/ant/taskdefs/optional/junit/"
1393:                            + resource;
1394:                }
1395:
1396:                File f = LoaderUtils.getResourceSource(getClass()
1397:                        .getClassLoader(), resource);
1398:                if (f != null) {
1399:                    log("Found " + f.getAbsolutePath(), Project.MSG_DEBUG);
1400:                    antRuntimeClasses.createPath().setLocation(f);
1401:                    return true;
1402:                } else {
1403:                    log("Couldn\'t find " + resource, Project.MSG_DEBUG);
1404:                    return false;
1405:                }
1406:            }
1407:
1408:            /**
1409:             * Take care that some output is produced in report files if the
1410:             * watchdog kills the test.
1411:             *
1412:             * @since Ant 1.5.2
1413:             */
1414:
1415:            private void logTimeout(FormatterElement[] feArray, JUnitTest test,
1416:                    String testCase) {
1417:                logVmExit(feArray, test,
1418:                        "Timeout occurred. Please note the time in the report does"
1419:                                + " not reflect the time until the timeout.",
1420:                        testCase);
1421:            }
1422:
1423:            /**
1424:             * Take care that some output is produced in report files if the
1425:             * forked machine exited before the test suite finished but the
1426:             * reason is not a timeout.
1427:             *
1428:             * @since Ant 1.7
1429:             */
1430:            private void logVmCrash(FormatterElement[] feArray, JUnitTest test,
1431:                    String testCase) {
1432:                logVmExit(
1433:                        feArray,
1434:                        test,
1435:                        "Forked Java VM exited abnormally. Please note the time in the report"
1436:                                + " does not reflect the time until the VM exit.",
1437:                        testCase);
1438:            }
1439:
1440:            /**
1441:             * Take care that some output is produced in report files if the
1442:             * forked machine terminated before the test suite finished
1443:             *
1444:             * @since Ant 1.7
1445:             */
1446:            private void logVmExit(FormatterElement[] feArray, JUnitTest test,
1447:                    String message, String testCase) {
1448:                try {
1449:                    log("Using System properties " + System.getProperties(),
1450:                            Project.MSG_VERBOSE);
1451:                    if (splitJunit) {
1452:                        classLoader = (AntClassLoader) delegate.getClass()
1453:                                .getClassLoader();
1454:                    } else {
1455:                        createClassLoader();
1456:                    }
1457:                    if (classLoader != null) {
1458:                        classLoader.setThreadContextLoader();
1459:                    }
1460:
1461:                    test.setCounts(1, 0, 1);
1462:                    test.setProperties(getProject().getProperties());
1463:                    for (int i = 0; i < feArray.length; i++) {
1464:                        FormatterElement fe = feArray[i];
1465:                        File outFile = getOutput(fe, test);
1466:                        JUnitTaskMirror.JUnitResultFormatterMirror formatter = fe
1467:                                .createFormatter(classLoader);
1468:                        if (outFile != null && formatter != null) {
1469:                            try {
1470:                                OutputStream out = new FileOutputStream(outFile);
1471:                                delegate.addVmExit(test, formatter, out,
1472:                                        message, testCase);
1473:                            } catch (IOException e) {
1474:                                // ignore
1475:                            }
1476:                        }
1477:                    }
1478:                    if (summary) {
1479:                        JUnitTaskMirror.SummaryJUnitResultFormatterMirror f = delegate
1480:                                .newSummaryJUnitResultFormatter();
1481:                        f.setWithOutAndErr("withoutanderr"
1482:                                .equalsIgnoreCase(summaryValue));
1483:                        delegate.addVmExit(test, f, getDefaultOutput(),
1484:                                message, testCase);
1485:                    }
1486:                } finally {
1487:                    if (classLoader != null) {
1488:                        classLoader.resetThreadContextLoader();
1489:                    }
1490:                }
1491:            }
1492:
1493:            /**
1494:             * Creates and configures an AntClassLoader instance from the
1495:             * nested classpath element.
1496:             *
1497:             * @since Ant 1.6
1498:             */
1499:            private void createClassLoader() {
1500:                Path userClasspath = getCommandline().getClasspath();
1501:                if (userClasspath != null) {
1502:                    if (reloading || classLoader == null) {
1503:                        deleteClassLoader();
1504:                        Path classpath = (Path) userClasspath.clone();
1505:                        if (includeAntRuntime) {
1506:                            log("Implicitly adding " + antRuntimeClasses
1507:                                    + " to CLASSPATH", Project.MSG_VERBOSE);
1508:                            classpath.append(antRuntimeClasses);
1509:                        }
1510:                        classLoader = getProject().createClassLoader(classpath);
1511:                        if (getClass().getClassLoader() != null
1512:                                && getClass().getClassLoader() != Project.class
1513:                                        .getClassLoader()) {
1514:                            classLoader.setParent(getClass().getClassLoader());
1515:                        }
1516:                        classLoader.setParentFirst(false);
1517:                        classLoader.addJavaLibraries();
1518:                        log("Using CLASSPATH " + classLoader.getClasspath(),
1519:                                Project.MSG_VERBOSE);
1520:                        // make sure the test will be accepted as a TestCase
1521:                        classLoader.addSystemPackageRoot("junit");
1522:                        // make sure the test annotation are accepted
1523:                        classLoader.addSystemPackageRoot("org.junit");
1524:                        // will cause trouble in JDK 1.1 if omitted
1525:                        classLoader
1526:                                .addSystemPackageRoot("org.apache.tools.ant");
1527:                    }
1528:                }
1529:            }
1530:
1531:            /**
1532:             * Removes a classloader if needed.
1533:             * @since Ant 1.7
1534:             */
1535:            private void deleteClassLoader() {
1536:                if (classLoader != null) {
1537:                    classLoader.cleanup();
1538:                    classLoader = null;
1539:                }
1540:            }
1541:
1542:            /**
1543:             * Get the command line used to run the tests.
1544:             * @return the command line.
1545:             * @since Ant 1.6.2
1546:             */
1547:            protected CommandlineJava getCommandline() {
1548:                if (commandline == null) {
1549:                    commandline = new CommandlineJava();
1550:                }
1551:                return commandline;
1552:            }
1553:
1554:            /**
1555:             * Forked test support
1556:             * @since Ant 1.6.2
1557:             */
1558:            private static final class ForkedTestConfiguration {
1559:                private boolean filterTrace;
1560:                private boolean haltOnError;
1561:                private boolean haltOnFailure;
1562:                private String errorProperty;
1563:                private String failureProperty;
1564:
1565:                /**
1566:                 * constructor for forked test configuration
1567:                 * @param filterTrace
1568:                 * @param haltOnError
1569:                 * @param haltOnFailure
1570:                 * @param errorProperty
1571:                 * @param failureProperty
1572:                 */
1573:                ForkedTestConfiguration(boolean filterTrace,
1574:                        boolean haltOnError, boolean haltOnFailure,
1575:                        String errorProperty, String failureProperty) {
1576:                    this .filterTrace = filterTrace;
1577:                    this .haltOnError = haltOnError;
1578:                    this .haltOnFailure = haltOnFailure;
1579:                    this .errorProperty = errorProperty;
1580:                    this .failureProperty = failureProperty;
1581:                }
1582:
1583:                /**
1584:                 * configure from a test; sets member variables to attributes of the test
1585:                 * @param test
1586:                 */
1587:                ForkedTestConfiguration(JUnitTest test) {
1588:                    this (test.getFiltertrace(), test.getHaltonerror(), test
1589:                            .getHaltonfailure(), test.getErrorProperty(), test
1590:                            .getFailureProperty());
1591:                }
1592:
1593:                /**
1594:                 * equality test checks all the member variables
1595:                 * @param other
1596:                 * @return true if everything is equal
1597:                 */
1598:                public boolean equals(Object other) {
1599:                    if (other == null
1600:                            || other.getClass() != ForkedTestConfiguration.class) {
1601:                        return false;
1602:                    }
1603:                    ForkedTestConfiguration o = (ForkedTestConfiguration) other;
1604:                    return filterTrace == o.filterTrace
1605:                            && haltOnError == o.haltOnError
1606:                            && haltOnFailure == o.haltOnFailure
1607:                            && ((errorProperty == null && o.errorProperty == null) || (errorProperty != null && errorProperty
1608:                                    .equals(o.errorProperty)))
1609:                            && ((failureProperty == null && o.failureProperty == null) || (failureProperty != null && failureProperty
1610:                                    .equals(o.failureProperty)));
1611:                }
1612:
1613:                /**
1614:                 * hashcode is based only on the boolean members, and returns a value
1615:                 * in the range 0-7.
1616:                 * @return hash code value
1617:                 */
1618:                public int hashCode() {
1619:                    return (filterTrace ? 1 : 0) + (haltOnError ? 2 : 0)
1620:                            + (haltOnFailure ? 4 : 0);
1621:                }
1622:            }
1623:
1624:            /**
1625:             * These are the different forking options
1626:             * @since 1.6.2
1627:             */
1628:            public static final class ForkMode extends EnumeratedAttribute {
1629:
1630:                /**
1631:                 * fork once only
1632:                 */
1633:                public static final String ONCE = "once";
1634:                /**
1635:                 * fork once per test class
1636:                 */
1637:                public static final String PER_TEST = "perTest";
1638:                /**
1639:                 * fork once per batch of tests
1640:                 */
1641:                public static final String PER_BATCH = "perBatch";
1642:
1643:                /** No arg constructor. */
1644:                public ForkMode() {
1645:                    super ();
1646:                }
1647:
1648:                /**
1649:                 * Constructor using a value.
1650:                 * @param value the value to use - once, perTest or perBatch.
1651:                 */
1652:                public ForkMode(String value) {
1653:                    super ();
1654:                    setValue(value);
1655:                }
1656:
1657:                /** {@inheritDoc}. */
1658:                public String[] getValues() {
1659:                    return new String[] { ONCE, PER_TEST, PER_BATCH };
1660:                }
1661:            }
1662:
1663:            /**
1664:             * Executes all tests that don't need to be forked (or all tests
1665:             * if the runIndividual argument is true.  Returns a collection of
1666:             * lists of tests that share the same VM configuration and haven't
1667:             * been executed yet.
1668:             * @param testList the list of tests to be executed or queued.
1669:             * @param runIndividual if true execute each test individually.
1670:             * @return a list of tasks to be executed.
1671:             * @since 1.6.2
1672:             */
1673:            protected Collection executeOrQueue(Enumeration testList,
1674:                    boolean runIndividual) {
1675:                Map testConfigurations = new HashMap();
1676:                while (testList.hasMoreElements()) {
1677:                    JUnitTest test = (JUnitTest) testList.nextElement();
1678:                    if (test.shouldRun(getProject())) {
1679:                        if (runIndividual || !test.getFork()) {
1680:                            execute(test);
1681:                        } else {
1682:                            ForkedTestConfiguration c = new ForkedTestConfiguration(
1683:                                    test);
1684:                            List l = (List) testConfigurations.get(c);
1685:                            if (l == null) {
1686:                                l = new ArrayList();
1687:                                testConfigurations.put(c, l);
1688:                            }
1689:                            l.add(test);
1690:                        }
1691:                    }
1692:                }
1693:                return testConfigurations.values();
1694:            }
1695:
1696:            /**
1697:             * Logs information about failed tests, potentially stops
1698:             * processing (by throwing a BuildException) if a failure/error
1699:             * occurred or sets a property.
1700:             * @param exitValue the exitValue of the test.
1701:             * @param wasKilled if true, the test had been killed.
1702:             * @param test      the test in question.
1703:             * @param name      the name of the test.
1704:             * @since Ant 1.6.2
1705:             */
1706:            protected void actOnTestResult(int exitValue, boolean wasKilled,
1707:                    JUnitTest test, String name) {
1708:                TestResultHolder t = new TestResultHolder();
1709:                t.exitCode = exitValue;
1710:                t.timedOut = wasKilled;
1711:                actOnTestResult(t, test, name);
1712:            }
1713:
1714:            /**
1715:             * Logs information about failed tests, potentially stops
1716:             * processing (by throwing a BuildException) if a failure/error
1717:             * occurred or sets a property.
1718:             * @param result    the result of the test.
1719:             * @param test      the test in question.
1720:             * @param name      the name of the test.
1721:             * @since Ant 1.7
1722:             */
1723:            protected void actOnTestResult(TestResultHolder result,
1724:                    JUnitTest test, String name) {
1725:                // if there is an error/failure and that it should halt, stop
1726:                // everything otherwise just log a statement
1727:                boolean fatal = result.timedOut || result.crashed;
1728:                boolean errorOccurredHere = result.exitCode == JUnitTaskMirror.JUnitTestRunnerMirror.ERRORS
1729:                        || fatal;
1730:                boolean failureOccurredHere = result.exitCode != JUnitTaskMirror.JUnitTestRunnerMirror.SUCCESS
1731:                        || fatal;
1732:                if (errorOccurredHere || failureOccurredHere) {
1733:                    if ((errorOccurredHere && test.getHaltonerror())
1734:                            || (failureOccurredHere && test.getHaltonfailure())) {
1735:                        throw new BuildException(name + " failed"
1736:                                + (result.timedOut ? " (timeout)" : "")
1737:                                + (result.crashed ? " (crashed)" : ""),
1738:                                getLocation());
1739:                    } else {
1740:                        log(name + " FAILED"
1741:                                + (result.timedOut ? " (timeout)" : "")
1742:                                + (result.crashed ? " (crashed)" : ""),
1743:                                Project.MSG_ERR);
1744:                        if (errorOccurredHere
1745:                                && test.getErrorProperty() != null) {
1746:                            getProject().setNewProperty(
1747:                                    test.getErrorProperty(), "true");
1748:                        }
1749:                        if (failureOccurredHere
1750:                                && test.getFailureProperty() != null) {
1751:                            getProject().setNewProperty(
1752:                                    test.getFailureProperty(), "true");
1753:                        }
1754:                    }
1755:                }
1756:            }
1757:
1758:            /**
1759:             * A value class that contains thee result of a test.
1760:             */
1761:            protected class TestResultHolder {
1762:                // CheckStyle:VisibilityModifier OFF - bc
1763:                /** the exit code of the test. */
1764:                public int exitCode = JUnitTaskMirror.JUnitTestRunnerMirror.ERRORS;
1765:                /** true if the test timed out */
1766:                public boolean timedOut = false;
1767:                /** true if the test crashed */
1768:                public boolean crashed = false;
1769:                // CheckStyle:VisibilityModifier ON
1770:            }
1771:
1772:            /**
1773:             * A stream handler for handling the junit task.
1774:             * @since Ant 1.7
1775:             */
1776:            protected static class JUnitLogOutputStream extends LogOutputStream {
1777:                private Task task; // local copy since LogOutputStream.task is private
1778:
1779:                /**
1780:                 * Constructor.
1781:                 * @param task the task being logged.
1782:                 * @param level the log level used to log data written to this stream.
1783:                 */
1784:                public JUnitLogOutputStream(Task task, int level) {
1785:                    super (task, level);
1786:                    this .task = task;
1787:                }
1788:
1789:                /**
1790:                 * Logs a line.
1791:                 * If the line starts with junit.framework.TestListener: set the level
1792:                 * to MSG_VERBOSE.
1793:                 * @param line the line to log.
1794:                 * @param level the logging level to use.
1795:                 */
1796:                protected void processLine(String line, int level) {
1797:                    if (line.startsWith(TESTLISTENER_PREFIX)) {
1798:                        task.log(line, Project.MSG_VERBOSE);
1799:                    } else {
1800:                        super .processLine(line, level);
1801:                    }
1802:                }
1803:            }
1804:
1805:            /**
1806:             * A log stream handler for junit.
1807:             * @since Ant 1.7
1808:             */
1809:            protected static class JUnitLogStreamHandler extends
1810:                    PumpStreamHandler {
1811:                /**
1812:                 * Constructor.
1813:                 * @param task the task to log.
1814:                 * @param outlevel the level to use for standard output.
1815:                 * @param errlevel the level to use for error output.
1816:                 */
1817:                public JUnitLogStreamHandler(Task task, int outlevel,
1818:                        int errlevel) {
1819:                    super (new JUnitLogOutputStream(task, outlevel),
1820:                            new LogOutputStream(task, errlevel));
1821:                }
1822:            }
1823:        }
w__w__w.java_2s__._c___om___ | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.