diff options
Diffstat (limited to 'framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTest.java')
-rw-r--r-- | framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTest.java | 542 |
1 files changed, 542 insertions, 0 deletions
diff --git a/framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTest.java b/framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTest.java new file mode 100644 index 00000000..835c013b --- /dev/null +++ b/framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTest.java @@ -0,0 +1,542 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.apache.tools.ant.taskdefs.optional.junit; + +import java.util.Enumeration; +import java.util.Hashtable; +import java.util.Properties; +import java.util.Vector; + +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.Project; +import org.apache.tools.ant.PropertyHelper; + +/** + * <p> Run a single JUnit test. + * + * <p> The JUnit test is actually run by {@link JUnitTestRunner}. + * So read the doc comments for that class :) + * + * @since Ant 1.2 + * + * @see JUnitTask + * @see JUnitTestRunner + */ +public class JUnitTest extends BaseTest implements Cloneable { + + /** the name of the test case */ + private String name = null; + + /** + * whether the list of test methods has been specified + * @see #setMethods(java.lang.String) + * @see #setMethods(java.lang.String[]) + */ + private boolean methodsSpecified = false; + + /** comma-separated list of names of test methods to execute */ + private String methodsList = null; + + /** the names of test methods to execute */ + private String[] methods = null; + + /** the name of the result file */ + private String outfile = null; + + // @todo this is duplicating TestResult information. Only the time is not + // part of the result. So we'd better derive a new class from TestResult + // and deal with it. (SB) + private long runs, failures, errors; + /** + @since Ant 1.9.0 + */ + private long skips; + + private long runTime; + + private int antThreadID; + + // Snapshot of the system properties + private Properties props = null; + + /** No arg constructor. */ + public JUnitTest() { + } + + /** + * Constructor with name. + * @param name the name of the test. + */ + public JUnitTest(String name) { + this.name = name; + } + + /** + * Constructor with options. + * @param name the name of the test. + * @param haltOnError if true halt the tests if there is an error. + * @param haltOnFailure if true halt the tests if there is a failure. + * @param filtertrace if true filter stack traces. + */ + public JUnitTest(String name, boolean haltOnError, boolean haltOnFailure, + boolean filtertrace) { + this(name, haltOnError, haltOnFailure, filtertrace, null, 0); + } + + /** + * Constructor with options. + * @param name the name of the test. + * @param haltOnError if true halt the tests if there is an error. + * @param haltOnFailure if true halt the tests if there is a failure. + * @param filtertrace if true filter stack traces. + * @param methods if non-null run only these test methods + * @since 1.8.2 + */ + public JUnitTest(String name, boolean haltOnError, boolean haltOnFailure, + boolean filtertrace, String[] methods) { + this(name, haltOnError, haltOnFailure, filtertrace, methods, 0); + } + + /** + * Constructor with options. + * @param name the name of the test. + * @param haltOnError if true halt the tests if there is an error. + * @param haltOnFailure if true halt the tests if there is a failure. + * @param filtertrace if true filter stack traces. + * @param methods if non-null run only these test methods + * @param thread Ant thread ID in which test is currently running + * @since 1.9.4 + */ + public JUnitTest(String name, boolean haltOnError, boolean haltOnFailure, + boolean filtertrace, String[] methods, int thread) { + this.name = name; + this.haltOnError = haltOnError; + this.haltOnFail = haltOnFailure; + this.filtertrace = filtertrace; + this.methodsSpecified = methods != null; + this.methods = methodsSpecified ? (String[]) methods.clone() : null; + this.antThreadID = thread; + } + + /** + * Sets names of individual test methods to be executed. + * @param value comma-separated list of names of individual test methods + * to be executed, + * or <code>null</code> if all test methods should be executed + * @since 1.8.2 + */ + public void setMethods(String value) { + methodsList = value; + methodsSpecified = (value != null); + methods = null; + } + + /** + * Sets names of individual test methods to be executed. + * @param value non-empty array of names of test methods to be executed + * @see #setMethods(String) + * @since 1.8.2 + */ + void setMethods(String[] value) { + methods = value; + methodsSpecified = (value != null); + methodsList = null; + } + + /** + * Set the name of the test class. + * @param value the name to use. + */ + public void setName(String value) { + name = value; + } + + /** + * Set the thread id + * @param thread the Ant id of the thread running this test + * (this is not the system process or thread id) + * (this will be 0 in single-threaded mode). + * @since Ant 1.9.4 + */ + public void setThread(int thread) { + this.antThreadID = thread; + } + + /** + * Set the name of the output file. + * @param value the name of the output file to use. + */ + public void setOutfile(String value) { + outfile = value; + } + + /** + * Informs whether a list of test methods has been specified in this test. + * @return <code>true</code> if test methods to be executed have been + * specified, <code>false</code> otherwise + * @see #setMethods(java.lang.String) + * @see #setMethods(java.lang.String[]) + * @since 1.8.2 + */ + boolean hasMethodsSpecified() { + return methodsSpecified; + } + + /** + * Get names of individual test methods to be executed. + * + * @return array of names of the individual test methods to be executed, + * or <code>null</code> if all test methods in the suite + * defined by the test class will be executed + * @since 1.8.2 + */ + String[] getMethods() { + if (methodsSpecified && (methods == null)) { + resolveMethods(); + } + return methods; + } + + /** + * Gets a comma-separated list of names of methods that are to be executed + * by this test. + * @return the comma-separated list of test method names, or an empty + * string of no method is to be executed, or <code>null</code> + * if no method is specified + * @since 1.8.2 + */ + String getMethodsString() { + if ((methodsList == null) && methodsSpecified) { + if (methods.length == 0) { + methodsList = ""; + } else if (methods.length == 1) { + methodsList = methods[0]; + } else { + StringBuffer buf = new StringBuffer(methods.length * 16); + buf.append(methods[0]); + for (int i = 1; i < methods.length; i++) { + buf.append(',').append(methods[i]); + } + methodsList = buf.toString(); + } + } + return methodsList; + } + + /** + * Computes the value of the {@link #methods} field from the value + * of the {@link #methodsList} field, if it has not been computed yet. + * @exception BuildException if the value of the {@link #methodsList} field + * was invalid + * @since 1.8.2 + */ + void resolveMethods() { + if ((methods == null) && methodsSpecified) { + try { + methods = parseTestMethodNamesList(methodsList); + } catch (IllegalArgumentException ex) { + throw new BuildException( + "Invalid specification of test methods: \"" + + methodsList + + "\"; expected: comma-separated list of valid Java identifiers", + ex); + } + } + } + + /** + * Parses a comma-separated list of method names and check their validity. + * @param methodNames comma-separated list of method names to be parsed + * @return array of individual test method names + * @exception java.lang.IllegalArgumentException + * if the given string is <code>null</code> or if it is not + * a comma-separated list of valid Java identifiers; + * an empty string is acceptable and is handled as an empty + * list + * @since 1.8.2 + */ + public static String[] parseTestMethodNamesList(String methodNames) + throws IllegalArgumentException { + if (methodNames == null) { + throw new IllegalArgumentException("methodNames is <null>"); + } + + methodNames = methodNames.trim(); + + int length = methodNames.length(); + if (length == 0) { + return new String[0]; + } + + /* strip the trailing comma, if any */ + if (methodNames.charAt(length - 1) == ',') { + methodNames = methodNames.substring(0, length - 1).trim(); + length = methodNames.length(); + if (length == 0) { + throw new IllegalArgumentException("Empty method name"); + } + } + + final char[] chars = methodNames.toCharArray(); + /* easy detection of one particular case of illegal string: */ + if (chars[0] == ',') { + throw new IllegalArgumentException("Empty method name"); + } + /* count number of method names: */ + int wordCount = 1; + for (int i = 1; i < chars.length; i++) { + if (chars[i] == ',') { + wordCount++; + } + } + /* prepare the resulting array: */ + String[] result = new String[wordCount]; + /* parse the string: */ + final int stateBeforeWord = 1; + final int stateInsideWord = 2; + final int stateAfterWord = 3; + // + int state = stateBeforeWord; + int wordStartIndex = -1; + int wordIndex = 0; + for (int i = 0; i < chars.length; i++) { + char c = chars[i]; + switch (state) { + case stateBeforeWord: + if (c == ',') { + throw new IllegalArgumentException("Empty method name"); + } else if (c == ' ') { + // remain in the same state + } else if (Character.isJavaIdentifierStart(c)) { + wordStartIndex = i; + state = stateInsideWord; + } else { + throw new IllegalArgumentException("Illegal start of method name: " + c); + } + break; + case stateInsideWord: + if (c == ',') { + result[wordIndex++] = methodNames.substring(wordStartIndex, i); + state = stateBeforeWord; + } else if (c == ' ') { + result[wordIndex++] = methodNames.substring(wordStartIndex, i); + state = stateAfterWord; + } else if (Character.isJavaIdentifierPart(c)) { + // remain in the same state + } else { + throw new IllegalArgumentException("Illegal character in method name: " + c); + } + break; + case stateAfterWord: + if (c == ',') { + state = stateBeforeWord; + } else if (c == ' ') { + // remain in the same state + } else { + throw new IllegalArgumentException("Space in method name"); + } + break; + default: + // this should never happen + } + } + switch (state) { + case stateBeforeWord: + case stateAfterWord: + break; + case stateInsideWord: + result[wordIndex++] = methodNames.substring(wordStartIndex, chars.length); + break; + default: + // this should never happen + } + return result; + } + + /** + * Get the name of the test class. + * @return the name of the test. + */ + public String getName() { + return name; + } + + /** + * Get the Ant id of the thread running the test. + * @return the thread id + */ + public int getThread() { + return antThreadID; + } + + /** + * Get the name of the output file + * + * @return the name of the output file. + */ + public String getOutfile() { + return outfile; + } + + /** + * Set the number of runs, failures, errors, and skipped tests. + * @param runs the number of runs. + * @param failures the number of failures. + * @param errors the number of errors. + * Kept for backward compatibility with Ant 1.8.4 + */ + public void setCounts(long runs, long failures, long errors) { + this.runs = runs; + this.failures = failures; + this.errors = errors; + } + /** + * Set the number of runs, failures, errors, and skipped tests. + * @param runs the number of runs. + * @param failures the number of failures. + * @param errors the number of errors. + * @param skips the number of skipped tests. + * @since Ant 1.9.0 + */ + public void setCounts(long runs, long failures, long errors, long skips) { + this.runs = runs; + this.failures = failures; + this.errors = errors; + this.skips = skips; + } + + /** + * Set the runtime. + * @param runTime the time in milliseconds. + */ + public void setRunTime(long runTime) { + this.runTime = runTime; + } + + /** + * Get the number of runs. + * @return the number of runs. + */ + public long runCount() { + return runs; + } + + /** + * Get the number of failures. + * @return the number of failures. + */ + public long failureCount() { + return failures; + } + + /** + * Get the number of errors. + * @return the number of errors. + */ + public long errorCount() { + return errors; + } + + /** + * Get the number of skipped tests. + * @return the number of skipped tests. + */ + public long skipCount() { + return skips; + } + + /** + * Get the run time. + * @return the run time in milliseconds. + */ + public long getRunTime() { + return runTime; + } + + /** + * Get the properties used in the test. + * @return the properties. + */ + public Properties getProperties() { + return props; + } + + /** + * Set the properties to be used in the test. + * @param p the properties. + * This is a copy of the projects ant properties. + */ + public void setProperties(Hashtable p) { + props = new Properties(); + for (Enumeration e = p.keys(); e.hasMoreElements();) { + Object key = e.nextElement(); + props.put(key, p.get(key)); + } + } + + /** + * Check if this test should run based on the if and unless + * attributes. + * @param p the project to use to check if the if and unless + * properties exist in. + * @return true if this test or testsuite should be run. + */ + public boolean shouldRun(Project p) { + PropertyHelper ph = PropertyHelper.getPropertyHelper(p); + return ph.testIfCondition(getIfCondition()) + && ph.testUnlessCondition(getUnlessCondition()); + } + + /** + * Get the formatters set for this test. + * @return the formatters as an array. + */ + public FormatterElement[] getFormatters() { + FormatterElement[] fes = new FormatterElement[formatters.size()]; + formatters.copyInto(fes); + return fes; + } + + /** + * Convenient method to add formatters to a vector + */ + void addFormattersTo(Vector v) { + final int count = formatters.size(); + for (int i = 0; i < count; i++) { + v.addElement(formatters.elementAt(i)); + } + } + + /** + * @since Ant 1.5 + * @return a clone of this test. + */ + @Override + public Object clone() { + try { + JUnitTest t = (JUnitTest) super.clone(); + t.props = props == null ? null : (Properties) props.clone(); + t.formatters = (Vector) formatters.clone(); + return t; + } catch (CloneNotSupportedException e) { + // plain impossible + return this; + } + } +} |